Skip to content

Commit

Permalink
poc(ddtrace/tracer): migrate partialFlushMinSpans & partialFlushEnabled
Browse files Browse the repository at this point in the history
  • Loading branch information
darccio committed Dec 12, 2024
1 parent 522fd00 commit 6b7054d
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 44 deletions.
6 changes: 4 additions & 2 deletions ddtrace/tracer/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
"gopkg.in/DataDog/dd-trace-go.v1/internal/log"
"gopkg.in/DataDog/dd-trace-go.v1/internal/osinfo"
"gopkg.in/DataDog/dd-trace-go.v1/internal/version"

"github.com/darccio/knobs"
)

// startupInfo contains various information about the status of the tracer on startup.
Expand Down Expand Up @@ -141,8 +143,8 @@ func logStartup(t *tracer) {
AgentFeatures: t.config.agent,
Integrations: t.config.integrations,
AppSec: appsec.Enabled(),
PartialFlushEnabled: t.config.partialFlushEnabled,
PartialFlushMinSpans: t.config.partialFlushMinSpans,
PartialFlushEnabled: knobs.GetScope(t.config.Scope, partialFlushEnabled),
PartialFlushMinSpans: knobs.GetScope(t.config.Scope, partialFlushMinSpans),
Orchestrion: t.config.orchestrionCfg,
FeatureFlags: featureFlags,
PropagationStyleInject: injectorNames,
Expand Down
66 changes: 39 additions & 27 deletions ddtrace/tracer/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"gopkg.in/DataDog/dd-trace-go.v1/internal/version"

"github.com/DataDog/datadog-go/v5/statsd"
"github.com/darccio/knobs"
)

