Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c2e12d4
move shared logic to 'get' generic
mtoffl01 Dec 2, 2025
3192654
Make Config mutable: Modify debug field from tracer options
mtoffl01 Dec 2, 2025
d8f7d4b
rename trace_debug_enabled to DD_TRACE_DEBUG
mtoffl01 Dec 2, 2025
63a09e6
introduce usefreshconfig
mtoffl01 Dec 2, 2025
ef4772a
nits
mtoffl01 Dec 3, 2025
b0b138b
delete ResetForTesting
mtoffl01 Dec 3, 2025
e12fcf6
Modify SetDebug to take in an origin
mtoffl01 Dec 3, 2025
19d7eb4
restore configprovider.go to main
mtoffl01 Dec 4, 2025
5ade4e8
Add unit tests for config
mtoffl01 Dec 4, 2025
8eb1f41
Fix config tests
mtoffl01 Dec 5, 2025
ceb8a0b
Introduce OriginCalculated
mtoffl01 Dec 5, 2025
56f0686
Have config re-export Origin
mtoffl01 Dec 5, 2025
24b9465
Also re-export OriginCalculated and OriginCode
mtoffl01 Dec 5, 2025
f7cce1f
Use mutex instead of atomics for config
mtoffl01 Dec 8, 2025
85ac979
Merge branch 'mtoff/revamp-debug-api' into mtoff/config-origin
mtoffl01 Dec 8, 2025
d934ece
support all boolean formatS
mtoffl01 Dec 8, 2025
f3c2d43
migrate ciVisibilityEnabled
mtoffl01 Dec 8, 2025
e66f38e
Remove agentless code
mtoffl01 Dec 8, 2025
9c391d0
restore unrelated configprovider changes
mtoffl01 Dec 8, 2025
d48d8a5
Restore with mtoff/getBool
mtoffl01 Dec 8, 2025
25a03c9
fix merge conflicts
mtoffl01 Dec 9, 2025
40df74a
fix merge conflicts
mtoffl01 Dec 9, 2025
e602454
Merge branch 'mtoff/getBool' into mtoff/ciVisibilityEnabled
mtoffl01 Dec 9, 2025
744a237
Merge branch 'main' into mtoff/ciVisibilityEnabled
mtoffl01 Dec 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions ddtrace/tracer/civisibility_transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"strings"
"testing"

"github.com/DataDog/dd-trace-go/v2/internal"
internalconfig "github.com/DataDog/dd-trace-go/v2/internal/config"
"github.com/stretchr/testify/assert"
"github.com/tinylib/msgp/msgp"

