diff --git a/ddtrace/tracer/log.go b/ddtrace/tracer/log.go index 71dc2e9f74..5e1a6e18fa 100644 --- a/ddtrace/tracer/log.go +++ b/ddtrace/tracer/log.go @@ -166,7 +166,7 @@ func logStartup(t *tracer) { info.SampleRateLimit = fmt.Sprintf("%v", limit) } if !t.config.logToStdout { - if err := checkEndpoint(t.config.httpClient, t.config.transport.endpoint(), t.config.traceProtocol); err != nil { + if err := checkEndpoint(t.config.httpClient, t.config.transport.endpoint(), t.config.internalConfig.TraceProtocol()); err != nil { info.AgentError = fmt.Sprintf("%s", err.Error()) log.Warn("DIAGNOSTICS Unable to reach agent intake: %s", err.Error()) } diff --git a/ddtrace/tracer/option.go b/ddtrace/tracer/option.go index 0ce39ee3a7..dfbc41b064 100644 --- a/ddtrace/tracer/option.go +++ b/ddtrace/tracer/option.go @@ -334,9 +334,6 @@ type config struct { // traceRateLimitPerSecond specifies the rate limit for traces. traceRateLimitPerSecond float64 - // traceProtocol specifies the trace protocol to use. - traceProtocol float64 - // llmobs contains the LLM Observability config llmobs llmobsconfig.Config @@ -629,13 +626,11 @@ func newConfig(opts ...StartOption) (*config, error) { // if using stdout or traces are disabled or we are in ci visibility agentless mode, agent is disabled agentDisabled := c.logToStdout || !c.enabled.current || c.ciVisibilityAgentless c.agent = loadAgentFeatures(agentDisabled, c.agentURL, c.httpClient) - if c.agent.v1ProtocolAvailable { - c.traceProtocol = traceProtocolV1 + if c.internalConfig.V1ProtocolEnabled() && c.agent.v1ProtocolAvailable { + c.internalConfig.SetTraceProtocol(traceProtocolV1, internalconfig.OriginCalculated) if t, ok := c.transport.(*httpTransport); ok { t.traceURL = fmt.Sprintf("%s%s", c.agentURL.String(), tracesAPIPathV1) } - } else { - c.traceProtocol = traceProtocolV04 } info, ok := debug.ReadBuildInfo() @@ -806,7 +801,6 @@ type agentFeatures struct { // evpProxyV2 reports if the trace-agent can receive payloads on the /evp_proxy/v2 endpoint. evpProxyV2 bool - // v1ProtocolAvailable reports whether the trace-agent and tracer are configured to use the v1 protocol. v1ProtocolAvailable bool } @@ -868,10 +862,7 @@ func loadAgentFeatures(agentDisabled bool, agentURL *url.URL, httpClient *http.C case "/evp_proxy/v2/": features.evpProxyV2 = true case "/v1.0/traces": - // Set the trace protocol to use. - if internal.BoolEnv("DD_TRACE_V1_PAYLOAD_FORMAT_ENABLED", false) { - features.v1ProtocolAvailable = true - } + features.v1ProtocolAvailable = true } } features.featureFlags = make(map[string]struct{}, len(info.FeatureFlags)) diff --git a/ddtrace/tracer/writer.go b/ddtrace/tracer/writer.go index ea5c1c55b6..ef1d98842e 100644 --- a/ddtrace/tracer/writer.go +++ b/ddtrace/tracer/writer.go @@ -98,7 +98,7 @@ func (h *agentTraceWriter) stop() { // newPayload returns a new payload based on the trace protocol. func (h *agentTraceWriter) newPayload() payload { - return newPayload(h.config.traceProtocol) + return newPayload(h.config.internalConfig.TraceProtocol()) } // flush will push any currently buffered traces to the server. diff --git a/internal/config/config.go b/internal/config/config.go index 143e1adf78..1ec8980015 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -30,6 +30,12 @@ const ( OriginCalculated = telemetry.OriginCalculated ) +// Supported trace protocols. +const ( + traceProtocolV04 = 0.4 // v0.4 (default) + traceProtocolV1 = 1.0 // v1.0 +) + // Config represents global configuration properties. // Config instances should be obtained via Get() which always returns a non-nil value. // Methods on Config assume a non-nil receiver and will panic if called on nil. @@ -63,6 +69,10 @@ type Config struct { ciVisibilityAgentless bool logDirectory string traceRateLimitPerSecond float64 + // traceProtocol specifies the trace protocol to use. + traceProtocol float64 + // v1ProtocolEnabled reports whether the trace-agent and tracer are configured to use the v1 protocol. + v1ProtocolEnabled bool } // loadConfig initializes and returns a new config by reading from all configured sources. @@ -98,6 +108,8 @@ func loadConfig() *Config { 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) + cfg.v1ProtocolEnabled = provider.getBool("DD_TRACE_V1_PAYLOAD_FORMAT_ENABLED", false) + cfg.traceProtocol = traceProtocolV04 return cfg } @@ -134,3 +146,29 @@ func (c *Config) SetDebug(enabled bool, origin telemetry.Origin) { c.debug = enabled telemetry.RegisterAppConfig("DD_TRACE_DEBUG", enabled, origin) } + +func (c *Config) V1ProtocolEnabled() bool { + c.mu.RLock() + defer c.mu.RUnlock() + return c.v1ProtocolEnabled +} + +func (c *Config) SetV1ProtocolEnabled(enabled bool, origin telemetry.Origin) { + c.mu.Lock() + defer c.mu.Unlock() + c.v1ProtocolEnabled = enabled + telemetry.RegisterAppConfig("DD_TRACE_V1_PAYLOAD_FORMAT_ENABLED", enabled, origin) +} + +func (c *Config) TraceProtocol() float64 { + c.mu.RLock() + defer c.mu.RUnlock() + return c.traceProtocol +} + +func (c *Config) SetTraceProtocol(protocol float64, origin telemetry.Origin) { + c.mu.Lock() + defer c.mu.Unlock() + c.traceProtocol = protocol + // TODO: Report telemetry? +}