Skip to content

Commit f82ef33

Browse files
committed
migrate traceRateLimitPerSecond
1 parent b2ed039 commit f82ef33

File tree

5 files changed

+50
-41
lines changed

5 files changed

+50
-41
lines changed

ddtrace/tracer/option.go

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,6 @@ var (
127127

128128
// defaultMaxTagsHeaderLen specifies the default maximum length of the X-Datadog-Tags header value.
129129
defaultMaxTagsHeaderLen = 512
130-
131-
// defaultRateLimit specifies the default trace rate limit used when DD_TRACE_RATE_LIMIT is not set.
132-
defaultRateLimit = 100.0
133130
)
134131

135132
// Supported trace protocols.
@@ -304,9 +301,6 @@ type config struct {
304301
// tracingAsTransport specifies whether the tracer is running in transport-only mode, where traces are only sent when other products request it.
305302
tracingAsTransport bool
306303

307-
// traceRateLimitPerSecond specifies the rate limit for traces.
308-
traceRateLimitPerSecond float64
309-
310304
// traceProtocol specifies the trace protocol to use.
311305
traceProtocol float64
312306

@@ -361,22 +355,6 @@ func newConfig(opts ...StartOption) (*config, error) {
361355
c.sampler = NewAllSampler()
362356
c.httpClientTimeout = time.Second * 10 // 10 seconds
363357

364-
c.traceRateLimitPerSecond = defaultRateLimit
365-
origin := telemetry.OriginDefault
366-
if v, ok := env.Lookup("DD_TRACE_RATE_LIMIT"); ok {
367-
l, err := strconv.ParseFloat(v, 64)
368-
if err != nil {
369-
log.Warn("DD_TRACE_RATE_LIMIT invalid, using default value %f: %v", defaultRateLimit, err.Error())
370-
} else if l < 0.0 {
371-
log.Warn("DD_TRACE_RATE_LIMIT negative, using default value %f", defaultRateLimit)
372-
} else {
373-
c.traceRateLimitPerSecond = l
374-
origin = telemetry.OriginEnvVar
375-
}
376-
}
377-
378-
reportTelemetryOnAppStarted(telemetry.Configuration{Name: "trace_rate_limit", Value: c.traceRateLimitPerSecond, Origin: origin})
379-
380358
if v := env.Get("OTEL_LOGS_EXPORTER"); v != "" {
381359
log.Warn("OTEL_LOGS_EXPORTER is not supported")
382360
}
@@ -632,7 +610,7 @@ func apmTracingDisabled(c *config) {
632610
// using the tracer as transport layer for their data. And finally adding the _dd.apm.enabled=0 tag to all traces
633611
// to let the backend know that it needs to keep APM UI disabled.
634612
c.internalConfig.SetGlobalSampleRate(1.0, internalconfig.OriginCalculated)
635-
c.traceRateLimitPerSecond = 1.0 / 60
613+
c.internalConfig.SetTraceRateLimitPerSecond(1.0/60, internalconfig.OriginCalculated)
636614
c.tracingAsTransport = true
637615
WithGlobalTag("_dd.apm.enabled", 0)(c)
638616
// Disable runtime metrics. In `tracingAsTransport` mode, we'll still

ddtrace/tracer/sampler_test.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@ import (
1818
"time"
1919

2020
"github.com/DataDog/dd-trace-go/v2/ddtrace/ext"
21+
internalconfig "github.com/DataDog/dd-trace-go/v2/internal/config"
2122
"github.com/DataDog/dd-trace-go/v2/internal/samplernames"
2223

2324
"github.com/stretchr/testify/assert"
2425
"golang.org/x/time/rate"
2526
)
2627

28+
const defaultRateLimit = internalconfig.DefaultRateLimit
29+
2730
func TestPrioritySampler(t *testing.T) {
2831
// create a new span with given service/env
2932
mkSpan := func(svc, env string) *Span {
@@ -273,7 +276,7 @@ func TestRuleEnvVars(t *testing.T) {
273276
t.Setenv("DD_TRACE_RATE_LIMIT", tt.in)
274277
c, err := newTestConfig()
275278
assert.NoError(err)
276-
res := newRateLimiter(c.traceRateLimitPerSecond)
279+
res := newRateLimiter(c.internalConfig.TraceRateLimitPerSecond())
277280
assert.Equal(tt.out, res.limiter)
278281
}
279282
})
@@ -506,7 +509,7 @@ func TestRulesSampler(t *testing.T) {
506509
assert := assert.New(t)
507510
c, err := newTestConfig()
508511
assert.NoError(err)
509-
rs := newRulesSampler(nil, nil, c.internalConfig.GlobalSampleRate(), c.traceRateLimitPerSecond)
512+
rs := newRulesSampler(nil, nil, c.internalConfig.GlobalSampleRate(), c.internalConfig.TraceRateLimitPerSecond())
510513

511514
span := makeSpan("http.request", "test-service")
512515
result := rs.SampleTrace(span)
@@ -573,7 +576,7 @@ func TestRulesSampler(t *testing.T) {
573576
assert := assert.New(t)
574577
c, err := newTestConfig()
575578
assert.NoError(err)
576-
rs := newRulesSampler(rules, nil, c.internalConfig.GlobalSampleRate(), c.traceRateLimitPerSecond)
579+
rs := newRulesSampler(rules, nil, c.internalConfig.GlobalSampleRate(), c.internalConfig.TraceRateLimitPerSecond())
577580

578581
span := makeFinishedSpan(tt.spanName, tt.spanSrv, tt.spanRsc, tt.spanTags)
579582

@@ -599,7 +602,7 @@ func TestRulesSampler(t *testing.T) {
599602
assert := assert.New(t)
600603
c, err := newTestConfig()
601604
assert.NoError(err)
602-
rs := newRulesSampler(v, nil, c.internalConfig.GlobalSampleRate(), c.traceRateLimitPerSecond)
605+
rs := newRulesSampler(v, nil, c.internalConfig.GlobalSampleRate(), c.internalConfig.TraceRateLimitPerSecond())
603606

604607
span := makeSpan("http.request", "test-service")
605608
result := rs.SampleTrace(span)
@@ -629,7 +632,7 @@ func TestRulesSampler(t *testing.T) {
629632
assert := assert.New(t)
630633
c, err := newTestConfig()
631634
assert.NoError(err)
632-
rs := newRulesSampler(v, nil, c.internalConfig.GlobalSampleRate(), c.traceRateLimitPerSecond)
635+
rs := newRulesSampler(v, nil, c.internalConfig.GlobalSampleRate(), c.internalConfig.TraceRateLimitPerSecond())
633636

634637
span := makeSpan("http.request", "test-service")
635638
result := rs.SampleTrace(span)
@@ -677,7 +680,7 @@ func TestRulesSampler(t *testing.T) {
677680
assert := assert.New(t)
678681
c, err := newTestConfig()
679682
assert.NoError(err)
680-
rs := newRulesSampler(nil, rules, c.internalConfig.GlobalSampleRate(), c.traceRateLimitPerSecond)
683+
rs := newRulesSampler(nil, rules, c.internalConfig.GlobalSampleRate(), c.internalConfig.TraceRateLimitPerSecond())
681684

682685
span := makeFinishedSpan(tt.spanName, tt.spanSrv, "res-10", map[string]interface{}{"hostname": "hn-30"})
683686

@@ -801,7 +804,7 @@ func TestRulesSampler(t *testing.T) {
801804
assert := assert.New(t)
802805
c, err := newTestConfig(WithSamplingRules(tt.rules))
803806
assert.NoError(err)
804-
rs := newRulesSampler(nil, c.spanRules, c.internalConfig.GlobalSampleRate(), c.traceRateLimitPerSecond)
807+
rs := newRulesSampler(nil, c.spanRules, c.internalConfig.GlobalSampleRate(), c.internalConfig.TraceRateLimitPerSecond())
805808

806809
span := makeFinishedSpan(tt.spanName, tt.spanSrv, "res-10", map[string]interface{}{"hostname": "hn-30",
807810
"tag": 20.1,
@@ -871,7 +874,7 @@ func TestRulesSampler(t *testing.T) {
871874
assert := assert.New(t)
872875
c, err := newTestConfig()
873876
assert.NoError(err)
874-
rs := newRulesSampler(nil, rules, c.internalConfig.GlobalSampleRate(), c.traceRateLimitPerSecond)
877+
rs := newRulesSampler(nil, rules, c.internalConfig.GlobalSampleRate(), c.internalConfig.TraceRateLimitPerSecond())
875878

876879
span := makeFinishedSpan(tt.spanName, tt.spanSrv, tt.resName, map[string]interface{}{"hostname": "hn-30"})
877880
result := rs.SampleSpan(span)
@@ -980,7 +983,7 @@ func TestRulesSampler(t *testing.T) {
980983
assert := assert.New(t)
981984
c, err := newTestConfig(WithSamplingRules(tt.rules))
982985
assert.NoError(err)
983-
rs := newRulesSampler(nil, c.spanRules, c.internalConfig.GlobalSampleRate(), c.traceRateLimitPerSecond)
986+
rs := newRulesSampler(nil, c.spanRules, c.internalConfig.GlobalSampleRate(), c.internalConfig.TraceRateLimitPerSecond())
984987

985988
span := makeFinishedSpan(tt.spanName, tt.spanSrv, "res-10", map[string]interface{}{"hostname": "hn-30",
986989
"tag": 20.1,
@@ -1011,7 +1014,7 @@ func TestRulesSampler(t *testing.T) {
10111014
t.Setenv("DD_TRACE_SAMPLE_RATE", fmt.Sprint(rate))
10121015
c, err := newTestConfig()
10131016
assert.NoError(err)
1014-
rs := newRulesSampler(nil, rules, c.internalConfig.GlobalSampleRate(), c.traceRateLimitPerSecond)
1017+
rs := newRulesSampler(nil, rules, c.internalConfig.GlobalSampleRate(), c.internalConfig.TraceRateLimitPerSecond())
10151018

10161019
span := makeSpan("http.request", "test-service")
10171020
result := rs.SampleTrace(span)
@@ -1438,7 +1441,7 @@ func TestRulesSamplerInternals(t *testing.T) {
14381441
now := time.Now()
14391442
c, err := newTestConfig()
14401443
assert.NoError(err)
1441-
rs := newRulesSampler(nil, nil, c.internalConfig.GlobalSampleRate(), c.traceRateLimitPerSecond)
1444+
rs := newRulesSampler(nil, nil, c.internalConfig.GlobalSampleRate(), c.internalConfig.TraceRateLimitPerSecond())
14421445
// set samplingLimiter to specific state
14431446
rs.traces.limiter.prevTime = now.Add(-1 * time.Second)
14441447
rs.traces.limiter.allowed = 1
@@ -1457,7 +1460,7 @@ func TestRulesSamplerInternals(t *testing.T) {
14571460
now := time.Now()
14581461
c, err := newTestConfig()
14591462
assert.NoError(err)
1460-
rs := newRulesSampler(nil, nil, c.internalConfig.GlobalSampleRate(), c.traceRateLimitPerSecond)
1463+
rs := newRulesSampler(nil, nil, c.internalConfig.GlobalSampleRate(), c.internalConfig.TraceRateLimitPerSecond())
14611464
// force sampling limiter to 1.0 spans/sec
14621465
rs.traces.limiter.limiter = rate.NewLimiter(rate.Limit(1.0), 1)
14631466
rs.traces.limiter.prevTime = now.Add(-1 * time.Second)
@@ -1484,6 +1487,7 @@ func TestRulesSamplerInternals(t *testing.T) {
14841487
}
14851488

14861489
func TestSamplingLimiter(t *testing.T) {
1490+
14871491
t.Run("resets-every-second", func(t *testing.T) {
14881492
assert := assert.New(t)
14891493
sl := newRateLimiter(defaultRateLimit)

ddtrace/tracer/tracer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ func newUnstartedTracer(opts ...StartOption) (t *tracer, err error) {
419419
c.spanRules = spans
420420
}
421421

422-
rulesSampler := newRulesSampler(c.traceRules, c.spanRules, c.internalConfig.GlobalSampleRate(), c.traceRateLimitPerSecond)
422+
rulesSampler := newRulesSampler(c.traceRules, c.spanRules, c.internalConfig.GlobalSampleRate(), c.internalConfig.TraceRateLimitPerSecond())
423423
c.traceSampleRate = newDynamicConfig("trace_sample_rate", c.internalConfig.GlobalSampleRate(), rulesSampler.traces.setGlobalSampleRate, equal[float64])
424424
// If globalSampleRate returns NaN, it means the environment variable was not set or valid.
425425
// We could always set the origin to "env_var" inconditionally, but then it wouldn't be possible

internal/config/config.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,11 @@ type Config struct {
6363
dataStreamsMonitoringEnabled bool
6464
dynamicInstrumentationEnabled bool
6565
// globalSampleRate holds the sample rate for the tracer.
66-
globalSampleRate float64
67-
ciVisibilityEnabled bool
68-
ciVisibilityAgentless bool
69-
logDirectory string
66+
globalSampleRate float64
67+
ciVisibilityEnabled bool
68+
ciVisibilityAgentless bool
69+
logDirectory string
70+
// traceRateLimitPerSecond specifies the rate limit for traces.
7071
traceRateLimitPerSecond float64
7172
// logToStdout, if true, indicates we should log all traces to the standard output
7273
logToStdout bool
@@ -106,7 +107,7 @@ func loadConfig() *Config {
106107
cfg.ciVisibilityEnabled = provider.getBool("DD_CIVISIBILITY_ENABLED", false)
107108
cfg.ciVisibilityAgentless = provider.getBool("DD_CIVISIBILITY_AGENTLESS_ENABLED", false)
108109
cfg.logDirectory = provider.getString("DD_TRACE_LOG_DIRECTORY", "")
109-
cfg.traceRateLimitPerSecond = provider.getFloat("DD_TRACE_RATE_LIMIT", 0.0)
110+
cfg.traceRateLimitPerSecond = provider.getFloatWithValidator("DD_TRACE_RATE_LIMIT", DefaultRateLimit, validateRateLimit)
110111
cfg.globalSampleRate = provider.getFloatWithValidator("DD_TRACE_SAMPLE_RATE", math.NaN(), validateSampleRate)
111112

112113
// AWS_LAMBDA_FUNCTION_NAME being set indicates that we're running in an AWS Lambda environment.
@@ -270,3 +271,16 @@ func (c *Config) SetGlobalSampleRate(rate float64, origin telemetry.Origin) {
270271
c.globalSampleRate = rate
271272
telemetry.RegisterAppConfig("DD_TRACE_SAMPLE_RATE", rate, origin)
272273
}
274+
275+
func (c *Config) TraceRateLimitPerSecond() float64 {
276+
c.mu.RLock()
277+
defer c.mu.RUnlock()
278+
return c.traceRateLimitPerSecond
279+
}
280+
281+
func (c *Config) SetTraceRateLimitPerSecond(rate float64, origin telemetry.Origin) {
282+
c.mu.Lock()
283+
defer c.mu.Unlock()
284+
c.traceRateLimitPerSecond = rate
285+
telemetry.RegisterAppConfig("DD_TRACE_RATE_LIMIT", rate, origin)
286+
}

internal/config/config_helpers.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,23 @@ package config
77

88
import "github.com/DataDog/dd-trace-go/v2/internal/log"
99

10+
const (
11+
// DefaultRateLimit specifies the default rate limit per second for traces.
12+
DefaultRateLimit = 100.0
13+
)
14+
1015
func validateSampleRate(rate float64) bool {
1116
if rate < 0.0 || rate > 1.0 {
1217
log.Warn("ignoring DD_TRACE_SAMPLE_RATE: out of range %f", rate)
1318
return false
1419
}
1520
return true
1621
}
22+
23+
func validateRateLimit(rate float64) bool {
24+
if rate < 0.0 {
25+
log.Warn("ignoring DD_TRACE_RATE_LIMIT: negative value %f", rate)
26+
return false
27+
}
28+
return true
29+
}

0 commit comments

Comments
 (0)