diff --git a/cmd/trace-agent/config/config.go b/cmd/trace-agent/config/config.go index 0a786c409d92..9ae22276b4d9 100644 --- a/cmd/trace-agent/config/config.go +++ b/cmd/trace-agent/config/config.go @@ -74,6 +74,7 @@ func prepareConfig(path string) (*config.AgentConfig, error) { cfg.LogFilePath = DefaultLogFilePath cfg.DDAgentBin = defaultDDAgentBin cfg.AgentVersion = version.AgentVersion + cfg.GitCommit = version.Commit ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) orch := fargate.GetOrchestrator(ctx) cancel() diff --git a/cmd/trace-agent/run.go b/cmd/trace-agent/run.go index d53c2cc05334..c244c93f583d 100644 --- a/cmd/trace-agent/run.go +++ b/cmd/trace-agent/run.go @@ -37,6 +37,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/util/grpc" "github.com/DataDog/datadog-agent/pkg/util/log" "github.com/DataDog/datadog-agent/pkg/util/profiling" + "github.com/DataDog/datadog-agent/pkg/version" "github.com/DataDog/datadog-agent/pkg/workloadmeta" // register all workloadmeta collectors @@ -50,7 +51,7 @@ to your datadog.yaml. Exiting...` // Run is the entrypoint of our code, which starts the agent. func Run(ctx context.Context) { if flags.Version { - fmt.Print(info.VersionString()) + fmt.Println(version.AgentVersion) return } @@ -141,7 +142,7 @@ func Run(ctx context.Context) { return } - err = metrics.Configure(cfg, []string{"version:" + info.Version}) + err = metrics.Configure(cfg, []string{"version:" + version.AgentVersion}) if err != nil { osutil.Exitf("cannot configure dogstatsd: %v", err) } @@ -296,6 +297,6 @@ func profilingConfig(cfg *config.AgentConfig) *profiling.Settings { MutexProfileFraction: coreconfig.Datadog.GetInt("internal_profiling.mutex_profile_fraction"), BlockProfileRate: coreconfig.Datadog.GetInt("internal_profiling.block_profile_rate"), WithGoroutineProfile: coreconfig.Datadog.GetBool("internal_profiling.enable_goroutine_stacktraces"), - Tags: []string{fmt.Sprintf("version:%s", info.Version)}, + Tags: []string{fmt.Sprintf("version:%s", version.AgentVersion)}, } } diff --git a/cmd/trace-agent/test/testsuite/testdata/clientstats.go b/cmd/trace-agent/test/testsuite/testdata/clientstats.go index f8f4459b6b61..38bd4841f735 100644 --- a/cmd/trace-agent/test/testsuite/testdata/clientstats.go +++ b/cmd/trace-agent/test/testsuite/testdata/clientstats.go @@ -58,6 +58,7 @@ var ClientStatsTests = []struct { Out: []pb.StatsPayload{{ AgentHostname: "agent-hostname", AgentEnv: "agent-env", + AgentVersion: "6.0.0", ClientComputed: true, Stats: []pb.ClientStatsPayload{{ Hostname: "testhost", @@ -155,6 +156,7 @@ var ClientStatsTests = []struct { { AgentHostname: "agent-hostname", AgentEnv: "agent-env", + AgentVersion: "6.0.0", ClientComputed: true, Stats: []pb.ClientStatsPayload{ { diff --git a/omnibus/config/software/datadog-agent.rb b/omnibus/config/software/datadog-agent.rb index 9be1574dd6c1..09ba2c990df1 100644 --- a/omnibus/config/software/datadog-agent.rb +++ b/omnibus/config/software/datadog-agent.rb @@ -115,7 +115,6 @@ block do # defer compilation step in a block to allow getting the project's build version, which is populated # only once the software that the project takes its version from (i.e. `datadog-agent`) has finished building - env['TRACE_AGENT_VERSION'] = project.build_version.gsub(/[^0-9\.]/, '') # used by gorake.rb in the trace-agent, only keep digits and dots platform = windows_arch_i386? ? "x86" : "x64" command "invoke trace-agent.build --python-runtimes #{py_runtimes_arg} --major-version #{major_version_arg} --arch #{platform} --flavor #{flavor_arg}", :env => env diff --git a/omnibus/config/software/datadog-iot-agent.rb b/omnibus/config/software/datadog-iot-agent.rb index 1b745f574766..9c54bd61df1b 100644 --- a/omnibus/config/software/datadog-iot-agent.rb +++ b/omnibus/config/software/datadog-iot-agent.rb @@ -112,7 +112,6 @@ if windows? # defer compilation step in a block to allow getting the project's build version, which is populated # only once the software that the project takes its version from (i.e. `datadog-agent`) has finished building - env['TRACE_AGENT_VERSION'] = project.build_version.gsub(/[^0-9\.]/, '') # used by gorake.rb in the trace-agent, only keep digits and dots platform = windows_arch_i386? ? "x86" : "x64" command "invoke trace-agent.build --major-version #{major_version_arg} --arch #{platform}", :env => env diff --git a/pkg/trace/api/api.go b/pkg/trace/api/api.go index 966646f9ebd9..7e898908533e 100644 --- a/pkg/trace/api/api.go +++ b/pkg/trace/api/api.go @@ -112,7 +112,7 @@ func (r *HTTPReceiver) buildMux() *http.ServeMux { if e.IsEnabled != nil && !e.IsEnabled(r.conf) { continue } - mux.Handle(e.Pattern, replyWithVersion(hash, e.Handler(r))) + mux.Handle(e.Pattern, replyWithVersion(hash, r.conf.AgentVersion, e.Handler(r))) } mux.HandleFunc("/info", infoHandler) @@ -121,9 +121,9 @@ func (r *HTTPReceiver) buildMux() *http.ServeMux { // replyWithVersion returns an http.Handler which calls h with an addition of some // HTTP headers containing version and state information. -func replyWithVersion(hash string, h http.Handler) http.Handler { +func replyWithVersion(hash string, version string, h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Datadog-Agent-Version", info.Version) + w.Header().Set("Datadog-Agent-Version", version) w.Header().Set("Datadog-Agent-State", hash) h.ServeHTTP(w, r) }) diff --git a/pkg/trace/api/api_test.go b/pkg/trace/api/api_test.go index 67d20a3cfee1..0abe0ac47849 100644 --- a/pkg/trace/api/api_test.go +++ b/pkg/trace/api/api_test.go @@ -143,7 +143,9 @@ func TestListenTCP(t *testing.T) { func TestStateHeaders(t *testing.T) { assert := assert.New(t) - r := newTestReceiverFromConfig(config.New()) + cfg := config.New() + cfg.AgentVersion = "testVersion" + r := newTestReceiverFromConfig(cfg) r.Start() defer r.Stop() data := msgpTraces(t, pb.Traces{ @@ -168,7 +170,7 @@ func TestStateHeaders(t *testing.T) { _, ok := resp.Header["Datadog-Agent-Version"] assert.True(ok) v := resp.Header.Get("Datadog-Agent-Version") - assert.Equal(v, info.Version) + assert.Equal("testVersion", v) _, ok = resp.Header["Datadog-Agent-State"] assert.True(ok) diff --git a/pkg/trace/api/debugger.go b/pkg/trace/api/debugger.go index 5a056a977c72..228ddfd0892d 100644 --- a/pkg/trace/api/debugger.go +++ b/pkg/trace/api/debugger.go @@ -15,7 +15,6 @@ import ( "time" "github.com/DataDog/datadog-agent/pkg/trace/config" - "github.com/DataDog/datadog-agent/pkg/trace/info" "github.com/DataDog/datadog-agent/pkg/trace/log" "github.com/DataDog/datadog-agent/pkg/trace/metrics" ) @@ -28,7 +27,7 @@ const ( // debuggerProxyHandler returns an http.Handler proxying requests to the logs intake. If the logs intake url cannot be // parsed, the returned handler will always return http.StatusInternalServerError with a clarifying message. func (r *HTTPReceiver) debuggerProxyHandler() http.Handler { - tags := fmt.Sprintf("host:%s,default_env:%s,agent_version:%s", r.conf.Hostname, r.conf.DefaultEnv, info.Version) + tags := fmt.Sprintf("host:%s,default_env:%s,agent_version:%s", r.conf.Hostname, r.conf.DefaultEnv, r.conf.AgentVersion) if orch := r.conf.FargateOrchestrator; orch != config.OrchestratorUnknown { tags = tags + ",orchestrator:fargate_" + strings.ToLower(string(orch)) } diff --git a/pkg/trace/api/evp_proxy.go b/pkg/trace/api/evp_proxy.go index b3e5dbe930ac..3642def8db57 100644 --- a/pkg/trace/api/evp_proxy.go +++ b/pkg/trace/api/evp_proxy.go @@ -18,7 +18,6 @@ import ( "github.com/DataDog/datadog-agent/pkg/trace/api/apiutil" "github.com/DataDog/datadog-agent/pkg/trace/config" - "github.com/DataDog/datadog-agent/pkg/trace/info" "github.com/DataDog/datadog-agent/pkg/trace/log" "github.com/DataDog/datadog-agent/pkg/trace/metrics" ) @@ -139,7 +138,7 @@ func (t *evpProxyTransport) RoundTrip(req *http.Request) (rresp *http.Response, req.Header = http.Header{} // Set standard headers - req.Header.Set("Via", fmt.Sprintf("trace-agent %s", info.Version)) + req.Header.Set("Via", fmt.Sprintf("trace-agent %s", t.conf.AgentVersion)) if contentType != "" { req.Header.Set("Content-Type", contentType) } diff --git a/pkg/trace/api/evp_proxy_test.go b/pkg/trace/api/evp_proxy_test.go index 0b24a0d25a3d..9c05c00365b0 100644 --- a/pkg/trace/api/evp_proxy_test.go +++ b/pkg/trace/api/evp_proxy_test.go @@ -19,7 +19,6 @@ import ( "testing" "github.com/DataDog/datadog-agent/pkg/trace/config" - "github.com/DataDog/datadog-agent/pkg/trace/info" "github.com/DataDog/datadog-agent/pkg/trace/metrics" "github.com/DataDog/datadog-agent/pkg/trace/testutil" "github.com/stretchr/testify/assert" @@ -73,6 +72,7 @@ func TestEVPProxyForwarder(t *testing.T) { conf.Hostname = "test_hostname" conf.DefaultEnv = "test_env" conf.Site = "us3.datadoghq.com" + conf.AgentVersion = "testVersion" conf.Endpoints[0].APIKey = "test_api_key" req := httptest.NewRequest("POST", "/mypath/mysubpath?arg=test", bytes.NewReader(randBodyBuf)) @@ -93,7 +93,7 @@ func TestEVPProxyForwarder(t *testing.T) { assert.Equal(t, "test_api_key", proxyreq.Header.Get("DD-API-KEY")) assert.Equal(t, conf.Hostname, proxyreq.Header.Get("X-Datadog-Hostname")) assert.Equal(t, conf.DefaultEnv, proxyreq.Header.Get("X-Datadog-AgentDefaultEnv")) - assert.Equal(t, fmt.Sprintf("trace-agent %s", info.Version), proxyreq.Header.Get("Via")) + assert.Equal(t, "trace-agent testVersion", proxyreq.Header.Get("Via")) assert.Equal(t, "test_user_agent", proxyreq.Header.Get("User-Agent")) assert.Equal(t, "text/json", proxyreq.Header.Get("Content-Type")) assert.NotContains(t, proxyreq.Header, "Unexpected-Header") diff --git a/pkg/trace/api/info.go b/pkg/trace/api/info.go index 0de9e1b790ae..4b139ec9044d 100644 --- a/pkg/trace/api/info.go +++ b/pkg/trace/api/info.go @@ -13,7 +13,6 @@ import ( "github.com/DataDog/datadog-agent/pkg/trace/config" "github.com/DataDog/datadog-agent/pkg/trace/config/features" - "github.com/DataDog/datadog-agent/pkg/trace/info" ) // makeInfoHandler returns a new handler for handling the discovery endpoint. @@ -66,7 +65,6 @@ func (r *HTTPReceiver) makeInfoHandler() (hash string, handler http.HandlerFunc) txt, err := json.MarshalIndent(struct { Version string `json:"version"` GitCommit string `json:"git_commit"` - BuildDate string `json:"build_date"` Endpoints []string `json:"endpoints"` FeatureFlags []string `json:"feature_flags,omitempty"` ClientDropP0s bool `json:"client_drop_p0s"` @@ -74,9 +72,8 @@ func (r *HTTPReceiver) makeInfoHandler() (hash string, handler http.HandlerFunc) LongRunningSpans bool `json:"long_running_spans"` Config reducedConfig `json:"config"` }{ - Version: info.Version, - GitCommit: info.GitCommit, - BuildDate: info.BuildDate, + Version: r.conf.AgentVersion, + GitCommit: r.conf.GitCommit, Endpoints: all, FeatureFlags: features.All(), ClientDropP0s: true, diff --git a/pkg/trace/api/info_test.go b/pkg/trace/api/info_test.go index 92abe323cdeb..75a1d4fd6513 100644 --- a/pkg/trace/api/info_test.go +++ b/pkg/trace/api/info_test.go @@ -13,7 +13,6 @@ import ( "time" "github.com/DataDog/datadog-agent/pkg/trace/config" - "github.com/DataDog/datadog-agent/pkg/trace/info" "github.com/DataDog/datadog-agent/pkg/trace/testutil" "github.com/stretchr/testify/assert" ) @@ -49,10 +48,12 @@ func TestInfoHandler(t *testing.T) { Memcached: config.Enablable{Enabled: false}, } conf := &config.AgentConfig{ - Enabled: true, - Hostname: "test.host.name", - DefaultEnv: "prod", - ConfigPath: "/path/to/config", + Enabled: true, + AgentVersion: "0.99.0", + GitCommit: "fab047e10", + Hostname: "test.host.name", + DefaultEnv: "prod", + ConfigPath: "/path/to/config", Endpoints: []*config.Endpoint{{ APIKey: "123", Host: "https://target-intake.datadoghq.com", @@ -115,7 +116,6 @@ func TestInfoHandler(t *testing.T) { expected: `{ "version": "0.99.0", "git_commit": "fab047e10", - "build_date": "2020-12-04 15:57:06.74187 +0200 EET m=+0.029001792", "endpoints": [ "/v0.3/traces", "/v0.3/services", @@ -175,7 +175,6 @@ func TestInfoHandler(t *testing.T) { expected: `{ "version": "0.99.0", "git_commit": "fab047e10", - "build_date": "2020-12-04 15:57:06.74187 +0200 EET m=+0.029001792", "endpoints": [ "/v0.3/traces", "/v0.3/services", @@ -235,17 +234,11 @@ func TestInfoHandler(t *testing.T) { t.Run(tt.name, func(t *testing.T) { rcv := newTestReceiverFromConfig(conf) defer testutil.WithFeatures("feature_flag")() - defer func(old string) { info.Version = old }(info.Version) - defer func(old string) { info.GitCommit = old }(info.GitCommit) - defer func(old string) { info.BuildDate = old }(info.BuildDate) - info.Version = "0.99.0" - info.GitCommit = "fab047e10" - info.BuildDate = "2020-12-04 15:57:06.74187 +0200 EET m=+0.029001792" _, h := rcv.makeInfoHandler() rec := httptest.NewRecorder() req := httptest.NewRequest("GET", "/info", nil) h.ServeHTTP(rec, req) - assert.Equal(t, rec.Body.String(), tt.expected) + assert.Equal(t, tt.expected, rec.Body.String()) if rec.Body.String() != tt.expected { t.Fatalf("Output of /info has changed. Changing the keys "+ "is not allowed because the client rely on them and "+ diff --git a/pkg/trace/api/pipeline_stats.go b/pkg/trace/api/pipeline_stats.go index 696dd3c59111..eff6668090e5 100644 --- a/pkg/trace/api/pipeline_stats.go +++ b/pkg/trace/api/pipeline_stats.go @@ -16,7 +16,6 @@ import ( "time" "github.com/DataDog/datadog-agent/pkg/trace/config" - "github.com/DataDog/datadog-agent/pkg/trace/info" "github.com/DataDog/datadog-agent/pkg/trace/log" "github.com/DataDog/datadog-agent/pkg/trace/metrics" ) @@ -45,7 +44,7 @@ func (r *HTTPReceiver) pipelineStatsProxyHandler() http.Handler { log.Errorf("Failed to start pipeline stats proxy handler: %v", err) return pipelineStatsErrorHandler(err) } - tags := fmt.Sprintf("host:%s,default_env:%s,agent_version:%s", r.conf.Hostname, r.conf.DefaultEnv, info.Version) + tags := fmt.Sprintf("host:%s,default_env:%s,agent_version:%s", r.conf.Hostname, r.conf.DefaultEnv, r.conf.AgentVersion) if orch := r.conf.FargateOrchestrator; orch != config.OrchestratorUnknown { tag := fmt.Sprintf("orchestrator:fargate_%s", strings.ToLower(string(orch))) tags = tags + "," + tag @@ -64,7 +63,7 @@ func pipelineStatsErrorHandler(err error) http.Handler { // The tags will be added as a header to all proxied requests. func newPipelineStatsProxy(conf *config.AgentConfig, target *url.URL, key string, tags string) *httputil.ReverseProxy { director := func(req *http.Request) { - req.Header.Set("Via", fmt.Sprintf("trace-agent %s", info.Version)) + req.Header.Set("Via", fmt.Sprintf("trace-agent %s", conf.AgentVersion)) if _, ok := req.Header["User-Agent"]; !ok { // explicitly disable User-Agent so it's not set to the default value // that net/http gives it: Go-http-client/1.1 diff --git a/pkg/trace/api/profiles.go b/pkg/trace/api/profiles.go index 7b20a4108d4d..60f0ea9623ce 100644 --- a/pkg/trace/api/profiles.go +++ b/pkg/trace/api/profiles.go @@ -18,7 +18,6 @@ import ( "time" "github.com/DataDog/datadog-agent/pkg/trace/config" - "github.com/DataDog/datadog-agent/pkg/trace/info" "github.com/DataDog/datadog-agent/pkg/trace/log" "github.com/DataDog/datadog-agent/pkg/trace/metrics" ) @@ -78,7 +77,7 @@ func (r *HTTPReceiver) profileProxyHandler() http.Handler { if err != nil { return errorHandler(err) } - tags := fmt.Sprintf("host:%s,default_env:%s,agent_version:%s", r.conf.Hostname, r.conf.DefaultEnv, info.Version) + tags := fmt.Sprintf("host:%s,default_env:%s,agent_version:%s", r.conf.Hostname, r.conf.DefaultEnv, r.conf.AgentVersion) if orch := r.conf.FargateOrchestrator; orch != config.OrchestratorUnknown { tag := fmt.Sprintf("orchestrator:fargate_%s", strings.ToLower(string(orch))) tags = tags + "," + tag @@ -103,7 +102,7 @@ func errorHandler(err error) http.Handler { // For more details please see multiTransport. func newProfileProxy(conf *config.AgentConfig, targets []*url.URL, keys []string, tags string) *httputil.ReverseProxy { director := func(req *http.Request) { - req.Header.Set("Via", fmt.Sprintf("trace-agent %s", info.Version)) + req.Header.Set("Via", fmt.Sprintf("trace-agent %s", conf.AgentVersion)) if _, ok := req.Header["User-Agent"]; !ok { // explicitly disable User-Agent so it's not set to the default value // that net/http gives it: Go-http-client/1.1 diff --git a/pkg/trace/api/telemetry.go b/pkg/trace/api/telemetry.go index fab4553f75c6..b97b3a1bfa0a 100644 --- a/pkg/trace/api/telemetry.go +++ b/pkg/trace/api/telemetry.go @@ -17,7 +17,6 @@ import ( "time" "github.com/DataDog/datadog-agent/pkg/trace/config" - "github.com/DataDog/datadog-agent/pkg/trace/info" "github.com/DataDog/datadog-agent/pkg/trace/log" "github.com/DataDog/datadog-agent/pkg/trace/metrics" ) @@ -68,7 +67,7 @@ func (r *HTTPReceiver) telemetryProxyHandler() http.Handler { limitedLogger := log.NewThrottled(5, 10*time.Second) // limit to 5 messages every 10 seconds logger := stdlog.New(limitedLogger, "telemetry.Proxy: ", 0) director := func(req *http.Request) { - req.Header.Set("Via", fmt.Sprintf("trace-agent %s", info.Version)) + req.Header.Set("Via", fmt.Sprintf("trace-agent %s", r.conf.AgentVersion)) if _, ok := req.Header["User-Agent"]; !ok { // explicitly disable User-Agent so it's not set to the default value // that net/http gives it: Go-http-client/1.1 diff --git a/pkg/trace/appsec/appsec.go b/pkg/trace/appsec/appsec.go index 1923d2af8f1b..915d4ed19dcd 100644 --- a/pkg/trace/appsec/appsec.go +++ b/pkg/trace/appsec/appsec.go @@ -18,7 +18,6 @@ import ( "github.com/DataDog/datadog-agent/pkg/trace/api/apiutil" "github.com/DataDog/datadog-agent/pkg/trace/config" - "github.com/DataDog/datadog-agent/pkg/trace/info" "github.com/DataDog/datadog-agent/pkg/trace/log" "github.com/DataDog/datadog-agent/pkg/trace/metrics" ) @@ -43,16 +42,16 @@ func NewIntakeReverseProxy(conf *config.AgentConfig) (http.Handler, error) { log.Info("AppSec proxy disabled by configuration") return disabled("appsec agent disabled by configuration"), nil } - return newIntakeReverseProxy(cfg.IntakeURL, cfg.APIKey, cfg.MaxPayloadSize, conf.NewHTTPTransport()), nil + return newIntakeReverseProxy(cfg.IntakeURL, cfg.APIKey, cfg.MaxPayloadSize, conf.NewHTTPTransport(), conf.AgentVersion), nil } // newIntakeReverseProxy creates a reverse proxy to the intake backend using the // given transport round-tripper. // The reverse proxy handler also limits the request body size and adds extra // headers such as Dd-Api-Key and Via. -func newIntakeReverseProxy(target *url.URL, apiKey string, maxPayloadSize int64, transport http.RoundTripper) http.Handler { +func newIntakeReverseProxy(target *url.URL, apiKey string, maxPayloadSize int64, transport http.RoundTripper, agentVersion string) http.Handler { proxy := httputil.NewSingleHostReverseProxy(target) - via := fmt.Sprintf("trace-agent %s", info.Version) + via := fmt.Sprintf("trace-agent %s", agentVersion) // Wrap and overwrite the returned director to add extra headers director := proxy.Director proxy.Director = func(req *http.Request) { diff --git a/pkg/trace/appsec/appsec_test.go b/pkg/trace/appsec/appsec_test.go index e6dcc1a09349..1e2f33955265 100644 --- a/pkg/trace/appsec/appsec_test.go +++ b/pkg/trace/appsec/appsec_test.go @@ -63,7 +63,7 @@ func TestIntakeReverseProxy(t *testing.T) { ) requireProxyHeaders := func(t *testing.T, req *http.Request) { - require.Contains(t, "trace-agent", req.Header.Get("Via")) + require.Contains(t, "trace-agent 0.99.0", req.Header.Get("Via")) require.Equal(t, expectedAPIKey, req.Header.Get("Dd-Api-Key")) } requireRequest := func(t *testing.T, req *http.Request, expectedMethod, expectedEndpoint string, expectedBody []byte) { @@ -170,7 +170,7 @@ func TestIntakeReverseProxy(t *testing.T) { url, err := url.Parse(srv.URL + expectedServerEndpoint) require.NoError(t, err) - proxy := newIntakeReverseProxy(url, expectedAPIKey, expectedMaxPayloadSize, http.DefaultTransport) + proxy := newIntakeReverseProxy(url, expectedAPIKey, expectedMaxPayloadSize, http.DefaultTransport, "0.99.0") req := tc.prepareServerRequest(t) rec := httptest.NewRecorder() diff --git a/pkg/trace/config/config.go b/pkg/trace/config/config.go index 3ec3a0e2d145..92f0567aa6f1 100644 --- a/pkg/trace/config/config.go +++ b/pkg/trace/config/config.go @@ -288,6 +288,7 @@ type DebuggerProxyConfig struct { type AgentConfig struct { Enabled bool AgentVersion string + GitCommit string Site string // the intake site to use (e.g. "datadoghq.com") // FargateOrchestrator specifies the name of the Fargate orchestrator. e.g. "ECS", "EKS", "Unknown" diff --git a/pkg/trace/info/info.go b/pkg/trace/info/info.go index bc31576c8c20..f13493e7e28d 100644 --- a/pkg/trace/info/info.go +++ b/pkg/trace/info/info.go @@ -200,6 +200,15 @@ func (s infoString) String() string { return string(s) } func InitInfo(conf *config.AgentConfig) error { var err error + publishVersion := func() interface{} { + return struct { + Version string + GitCommit string + }{ + Version: conf.AgentVersion, + GitCommit: conf.GitCommit, + } + } funcMap := template.FuncMap{ "add": func(a, b int64) int64 { return a + b @@ -269,7 +278,10 @@ type StatusInfo struct { MemStats struct { Alloc uint64 } `json:"memstats"` - Version infoVersion `json:"version"` + Version struct { + Version string + GitCommit string + } `json:"version"` Receiver []TagStats `json:"receiver"` RateByService map[string]float64 `json:"ratebyservice"` TraceWriter TraceWriterInfo `json:"trace_writer"` @@ -301,7 +313,7 @@ func Info(w io.Writer, conf *config.AgentConfig) error { // so we can assume it's not even running, or at least, not with // these parameters. We display the port as a hint on where to // debug further, this is where the expvar JSON should come from. - program, banner := getProgramBanner(Version) + program, banner := getProgramBanner(conf.AgentVersion) _ = notRunningTmpl.Execute(w, struct { Banner string Program string @@ -318,7 +330,7 @@ func Info(w io.Writer, conf *config.AgentConfig) error { var info StatusInfo if err := json.NewDecoder(resp.Body).Decode(&info); err != nil { - program, banner := getProgramBanner(Version) + program, banner := getProgramBanner(conf.AgentVersion) _ = errorTmpl.Execute(w, struct { Banner string Program string diff --git a/pkg/trace/info/make.go b/pkg/trace/info/make.go deleted file mode 100644 index 5bfeba28eba3..000000000000 --- a/pkg/trace/info/make.go +++ /dev/null @@ -1,68 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -//go:build ignore -// +build ignore - -// The 'make' program is run by go generate to compile the versioning information -// into the info package. It expects the 'git' command to be installed. -package main - -import ( - "bytes" - "fmt" - "io/ioutil" - "log" - "os" - "os/exec" - "time" -) - -// runs runs the given command and returns the output. If it fails, -// or if the result is an empty string, it returns the fallback. -func run(fallback, name string, args ...string) string { - cmd := exec.Command(name, args...) - out, err := cmd.Output() - if err != nil || len(out) == 0 { - return fallback - } - return string(bytes.Trim(out, "\n")) -} - -func main() { - log.SetPrefix("make_version") - log.SetFlags(0) - - commit := run("master", "git", "rev-parse", "--short", "HEAD") - branch := run("master", "git", "rev-parse", "--abbrev-ref", "HEAD") - version := os.Getenv("TRACE_AGENT_VERSION") - if version == "" { - version = "0.99.0" - } - - output := fmt.Sprintf(template, version, commit, branch, time.Now().String()) - err := ioutil.WriteFile("git_version.go", []byte(output), 0664) - if err != nil { - log.Fatal(err) - } -} - -const template = `// Code generated by 'go run make.go'. DO NOT EDIT. - -package info - -import ( - "runtime" - "strings" -) - -func init() { - Version = %[1]q - GitCommit = %[2]q - GitBranch = %[3]q - BuildDate = %[4]q - GoVersion = strings.TrimPrefix(runtime.Version(), "go") -} -` diff --git a/pkg/trace/info/version.go b/pkg/trace/info/version.go deleted file mode 100644 index f64421f8e794..000000000000 --- a/pkg/trace/info/version.go +++ /dev/null @@ -1,63 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -//go:generate go run make.go - -package info - -import ( - "bytes" - "fmt" -) - -// version info sourced from build flags -var ( - Version string - GitCommit string - GitBranch string - BuildDate string - GoVersion string -) - -// VersionString returns the version information filled in at build time -func VersionString() string { - var buf bytes.Buffer - - if Version != "" { - fmt.Fprintf(&buf, "Version: %s\n", Version) - } - if GitCommit != "" { - fmt.Fprintf(&buf, "Git hash: %s\n", GitCommit) - } - if GitBranch != "" { - fmt.Fprintf(&buf, "Git branch: %s\n", GitBranch) - } - if BuildDate != "" { - fmt.Fprintf(&buf, "Build date: %s\n", BuildDate) - } - if GoVersion != "" { - fmt.Fprintf(&buf, "Go Version: %s\n", GoVersion) - } - - return buf.String() -} - -type infoVersion struct { - Version string - GitCommit string - GitBranch string - BuildDate string - GoVersion string -} - -func publishVersion() interface{} { - return infoVersion{ - Version: Version, - GitCommit: GitCommit, - GitBranch: GitBranch, - BuildDate: BuildDate, - GoVersion: GoVersion, - } -} diff --git a/pkg/trace/info/version_test.go b/pkg/trace/info/version_test.go deleted file mode 100644 index 3a9dae15788c..000000000000 --- a/pkg/trace/info/version_test.go +++ /dev/null @@ -1,27 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2022-present Datadog, Inc. - -package info - -import ( - "testing" -) - -func TestPublishVersion(t *testing.T) { - Version = "v" - GitCommit = "gc" - GitBranch = "gb" - BuildDate = "bd" - GoVersion = "gv" - - testExpvarPublish(t, publishVersion, - map[string]interface{}{ - "Version": "v", - "GitCommit": "gc", - "GitBranch": "gb", - "BuildDate": "bd", - "GoVersion": "gv", - }) -} diff --git a/pkg/trace/stats/client_stats_aggregator.go b/pkg/trace/stats/client_stats_aggregator.go index 0f11612196bf..28d56f034cab 100644 --- a/pkg/trace/stats/client_stats_aggregator.go +++ b/pkg/trace/stats/client_stats_aggregator.go @@ -9,7 +9,6 @@ import ( "time" "github.com/DataDog/datadog-agent/pkg/trace/config" - "github.com/DataDog/datadog-agent/pkg/trace/info" "github.com/DataDog/datadog-agent/pkg/trace/pb" "github.com/DataDog/datadog-agent/pkg/trace/watchdog" ) @@ -44,6 +43,7 @@ type ClientStatsAggregator struct { oldestTs time.Time agentEnv string agentHostname string + agentVersion string exit chan struct{} done chan struct{} @@ -58,6 +58,7 @@ func NewClientStatsAggregator(conf *config.AgentConfig, out chan pb.StatsPayload out: out, agentEnv: conf.DefaultEnv, agentHostname: conf.Hostname, + agentVersion: conf.AgentVersion, oldestTs: alignAggTs(time.Now().Add(bucketDuration - oldestBucketStart)), exit: make(chan struct{}), done: make(chan struct{}), @@ -146,7 +147,7 @@ func (a *ClientStatsAggregator) flush(p []pb.ClientStatsPayload) { Stats: p, AgentEnv: a.agentEnv, AgentHostname: a.agentHostname, - AgentVersion: info.Version, + AgentVersion: a.agentVersion, ClientComputed: true, } } diff --git a/pkg/trace/stats/concentrator.go b/pkg/trace/stats/concentrator.go index 304fab3d5897..19ea445d703e 100644 --- a/pkg/trace/stats/concentrator.go +++ b/pkg/trace/stats/concentrator.go @@ -11,7 +11,6 @@ import ( "github.com/DataDog/datadog-agent/pkg/trace/config" "github.com/DataDog/datadog-agent/pkg/trace/config/features" - "github.com/DataDog/datadog-agent/pkg/trace/info" "github.com/DataDog/datadog-agent/pkg/trace/log" "github.com/DataDog/datadog-agent/pkg/trace/pb" "github.com/DataDog/datadog-agent/pkg/trace/traceutil" @@ -46,6 +45,7 @@ type Concentrator struct { mu sync.Mutex agentEnv string agentHostname string + agentVersion string } // NewConcentrator initializes a new concentrator ready to be started @@ -64,6 +64,7 @@ func NewConcentrator(conf *config.AgentConfig, out chan pb.StatsPayload, now tim exit: make(chan struct{}), agentEnv: conf.DefaultEnv, agentHostname: conf.Hostname, + agentVersion: conf.AgentVersion, } return &c } @@ -224,7 +225,7 @@ func (c *Concentrator) flushNow(now int64) pb.StatsPayload { } sb = append(sb, p) } - return pb.StatsPayload{Stats: sb, AgentHostname: c.agentHostname, AgentEnv: c.agentEnv, AgentVersion: info.Version} + return pb.StatsPayload{Stats: sb, AgentHostname: c.agentHostname, AgentEnv: c.agentEnv, AgentVersion: c.agentVersion} } // alignTs returns the provided timestamp truncated to the bucket size. diff --git a/pkg/trace/stats/concentrator_test.go b/pkg/trace/stats/concentrator_test.go index 5e687144cb94..a602f2307237 100644 --- a/pkg/trace/stats/concentrator_test.go +++ b/pkg/trace/stats/concentrator_test.go @@ -12,7 +12,6 @@ import ( "time" "github.com/DataDog/datadog-agent/pkg/trace/config" - "github.com/DataDog/datadog-agent/pkg/trace/info" "github.com/DataDog/datadog-agent/pkg/trace/pb" "github.com/DataDog/datadog-agent/pkg/trace/sampler" "github.com/DataDog/datadog-agent/pkg/trace/traceutil" @@ -31,6 +30,7 @@ func NewTestConcentrator(now time.Time) *Concentrator { statsChan := make(chan pb.StatsPayload) cfg := config.AgentConfig{ BucketInterval: time.Duration(testBucketInterval), + AgentVersion: "0.99.0", DefaultEnv: "env", Hostname: "hostname", } @@ -285,8 +285,6 @@ func TestConcentratorStatsTotals(t *testing.T) { // TestConcentratorStatsCounts tests exhaustively each stats bucket, over multiple time buckets. func TestConcentratorStatsCounts(t *testing.T) { - defer func(old string) { info.Version = old }(info.Version) - info.Version = "0.99.0" assert := assert.New(t) now := time.Now() c := NewTestConcentrator(now) diff --git a/pkg/trace/writer/sender.go b/pkg/trace/writer/sender.go index 8cca2d7781e6..7b89e88d3ec3 100644 --- a/pkg/trace/writer/sender.go +++ b/pkg/trace/writer/sender.go @@ -21,7 +21,6 @@ import ( "time" "github.com/DataDog/datadog-agent/pkg/trace/config" - "github.com/DataDog/datadog-agent/pkg/trace/info" "github.com/DataDog/datadog-agent/pkg/trace/log" "go.uber.org/atomic" ) @@ -48,6 +47,7 @@ func newSenders(cfg *config.AgentConfig, r eventRecorder, path string, climit, q url: url, apiKey: endpoint.APIKey, recorder: r, + userAgent: fmt.Sprintf("Datadog Trace Agent/%s/%s", cfg.AgentVersion, cfg.GitCommit), }) } return senders @@ -125,6 +125,8 @@ type senderConfig struct { // recorder specifies the eventRecorder to use when reporting events occurring // in the sender. recorder eventRecorder + // userAgent is the computed user agent we'll use when communicating with Datadog + userAgent string } // sender is responsible for sending payloads to a given URL. It uses a size-limited @@ -319,9 +321,6 @@ func (s *sender) recordEvent(t eventType, data *eventData) { s.cfg.recorder.recordEvent(t, data) } -// userAgent is the computed user agent we'll use when communicating with Datadog -var userAgent = fmt.Sprintf("Datadog Trace Agent/%s/%s", info.Version, info.GitCommit) - // retriableError is an error returned by the server which may be retried at a later time. type retriableError struct{ err error } @@ -335,7 +334,7 @@ const ( func (s *sender) do(req *http.Request) error { req.Header.Set(headerAPIKey, s.cfg.apiKey) - req.Header.Set(headerUserAgent, userAgent) + req.Header.Set(headerUserAgent, s.cfg.userAgent) resp, err := s.cfg.client.Do(req) if err != nil { // request errors include timeouts or name resolution errors and diff --git a/pkg/trace/writer/sender_test.go b/pkg/trace/writer/sender_test.go index 3c99678f751d..792371c7535a 100644 --- a/pkg/trace/writer/sender_test.go +++ b/pkg/trace/writer/sender_test.go @@ -65,6 +65,7 @@ func TestSender(t *testing.T) { maxConns: climit, maxQueued: 40, apiKey: testAPIKey, + userAgent: "testUserAgent", } } @@ -200,7 +201,7 @@ func TestSender(t *testing.T) { wg.Add(1) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { assert.Equal(testAPIKey, req.Header.Get(headerAPIKey)) - assert.Equal(userAgent, req.Header.Get(headerUserAgent)) + assert.Equal("testUserAgent", req.Header.Get(headerUserAgent)) wg.Done() })) defer server.Close() diff --git a/pkg/trace/writer/trace.go b/pkg/trace/writer/trace.go index 99dc2e3f314a..1bdd09161be4 100644 --- a/pkg/trace/writer/trace.go +++ b/pkg/trace/writer/trace.go @@ -48,15 +48,16 @@ type TraceWriter struct { // Channel should only be received from when testing. In chan *SampledChunks - hostname string - env string - targetTPS float64 - errorTPS float64 - senders []*sender - stop chan struct{} - stats *info.TraceWriterInfo - wg sync.WaitGroup // waits for gzippers - tick time.Duration // flush frequency + hostname string + env string + targetTPS float64 + errorTPS float64 + senders []*sender + stop chan struct{} + stats *info.TraceWriterInfo + wg sync.WaitGroup // waits for gzippers + tick time.Duration // flush frequency + agentVersion string tracerPayloads []*pb.TracerPayload // tracer payloads buffered bufferedSize int // estimated buffer size @@ -72,17 +73,18 @@ type TraceWriter struct { // will accept incoming spans via the in channel. func NewTraceWriter(cfg *config.AgentConfig) *TraceWriter { tw := &TraceWriter{ - In: make(chan *SampledChunks, 1000), - hostname: cfg.Hostname, - env: cfg.DefaultEnv, - targetTPS: cfg.TargetTPS, - errorTPS: cfg.ErrorTPS, - stats: &info.TraceWriterInfo{}, - stop: make(chan struct{}), - flushChan: make(chan chan struct{}), - syncMode: cfg.SynchronousFlushing, - tick: 5 * time.Second, - easylog: log.NewThrottled(5, 10*time.Second), // no more than 5 messages every 10 seconds + In: make(chan *SampledChunks, 1000), + hostname: cfg.Hostname, + env: cfg.DefaultEnv, + targetTPS: cfg.TargetTPS, + errorTPS: cfg.ErrorTPS, + stats: &info.TraceWriterInfo{}, + stop: make(chan struct{}), + flushChan: make(chan chan struct{}), + syncMode: cfg.SynchronousFlushing, + tick: 5 * time.Second, + agentVersion: cfg.AgentVersion, + easylog: log.NewThrottled(5, 10*time.Second), // no more than 5 messages every 10 seconds } climit := cfg.TraceWriter.ConnectionLimit if climit == 0 { @@ -225,7 +227,7 @@ func (w *TraceWriter) flush() { log.Debugf("Serializing %d tracer payloads.", len(w.tracerPayloads)) p := pb.AgentPayload{ - AgentVersion: info.Version, + AgentVersion: w.agentVersion, HostName: w.hostname, Env: w.env, TargetTPS: w.targetTPS, diff --git a/releasenotes/notes/consistent-agent-version-c701a790d52bdc6c.yaml b/releasenotes/notes/consistent-agent-version-c701a790d52bdc6c.yaml new file mode 100644 index 000000000000..0a9fb712857c --- /dev/null +++ b/releasenotes/notes/consistent-agent-version-c701a790d52bdc6c.yaml @@ -0,0 +1,14 @@ +# Each section from every release note are combined when the +# CHANGELOG.rst is rendered. So the text needs to be worded so that +# it does not depend on any information only available in another +# section. This may mean repeating some details, but each section +# must be readable independently of the other. +# +# Each section note must be formatted as reStructuredText. +--- +enhancements: + - | + APM: The trace-agent version string has been made more consistent and is now available in different build environments. +deprecations: + - | + APM: The trace-agent /info endpoint no longer reports "build_date". diff --git a/tasks/trace_agent.py b/tasks/trace_agent.py index be4b17ac5ec3..9ba35678c3d0 100644 --- a/tasks/trace_agent.py +++ b/tasks/trace_agent.py @@ -101,7 +101,6 @@ def cross_compile(ctx, tag=""): print(f"Building tag {tag}...") env = { - "TRACE_AGENT_VERSION": tag, "V": tag, }