diff --git a/packages/dd-trace/src/opentracing/propagation/text_map.js b/packages/dd-trace/src/opentracing/propagation/text_map.js index c404cfc5b6a..d09d86154fd 100644 --- a/packages/dd-trace/src/opentracing/propagation/text_map.js +++ b/packages/dd-trace/src/opentracing/propagation/text_map.js @@ -171,6 +171,14 @@ class TextMapPropagator { carrier[traceparentKey] = spanContext.toTraceparent() ts.forVendor('dd', state => { + if (!spanContext._isRemote) { + // SpanContext was created by a ddtrace span. + // Last datadog span id should be set to the current span. + state.set('p', spanContext._spanId) + } else if (spanContext._trace.tags['_dd.parent_id']) { + // Propagate the last Datadog span id set on the remote span. + state.set('p', spanContext._trace.tags['_dd.parent_id']) + } state.set('s', priority) if (mechanism) { state.set('t.dm', `-${mechanism}`) @@ -339,6 +347,10 @@ class TextMapPropagator { tracestate.forVendor('dd', state => { for (const [key, value] of state.entries()) { switch (key) { + case 'p': { + spanContext._trace.tags['_dd.parent_id'] = value + break + } case 's': { const priority = parseInt(value, 10) if (!Number.isInteger(priority)) continue @@ -369,6 +381,10 @@ class TextMapPropagator { } }) + if (!spanContext._trace.tags['_dd.parent_id']) { + spanContext._trace.tags['_dd.parent_id'] = '0000000000000000' + } + this._extractBaggageItems(carrier, spanContext) return spanContext } diff --git a/packages/dd-trace/test/opentracing/propagation/text_map.spec.js b/packages/dd-trace/test/opentracing/propagation/text_map.spec.js index 4f2e927bac9..8f792375879 100644 --- a/packages/dd-trace/test/opentracing/propagation/text_map.spec.js +++ b/packages/dd-trace/test/opentracing/propagation/text_map.spec.js @@ -23,7 +23,7 @@ describe('TextMapPropagator', () => { const spanContext = new SpanContext({ traceId: id('123', 10), spanId: id('456', 10), - isRemote: true, + isRemote: params.isRemote === undefined ? true : params.isRemote, baggageItems, ...params, trace: { @@ -257,7 +257,8 @@ describe('TextMapPropagator', () => { priority: USER_KEEP, mechanism: SAMPLING_MECHANISM_MANUAL }, - tracestate: TraceState.fromString('other=bleh,dd=s:2;o:foo_bar_;t.dm:-4') + tracestate: TraceState.fromString('other=bleh,dd=s:2;o:foo_bar_;t.dm:-4'), + isRemote: false }) // Include invalid characters to verify underscore conversion spanContext._trace.origin = 'foo,bar=' @@ -266,11 +267,12 @@ describe('TextMapPropagator', () => { config.tracePropagationStyle.inject = ['tracecontext'] propagator.inject(spanContext, carrier) + expect(spanContext._isRemote).to.equal(false) expect(carrier).to.have.property('traceparent', '00-1111aaaa2222bbbb3333cccc4444dddd-5555eeee6666ffff-01') expect(carrier).to.have.property( 'tracestate', - 'dd=t.foo_bar_baz_:abc_!@#$%^&*()_+`-~;s:2;o:foo_bar~;t.dm:-4,other=bleh' + 'dd=t.foo_bar_baz_:abc_!@#$%^&*()_+`-~;p:5555eeee6666ffff;s:2;o:foo_bar~;t.dm:-4,other=bleh' ) }) @@ -477,6 +479,27 @@ describe('TextMapPropagator', () => { expect(spanContext._tracestate.get('other')).to.equal('bleh') }) + it('should extract the last datadog parent id from tracestate when p dd member is availible', () => { + textMap['traceparent'] = '00-0000000000000000000000000000007B-0000000000000456-01' + textMap['tracestate'] = 'other=bleh,dd=s:2;o:foo;p:2244eeee6666aaaa' + config.tracePropagationStyle.extract = ['tracecontext'] + + const carrier = textMap + const spanContext = propagator.extract(carrier) + + expect(spanContext._trace.tags).to.have.property('_dd.parent_id', '2244eeee6666aaaa') + }) + + it('should set the last datadog parent id to zero when p: is NOT in the tracestate', () => { + textMap['traceparent'] = '00-0000000000000000000000000000007B-0000000000000456-01' + textMap['tracestate'] = 'other=gg,dd=s:-1;' + config.tracePropagationStyle.extract = ['tracecontext'] + + const carrier = textMap + const spanContext = propagator.extract(carrier) + expect(spanContext._trace.tags).to.have.property('_dd.parent_id', '0000000000000000') + }) + it(`should not extract tracestate from tracecontext when trace IDs don't match`, () => { textMap['traceparent'] = '00-00000000000000000000000000000789-0000000000000456-01' textMap['tracestate'] = 'other=bleh,dd=t.foo_bar_baz_:abc_!@#$%^&*()_+`-~;s:2;o:foo;t.dm:-4' @@ -795,6 +818,21 @@ describe('TextMapPropagator', () => { expect(carrier['tracestate']).to.include('other=bleh') }) + it('should propagate last datadog id', () => { + textMap['traceparent'] = '01-1111aaaa2222bbbb3333cccc4444dddd-5555eeee6666ffff-01' + textMap['tracestate'] = 'other=bleh,dd=s:2;o:foo;t.dm:-4;p:4444eeee6666aaaa' + config.tracePropagationStyle.extract = ['tracecontext'] + + const carrier = {} + const spanContext = propagator.extract(textMap) + // Ensure the span context is marked as remote (i.e. not generated by the current process) + expect(spanContext._isRemote).to.equal(true) + + propagator.inject(spanContext, carrier) + + expect(carrier['tracestate']).to.include('p:4444eeee6666aaaa') + }) + it('should fix _dd.p.dm if invalid (non-hyphenated) input is received', () => { textMap['traceparent'] = '01-1111aaaa2222bbbb3333cccc4444dddd-5555eeee6666ffff-01' textMap['tracestate'] = 'other=bleh,dd=t.foo_bar_baz_:abc_!@#$%^&*()_+`-~;s:2;o:foo;t.dm:4'