Expand Down Expand Up @@ -82,11 +82,6 @@ func runTransportTest(t *testing.T, agentless, shouldSetAPIKey bool) {
defer srv.Close()

parsedURL, _ := url.Parse(srv.URL)
c := config{
ciVisibilityEnabled: true,
httpClient: internal.DefaultHTTPClient(defaultHTTPTimeout, false),
agentURL: parsedURL,
}

// Set CI Visibility environment variables for the test
if agentless {
Expand All @@ -97,8 +92,14 @@ func runTransportTest(t *testing.T, agentless, shouldSetAPIKey bool) {
}
}

// Use newTestConfig to get proper HTTP client setup (keep-alives disabled)
c, err := newTestConfig()
assert.NoError(err)
c.agentURL = parsedURL
c.internalConfig.SetCiVisibilityEnabled(true, internalconfig.OriginCode)

for _, tc := range testCases {
transport := newCiVisibilityTransport(&c)
transport := newCiVisibilityTransport(c)

p := newCiVisibilityPayload()
for _, t := range tc.payload {
Expand Down Expand Up @@ -127,7 +128,8 @@ func TestCIVisibilityTransportSecureLogging(t *testing.T) {
os.Unsetenv(constants.CIVisibilityAgentlessURLEnvironmentVariable)
}()

cfg := &config{}
cfg, err := newTestConfig()
assert.NoError(t, err)
transport := newCiVisibilityTransport(cfg)
assert.NotNil(t, transport)

Expand Down
6 changes: 1 addition & 5 deletions ddtrace/tracer/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,6 @@ type config struct {
// globalSampleRate holds sample rate read from environment variables.
globalSampleRate float64

// ciVisibilityEnabled controls if the tracer is loaded with CI Visibility mode. default false
ciVisibilityEnabled bool

// ciVisibilityAgentless controls if the tracer is loaded with CI Visibility agentless mode. default false
ciVisibilityAgentless bool

Expand Down Expand Up @@ -616,8 +613,7 @@ func newConfig(opts ...StartOption) (*config, error) {
log.SetLevel(log.LevelDebug)
}
// Check if CI Visibility mode is enabled
if internal.BoolEnv(constants.CIVisibilityEnabledEnvironmentVariable, false) {
c.ciVisibilityEnabled = true // Enable CI Visibility mode
if c.internalConfig.CiVisibilityEnabled() {
c.httpClientTimeout = time.Second * 45 // Increase timeout up to 45 seconds (same as other tracers in CIVis mode)
c.logStartup = false // If we are in CI Visibility mode we don't want to log the startup to stdout to avoid polluting the output
ciTransport := newCiVisibilityTransport(c) // Create a default CI Visibility Transport
Expand Down
2 changes: 1 addition & 1 deletion ddtrace/tracer/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func newConcentrator(c *config, bucketSize int64, statsdClient internal.StatsdCl
log.Debug("No DD Env found, normally the agent should have one")
}
gitCommitSha := ""
if c.ciVisibilityEnabled {
if c.internalConfig.CiVisibilityEnabled() {
// We only have this data if we're in CI Visibility
gitCommitSha = utils.GetCITags()[constants.GitCommitSHA]
}
Expand Down
91 changes: 67 additions & 24 deletions ddtrace/tracer/stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/DataDog/dd-trace-go/v2/ddtrace/ext"
"github.com/DataDog/dd-trace-go/v2/internal/civisibility/constants"
"github.com/DataDog/dd-trace-go/v2/internal/civisibility/utils"
internalconfig "github.com/DataDog/dd-trace-go/v2/internal/config"
"github.com/DataDog/dd-trace-go/v2/internal/processtags"
"github.com/DataDog/dd-trace-go/v2/internal/statsdtest"
)
Expand Down Expand Up @@ -45,7 +46,9 @@ func TestConcentrator(t *testing.T) {
}
t.Run("start-stop", func(t *testing.T) {
assert := assert.New(t)
c := newConcentrator(&config{}, bucketSize, &statsd.NoOpClientDirect{})
cfg, err := newTestConfig()
assert.NoError(err)
c := newConcentrator(cfg, bucketSize, &statsd.NoOpClientDirect{})
assert.EqualValues(atomic.LoadUint32(&c.stopped), 1)
c.Start()
assert.EqualValues(atomic.LoadUint32(&c.stopped), 0)
Expand All @@ -64,7 +67,11 @@ func TestConcentrator(t *testing.T) {
t.Run("flusher", func(t *testing.T) {
t.Run("old", func(t *testing.T) {
transport := newDummyTransport()
c := newConcentrator(&config{transport: transport, env: "someEnv"}, 500_000, &statsd.NoOpClientDirect{})
cfg, err := newTestConfig()
assert.NoError(t, err)
cfg.transport = transport
cfg.env = "someEnv"
c := newConcentrator(cfg, 500_000, &statsd.NoOpClientDirect{})
assert.Len(t, transport.Stats(), 0)
ss1, ok := c.newTracerStatSpan(&s1, nil)
assert.True(t, ok)
Expand All @@ -82,7 +89,11 @@ func TestConcentrator(t *testing.T) {
t.Run("recent+stats", func(t *testing.T) {
transport := newDummyTransport()
testStats := &statsdtest.TestStatsdClient{}
c := newConcentrator(&config{transport: transport, env: "someEnv"}, (10 * time.Second).Nanoseconds(), testStats)
cfg, err := newTestConfig()
assert.NoError(t, err)
cfg.transport = transport
cfg.env = "someEnv"
c := newConcentrator(cfg, (10 * time.Second).Nanoseconds(), testStats)
assert.Len(t, transport.Stats(), 0)
ss1, ok := c.newTracerStatSpan(&s1, nil)
assert.True(t, ok)
Expand All @@ -109,7 +120,12 @@ func TestConcentrator(t *testing.T) {
t.Run("ciGitSha", func(t *testing.T) {
utils.AddCITags(constants.GitCommitSHA, "DEADBEEF")
transport := newDummyTransport()
c := newConcentrator(&config{transport: transport, env: "someEnv", ciVisibilityEnabled: true}, (10 * time.Second).Nanoseconds(), &statsd.NoOpClientDirect{})
cfg, err := newTestConfig()
assert.NoError(t, err)
cfg.transport = transport
cfg.env = "someEnv"
cfg.internalConfig.SetCiVisibilityEnabled(true, internalconfig.OriginCode)
c := newConcentrator(cfg, (10 * time.Second).Nanoseconds(), &statsd.NoOpClientDirect{})
assert.Len(t, transport.Stats(), 0)
ss1, ok := c.newTracerStatSpan(&s1, nil)
assert.True(t, ok)
Expand All @@ -123,7 +139,10 @@ func TestConcentrator(t *testing.T) {
// stats should be sent if the concentrator is stopped
t.Run("stop", func(t *testing.T) {
transport := newDummyTransport()
c := newConcentrator(&config{transport: transport}, 500_000, &statsd.NoOpClientDirect{})
cfg, err := newTestConfig()
assert.NoError(t, err)
cfg.transport = transport
c := newConcentrator(cfg, 500_000, &statsd.NoOpClientDirect{})
assert.Len(t, transport.Stats(), 0)
ss1, ok := c.newTracerStatSpan(&s1, nil)
assert.True(t, ok)
Expand All @@ -137,7 +156,10 @@ func TestConcentrator(t *testing.T) {
processtags.Reload()

transport := newDummyTransport()
c := newConcentrator(&config{transport: transport}, 500_000, &statsd.NoOpClientDirect{})
cfg, err := newTestConfig()
assert.NoError(t, err)
cfg.transport = transport
c := newConcentrator(cfg, 500_000, &statsd.NoOpClientDirect{})
assert.Len(t, transport.Stats(), 0)
ss1, ok := c.newTracerStatSpan(&s1, nil)
assert.True(t, ok)
Expand All @@ -154,7 +176,10 @@ func TestConcentrator(t *testing.T) {
processtags.Reload()

transport := newDummyTransport()
c := newConcentrator(&config{transport: transport}, 500_000, &statsd.NoOpClientDirect{})
cfg, err := newTestConfig()
assert.NoError(t, err)
cfg.transport = transport
c := newConcentrator(cfg, 500_000, &statsd.NoOpClientDirect{})
assert.Len(t, transport.Stats(), 0)
ss1, ok := c.newTracerStatSpan(&s1, nil)
assert.True(t, ok)
Expand Down Expand Up @@ -184,7 +209,12 @@ func TestShouldObfuscate(t *testing.T) {
{name: "agent version newer", tracerVersion: 2, agentVersion: 3, expectedShouldObfuscate: false},
} {
t.Run(params.name, func(t *testing.T) {
c := newConcentrator(&config{transport: tsp, env: "someEnv", agent: agentFeatures{obfuscationVersion: params.agentVersion}}, bucketSize, &statsd.NoOpClientDirect{})
cfg, err := newTestConfig()
assert.NoError(t, err)
cfg.transport = tsp
cfg.env = "someEnv"
cfg.agent.obfuscationVersion = params.agentVersion
c := newConcentrator(cfg, bucketSize, &statsd.NoOpClientDirect{})
defer func(oldVersion int) { tracerObfuscationVersion = oldVersion }(tracerObfuscationVersion)
tracerObfuscationVersion = params.tracerVersion
assert.Equal(t, params.expectedShouldObfuscate, c.shouldObfuscate())
Expand All @@ -203,7 +233,12 @@ func TestObfuscation(t *testing.T) {
resource: "GET somekey",
}
tsp := newDummyTransport()
c := newConcentrator(&config{transport: tsp, env: "someEnv", agent: agentFeatures{obfuscationVersion: 2}}, bucketSize, &statsd.NoOpClientDirect{})
cfg, err := newTestConfig()
assert.NoError(t, err)
cfg.transport = tsp
cfg.env = "someEnv"
cfg.agent.obfuscationVersion = 2
c := newConcentrator(cfg, bucketSize, &statsd.NoOpClientDirect{})
defer func(oldVersion int) { tracerObfuscationVersion = oldVersion }(tracerObfuscationVersion)
tracerObfuscationVersion = 2

Expand Down Expand Up @@ -237,7 +272,11 @@ func TestStatsByKind(t *testing.T) {
s1.SetTag("span.kind", "client")
s2.SetTag("span.kind", "invalid")

c := newConcentrator(&config{transport: newDummyTransport(), env: "someEnv"}, 100, &statsd.NoOpClientDirect{})
cfg, err := newTestConfig()
assert.NoError(t, err)
cfg.transport = newDummyTransport()
cfg.env = "someEnv"
c := newConcentrator(cfg, 100, &statsd.NoOpClientDirect{})
_, ok := c.newTracerStatSpan(&s1, nil)
assert.True(t, ok)

Expand All @@ -249,29 +288,29 @@ func TestConcentratorDefaultEnv(t *testing.T) {
assert := assert.New(t)

t.Run("uses-agent-default-env-when-no-tracer-env", func(t *testing.T) {
cfg := &config{
transport: newDummyTransport(),
agent: agentFeatures{defaultEnv: "agent-prod"},
}
cfg, err := newTestConfig()
assert.NoError(err)
cfg.transport = newDummyTransport()
cfg.agent.defaultEnv = "agent-prod"
c := newConcentrator(cfg, 100, &statsd.NoOpClientDirect{})
assert.Equal("agent-prod", c.aggregationKey.Env)
})

t.Run("prefers-tracer-env-over-agent-default", func(t *testing.T) {
cfg := &config{
transport: newDummyTransport(),
env: "tracer-staging",
agent: agentFeatures{defaultEnv: "agent-prod"},
}
cfg, err := newTestConfig()
assert.NoError(err)
cfg.transport = newDummyTransport()
cfg.env = "tracer-staging"
cfg.agent.defaultEnv = "agent-prod"
c := newConcentrator(cfg, 100, &statsd.NoOpClientDirect{})
assert.Equal("tracer-staging", c.aggregationKey.Env)
})

t.Run("falls-back-to-unknown-env-when-both-empty", func(t *testing.T) {
cfg := &config{
transport: newDummyTransport(),
agent: agentFeatures{},
}
cfg, err := newTestConfig()
assert.NoError(err)
cfg.transport = newDummyTransport()
cfg.agent = agentFeatures{}
c := newConcentrator(cfg, 100, &statsd.NoOpClientDirect{})
assert.Equal("unknown-env", c.aggregationKey.Env)
})
Expand All @@ -293,7 +332,11 @@ func TestStatsIncludeHTTPMethodAndEndpoint(t *testing.T) {
},
}
transport := newDummyTransport()
c := newConcentrator(&config{transport: transport, env: "someEnv"}, bucketSize, &statsd.NoOpClientDirect{})
cfg, err := newTestConfig()
assert.NoError(t, err)
cfg.transport = transport
cfg.env = "someEnv"
c := newConcentrator(cfg, bucketSize, &statsd.NoOpClientDirect{})
ss, ok := c.newTracerStatSpan(&s, nil)
require.True(t, ok)
c.Start()
Expand Down
4 changes: 2 additions & 2 deletions ddtrace/tracer/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ func Start(opts ...StartOption) error {
t.Stop()
return nil
}
if t.config.ciVisibilityEnabled && t.config.ciVisibilityNoopTracer {
if t.config.internalConfig.CiVisibilityEnabled() && t.config.ciVisibilityNoopTracer {
setGlobalTracer(wrapWithCiVisibilityNoopTracer(t))
} else {
setGlobalTracer(t)
Expand Down Expand Up @@ -400,7 +400,7 @@ func newUnstartedTracer(opts ...StartOption) (t *tracer, err error) {
}
}()
var writer traceWriter
if c.ciVisibilityEnabled {
if c.internalConfig.CiVisibilityEnabled() {
writer = newCiVisibilityTraceWriter(c)
} else if c.logToStdout {
writer = newLogTraceWriter(c, statsd)
Expand Down
6 changes: 5 additions & 1 deletion ddtrace/tracer/tracer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2464,8 +2464,12 @@ func TestFlush(t *testing.T) {
tr.statsd.Close()
tr.statsd = ts

cfg, err := newTestConfig()
assert.NoError(t, err)
transport := newDummyTransport()
c := newConcentrator(&config{transport: transport, env: "someEnv"}, defaultStatsBucketSize, &statsd.NoOpClientDirect{})
cfg.transport = transport
cfg.env = "someEnv"
c := newConcentrator(cfg, defaultStatsBucketSize, &statsd.NoOpClientDirect{})
tr.stats.Stop()
tr.stats = c
c.Start()
Expand Down
27 changes: 21 additions & 6 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"sync"
"time"

"github.com/DataDog/dd-trace-go/v2/internal/civisibility/constants"
"github.com/DataDog/dd-trace-go/v2/internal/telemetry"
)

Expand Down Expand Up @@ -59,10 +60,11 @@ type Config struct {
dataStreamsMonitoringEnabled bool
dynamicInstrumentationEnabled bool
globalSampleRate float64
ciVisibilityEnabled bool
ciVisibilityAgentless bool
logDirectory string
traceRateLimitPerSecond float64
// ciVisibilityEnabled controls if the tracer is loaded with CI Visibility mode. default false
ciVisibilityEnabled bool
ciVisibilityAgentless bool
logDirectory string
traceRateLimitPerSecond float64
}

// loadConfig initializes and returns a new config by reading from all configured sources.
Expand Down Expand Up @@ -94,8 +96,8 @@ func loadConfig() *Config {
cfg.dataStreamsMonitoringEnabled = provider.getBool("DD_DATA_STREAMS_ENABLED", false)
cfg.dynamicInstrumentationEnabled = provider.getBool("DD_DYNAMIC_INSTRUMENTATION_ENABLED", false)
cfg.globalSampleRate = provider.getFloat("DD_TRACE_SAMPLE_RATE", 0.0)
cfg.ciVisibilityEnabled = provider.getBool("DD_CIVISIBILITY_ENABLED", false)
cfg.ciVisibilityAgentless = provider.getBool("DD_CIVISIBILITY_AGENTLESS_ENABLED", false)
cfg.ciVisibilityEnabled = provider.getBool(constants.CIVisibilityEnabledEnvironmentVariable, false)
cfg.ciVisibilityAgentless = provider.getBool(constants.CIVisibilityAgentlessEnabledEnvironmentVariable, false)
cfg.logDirectory = provider.getString("DD_TRACE_LOG_DIRECTORY", "")
cfg.traceRateLimitPerSecond = provider.getFloat("DD_TRACE_RATE_LIMIT", 0.0)

Expand Down Expand Up @@ -134,3 +136,16 @@ func (c *Config) SetDebug(enabled bool, origin telemetry.Origin) {
c.debug = enabled
telemetry.RegisterAppConfig("DD_TRACE_DEBUG", enabled, origin)
}

func (c *Config) CiVisibilityEnabled() bool {
c.mu.RLock()
defer c.mu.RUnlock()
return c.ciVisibilityEnabled
}

func (c *Config) SetCiVisibilityEnabled(enabled bool, origin telemetry.Origin) {
c.mu.Lock()
defer c.mu.Unlock()
c.ciVisibilityEnabled = enabled
telemetry.RegisterAppConfig(constants.CIVisibilityEnabledEnvironmentVariable, enabled, origin)
}
Loading