var contribIntegrations = map[string]struct {
Expand Down Expand Up @@ -115,6 +116,8 @@ var (

// config holds the tracer configuration.
type config struct {
*knobs.Scope

// debug, when true, writes details to logs.
debug bool

Expand Down Expand Up @@ -252,15 +255,6 @@ type config struct {
// misconfiguration
spanTimeout time.Duration

// partialFlushMinSpans is the number of finished spans in a single trace to trigger a
// partial flush, or 0 if partial flushing is disabled.
// Value from DD_TRACE_PARTIAL_FLUSH_MIN_SPANS, default 1000.
partialFlushMinSpans int

// partialFlushEnabled specifices whether the tracer should enable partial flushing. Value
// from DD_TRACE_PARTIAL_FLUSH_ENABLED, default false.
partialFlushEnabled bool

// statsComputationEnabled enables client-side stats computation (aka trace metrics).
statsComputationEnabled bool

Expand Down Expand Up @@ -297,6 +291,39 @@ type config struct {
logDirectory string
}

var (
// partialFlushEnabled specifices whether the tracer should enable partial flushing. Value
// from DD_TRACE_PARTIAL_FLUSH_ENABLED, default false.
partialFlushEnabled = knobs.Register(&knobs.Definition[bool]{
Default: false,
EnvVars: []knobs.EnvVar{{Key: "DD_TRACE_PARTIAL_FLUSH_ENABLED"}},
Parse: knobs.ToBool,
})

// partialFlushMinSpans is the number of finished spans in a single trace to trigger a
// partial flush, or 0 if partial flushing is disabled.
// Value from DD_TRACE_PARTIAL_FLUSH_MIN_SPANS, default 1000.
partialFlushMinSpans = knobs.Register(&knobs.Definition[int]{
// TODO(partialFlush): consider logging a warning if DD_TRACE_PARTIAL_FLUSH_MIN_SPANS
// is set, but DD_TRACE_PARTIAL_FLUSH_ENABLED is not true. Or just assume it should be enabled
// if it's explicitly set, and don't require both variables to be configured.
Default: 1000,
EnvVars: []knobs.EnvVar{{Key: "DD_TRACE_PARTIAL_FLUSH_MIN_SPANS"}},
Requires: []any{partialFlushEnabled},
Parse: func(v string) (int, error) {
i, _ := strconv.Atoi(v)
if i <= 0 {
log.Warn("DD_TRACE_PARTIAL_FLUSH_MIN_SPANS=%d is not a valid value, setting to default %d", i, 1000)
return 0, knobs.ErrInvalidValue
} else if i >= traceMaxSize {
log.Warn("DD_TRACE_PARTIAL_FLUSH_MIN_SPANS=%d is above the max number of spans that can be kept in memory for a single trace (%d spans), so partial flushing will never trigger, setting to default %d", i, traceMaxSize, 1000)
return 0, knobs.ErrInvalidValue
}
return i, nil
},
})
)

// orchestrionConfig contains Orchestrion configuration.
type orchestrionConfig struct {
// Enabled indicates whether this tracer was instanciated via Orchestrion.
Expand All @@ -318,13 +345,11 @@ type StartOption func(*config)
// maxPropagatedTagsLength limits the size of DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH to prevent HTTP 413 responses.
const maxPropagatedTagsLength = 512

// partialFlushMinSpansDefault is the default number of spans for partial flushing, if enabled.
const partialFlushMinSpansDefault = 1000

// newConfig renders the tracer configuration based on defaults, environment variables
// and passed user opts.
func newConfig(opts ...StartOption) *config {
c := new(config)
c.Scope = knobs.NewScope()
c.sampler = NewAllSampler()
sampleRate := math.NaN()
if r := getDDorOtelConfig("sampleRate"); r != "" {
Expand Down Expand Up @@ -419,19 +444,6 @@ func newConfig(opts ...StartOption) *config {
}
c.statsComputationEnabled = internal.BoolEnv("DD_TRACE_STATS_COMPUTATION_ENABLED", false)
c.dataStreamsMonitoringEnabled = internal.BoolEnv("DD_DATA_STREAMS_ENABLED", false)
c.partialFlushEnabled = internal.BoolEnv("DD_TRACE_PARTIAL_FLUSH_ENABLED", false)
c.partialFlushMinSpans = internal.IntEnv("DD_TRACE_PARTIAL_FLUSH_MIN_SPANS", partialFlushMinSpansDefault)
if c.partialFlushMinSpans <= 0 {
log.Warn("DD_TRACE_PARTIAL_FLUSH_MIN_SPANS=%d is not a valid value, setting to default %d", c.partialFlushMinSpans, partialFlushMinSpansDefault)
c.partialFlushMinSpans = partialFlushMinSpansDefault
} else if c.partialFlushMinSpans >= traceMaxSize {
log.Warn("DD_TRACE_PARTIAL_FLUSH_MIN_SPANS=%d is above the max number of spans that can be kept in memory for a single trace (%d spans), so partial flushing will never trigger, setting to default %d", c.partialFlushMinSpans, traceMaxSize, partialFlushMinSpansDefault)
c.partialFlushMinSpans = partialFlushMinSpansDefault
}
// TODO(partialFlush): consider logging a warning if DD_TRACE_PARTIAL_FLUSH_MIN_SPANS
// is set, but DD_TRACE_PARTIAL_FLUSH_ENABLED is not true. Or just assume it should be enabled
// if it's explicitly set, and don't require both variables to be configured.

c.dynamicInstrumentationEnabled = internal.BoolEnv("DD_DYNAMIC_INSTRUMENTATION_ENABLED", false)

schemaVersionStr := os.Getenv("DD_TRACE_SPAN_ATTRIBUTE_SCHEMA")
Expand Down Expand Up @@ -1192,8 +1204,8 @@ func WithDebugSpansMode(timeout time.Duration) StartOption {
// is disabled by default.
func WithPartialFlushing(numSpans int) StartOption {
return func(c *config) {
c.partialFlushEnabled = true
c.partialFlushMinSpans = numSpans
knobs.SetScope(c.Scope, partialFlushEnabled, knobs.Code, true)
knobs.SetScope(c.Scope, partialFlushMinSpans, knobs.Code, numSpans)
}
}

Expand Down
29 changes: 15 additions & 14 deletions ddtrace/tracer/option_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"gopkg.in/DataDog/dd-trace-go.v1/internal/traceprof"
"gopkg.in/DataDog/dd-trace-go.v1/internal/version"

"github.com/darccio/knobs"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -1506,46 +1507,46 @@ func TestHostnameDisabled(t *testing.T) {
func TestPartialFlushing(t *testing.T) {
t.Run("None", func(t *testing.T) {
c := newConfig()
assert.False(t, c.partialFlushEnabled)
assert.Equal(t, partialFlushMinSpansDefault, c.partialFlushMinSpans)
assert.False(t, knobs.GetScope(c.Scope, partialFlushEnabled))
assert.Equal(t, 1000, knobs.GetScope(c.Scope, partialFlushMinSpans))
})
t.Run("Disabled-DefaultMinSpans", func(t *testing.T) {
t.Setenv("DD_TRACE_PARTIAL_FLUSH_ENABLED", "false")
c := newConfig()
assert.False(t, c.partialFlushEnabled)
assert.Equal(t, partialFlushMinSpansDefault, c.partialFlushMinSpans)
assert.False(t, knobs.GetScope(c.Scope, partialFlushEnabled))
assert.Equal(t, 1000, knobs.GetScope(c.Scope, partialFlushMinSpans))
})
t.Run("Default-SetMinSpans", func(t *testing.T) {
t.Setenv("DD_TRACE_PARTIAL_FLUSH_MIN_SPANS", "10")
c := newConfig()
assert.False(t, c.partialFlushEnabled)
assert.Equal(t, 10, c.partialFlushMinSpans)
assert.False(t, knobs.GetScope(c.Scope, partialFlushEnabled))
assert.Equal(t, 10, knobs.GetScope(c.Scope, partialFlushMinSpans))
})
t.Run("Enabled-DefaultMinSpans", func(t *testing.T) {
t.Setenv("DD_TRACE_PARTIAL_FLUSH_ENABLED", "true")
c := newConfig()
assert.True(t, c.partialFlushEnabled)
assert.Equal(t, partialFlushMinSpansDefault, c.partialFlushMinSpans)
assert.True(t, knobs.GetScope(c.Scope, partialFlushEnabled))
assert.Equal(t, 1000, knobs.GetScope(c.Scope, partialFlushMinSpans))
})
t.Run("Enabled-SetMinSpans", func(t *testing.T) {
t.Setenv("DD_TRACE_PARTIAL_FLUSH_ENABLED", "true")
t.Setenv("DD_TRACE_PARTIAL_FLUSH_MIN_SPANS", "10")
c := newConfig()
assert.True(t, c.partialFlushEnabled)
assert.Equal(t, 10, c.partialFlushMinSpans)
assert.True(t, knobs.GetScope(c.Scope, partialFlushEnabled))
assert.Equal(t, 10, knobs.GetScope(c.Scope, partialFlushMinSpans))
})
t.Run("Enabled-SetMinSpansNegative", func(t *testing.T) {
t.Setenv("DD_TRACE_PARTIAL_FLUSH_ENABLED", "true")
t.Setenv("DD_TRACE_PARTIAL_FLUSH_MIN_SPANS", "-1")
c := newConfig()
assert.True(t, c.partialFlushEnabled)
assert.Equal(t, partialFlushMinSpansDefault, c.partialFlushMinSpans)
assert.True(t, knobs.GetScope(c.Scope, partialFlushEnabled))
assert.Equal(t, 1000, knobs.GetScope(c.Scope, partialFlushMinSpans))
})
t.Run("WithPartialFlushOption", func(t *testing.T) {
c := newConfig()
WithPartialFlushing(20)(c)
assert.True(t, c.partialFlushEnabled)
assert.Equal(t, 20, c.partialFlushMinSpans)
assert.True(t, knobs.GetScope(c.Scope, partialFlushEnabled))
assert.Equal(t, 20, knobs.GetScope(c.Scope, partialFlushMinSpans))
})
}

Expand Down
4 changes: 3 additions & 1 deletion ddtrace/tracer/spancontext.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
"gopkg.in/DataDog/dd-trace-go.v1/internal/log"
"gopkg.in/DataDog/dd-trace-go.v1/internal/samplernames"
"gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry"

"github.com/darccio/knobs"
)

var _ ddtrace.SpanContext = (*spanContext)(nil)
Expand Down Expand Up @@ -499,7 +501,7 @@ func (t *trace) finishedOne(s *span) {
return
}

doPartialFlush := tr.config.partialFlushEnabled && t.finished >= tr.config.partialFlushMinSpans
doPartialFlush := knobs.GetScope(tr.config.Scope, partialFlushEnabled) && t.finished >= knobs.GetScope(tr.config.Scope, partialFlushMinSpans)
if !doPartialFlush {
return // The trace hasn't completed and partial flushing will not occur
}
Expand Down

0 comments on commit 6b7054d

Please sign in to comment.