Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b05560c
Introduce internal config package: Config object, ConfigProvider obje…
mtoffl01 Oct 22, 2025
3393771
Introduce envconfigsource, and add configprovider tests for all sources
mtoffl01 Oct 24, 2025
0bb66a1
Test migrating tracer.config.debug over to internal/config.IsDebugEna…
mtoffl01 Oct 24, 2025
e34de5d
nits
mtoffl01 Oct 24, 2025
8bdab95
fix test env vars; only use real settings
mtoffl01 Oct 27, 2025
0513a96
restore unrelated files to their status on main
mtoffl01 Oct 27, 2025
ee521b4
restore unrelated files to their status on main
mtoffl01 Oct 27, 2025
c3c69fe
Fix file format in supported_configurations.json
mtoffl01 Oct 27, 2025
eeebfd1
cleanup/nits
mtoffl01 Oct 27, 2025
0e2527e
Fix references to fake configs: DD_TRACE_HOSTNAME DD_TRACE_HTTP_CLIEN…
mtoffl01 Oct 30, 2025
85ae251
remove reference to DD_RUNTIME_METRICS
mtoffl01 Oct 30, 2025
2e5e8e6
Introduce otelenvconfigsource, and add tests for it in configprovider…
mtoffl01 Nov 3, 2025
378f08d
Remove DD_TRACE_AGENT_TIMEOUT; use DD_TRACE_STARTUP_LOGS in tests ins…
mtoffl01 Nov 3, 2025
7d873f4
Make loadConfig threadsafe
mtoffl01 Nov 3, 2025
f148316
Add godocs to loadConfig() and GlobalConfig() to document thread safe…
mtoffl01 Nov 3, 2025
6c45c9a
Merge branch 'main' into mtoff/config-revamp
mtoffl01 Nov 3, 2025
4057354
merge main and remove refs to DD_TRACE_AGENT_PROTOCOL
mtoffl01 Nov 3, 2025
bfdaae7
Fix c.debug assignment in tracer config
mtoffl01 Nov 4, 2025
2595c88
Always reload config in testing environment
mtoffl01 Nov 6, 2025
2fe6e13
Fix otel test that expects panic
mtoffl01 Nov 6, 2025
d4960bb
Report telemetry in configprovider
mtoffl01 Nov 6, 2025
0be643e
Report telemetry adn add tests
mtoffl01 Nov 6, 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
5 changes: 3 additions & 2 deletions ddtrace/tracer/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/DataDog/dd-trace-go/v2/internal"
appsecconfig "github.com/DataDog/dd-trace-go/v2/internal/appsec/config"
"github.com/DataDog/dd-trace-go/v2/internal/civisibility/constants"
internalconfig "github.com/DataDog/dd-trace-go/v2/internal/config"
"github.com/DataDog/dd-trace-go/v2/internal/env"
"github.com/DataDog/dd-trace-go/v2/internal/globalconfig"
llmobsconfig "github.com/DataDog/dd-trace-go/v2/internal/llmobs/config"
Expand Down Expand Up @@ -373,6 +374,7 @@ const partialFlushMinSpansDefault = 1000
// and passed user opts.
func newConfig(opts ...StartOption) (*config, error) {
c := new(config)
internalConfig := internalconfig.GlobalConfig()

// If this was built with a recent-enough version of Orchestrion, force the orchestrion config to
// the baked-in values. We do this early so that opts can be used to override the baked-in values,
Expand Down Expand Up @@ -475,7 +477,7 @@ func newConfig(opts ...StartOption) (*config, error) {
c.logStartup = internal.BoolEnv("DD_TRACE_STARTUP_LOGS", true)
c.runtimeMetrics = internal.BoolVal(getDDorOtelConfig("metrics"), false)
c.runtimeMetricsV2 = internal.BoolEnv("DD_RUNTIME_METRICS_V2_ENABLED", true)
c.debug = internal.BoolVal(getDDorOtelConfig("debugMode"), false)
c.debug = internalConfig.IsDebugEnabled()
c.logDirectory = env.Get("DD_TRACE_LOG_DIRECTORY")
c.enabled = newDynamicConfig("tracing_enabled", internal.BoolVal(getDDorOtelConfig("enabled"), true), func(_ bool) bool { return true }, equal[bool])
if _, ok := env.Lookup("DD_TRACE_ENABLED"); ok {
Expand Down Expand Up @@ -622,7 +624,6 @@ func newConfig(opts ...StartOption) (*config, error) {
if c.debug {
log.SetLevel(log.LevelDebug)
}

// Check if CI Visibility mode is enabled
if internal.BoolEnv(constants.CIVisibilityEnabledEnvironmentVariable, false) {
c.ciVisibilityEnabled = true // Enable CI Visibility mode
Expand Down
3 changes: 2 additions & 1 deletion ddtrace/tracer/otel_dd_mappings.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ var propagationMapping = map[string]string{
func getDDorOtelConfig(configName string) string {
config, ok := otelDDConfigs[configName]
if !ok {
panic(fmt.Sprintf("Programming Error: %v not found in supported configurations", configName))
log.Debug("Programming Error: %v not found in supported configurations", configName)
return ""
}

// 1. Check managed stable config if handsOff
Expand Down
3 changes: 2 additions & 1 deletion ddtrace/tracer/otel_dd_mappings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import (
)

func TestAssessSource(t *testing.T) {
// regression test
t.Run("invalid", func(t *testing.T) {
assert.Panics(t, func() { getDDorOtelConfig("invalid") }, "invalid config should panic")
assert.NotPanics(t, func() { getDDorOtelConfig("invalid") }, "invalid config should not panic")
})

t.Run("dd", func(t *testing.T) {
Expand Down
133 changes: 133 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// 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 2025 Datadog, Inc.

package config

import (
"net/url"
"sync"
"testing"
"time"
)

var (
globalConfig *Config
configOnce sync.Once
)

// Config represents global configuration properties.
type Config struct {
// agentURL is the URL of the Datadog agent.
agentURL *url.URL

// debug enables debug logging.
debug bool

logStartup bool

serviceName string

version string

env string

serviceMappings map[string]string

hostname string

runtimeMetrics bool

runtimeMetricsV2 bool

profilerHotspots bool

profilerEndpoints bool

spanAttributeSchemaVersion int

peerServiceDefaultsEnabled bool

peerServiceMappings map[string]string

debugAbandonedSpans bool

spanTimeout time.Duration

partialFlushMinSpans int

partialFlushEnabled bool

statsComputationEnabled bool

dataStreamsMonitoringEnabled bool

dynamicInstrumentationEnabled bool

globalSampleRate float64

ciVisibilityEnabled bool

ciVisibilityAgentless bool

logDirectory string

traceRateLimitPerSecond float64
}

// loadConfig initializes and returns a new Config by reading from all configured sources.
// This function is NOT thread-safe and should only be called once through GlobalConfig's sync.Once.
func loadConfig() *Config {
cfg := new(Config)

// TODO: Use defaults from config json instead of hardcoding them here
cfg.agentURL = provider.getURL("DD_TRACE_AGENT_URL", &url.URL{Scheme: "http", Host: "localhost:8126"})
cfg.debug = provider.getBool("DD_TRACE_DEBUG", false)
cfg.logStartup = provider.getBool("DD_TRACE_STARTUP_LOGS", false)
cfg.serviceName = provider.getString("DD_SERVICE", "")
cfg.version = provider.getString("DD_VERSION", "")
cfg.env = provider.getString("DD_ENV", "")
cfg.serviceMappings = provider.getMap("DD_SERVICE_MAPPING", nil)
cfg.hostname = provider.getString("DD_TRACE_SOURCE_HOSTNAME", "")
cfg.runtimeMetrics = provider.getBool("DD_RUNTIME_METRICS_ENABLED", false)
cfg.runtimeMetricsV2 = provider.getBool("DD_RUNTIME_METRICS_V2_ENABLED", false)
cfg.profilerHotspots = provider.getBool("DD_PROFILING_CODE_HOTSPOTS_COLLECTION_ENABLED", false)
cfg.profilerEndpoints = provider.getBool("DD_PROFILING_ENDPOINT_COLLECTION_ENABLED", false)
cfg.spanAttributeSchemaVersion = provider.getInt("DD_TRACE_SPAN_ATTRIBUTE_SCHEMA", 0)
cfg.peerServiceDefaultsEnabled = provider.getBool("DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED", false)
cfg.peerServiceMappings = provider.getMap("DD_TRACE_PEER_SERVICE_MAPPING", nil)
cfg.debugAbandonedSpans = provider.getBool("DD_TRACE_DEBUG_ABANDONED_SPANS", false)
cfg.spanTimeout = provider.getDuration("DD_TRACE_ABANDONED_SPAN_TIMEOUT", 0)
cfg.partialFlushMinSpans = provider.getInt("DD_TRACE_PARTIAL_FLUSH_MIN_SPANS", 0)
cfg.partialFlushEnabled = provider.getBool("DD_TRACE_PARTIAL_FLUSH_ENABLED", false)
cfg.statsComputationEnabled = provider.getBool("DD_TRACE_STATS_COMPUTATION_ENABLED", false)
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.logDirectory = provider.getString("DD_TRACE_LOG_DIRECTORY", "")
cfg.traceRateLimitPerSecond = provider.getFloat("DD_TRACE_RATE_LIMIT", 0.0)

return cfg
}

// GlobalConfig returns the global configuration singleton.
// This function is thread-safe and can be called from multiple goroutines concurrently.
// The configuration is lazily initialized on first access using sync.Once, ensuring
// loadConfig() is called exactly once even under concurrent access.
func GlobalConfig() *Config {
if testing.Testing() {
globalConfig = loadConfig()
} else {
configOnce.Do(func() {
globalConfig = loadConfig()
})
}
return globalConfig
}

func (c *Config) IsDebugEnabled() bool {
return c.debug
}
Loading
Loading