diff --git a/profiler/options.go b/profiler/options.go index 36e715c156..6299623087 100644 --- a/profiler/options.go +++ b/profiler/options.go @@ -111,6 +111,7 @@ type config struct { logStartup bool traceConfig executionTraceConfig endpointCountEnabled bool + enable bool } // logStartup records the configuration to the configured logger in JSON format @@ -146,6 +147,7 @@ func logStartup(c *config) { "execution_trace_size_limit": c.traceConfig.Limit, "endpoint_count_enabled": c.endpointCountEnabled, "custom_profiler_label_keys": c.customProfilerLabels, + "enable": c.enable, } b, err := json.Marshal(info) if err != nil { @@ -208,6 +210,13 @@ func defaultConfig() (*config, error) { } else { c.agentURL = url.String() + "/profiling/v1/input" } + // If DD_PROFILING_ENABLED is set to "auto", the profiler's activation will be determined by + // the Datadog admission controller, so we set it to true. + if os.Getenv("DD_PROFILING_ENABLED") == "auto" { + c.enable = true + } else { + c.enable = internal.BoolEnv("DD_PROFILING_ENABLED", true) + } if v := os.Getenv("DD_PROFILING_UPLOAD_TIMEOUT"); v != "" { d, err := time.ParseDuration(v) if err != nil { diff --git a/profiler/options_test.go b/profiler/options_test.go index 935a8ba18d..49e7274f94 100644 --- a/profiler/options_test.go +++ b/profiler/options_test.go @@ -264,6 +264,21 @@ func TestEnvVars(t *testing.T) { assert.Equal(t, "http://localhost:6218/profiling/v1/input", cfg.agentURL) }) + t.Run("DD_PROFILING_ENABLED", func(t *testing.T) { + t.Run("default", func(t *testing.T) { + cfg, err := defaultConfig() + require.NoError(t, err) + assert.Equal(t, true, cfg.enable) + }) + + t.Run("override", func(t *testing.T) { + t.Setenv("DD_PROFILING_ENABLED", "false") + cfg, err := defaultConfig() + require.NoError(t, err) + assert.Equal(t, false, cfg.enable) + }) + }) + t.Run("DD_PROFILING_UPLOAD_TIMEOUT", func(t *testing.T) { t.Setenv("DD_PROFILING_UPLOAD_TIMEOUT", "3s") cfg, err := defaultConfig() diff --git a/profiler/profiler.go b/profiler/profiler.go index 5e1d1736e8..5ef08c1705 100644 --- a/profiler/profiler.go +++ b/profiler/profiler.go @@ -54,6 +54,9 @@ func Start(opts ...Option) error { if err != nil { return err } + if !p.cfg.enable { + return nil + } activeProfiler = p activeProfiler.run() traceprof.SetProfilerEnabled(true) diff --git a/profiler/profiler_test.go b/profiler/profiler_test.go index 844078948b..cb399af3f6 100644 --- a/profiler/profiler_test.go +++ b/profiler/profiler_test.go @@ -82,6 +82,20 @@ func TestStart(t *testing.T) { mu.Unlock() }) + t.Run("dd_profiling_not_enabled", func(t *testing.T) { + t.Setenv("DD_PROFILING_ENABLED", "false") + if err := Start(); err != nil { + t.Fatal(err) + } + defer Stop() + + mu.Lock() + // if DD_PROFILING_ENABLED is false, the profiler should not be started even if Start() is called + // So we should not have an activeProfiler + assert.Nil(t, activeProfiler) + mu.Unlock() + }) + t.Run("options", func(t *testing.T) { if err := Start(); err != nil { t.Fatal(err) @@ -447,6 +461,19 @@ func TestImmediateProfile(t *testing.T) { } } +func TestEnabledFalse(t *testing.T) { + t.Setenv("DD_PROFILING_ENABLED", "false") + ch := startTestProfiler(t, 1, WithPeriod(10*time.Millisecond), WithProfileTypes()) + select { + case <-ch: + t.Fatal("received profile when profiler should have been disabled") + case <-time.After(time.Second): + // This test might succeed incorrectly on an overloaded + // CI server, but is very likely to fail locally given a + // buggy implementation + } +} + func TestExecutionTraceCPUProfileRate(t *testing.T) { // cpuProfileRate is picked randomly so we can check for it in the trace // data to reduce the chance that it occurs in the trace data for some other diff --git a/profiler/telemetry.go b/profiler/telemetry.go index 2e6a5fa88c..511361c0aa 100644 --- a/profiler/telemetry.go +++ b/profiler/telemetry.go @@ -54,6 +54,7 @@ func startTelemetry(c *config) { {Name: "execution_trace_size_limit", Value: c.traceConfig.Limit}, {Name: "endpoint_count_enabled", Value: c.endpointCountEnabled}, {Name: "num_custom_profiler_label_keys", Value: len(c.customProfilerLabels)}, + {Name: "enable", Value: c.enable}, }, ) }