diff --git a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts index d801082acaa..aba6290d66a 100644 --- a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts +++ b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts @@ -37,6 +37,7 @@ export const DEBUG_FLAG_KEY = Context.createKey( const VALID_TRACEID_REGEX = /^([0-9a-f]{16}){1,2}$/i; const VALID_SPANID_REGEX = /^[0-9a-f]{16}$/i; const INVALID_ID_REGEX = /^0+$/i; +const VALID_SAMPLED_VALUES = [true, 'true', '1']; function isValidTraceId(traceId: string): boolean { return VALID_TRACEID_REGEX.test(traceId) && !INVALID_ID_REGEX.test(traceId); @@ -64,7 +65,7 @@ export class B3Propagator implements HttpTextPropagator { isValidSpanId(spanContext.spanId) ) { if (parentSpanId) { - if (isValidTraceId(parentSpanId as string)) { + if (isValidSpanId(parentSpanId as string)) { setter(carrier, X_B3_PARENT_SPAN_ID, parentSpanId); } else { return; @@ -104,7 +105,9 @@ export class B3Propagator implements HttpTextPropagator { const options = parseHeader(sampledHeader); const debugHeaderValue = parseHeader(flagsHeader); const debug = debugHeaderValue === '1'; - const traceFlagsOrDebug = Number(debug) || Number(options); + const isSampled = VALID_SAMPLED_VALUES.includes(options); + const traceFlags = + debug || isSampled ? TraceFlags.SAMPLED : TraceFlags.NONE; if ( typeof traceIdHeaderValue !== 'string' || @@ -124,8 +127,7 @@ export class B3Propagator implements HttpTextPropagator { traceId, spanId, isRemote: true, - // Set traceFlags as 1 if debug is 1 - traceFlags: traceFlagsOrDebug || TraceFlags.NONE, + traceFlags, }); } return context; diff --git a/packages/opentelemetry-core/test/context/B3Propagator.test.ts b/packages/opentelemetry-core/test/context/B3Propagator.test.ts index 7d9c59be66f..733c448df00 100644 --- a/packages/opentelemetry-core/test/context/B3Propagator.test.ts +++ b/packages/opentelemetry-core/test/context/B3Propagator.test.ts @@ -287,6 +287,71 @@ describe('B3Propagator', () => { assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); + it('should extract context of a span from carrier when debug flag is invalidly set as false', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_FLAGS] = 'false'; + carrier[X_B3_SAMPLED] = '0'; + const context = b3Propagator.extract( + Context.ROOT_CONTEXT, + carrier, + defaultGetter + ); + const extractedSpanContext = getExtractedSpanContext(context); + + assert.deepStrictEqual(extractedSpanContext, { + spanId: 'b7ad6b7169203331', + traceId: '0af7651916cd43dd8448eb211c80319c', + isRemote: true, + traceFlags: TraceFlags.NONE, + }); + assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); + }); + + it('should extract context of a span from carrier when debug flag is invalidly set as true', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_FLAGS] = 'true'; + carrier[X_B3_SAMPLED] = '0'; + const context = b3Propagator.extract( + Context.ROOT_CONTEXT, + carrier, + defaultGetter + ); + const extractedSpanContext = getExtractedSpanContext(context); + + assert.deepStrictEqual(extractedSpanContext, { + spanId: 'b7ad6b7169203331', + traceId: '0af7651916cd43dd8448eb211c80319c', + isRemote: true, + traceFlags: TraceFlags.NONE, + }); + assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); + }); + + it('should extract context of a span from carrier when debug flag is invalidly set as 2', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_FLAGS] = '3'; + carrier[X_B3_SAMPLED] = '0'; + const context = b3Propagator.extract( + Context.ROOT_CONTEXT, + carrier, + defaultGetter + ); + const extractedSpanContext = getExtractedSpanContext(context); + + assert.deepStrictEqual(extractedSpanContext, { + spanId: 'b7ad6b7169203331', + traceId: '0af7651916cd43dd8448eb211c80319c', + isRemote: true, + traceFlags: TraceFlags.NONE, + }); + assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); + }); it('should extract context of a span from carrier with a parent span id', () => { carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; @@ -311,6 +376,29 @@ describe('B3Propagator', () => { assert.equal(context.getValue(PARENT_SPAN_ID_KEY), 'f4592dc481026a8c'); }); + it('should extract context of a span from carrier with a parent span id and debug set', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_PARENT_SPAN_ID] = 'f4592dc481026a8c'; + carrier[X_B3_FLAGS] = '1'; + carrier[X_B3_SAMPLED] = '0'; + const context = b3Propagator.extract( + Context.ROOT_CONTEXT, + carrier, + defaultGetter + ); + const extractedSpanContext = getExtractedSpanContext(context); + + assert.deepStrictEqual(extractedSpanContext, { + spanId: 'b7ad6b7169203331', + traceId: '0af7651916cd43dd8448eb211c80319c', + isRemote: true, + traceFlags: TraceFlags.SAMPLED, + }); + assert.equal(context.getValue(DEBUG_FLAG_KEY), '1'); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), 'f4592dc481026a8c'); + }); + it('should return undefined when traceId is undefined', () => { carrier[X_B3_TRACE_ID] = undefined; carrier[X_B3_SPAN_ID] = undefined; @@ -339,6 +427,16 @@ describe('B3Propagator', () => { assert.deepStrictEqual(context, undefined); }); + it('should return undefined when parentSpanId is a trace id', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_PARENT_SPAN_ID] = '0af7651916cd43dd8448eb211c80319d'; + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + assert.deepStrictEqual(context, undefined); + }); + it('returns undefined if b3 header is missing', () => { const context = getExtractedSpanContext( b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) @@ -357,7 +455,7 @@ describe('B3Propagator', () => { it('extracts b3 from list of header', () => { carrier[X_B3_TRACE_ID] = ['0af7651916cd43dd8448eb211c80319c']; carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_SAMPLED] = '01'; + carrier[X_B3_SAMPLED] = '1'; const context = b3Propagator.extract( Context.ROOT_CONTEXT, carrier,