Skip to content

Commit 28e8a59

Browse files
authored
Adding Support for TRACE_PROPAGATION_BEHAVIOR_EXTRACT (#5525)
* initial implementation * updating config test * fixing CI * update PR comments * updating test cases * updating config * fixing tests * addressing comments and cleanup
1 parent 34787c1 commit 28e8a59

6 files changed

Lines changed: 128 additions & 3 deletions

File tree

packages/dd-trace/src/config.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ const otelDdEnvMapping = {
6363

6464
const VALID_PROPAGATION_STYLES = new Set(['datadog', 'tracecontext', 'b3', 'b3 single header', 'none'])
6565

66+
const VALID_PROPAGATION_BEHAVIOR_EXTRACT = new Set(['continue', 'restart', 'ignore'])
67+
6668
const VALID_LOG_LEVELS = new Set(['debug', 'info', 'warn', 'error'])
6769

6870
function getFromOtelSamplerMap (otelTracesSampler, otelTracesSamplerArg) {
@@ -584,6 +586,7 @@ class Config {
584586
this._setValue(defaults, 'traceId128BitGenerationEnabled', true)
585587
this._setValue(defaults, 'traceId128BitLoggingEnabled', true)
586588
this._setValue(defaults, 'tracePropagationExtractFirst', false)
589+
this._setValue(defaults, 'tracePropagationBehaviorExtract', 'continue')
587590
this._setValue(defaults, 'tracePropagationStyle.inject', ['datadog', 'tracecontext', 'baggage'])
588591
this._setValue(defaults, 'tracePropagationStyle.extract', ['datadog', 'tracecontext', 'baggage'])
589592
this._setValue(defaults, 'tracePropagationStyle.otelPropagators', false)
@@ -746,6 +749,7 @@ class Config {
746749
DD_TRACE_PARTIAL_FLUSH_MIN_SPANS,
747750
DD_TRACE_PEER_SERVICE_MAPPING,
748751
DD_TRACE_PROPAGATION_EXTRACT_FIRST,
752+
DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT,
749753
DD_TRACE_PROPAGATION_STYLE,
750754
DD_TRACE_PROPAGATION_STYLE_INJECT,
751755
DD_TRACE_PROPAGATION_STYLE_EXTRACT,
@@ -967,6 +971,11 @@ class Config {
967971
this._setBoolean(env, 'traceId128BitGenerationEnabled', DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED)
968972
this._setBoolean(env, 'traceId128BitLoggingEnabled', DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED)
969973
this._setBoolean(env, 'tracePropagationExtractFirst', DD_TRACE_PROPAGATION_EXTRACT_FIRST)
974+
const stringPropagationBehaviorExtract = String(DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT)
975+
this._setValue(env, 'tracePropagationBehaviorExtract',
976+
VALID_PROPAGATION_BEHAVIOR_EXTRACT.has(stringPropagationBehaviorExtract)
977+
? stringPropagationBehaviorExtract
978+
: 'continue')
970979
this._setBoolean(env, 'tracePropagationStyle.otelPropagators',
971980
DD_TRACE_PROPAGATION_STYLE ||
972981
DD_TRACE_PROPAGATION_STYLE_INJECT ||

packages/dd-trace/src/opentracing/propagation/text_map.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ class TextMapPropagator {
298298

299299
_extractSpanContext (carrier) {
300300
let context = null
301+
let style = ''
301302
for (const extractor of this._config.tracePropagationStyle.extract) {
302303
let extractedContext = null
303304
switch (extractor) {
@@ -331,9 +332,9 @@ class TextMapPropagator {
331332

332333
if (context === null) {
333334
context = extractedContext
335+
style = extractor
334336
if (this._config.tracePropagationExtractFirst) {
335-
this._extractBaggageItems(carrier, context)
336-
return context
337+
break
337338
}
338339
} else {
339340
// If extractor is tracecontext, add tracecontext specific information to the context
@@ -342,7 +343,7 @@ class TextMapPropagator {
342343
this._extractTraceparentContext(carrier), context, carrier)
343344
}
344345
if (extractedContext._traceId && extractedContext._spanId &&
345-
extractedContext.toTraceId(true) !== context.toTraceId(true)) {
346+
extractedContext.toTraceId(true) !== context.toTraceId(true)) {
346347
const link = {
347348
context: extractedContext,
348349
attributes: { reason: 'terminated_context', context_headers: extractor }
@@ -354,6 +355,19 @@ class TextMapPropagator {
354355

355356
this._extractBaggageItems(carrier, context)
356357

358+
if (this._config.tracePropagationBehaviorExtract === 'ignore') {
359+
context._links = []
360+
} else if (this._config.tracePropagationBehaviorExtract === 'restart') {
361+
context._links = []
362+
context._links.push({
363+
context,
364+
attributes:
365+
{
366+
reason: 'propagation_behavior_extract', context_headers: style
367+
}
368+
})
369+
}
370+
357371
return context || this._extractSqsdContext(carrier)
358372
}
359373

packages/dd-trace/src/opentracing/span.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,12 @@ class DatadogSpan {
319319
let spanContext
320320
let startTime
321321

322+
let baggage = {}
323+
if (parent && parent._isRemote && this._parentTracer?._config?.tracePropagationBehaviorExtract !== 'continue') {
324+
baggage = parent._baggageItems
325+
parent = null
326+
}
327+
322328
if (fields.context) {
323329
spanContext = fields.context
324330
if (!spanContext._trace.startTime) {
@@ -352,6 +358,10 @@ class DatadogSpan {
352358
.padStart(8, '0')
353359
.padEnd(16, '0')
354360
}
361+
362+
if (this._parentTracer?._config?.tracePropagationBehaviorExtract === 'restart') {
363+
spanContext._baggageItems = baggage
364+
}
355365
}
356366

357367
spanContext._trace.ticks = spanContext._trace.ticks || now()

packages/dd-trace/test/config.spec.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ describe('Config', () => {
238238
expect(config).to.have.deep.property('serviceMapping', {})
239239
expect(config).to.have.nested.deep.property('tracePropagationStyle.inject', ['datadog', 'tracecontext', 'baggage'])
240240
expect(config).to.have.nested.deep.property('tracePropagationStyle.extract', ['datadog', 'tracecontext', 'baggage'])
241+
expect(config).to.have.nested.property('tracePropagationBehaviorExtract', 'continue')
241242
expect(config).to.have.nested.property('experimental.runtimeId', false)
242243
expect(config).to.have.nested.property('experimental.exporter', undefined)
243244
expect(config).to.have.nested.property('experimental.enableGetRumData', false)
@@ -479,6 +480,7 @@ describe('Config', () => {
479480
]`
480481
process.env.DD_TRACE_PROPAGATION_STYLE_INJECT = 'b3,tracecontext'
481482
process.env.DD_TRACE_PROPAGATION_STYLE_EXTRACT = 'b3,tracecontext'
483+
process.env.DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT = 'restart'
482484
process.env.DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED = 'true'
483485
process.env.DD_TRACE_EXPERIMENTAL_EXPORTER = 'log'
484486
process.env.DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED = 'true'
@@ -602,6 +604,7 @@ describe('Config', () => {
602604
})
603605
expect(config).to.have.nested.deep.property('tracePropagationStyle.inject', ['b3', 'tracecontext'])
604606
expect(config).to.have.nested.deep.property('tracePropagationStyle.extract', ['b3', 'tracecontext'])
607+
expect(config).to.have.nested.property('tracePropagationBehaviorExtract', 'restart')
605608
expect(config).to.have.nested.property('experimental.runtimeId', true)
606609
expect(config).to.have.nested.property('experimental.exporter', 'log')
607610
expect(config).to.have.nested.property('experimental.enableGetRumData', true)
@@ -1277,6 +1280,7 @@ describe('Config', () => {
12771280
process.env.DD_TRACE_EXPERIMENTAL_TRACEPARENT_ENABLED = 'true'
12781281
process.env.DD_TRACE_PROPAGATION_STYLE_INJECT = 'datadog'
12791282
process.env.DD_TRACE_PROPAGATION_STYLE_EXTRACT = 'datadog'
1283+
process.env.DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT = 'restart'
12801284
process.env.DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED = 'true'
12811285
process.env.DD_TRACE_EXPERIMENTAL_EXPORTER = 'log'
12821286
process.env.DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED = 'true'

packages/dd-trace/test/opentracing/propagation/text_map.spec.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,5 +1177,54 @@ describe('TextMapPropagator', () => {
11771177
].join(' '))
11781178
})
11791179
})
1180+
1181+
describe('tracePropagationBehaviorExtract', () => {
1182+
let traceId
1183+
let spanId
1184+
1185+
beforeEach(() => {
1186+
traceId = '1111aaaa2222bbbb3333cccc4444dddd'
1187+
spanId = '5555eeee6666ffff'
1188+
textMap = {
1189+
'x-datadog-trace-id': '123',
1190+
'x-datadog-parent-id': '456',
1191+
'ot-baggage-foo': 'bar',
1192+
traceparent: `00-${traceId}-${spanId}-01`,
1193+
baggage: 'foo=bar'
1194+
}
1195+
})
1196+
1197+
it('should reset span links when Trace_Propagation_Behavior_Extract is set to ignore', () => {
1198+
process.env.DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT = 'ignore'
1199+
config = new Config({
1200+
tracePropagationStyle: {
1201+
extract: ['tracecontext', 'datadog']
1202+
}
1203+
})
1204+
propagator = new TextMapPropagator(config)
1205+
const extractedContext = propagator.extract(textMap)
1206+
1207+
// No span links should occur when we return from extract
1208+
expect(extractedContext._links.length).to.equal(0)
1209+
})
1210+
1211+
it('should set span link to extracted trace when Trace_Propagation_Behavior_Extract is set to restart', () => {
1212+
process.env.DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT = 'restart'
1213+
config = new Config({
1214+
tracePropagationStyle: {
1215+
extract: ['tracecontext', 'datadog']
1216+
}
1217+
})
1218+
propagator = new TextMapPropagator(config)
1219+
const extractedContext = propagator.extract(textMap)
1220+
1221+
// Expect to see span links related to the extracted span
1222+
expect(extractedContext._links.length).to.equal(1)
1223+
expect(extractedContext._links[0].context.toTraceId(true)).to.equal(traceId)
1224+
expect(extractedContext._links[0].context.toSpanId(true)).to.equal(spanId)
1225+
expect(extractedContext._links[0].attributes.reason).to.equal('propagation_behavior_extract')
1226+
expect(extractedContext._links[0].attributes.context_headers).to.equal('tracecontext')
1227+
})
1228+
})
11801229
})
11811230
})

packages/dd-trace/test/opentracing/span.spec.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,5 +470,44 @@ describe('Span', () => {
470470

471471
expect(processor.process).to.have.been.calledOnce
472472
})
473+
474+
describe('tracePropagationBehaviorExtract and Baggage', () => {
475+
let parent
476+
477+
beforeEach(() => {
478+
parent = {
479+
traceId: '123',
480+
spanId: '456',
481+
_baggageItems: {
482+
foo: 'bar'
483+
},
484+
_trace: {
485+
started: ['span'],
486+
finished: ['span']
487+
},
488+
_isRemote: true
489+
}
490+
})
491+
492+
it('should not propagate baggage items when Trace_Propagation_Behavior_Extract is set to ignore', () => {
493+
tracer = {
494+
_config: {
495+
tracePropagationBehaviorExtract: 'ignore'
496+
}
497+
}
498+
span = new Span(tracer, processor, prioritySampler, { operationName: 'operation', parent })
499+
expect(span._spanContext._baggageItems).to.deep.equal({})
500+
})
501+
502+
it('should propagate baggage items when Trace_Propagation_Behavior_Extract is set to restart', () => {
503+
tracer = {
504+
_config: {
505+
tracePropagationBehaviorExtract: 'restart'
506+
}
507+
}
508+
span = new Span(tracer, processor, prioritySampler, { operationName: 'operation', parent })
509+
expect(span._spanContext._baggageItems).to.deep.equal({ foo: 'bar' })
510+
})
511+
})
473512
})
474513
})

0 commit comments

Comments
 (0)