From 0b8d652e7cb54cac3a0589fdb617d170a54a5e04 Mon Sep 17 00:00:00 2001 From: Steven Date: Thu, 23 Jul 2020 16:42:54 -0400 Subject: [PATCH 01/10] fix: add debug flag to b3 propagator --- .../src/trace/span_context.ts | 12 ++++ .../src/context/propagation/B3Propagator.ts | 23 ++++++- .../test/context/B3Propagator.test.ts | 66 +++++++++++++++++++ 3 files changed, 98 insertions(+), 3 deletions(-) diff --git a/packages/opentelemetry-api/src/trace/span_context.ts b/packages/opentelemetry-api/src/trace/span_context.ts index 82eafe4332..323d3af93a 100644 --- a/packages/opentelemetry-api/src/trace/span_context.ts +++ b/packages/opentelemetry-api/src/trace/span_context.ts @@ -50,6 +50,18 @@ export interface SpanContext { * SAMPLED = 0x1 and NONE = 0x0; */ traceFlags: TraceFlags; + /** + * Debug flag to propagate. + * + * This flag only seems relevant to b3. According to the b3 spec, + * Debug is encoded as X-B3-Flags: 1. Absent or any other value can be ignored. + * Debug is a production troubleshooting aid used in tools like curl or chrome debug. + * Debug is an emphasized accept decision that implies accept (or setting traceFlags to accept), + * additionally reporting Span.debug = true for each span in the trace. Adding this + * to the span context because the b3 spec says when this flag is set properly, + * do not send the sampled header as well. + */ + debug?: boolean; /** * Tracing-system-specific info to propagate. * diff --git a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts index 126be42c17..77b7d52ab5 100644 --- a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts +++ b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts @@ -26,6 +26,8 @@ import { getParentSpanContext, setExtractedSpanContext } from '../context'; export const X_B3_TRACE_ID = 'x-b3-traceid'; export const X_B3_SPAN_ID = 'x-b3-spanid'; export const X_B3_SAMPLED = 'x-b3-sampled'; +export const X_B3_PARENT_SPAN_ID = 'x-b3-parentspanid'; +export const X_B3_FLAGS = 'x-b3-flags'; 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; @@ -53,10 +55,18 @@ export class B3Propagator implements HttpTextPropagator { ) { setter(carrier, X_B3_TRACE_ID, spanContext.traceId); setter(carrier, X_B3_SPAN_ID, spanContext.spanId); - + // According to the B3 spec, if the debug flag is set, + // the sampled flag shouldn't be propagated as well. + if (spanContext.debug) { + setter( + carrier, + X_B3_FLAGS, + '1' + ); + } // We set the header only if there is an existing sampling decision. // Otherwise we will omit it => Absent. - if (spanContext.traceFlags !== undefined) { + else if (spanContext.traceFlags !== undefined) { setter( carrier, X_B3_SAMPLED, @@ -72,6 +82,7 @@ export class B3Propagator implements HttpTextPropagator { const traceIdHeader = getter(carrier, X_B3_TRACE_ID); const spanIdHeader = getter(carrier, X_B3_SPAN_ID); const sampledHeader = getter(carrier, X_B3_SAMPLED); + const flagsHeader = getter(carrier, X_B3_FLAGS); const traceIdHeaderValue = Array.isArray(traceIdHeader) ? traceIdHeader[0] @@ -82,6 +93,10 @@ export class B3Propagator implements HttpTextPropagator { ? sampledHeader[0] : sampledHeader; + const debugHeaderValue = Array.isArray(flagsHeader) ? flagsHeader[0] : flagsHeader; + const debug = isNaN(Number(debugHeaderValue)) ? false : debugHeaderValue === "1"; + const traceFlagsOrDebug = Number(debug) || Number(options); + if (typeof traceIdHeaderValue !== 'string' || typeof spanId !== 'string') { return context; } @@ -93,7 +108,9 @@ export class B3Propagator implements HttpTextPropagator { traceId, spanId, isRemote: true, - traceFlags: isNaN(Number(options)) ? TraceFlags.NONE : Number(options), + // Set traceFlags as 1 if debug is 1 + traceFlags: traceFlagsOrDebug || TraceFlags.NONE , + debug, }); } return context; diff --git a/packages/opentelemetry-core/test/context/B3Propagator.test.ts b/packages/opentelemetry-core/test/context/B3Propagator.test.ts index 436033480e..3b73184174 100644 --- a/packages/opentelemetry-core/test/context/B3Propagator.test.ts +++ b/packages/opentelemetry-core/test/context/B3Propagator.test.ts @@ -28,6 +28,7 @@ import { } from '../../src/context/context'; import { B3Propagator, + X_B3_FLAGS, X_B3_SAMPLED, X_B3_SPAN_ID, X_B3_TRACE_ID, @@ -61,6 +62,7 @@ describe('B3Propagator', () => { ); assert.deepStrictEqual(carrier[X_B3_SPAN_ID], '6e0c63257de34c92'); assert.deepStrictEqual(carrier[X_B3_SAMPLED], '1'); + assert.deepStrictEqual(carrier[X_B3_FLAGS], undefined); }); it('should set b3 traceId and spanId headers - ignore tracestate', () => { @@ -83,8 +85,31 @@ describe('B3Propagator', () => { ); assert.deepStrictEqual(carrier[X_B3_SPAN_ID], '6e0c63257de34c92'); assert.deepStrictEqual(carrier[X_B3_SAMPLED], '0'); + assert.deepStrictEqual(carrier[X_B3_FLAGS], undefined); }); + it('should set set b3 traceId, spanId, and flags headers', () => { + const spanContext: SpanContext = { + traceId: 'd4cda95b652f4a1592b449d5929fda1b', + spanId: '6e0c63257de34c92', + traceFlags: TraceFlags.NONE, + debug: true, + }; + + b3Propagator.inject( + setExtractedSpanContext(Context.ROOT_CONTEXT, spanContext), + carrier, + defaultSetter + ); + assert.deepStrictEqual( + carrier[X_B3_TRACE_ID], + 'd4cda95b652f4a1592b449d5929fda1b' + ); + assert.deepStrictEqual(carrier[X_B3_SPAN_ID], '6e0c63257de34c92'); + assert.deepStrictEqual(carrier[X_B3_FLAGS], '1'); + assert.deepStrictEqual(carrier[X_B3_SAMPLED], undefined); + }) + it('should not inject empty spancontext', () => { const emptySpanContext = { traceId: '', @@ -110,6 +135,7 @@ describe('B3Propagator', () => { ); assert.deepStrictEqual(extractedSpanContext, { + debug: false, spanId: 'b7ad6b7169203331', traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, @@ -126,6 +152,7 @@ describe('B3Propagator', () => { ); assert.deepStrictEqual(extractedSpanContext, { + debug: false, spanId: 'b7ad6b7169203331', traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, @@ -142,6 +169,7 @@ describe('B3Propagator', () => { ); assert.deepStrictEqual(extractedSpanContext, { + debug: false, spanId: 'b7ad6b7169203331', traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, @@ -158,6 +186,7 @@ describe('B3Propagator', () => { ); assert.deepStrictEqual(extractedSpanContext, { + debug: false, spanId: 'b7ad6b7169203331', traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, @@ -165,6 +194,41 @@ describe('B3Propagator', () => { }); }); + it("should extract context of a debug span from carrier when debug flag is valid", () => { + carrier[X_B3_TRACE_ID] = "0af7651916cd43dd8448eb211c80319c"; + carrier[X_B3_SPAN_ID] = "b7ad6b7169203331"; + carrier[X_B3_FLAGS] = "1"; + const extractedSpanContext = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + + assert.deepStrictEqual(extractedSpanContext, { + debug: true, + spanId: "b7ad6b7169203331", + traceId: "0af7651916cd43dd8448eb211c80319c", + isRemote: true, + traceFlags: TraceFlags.SAMPLED, + }); + }); + + it("should extract context of a span from carrier when debug flag is invalidly set as 0", () => { + carrier[X_B3_TRACE_ID] = "0af7651916cd43dd8448eb211c80319c"; + carrier[X_B3_SPAN_ID] = "b7ad6b7169203331"; + carrier[X_B3_FLAGS] = "0"; + carrier[X_B3_SAMPLED] ="1" + const extractedSpanContext = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + + assert.deepStrictEqual(extractedSpanContext, { + debug: false, + spanId: "b7ad6b7169203331", + traceId: "0af7651916cd43dd8448eb211c80319c", + isRemote: true, + traceFlags: TraceFlags.SAMPLED, + }); + }); + it('should return undefined when traceId is undefined', () => { carrier[X_B3_TRACE_ID] = undefined; carrier[X_B3_SPAN_ID] = undefined; @@ -214,6 +278,7 @@ describe('B3Propagator', () => { b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) ); assert.deepStrictEqual(extractedSpanContext, { + debug: false, spanId: 'b7ad6b7169203331', traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, @@ -299,6 +364,7 @@ describe('B3Propagator', () => { ); assert.deepStrictEqual(extractedSpanContext, { + debug: false, spanId: 'b7ad6b7169203331', traceId: '00000000000000008448eb211c80319c', isRemote: true, From 39a0422d90d4df107be64f1046a35924d0015142 Mon Sep 17 00:00:00 2001 From: Steven Date: Thu, 23 Jul 2020 20:51:37 -0400 Subject: [PATCH 02/10] fix: add debug flag to b3 propagator --- .../src/trace/span_context.ts | 9 +- .../src/context/propagation/B3Propagator.ts | 36 ++++--- .../test/context/B3Propagator.test.ts | 96 +++++++++++++++---- 3 files changed, 113 insertions(+), 28 deletions(-) diff --git a/packages/opentelemetry-api/src/trace/span_context.ts b/packages/opentelemetry-api/src/trace/span_context.ts index 323d3af93a..183fe7cc0d 100644 --- a/packages/opentelemetry-api/src/trace/span_context.ts +++ b/packages/opentelemetry-api/src/trace/span_context.ts @@ -53,7 +53,7 @@ export interface SpanContext { /** * Debug flag to propagate. * - * This flag only seems relevant to b3. According to the b3 spec, + * This flag is relevant to b3. According to the b3 spec, * Debug is encoded as X-B3-Flags: 1. Absent or any other value can be ignored. * Debug is a production troubleshooting aid used in tools like curl or chrome debug. * Debug is an emphasized accept decision that implies accept (or setting traceFlags to accept), @@ -62,6 +62,13 @@ export interface SpanContext { * do not send the sampled header as well. */ debug?: boolean; + /** + * + * The ID of the parent span propagated by b3. Encoded as a 16 + * lowercase hex characters corresponding to 64 bits. + * May be present on a child span and must be absent on the root span + */ + parentSpanId?: string; /** * Tracing-system-specific info to propagate. * diff --git a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts index 77b7d52ab5..8b7cfd208a 100644 --- a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts +++ b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts @@ -48,22 +48,23 @@ export class B3Propagator implements HttpTextPropagator { inject(context: Context, carrier: unknown, setter: SetterFunction) { const spanContext = getParentSpanContext(context); if (!spanContext) return; - if ( isValidTraceId(spanContext.traceId) && isValidSpanId(spanContext.spanId) ) { + const parentSpanExists = !!spanContext.parentSpanId; + if (parentSpanExists) { + if (isValidTraceId(spanContext.parentSpanId || '')) + setter(carrier, X_B3_PARENT_SPAN_ID, spanContext.parentSpanId); + else return; + } setter(carrier, X_B3_TRACE_ID, spanContext.traceId); setter(carrier, X_B3_SPAN_ID, spanContext.spanId); // According to the B3 spec, if the debug flag is set, // the sampled flag shouldn't be propagated as well. if (spanContext.debug) { - setter( - carrier, - X_B3_FLAGS, - '1' - ); - } + setter(carrier, X_B3_FLAGS, '1'); + } // We set the header only if there is an existing sampling decision. // Otherwise we will omit it => Absent. else if (spanContext.traceFlags !== undefined) { @@ -81,6 +82,7 @@ export class B3Propagator implements HttpTextPropagator { extract(context: Context, carrier: unknown, getter: GetterFunction): Context { const traceIdHeader = getter(carrier, X_B3_TRACE_ID); const spanIdHeader = getter(carrier, X_B3_SPAN_ID); + const parentSpanIdHeader = getter(carrier, X_B3_PARENT_SPAN_ID); const sampledHeader = getter(carrier, X_B3_SAMPLED); const flagsHeader = getter(carrier, X_B3_FLAGS); @@ -88,16 +90,27 @@ export class B3Propagator implements HttpTextPropagator { ? traceIdHeader[0] : traceIdHeader; const spanId = Array.isArray(spanIdHeader) ? spanIdHeader[0] : spanIdHeader; + const parentSpanId = Array.isArray(parentSpanIdHeader) + ? parentSpanIdHeader[0] + : parentSpanIdHeader; const options = Array.isArray(sampledHeader) ? sampledHeader[0] : sampledHeader; - const debugHeaderValue = Array.isArray(flagsHeader) ? flagsHeader[0] : flagsHeader; - const debug = isNaN(Number(debugHeaderValue)) ? false : debugHeaderValue === "1"; + const debugHeaderValue = Array.isArray(flagsHeader) + ? flagsHeader[0] + : flagsHeader; + const debug = isNaN(Number(debugHeaderValue)) + ? false + : debugHeaderValue === '1'; const traceFlagsOrDebug = Number(debug) || Number(options); - if (typeof traceIdHeaderValue !== 'string' || typeof spanId !== 'string') { + if ( + typeof traceIdHeaderValue !== 'string' || + typeof spanId !== 'string' || + (typeof parentSpanIdHeader === 'string' && !isValidSpanId(parentSpanId)) + ) { return context; } @@ -109,8 +122,9 @@ export class B3Propagator implements HttpTextPropagator { spanId, isRemote: true, // Set traceFlags as 1 if debug is 1 - traceFlags: traceFlagsOrDebug || TraceFlags.NONE , + traceFlags: traceFlagsOrDebug || TraceFlags.NONE, debug, + parentSpanId, }); } return context; diff --git a/packages/opentelemetry-core/test/context/B3Propagator.test.ts b/packages/opentelemetry-core/test/context/B3Propagator.test.ts index 3b73184174..4c72866c51 100644 --- a/packages/opentelemetry-core/test/context/B3Propagator.test.ts +++ b/packages/opentelemetry-core/test/context/B3Propagator.test.ts @@ -29,6 +29,7 @@ import { import { B3Propagator, X_B3_FLAGS, + X_B3_PARENT_SPAN_ID, X_B3_SAMPLED, X_B3_SPAN_ID, X_B3_TRACE_ID, @@ -108,7 +109,31 @@ describe('B3Propagator', () => { assert.deepStrictEqual(carrier[X_B3_SPAN_ID], '6e0c63257de34c92'); assert.deepStrictEqual(carrier[X_B3_FLAGS], '1'); assert.deepStrictEqual(carrier[X_B3_SAMPLED], undefined); - }) + }); + + it('should set b3 traceId, spanId, and parentSpanId headers', () => { + const spanContext: SpanContext = { + traceId: 'd4cda95b652f4a1592b449d5929fda1b', + parentSpanId: 'f4592dc481026a8c', + spanId: '6e0c63257de34c92', + traceFlags: TraceFlags.NONE, + debug: true, + }; + + b3Propagator.inject( + setExtractedSpanContext(Context.ROOT_CONTEXT, spanContext), + carrier, + defaultSetter + ); + assert.deepStrictEqual( + carrier[X_B3_TRACE_ID], + 'd4cda95b652f4a1592b449d5929fda1b' + ); + assert.deepStrictEqual(carrier[X_B3_PARENT_SPAN_ID], 'f4592dc481026a8c'); + assert.deepStrictEqual(carrier[X_B3_SPAN_ID], '6e0c63257de34c92'); + assert.deepStrictEqual(carrier[X_B3_FLAGS], '1'); + assert.deepStrictEqual(carrier[X_B3_SAMPLED], undefined); + }); it('should not inject empty spancontext', () => { const emptySpanContext = { @@ -137,6 +162,7 @@ describe('B3Propagator', () => { assert.deepStrictEqual(extractedSpanContext, { debug: false, spanId: 'b7ad6b7169203331', + parentSpanId: undefined, traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, traceFlags: TraceFlags.NONE, @@ -154,6 +180,7 @@ describe('B3Propagator', () => { assert.deepStrictEqual(extractedSpanContext, { debug: false, spanId: 'b7ad6b7169203331', + parentSpanId: undefined, traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, traceFlags: TraceFlags.SAMPLED, @@ -171,6 +198,7 @@ describe('B3Propagator', () => { assert.deepStrictEqual(extractedSpanContext, { debug: false, spanId: 'b7ad6b7169203331', + parentSpanId: undefined, traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, traceFlags: TraceFlags.SAMPLED, @@ -188,42 +216,65 @@ describe('B3Propagator', () => { assert.deepStrictEqual(extractedSpanContext, { debug: false, spanId: 'b7ad6b7169203331', + parentSpanId: undefined, traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, traceFlags: TraceFlags.NONE, }); }); - it("should extract context of a debug span from carrier when debug flag is valid", () => { - carrier[X_B3_TRACE_ID] = "0af7651916cd43dd8448eb211c80319c"; - carrier[X_B3_SPAN_ID] = "b7ad6b7169203331"; - carrier[X_B3_FLAGS] = "1"; + it('should extract context of a debug span from carrier when debug flag is valid', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_FLAGS] = '1'; const extractedSpanContext = getExtractedSpanContext( b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) ); assert.deepStrictEqual(extractedSpanContext, { debug: true, - spanId: "b7ad6b7169203331", - traceId: "0af7651916cd43dd8448eb211c80319c", + spanId: 'b7ad6b7169203331', + parentSpanId: undefined, + traceId: '0af7651916cd43dd8448eb211c80319c', + isRemote: true, + traceFlags: TraceFlags.SAMPLED, + }); + }); + + it('should extract context of a span from carrier when debug flag is invalidly set as 0', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_FLAGS] = '0'; + carrier[X_B3_SAMPLED] = '1'; + const extractedSpanContext = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + + assert.deepStrictEqual(extractedSpanContext, { + debug: false, + spanId: 'b7ad6b7169203331', + parentSpanId: undefined, + traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, traceFlags: TraceFlags.SAMPLED, }); }); - it("should extract context of a span from carrier when debug flag is invalidly set as 0", () => { - carrier[X_B3_TRACE_ID] = "0af7651916cd43dd8448eb211c80319c"; - carrier[X_B3_SPAN_ID] = "b7ad6b7169203331"; - carrier[X_B3_FLAGS] = "0"; - carrier[X_B3_SAMPLED] ="1" + it('should extract context of a span from carrier with a parent span id', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_PARENT_SPAN_ID] = 'f4592dc481026a8c'; + carrier[X_B3_FLAGS] = '0'; + carrier[X_B3_SAMPLED] = '1'; const extractedSpanContext = getExtractedSpanContext( b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) ); assert.deepStrictEqual(extractedSpanContext, { debug: false, - spanId: "b7ad6b7169203331", - traceId: "0af7651916cd43dd8448eb211c80319c", + spanId: 'b7ad6b7169203331', + parentSpanId: 'f4592dc481026a8c', + traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, traceFlags: TraceFlags.SAMPLED, }); @@ -240,7 +291,7 @@ describe('B3Propagator', () => { ); }); - it('should return undefined when options and spanId are undefined', () => { + it('should return undefined when spanId is undefined', () => { carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; carrier[X_B3_SPAN_ID] = undefined; assert.deepStrictEqual( @@ -251,6 +302,18 @@ describe('B3Propagator', () => { ); }); + it('should return undefined when parentSpanId is invalid', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_PARENT_SPAN_ID] = 'invalid'; + assert.deepStrictEqual( + getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ), + undefined + ); + }); + it('returns undefined if b3 header is missing', () => { assert.deepStrictEqual( getExtractedSpanContext( @@ -280,6 +343,7 @@ describe('B3Propagator', () => { assert.deepStrictEqual(extractedSpanContext, { debug: false, spanId: 'b7ad6b7169203331', + parentSpanId: undefined, traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, traceFlags: TraceFlags.SAMPLED, @@ -325,7 +389,6 @@ describe('B3Propagator', () => { Object.getOwnPropertyNames(testCases).forEach(testCase => { carrier[X_B3_TRACE_ID] = testCases[testCase]; - const extractedSpanContext = getExtractedSpanContext( b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) ); @@ -366,6 +429,7 @@ describe('B3Propagator', () => { assert.deepStrictEqual(extractedSpanContext, { debug: false, spanId: 'b7ad6b7169203331', + parentSpanId: undefined, traceId: '00000000000000008448eb211c80319c', isRemote: true, traceFlags: TraceFlags.SAMPLED, From 032430d29226606de8542b4f441c18a04fa41ca4 Mon Sep 17 00:00:00 2001 From: Steven Date: Sat, 25 Jul 2020 18:52:26 -0400 Subject: [PATCH 03/10] fix: address review comments and use context --- .../src/trace/span_context.ts | 19 -- .../src/context/propagation/B3Propagator.ts | 24 +-- .../test/context/B3Propagator.test.ts | 165 ++++++++++-------- 3 files changed, 109 insertions(+), 99 deletions(-) diff --git a/packages/opentelemetry-api/src/trace/span_context.ts b/packages/opentelemetry-api/src/trace/span_context.ts index 183fe7cc0d..82eafe4332 100644 --- a/packages/opentelemetry-api/src/trace/span_context.ts +++ b/packages/opentelemetry-api/src/trace/span_context.ts @@ -50,25 +50,6 @@ export interface SpanContext { * SAMPLED = 0x1 and NONE = 0x0; */ traceFlags: TraceFlags; - /** - * Debug flag to propagate. - * - * This flag is relevant to b3. According to the b3 spec, - * Debug is encoded as X-B3-Flags: 1. Absent or any other value can be ignored. - * Debug is a production troubleshooting aid used in tools like curl or chrome debug. - * Debug is an emphasized accept decision that implies accept (or setting traceFlags to accept), - * additionally reporting Span.debug = true for each span in the trace. Adding this - * to the span context because the b3 spec says when this flag is set properly, - * do not send the sampled header as well. - */ - debug?: boolean; - /** - * - * The ID of the parent span propagated by b3. Encoded as a 16 - * lowercase hex characters corresponding to 64 bits. - * May be present on a child span and must be absent on the root span - */ - parentSpanId?: string; /** * Tracing-system-specific info to propagate. * diff --git a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts index 8b7cfd208a..3754617298 100644 --- a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts +++ b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts @@ -28,6 +28,8 @@ export const X_B3_SPAN_ID = 'x-b3-spanid'; export const X_B3_SAMPLED = 'x-b3-sampled'; export const X_B3_PARENT_SPAN_ID = 'x-b3-parentspanid'; export const X_B3_FLAGS = 'x-b3-flags'; +export const PARENT_SPAN_ID_KEY = Context.createKey(X_B3_PARENT_SPAN_ID); +export const DEBUG_FLAG_KEY = Context.createKey(X_B3_FLAGS); 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; @@ -48,22 +50,23 @@ export class B3Propagator implements HttpTextPropagator { inject(context: Context, carrier: unknown, setter: SetterFunction) { const spanContext = getParentSpanContext(context); if (!spanContext) return; + const parentSpanId = context.getValue(PARENT_SPAN_ID_KEY); if ( isValidTraceId(spanContext.traceId) && isValidSpanId(spanContext.spanId) ) { - const parentSpanExists = !!spanContext.parentSpanId; - if (parentSpanExists) { - if (isValidTraceId(spanContext.parentSpanId || '')) - setter(carrier, X_B3_PARENT_SPAN_ID, spanContext.parentSpanId); + if (parentSpanId) { + if (isValidTraceId(parentSpanId as string)) + setter(carrier, X_B3_PARENT_SPAN_ID, parentSpanId); else return; } + const debug = context.getValue(DEBUG_FLAG_KEY); setter(carrier, X_B3_TRACE_ID, spanContext.traceId); setter(carrier, X_B3_SPAN_ID, spanContext.spanId); // According to the B3 spec, if the debug flag is set, // the sampled flag shouldn't be propagated as well. - if (spanContext.debug) { - setter(carrier, X_B3_FLAGS, '1'); + if (debug === '1') { + setter(carrier, X_B3_FLAGS, debug); } // We set the header only if there is an existing sampling decision. // Otherwise we will omit it => Absent. @@ -101,9 +104,7 @@ export class B3Propagator implements HttpTextPropagator { const debugHeaderValue = Array.isArray(flagsHeader) ? flagsHeader[0] : flagsHeader; - const debug = isNaN(Number(debugHeaderValue)) - ? false - : debugHeaderValue === '1'; + const debug = debugHeaderValue === '1'; const traceFlagsOrDebug = Number(debug) || Number(options); if ( @@ -114,6 +115,9 @@ export class B3Propagator implements HttpTextPropagator { return context; } + context = context.setValue(PARENT_SPAN_ID_KEY, parentSpanId); + context = context.setValue(DEBUG_FLAG_KEY, debug ? '1' : undefined); + const traceId = traceIdHeaderValue.padStart(32, '0'); if (isValidTraceId(traceId) && isValidSpanId(spanId)) { @@ -123,8 +127,6 @@ export class B3Propagator implements HttpTextPropagator { isRemote: true, // Set traceFlags as 1 if debug is 1 traceFlags: traceFlagsOrDebug || TraceFlags.NONE, - debug, - parentSpanId, }); } return context; diff --git a/packages/opentelemetry-core/test/context/B3Propagator.test.ts b/packages/opentelemetry-core/test/context/B3Propagator.test.ts index 4c72866c51..7d9c59be66 100644 --- a/packages/opentelemetry-core/test/context/B3Propagator.test.ts +++ b/packages/opentelemetry-core/test/context/B3Propagator.test.ts @@ -33,6 +33,8 @@ import { X_B3_SAMPLED, X_B3_SPAN_ID, X_B3_TRACE_ID, + DEBUG_FLAG_KEY, + PARENT_SPAN_ID_KEY, } from '../../src/context/propagation/B3Propagator'; import { TraceState } from '../../src/trace/TraceState'; @@ -64,6 +66,7 @@ describe('B3Propagator', () => { assert.deepStrictEqual(carrier[X_B3_SPAN_ID], '6e0c63257de34c92'); assert.deepStrictEqual(carrier[X_B3_SAMPLED], '1'); assert.deepStrictEqual(carrier[X_B3_FLAGS], undefined); + assert.deepStrictEqual(carrier[X_B3_PARENT_SPAN_ID], undefined); }); it('should set b3 traceId and spanId headers - ignore tracestate', () => { @@ -87,6 +90,7 @@ describe('B3Propagator', () => { assert.deepStrictEqual(carrier[X_B3_SPAN_ID], '6e0c63257de34c92'); assert.deepStrictEqual(carrier[X_B3_SAMPLED], '0'); assert.deepStrictEqual(carrier[X_B3_FLAGS], undefined); + assert.deepStrictEqual(carrier[X_B3_PARENT_SPAN_ID], undefined); }); it('should set set b3 traceId, spanId, and flags headers', () => { @@ -94,11 +98,14 @@ describe('B3Propagator', () => { traceId: 'd4cda95b652f4a1592b449d5929fda1b', spanId: '6e0c63257de34c92', traceFlags: TraceFlags.NONE, - debug: true, }; + const contextWithDebug = Context.ROOT_CONTEXT.setValue( + DEBUG_FLAG_KEY, + '1' + ); b3Propagator.inject( - setExtractedSpanContext(Context.ROOT_CONTEXT, spanContext), + setExtractedSpanContext(contextWithDebug, spanContext), carrier, defaultSetter ); @@ -109,19 +116,22 @@ describe('B3Propagator', () => { assert.deepStrictEqual(carrier[X_B3_SPAN_ID], '6e0c63257de34c92'); assert.deepStrictEqual(carrier[X_B3_FLAGS], '1'); assert.deepStrictEqual(carrier[X_B3_SAMPLED], undefined); + assert.deepStrictEqual(carrier[X_B3_PARENT_SPAN_ID], undefined); }); it('should set b3 traceId, spanId, and parentSpanId headers', () => { const spanContext: SpanContext = { traceId: 'd4cda95b652f4a1592b449d5929fda1b', - parentSpanId: 'f4592dc481026a8c', spanId: '6e0c63257de34c92', traceFlags: TraceFlags.NONE, - debug: true, }; + const contextWithParentSpanId = Context.ROOT_CONTEXT.setValue( + PARENT_SPAN_ID_KEY, + 'f4592dc481026a8c' + ); b3Propagator.inject( - setExtractedSpanContext(Context.ROOT_CONTEXT, spanContext), + setExtractedSpanContext(contextWithParentSpanId, spanContext), carrier, defaultSetter ); @@ -131,8 +141,7 @@ describe('B3Propagator', () => { ); assert.deepStrictEqual(carrier[X_B3_PARENT_SPAN_ID], 'f4592dc481026a8c'); assert.deepStrictEqual(carrier[X_B3_SPAN_ID], '6e0c63257de34c92'); - assert.deepStrictEqual(carrier[X_B3_FLAGS], '1'); - assert.deepStrictEqual(carrier[X_B3_SAMPLED], undefined); + assert.deepStrictEqual(carrier[X_B3_FLAGS], undefined); }); it('should not inject empty spancontext', () => { @@ -148,6 +157,8 @@ describe('B3Propagator', () => { ); assert.deepStrictEqual(carrier[X_B3_TRACE_ID], undefined); assert.deepStrictEqual(carrier[X_B3_SPAN_ID], undefined); + assert.deepStrictEqual(carrier[X_B3_FLAGS], undefined); + assert.deepStrictEqual(carrier[X_B3_PARENT_SPAN_ID], undefined); }); }); @@ -155,90 +166,104 @@ describe('B3Propagator', () => { it('should extract context of a unsampled span from carrier', () => { carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - const extractedSpanContext = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + const context = b3Propagator.extract( + Context.ROOT_CONTEXT, + carrier, + defaultGetter ); - + const extractedSpanContext = getExtractedSpanContext(context); assert.deepStrictEqual(extractedSpanContext, { - debug: false, spanId: 'b7ad6b7169203331', - parentSpanId: undefined, 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 sampled span from carrier', () => { carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; carrier[X_B3_SAMPLED] = '1'; - const extractedSpanContext = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + const context = b3Propagator.extract( + Context.ROOT_CONTEXT, + carrier, + defaultGetter ); + const extractedSpanContext = getExtractedSpanContext(context); assert.deepStrictEqual(extractedSpanContext, { - debug: false, spanId: 'b7ad6b7169203331', - parentSpanId: undefined, traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, traceFlags: TraceFlags.SAMPLED, }); + assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); it('should extract context of a sampled span from carrier when sampled is mentioned as boolean true flag', () => { carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; carrier[X_B3_SAMPLED] = true; - const extractedSpanContext = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + const context = b3Propagator.extract( + Context.ROOT_CONTEXT, + carrier, + defaultGetter ); + const extractedSpanContext = getExtractedSpanContext(context); assert.deepStrictEqual(extractedSpanContext, { - debug: false, spanId: 'b7ad6b7169203331', - parentSpanId: undefined, traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, traceFlags: TraceFlags.SAMPLED, }); + assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); it('should extract context of a sampled span from carrier when sampled is mentioned as boolean false flag', () => { carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; carrier[X_B3_SAMPLED] = false; - const extractedSpanContext = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + const context = b3Propagator.extract( + Context.ROOT_CONTEXT, + carrier, + defaultGetter ); + const extractedSpanContext = getExtractedSpanContext(context); assert.deepStrictEqual(extractedSpanContext, { - debug: false, spanId: 'b7ad6b7169203331', - parentSpanId: undefined, 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 debug span from carrier when debug flag is valid', () => { carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; carrier[X_B3_FLAGS] = '1'; - const extractedSpanContext = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + const context = b3Propagator.extract( + Context.ROOT_CONTEXT, + carrier, + defaultGetter ); + const extractedSpanContext = getExtractedSpanContext(context); assert.deepStrictEqual(extractedSpanContext, { - debug: true, spanId: 'b7ad6b7169203331', - parentSpanId: undefined, traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, traceFlags: TraceFlags.SAMPLED, }); + assert.strictEqual(context.getValue(DEBUG_FLAG_KEY), '1'); + 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 0', () => { @@ -246,18 +271,21 @@ describe('B3Propagator', () => { carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; carrier[X_B3_FLAGS] = '0'; carrier[X_B3_SAMPLED] = '1'; - const extractedSpanContext = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + const context = b3Propagator.extract( + Context.ROOT_CONTEXT, + carrier, + defaultGetter ); + const extractedSpanContext = getExtractedSpanContext(context); assert.deepStrictEqual(extractedSpanContext, { - debug: false, spanId: 'b7ad6b7169203331', - parentSpanId: undefined, traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, traceFlags: TraceFlags.SAMPLED, }); + 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', () => { @@ -266,88 +294,84 @@ describe('B3Propagator', () => { carrier[X_B3_PARENT_SPAN_ID] = 'f4592dc481026a8c'; carrier[X_B3_FLAGS] = '0'; carrier[X_B3_SAMPLED] = '1'; - const extractedSpanContext = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + const context = b3Propagator.extract( + Context.ROOT_CONTEXT, + carrier, + defaultGetter ); + const extractedSpanContext = getExtractedSpanContext(context); assert.deepStrictEqual(extractedSpanContext, { - debug: false, spanId: 'b7ad6b7169203331', - parentSpanId: 'f4592dc481026a8c', traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, traceFlags: TraceFlags.SAMPLED, }); + assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); + 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; - assert.deepStrictEqual( - getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ), - undefined + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) ); + assert.deepStrictEqual(context, undefined); }); it('should return undefined when spanId is undefined', () => { carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; carrier[X_B3_SPAN_ID] = undefined; - assert.deepStrictEqual( - getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ), - undefined + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) ); + assert.deepStrictEqual(context, undefined); }); it('should return undefined when parentSpanId is invalid', () => { carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; carrier[X_B3_PARENT_SPAN_ID] = 'invalid'; - assert.deepStrictEqual( - getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ), - undefined + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) ); + assert.deepStrictEqual(context, undefined); }); it('returns undefined if b3 header is missing', () => { - assert.deepStrictEqual( - getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ), - undefined + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) ); + assert.deepStrictEqual(context, undefined); }); it('returns undefined if b3 header is invalid', () => { carrier[X_B3_TRACE_ID] = 'invalid!'; - assert.deepStrictEqual( - getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ), - undefined + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) ); + assert.deepStrictEqual(context, undefined); }); it('extracts b3 from list of header', () => { carrier[X_B3_TRACE_ID] = ['0af7651916cd43dd8448eb211c80319c']; carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; carrier[X_B3_SAMPLED] = '01'; - const extractedSpanContext = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + const context = b3Propagator.extract( + Context.ROOT_CONTEXT, + carrier, + defaultGetter ); + const extractedSpanContext = getExtractedSpanContext(context); assert.deepStrictEqual(extractedSpanContext, { - debug: false, spanId: 'b7ad6b7169203331', - parentSpanId: undefined, traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, traceFlags: TraceFlags.SAMPLED, }); + assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); it('should gracefully handle an invalid b3 header', () => { @@ -422,18 +446,21 @@ describe('B3Propagator', () => { carrier[X_B3_TRACE_ID] = '8448eb211c80319c'; carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; carrier[X_B3_SAMPLED] = '1'; - const extractedSpanContext = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + const context = b3Propagator.extract( + Context.ROOT_CONTEXT, + carrier, + defaultGetter ); + const extractedSpanContext = getExtractedSpanContext(context); assert.deepStrictEqual(extractedSpanContext, { - debug: false, spanId: 'b7ad6b7169203331', - parentSpanId: undefined, traceId: '00000000000000008448eb211c80319c', isRemote: true, traceFlags: TraceFlags.SAMPLED, }); + assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); }); }); From 38fa5d396f992a5e7e6cb20ab0aeca8967c5bed0 Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 27 Jul 2020 14:35:32 -0400 Subject: [PATCH 04/10] style: rename context keys and move comment --- .../src/context/propagation/B3Propagator.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts index 3754617298..0303669735 100644 --- a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts +++ b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts @@ -28,8 +28,12 @@ export const X_B3_SPAN_ID = 'x-b3-spanid'; export const X_B3_SAMPLED = 'x-b3-sampled'; export const X_B3_PARENT_SPAN_ID = 'x-b3-parentspanid'; export const X_B3_FLAGS = 'x-b3-flags'; -export const PARENT_SPAN_ID_KEY = Context.createKey(X_B3_PARENT_SPAN_ID); -export const DEBUG_FLAG_KEY = Context.createKey(X_B3_FLAGS); +export const PARENT_SPAN_ID_KEY = Context.createKey( + 'OpenTelemetry Context Key B3 Parent Span Id' +); +export const DEBUG_FLAG_KEY = Context.createKey( + 'OpenTelemetry Context Key B3 Debug Flag' +); 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; @@ -67,10 +71,9 @@ export class B3Propagator implements HttpTextPropagator { // the sampled flag shouldn't be propagated as well. if (debug === '1') { setter(carrier, X_B3_FLAGS, debug); - } - // We set the header only if there is an existing sampling decision. - // Otherwise we will omit it => Absent. - else if (spanContext.traceFlags !== undefined) { + } else if (spanContext.traceFlags !== undefined) { + // We set the header only if there is an existing sampling decision. + // Otherwise we will omit it => Absent. setter( carrier, X_B3_SAMPLED, From e035583e3b4097587b34d1be6393b5dc057a4330 Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 27 Jul 2020 15:16:50 -0400 Subject: [PATCH 05/10] style: fix if case brackets and add header parser --- .../src/context/propagation/B3Propagator.ts | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts index 0303669735..d801082aca 100644 --- a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts +++ b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts @@ -46,6 +46,10 @@ function isValidSpanId(spanId: string): boolean { return VALID_SPANID_REGEX.test(spanId) && !INVALID_ID_REGEX.test(spanId); } +function parseHeader(header: unknown) { + return Array.isArray(header) ? header[0] : header; +} + /** * Propagator for the B3 HTTP header format. * Based on: https://github.com/openzipkin/b3-propagation @@ -60,9 +64,11 @@ export class B3Propagator implements HttpTextPropagator { isValidSpanId(spanContext.spanId) ) { if (parentSpanId) { - if (isValidTraceId(parentSpanId as string)) + if (isValidTraceId(parentSpanId as string)) { setter(carrier, X_B3_PARENT_SPAN_ID, parentSpanId); - else return; + } else { + return; + } } const debug = context.getValue(DEBUG_FLAG_KEY); setter(carrier, X_B3_TRACE_ID, spanContext.traceId); @@ -92,21 +98,11 @@ export class B3Propagator implements HttpTextPropagator { const sampledHeader = getter(carrier, X_B3_SAMPLED); const flagsHeader = getter(carrier, X_B3_FLAGS); - const traceIdHeaderValue = Array.isArray(traceIdHeader) - ? traceIdHeader[0] - : traceIdHeader; - const spanId = Array.isArray(spanIdHeader) ? spanIdHeader[0] : spanIdHeader; - const parentSpanId = Array.isArray(parentSpanIdHeader) - ? parentSpanIdHeader[0] - : parentSpanIdHeader; - - const options = Array.isArray(sampledHeader) - ? sampledHeader[0] - : sampledHeader; - - const debugHeaderValue = Array.isArray(flagsHeader) - ? flagsHeader[0] - : flagsHeader; + const traceIdHeaderValue = parseHeader(traceIdHeader); + const spanId = parseHeader(spanIdHeader); + const parentSpanId = parseHeader(parentSpanIdHeader); + const options = parseHeader(sampledHeader); + const debugHeaderValue = parseHeader(flagsHeader); const debug = debugHeaderValue === '1'; const traceFlagsOrDebug = Number(debug) || Number(options); From bbc08dcc2a9473811c74c840e8caf299c4eb752c Mon Sep 17 00:00:00 2001 From: Steven Date: Thu, 30 Jul 2020 19:25:37 -0400 Subject: [PATCH 06/10] fix: add more tests and fix parentid check --- .../src/context/propagation/B3Propagator.ts | 10 +- .../test/context/B3Propagator.test.ts | 100 +++++++++++++++++- 2 files changed, 105 insertions(+), 5 deletions(-) diff --git a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts index d801082aca..aba6290d66 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 7d9c59be66..733c448df0 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, From 849f91559790c73a255f6f6cf039d1e4ebc0faf2 Mon Sep 17 00:00:00 2001 From: Steven Date: Fri, 31 Jul 2020 14:50:11 -0400 Subject: [PATCH 07/10] style: refactor b3 extract and tests --- .../src/trace/span_context.ts | 2 +- .../src/context/propagation/B3Propagator.ts | 125 +++-- .../src/trace/sampler/ParentOrElseSampler.ts | 2 +- .../src/trace/sampler/ProbabilitySampler.ts | 2 +- .../test/context/B3Propagator.test.ts | 513 ++++++++++-------- 5 files changed, 363 insertions(+), 281 deletions(-) diff --git a/packages/opentelemetry-api/src/trace/span_context.ts b/packages/opentelemetry-api/src/trace/span_context.ts index 82eafe4332..d75f2efbb1 100644 --- a/packages/opentelemetry-api/src/trace/span_context.ts +++ b/packages/opentelemetry-api/src/trace/span_context.ts @@ -49,7 +49,7 @@ export interface SpanContext { * * SAMPLED = 0x1 and NONE = 0x0; */ - traceFlags: TraceFlags; + traceFlags?: TraceFlags; /** * Tracing-system-specific info to propagate. * diff --git a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts index aba6290d66..2b713d0d38 100644 --- a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts +++ b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts @@ -37,7 +37,8 @@ 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']; +const VALID_SAMPLED_VALUES = [true, 'true', '1', 1]; +const VALID_UNSAMPLED_VALUES = [0, '0', 'false', false]; function isValidTraceId(traceId: string): boolean { return VALID_TRACEID_REGEX.test(traceId) && !INVALID_ID_REGEX.test(traceId); @@ -47,6 +48,18 @@ function isValidSpanId(spanId: string): boolean { return VALID_SPANID_REGEX.test(spanId) && !INVALID_ID_REGEX.test(spanId); } +function isValidParentSpanID(spanId: string | undefined): boolean { + return spanId === undefined || isValidSpanId(spanId); +} + +function isValidSampledValue(sampled: number | undefined): boolean { + return ( + sampled === undefined || + VALID_SAMPLED_VALUES.includes(sampled) || + VALID_UNSAMPLED_VALUES.includes(sampled) + ); +} + function parseHeader(header: unknown) { return Array.isArray(header) ? header[0] : header; } @@ -56,24 +69,78 @@ function parseHeader(header: unknown) { * Based on: https://github.com/openzipkin/b3-propagation */ export class B3Propagator implements HttpTextPropagator { + _getHeaderValue(carrier: unknown, getter: GetterFunction, key: string) { + const header = getter(carrier, key); + return parseHeader(header); + } + + _getTraceId(carrier: unknown, getter: GetterFunction): string { + const traceId = this._getHeaderValue(carrier, getter, X_B3_TRACE_ID); + if (typeof traceId === 'string') { + return traceId.padStart(32, '0'); + } + return ''; + } + + _getSpanId(carrier: unknown, getter: GetterFunction): string { + const spanId = this._getHeaderValue(carrier, getter, X_B3_SPAN_ID); + if (typeof spanId === 'string') { + return spanId; + } + return ''; + } + + _getParentSpanId( + carrier: unknown, + getter: GetterFunction + ): string | undefined { + const spanId = this._getHeaderValue(carrier, getter, X_B3_PARENT_SPAN_ID); + if (typeof spanId === 'string') { + return spanId; + } + return; + } + + _getDebug(carrier: unknown, getter: GetterFunction): string | undefined { + const debug = this._getHeaderValue(carrier, getter, X_B3_FLAGS); + return debug === '1' ? '1' : undefined; + } + + _getTraceFlags(carrier: unknown, getter: GetterFunction): number | undefined { + const traceFlags = this._getHeaderValue(carrier, getter, X_B3_SAMPLED); + const debug = this._getDebug(carrier, getter); + if (debug === '1') { + return TraceFlags.SAMPLED; + } else if (traceFlags !== undefined) { + if (VALID_SAMPLED_VALUES.includes(traceFlags)) { + return TraceFlags.SAMPLED; + } else if (VALID_UNSAMPLED_VALUES.includes(traceFlags)) { + return TraceFlags.NONE; + } else { + // Invalid traceflag + return 2; + } + } + return; + } + inject(context: Context, carrier: unknown, setter: SetterFunction) { const spanContext = getParentSpanContext(context); if (!spanContext) return; - const parentSpanId = context.getValue(PARENT_SPAN_ID_KEY); + const parentSpanId = context.getValue(PARENT_SPAN_ID_KEY) as + | undefined + | string; if ( isValidTraceId(spanContext.traceId) && - isValidSpanId(spanContext.spanId) + isValidSpanId(spanContext.spanId) && + isValidParentSpanID(parentSpanId) ) { - if (parentSpanId) { - if (isValidSpanId(parentSpanId as string)) { - setter(carrier, X_B3_PARENT_SPAN_ID, parentSpanId); - } else { - return; - } - } const debug = context.getValue(DEBUG_FLAG_KEY); setter(carrier, X_B3_TRACE_ID, spanContext.traceId); setter(carrier, X_B3_SPAN_ID, spanContext.spanId); + if (parentSpanId) { + setter(carrier, X_B3_PARENT_SPAN_ID, parentSpanId); + } // According to the B3 spec, if the debug flag is set, // the sampled flag shouldn't be propagated as well. if (debug === '1') { @@ -93,36 +160,20 @@ export class B3Propagator implements HttpTextPropagator { } extract(context: Context, carrier: unknown, getter: GetterFunction): Context { - const traceIdHeader = getter(carrier, X_B3_TRACE_ID); - const spanIdHeader = getter(carrier, X_B3_SPAN_ID); - const parentSpanIdHeader = getter(carrier, X_B3_PARENT_SPAN_ID); - const sampledHeader = getter(carrier, X_B3_SAMPLED); - const flagsHeader = getter(carrier, X_B3_FLAGS); - - const traceIdHeaderValue = parseHeader(traceIdHeader); - const spanId = parseHeader(spanIdHeader); - const parentSpanId = parseHeader(parentSpanIdHeader); - const options = parseHeader(sampledHeader); - const debugHeaderValue = parseHeader(flagsHeader); - const debug = debugHeaderValue === '1'; - const isSampled = VALID_SAMPLED_VALUES.includes(options); - const traceFlags = - debug || isSampled ? TraceFlags.SAMPLED : TraceFlags.NONE; + const traceId = this._getTraceId(carrier, getter); + const spanId = this._getSpanId(carrier, getter); + const parentSpanId = this._getParentSpanId(carrier, getter); + const traceFlags = this._getTraceFlags(carrier, getter); + const debug = this._getDebug(carrier, getter); if ( - typeof traceIdHeaderValue !== 'string' || - typeof spanId !== 'string' || - (typeof parentSpanIdHeader === 'string' && !isValidSpanId(parentSpanId)) + isValidTraceId(traceId) && + isValidSpanId(spanId) && + isValidParentSpanID(parentSpanId) && + isValidSampledValue(traceFlags) ) { - return context; - } - - context = context.setValue(PARENT_SPAN_ID_KEY, parentSpanId); - context = context.setValue(DEBUG_FLAG_KEY, debug ? '1' : undefined); - - const traceId = traceIdHeaderValue.padStart(32, '0'); - - if (isValidTraceId(traceId) && isValidSpanId(spanId)) { + context = context.setValue(PARENT_SPAN_ID_KEY, parentSpanId); + context = context.setValue(DEBUG_FLAG_KEY, debug); return setExtractedSpanContext(context, { traceId, spanId, diff --git a/packages/opentelemetry-core/src/trace/sampler/ParentOrElseSampler.ts b/packages/opentelemetry-core/src/trace/sampler/ParentOrElseSampler.ts index 71495a3c70..c3ff5d752f 100644 --- a/packages/opentelemetry-core/src/trace/sampler/ParentOrElseSampler.ts +++ b/packages/opentelemetry-core/src/trace/sampler/ParentOrElseSampler.ts @@ -41,7 +41,7 @@ export class ParentOrElseSampler implements Sampler { links: Link[] ): SamplingResult { // Respect the parent sampling decision if there is one - if (parentContext) { + if (parentContext && parentContext.traceFlags !== undefined) { return { decision: (TraceFlags.SAMPLED & parentContext.traceFlags) === TraceFlags.SAMPLED diff --git a/packages/opentelemetry-core/src/trace/sampler/ProbabilitySampler.ts b/packages/opentelemetry-core/src/trace/sampler/ProbabilitySampler.ts index bec3df6f91..83b334834d 100644 --- a/packages/opentelemetry-core/src/trace/sampler/ProbabilitySampler.ts +++ b/packages/opentelemetry-core/src/trace/sampler/ProbabilitySampler.ts @@ -31,7 +31,7 @@ export class ProbabilitySampler implements Sampler { shouldSample(parentContext?: SpanContext): SamplingResult { // Respect the parent sampling decision if there is one. // TODO(#1284): add an option to ignore parent regarding to spec. - if (parentContext) { + if (parentContext && parentContext.traceFlags !== undefined) { return { decision: (TraceFlags.SAMPLED & parentContext.traceFlags) === TraceFlags.SAMPLED diff --git a/packages/opentelemetry-core/test/context/B3Propagator.test.ts b/packages/opentelemetry-core/test/context/B3Propagator.test.ts index 733c448df0..1a00e98bf4 100644 --- a/packages/opentelemetry-core/test/context/B3Propagator.test.ts +++ b/packages/opentelemetry-core/test/context/B3Propagator.test.ts @@ -93,7 +93,7 @@ describe('B3Propagator', () => { assert.deepStrictEqual(carrier[X_B3_PARENT_SPAN_ID], undefined); }); - it('should set set b3 traceId, spanId, and flags headers', () => { + it('should set flags headers', () => { const spanContext: SpanContext = { traceId: 'd4cda95b652f4a1592b449d5929fda1b', spanId: '6e0c63257de34c92', @@ -119,7 +119,7 @@ describe('B3Propagator', () => { assert.deepStrictEqual(carrier[X_B3_PARENT_SPAN_ID], undefined); }); - it('should set b3 traceId, spanId, and parentSpanId headers', () => { + it('should set parentSpanId headers', () => { const spanContext: SpanContext = { traceId: 'd4cda95b652f4a1592b449d5929fda1b', spanId: '6e0c63257de34c92', @@ -163,7 +163,7 @@ describe('B3Propagator', () => { }); describe('.extract()', () => { - it('should extract context of a unsampled span from carrier', () => { + it('should extract context of a deferred span from carrier', () => { carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; const context = b3Propagator.extract( @@ -176,280 +176,311 @@ describe('B3Propagator', () => { spanId: 'b7ad6b7169203331', traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, - traceFlags: TraceFlags.NONE, + traceFlags: undefined, }); assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); - it('should extract context of a sampled span from carrier', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_SAMPLED] = '1'; - 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, + describe('when sampled flag is set', () => { + it('should extract context of a sampled span from carrier', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_SAMPLED] = '1'; + 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), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); - assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); - assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); - }); - - it('should extract context of a sampled span from carrier when sampled is mentioned as boolean true flag', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_SAMPLED] = true; - 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, + it('should extract context of a sampled span from carrier when sampled is mentioned as boolean true flag', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_SAMPLED] = true; + 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), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); - assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); - assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); - }); - it('should extract context of a sampled span from carrier when sampled is mentioned as boolean false flag', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_SAMPLED] = false; - 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, + it('should extract context of a sampled span from carrier when sampled is mentioned as boolean false flag', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_SAMPLED] = false; + 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); }); - assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); - assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); - it('should extract context of a debug span from carrier when debug flag is valid', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_FLAGS] = '1'; - 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, + describe('when debug flag is valid', () => { + it('should extract context of a debug span from carrier when debug flag is valid', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_FLAGS] = '1'; + 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.strictEqual(context.getValue(DEBUG_FLAG_KEY), '1'); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); - assert.strictEqual(context.getValue(DEBUG_FLAG_KEY), '1'); - 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 0', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_FLAGS] = '0'; - carrier[X_B3_SAMPLED] = '1'; - 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, + describe('when debug flag is invalid', () => { + it('should extract context of a span from carrier when debug flag is invalidly set as 0', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_FLAGS] = '0'; + carrier[X_B3_SAMPLED] = '1'; + 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), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); - 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, + 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); }); - 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, + 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); }); - 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, + 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); }); - 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'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_PARENT_SPAN_ID] = 'f4592dc481026a8c'; - carrier[X_B3_FLAGS] = '0'; - carrier[X_B3_SAMPLED] = '1'; - const context = b3Propagator.extract( - Context.ROOT_CONTEXT, - carrier, - defaultGetter - ); - const extractedSpanContext = getExtractedSpanContext(context); + describe('when parent span id is set', () => { + it('should extract context of a span from carrier with a parent span id', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_PARENT_SPAN_ID] = 'f4592dc481026a8c'; + carrier[X_B3_FLAGS] = '0'; + carrier[X_B3_SAMPLED] = '1'; + 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), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), 'f4592dc481026a8c'); + }); - assert.deepStrictEqual(extractedSpanContext, { - spanId: 'b7ad6b7169203331', - traceId: '0af7651916cd43dd8448eb211c80319c', - isRemote: true, - traceFlags: TraceFlags.SAMPLED, + 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'); }); - assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); - 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); + describe('when headers are invalid', () => { + it('should return undefined when traceId is undefined', () => { + carrier[X_B3_TRACE_ID] = undefined; + carrier[X_B3_SPAN_ID] = undefined; + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + assert.deepStrictEqual(context, undefined); + }); - assert.deepStrictEqual(extractedSpanContext, { - spanId: 'b7ad6b7169203331', - traceId: '0af7651916cd43dd8448eb211c80319c', - isRemote: true, - traceFlags: TraceFlags.SAMPLED, + it('should return undefined when spanId is undefined', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = undefined; + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + assert.deepStrictEqual(context, undefined); }); - 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; - const context = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ); - assert.deepStrictEqual(context, undefined); - }); + it('should return undefined when parentSpanId is invalid', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_PARENT_SPAN_ID] = 'invalid'; + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + assert.deepStrictEqual(context, undefined); + }); - it('should return undefined when spanId is undefined', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = undefined; - const context = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ); - 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('should return undefined when parentSpanId is invalid', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_PARENT_SPAN_ID] = 'invalid'; - const context = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ); - 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('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('should return undefined when sample is invalid', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_SAMPLED] = '2'; + 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) - ); - assert.deepStrictEqual(context, undefined); - }); + it('returns undefined if b3 header is missing', () => { + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + assert.deepStrictEqual(context, undefined); + }); - it('returns undefined if b3 header is invalid', () => { - carrier[X_B3_TRACE_ID] = 'invalid!'; - const context = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ); - assert.deepStrictEqual(context, undefined); + it('returns undefined if b3 header is invalid', () => { + carrier[X_B3_TRACE_ID] = 'invalid!'; + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + assert.deepStrictEqual(context, undefined); + }); }); it('extracts b3 from list of header', () => { From 4209039a70c0473b72ba8b2fbca2810eae37a1a5 Mon Sep 17 00:00:00 2001 From: Steven Date: Fri, 31 Jul 2020 16:49:05 -0400 Subject: [PATCH 08/10] fix: remove undefined traceFlags in spanContext --- .../src/trace/span_context.ts | 2 +- .../src/context/propagation/B3Propagator.ts | 126 +++++++++--------- .../src/trace/sampler/ParentOrElseSampler.ts | 2 +- .../src/trace/sampler/ProbabilitySampler.ts | 2 +- .../test/context/B3Propagator.test.ts | 3 +- 5 files changed, 68 insertions(+), 67 deletions(-) diff --git a/packages/opentelemetry-api/src/trace/span_context.ts b/packages/opentelemetry-api/src/trace/span_context.ts index d75f2efbb1..82eafe4332 100644 --- a/packages/opentelemetry-api/src/trace/span_context.ts +++ b/packages/opentelemetry-api/src/trace/span_context.ts @@ -49,7 +49,7 @@ export interface SpanContext { * * SAMPLED = 0x1 and NONE = 0x0; */ - traceFlags?: TraceFlags; + traceFlags: TraceFlags; /** * Tracing-system-specific info to propagate. * diff --git a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts index 2b713d0d38..fb577f9f90 100644 --- a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts +++ b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts @@ -37,8 +37,8 @@ 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', 1]; -const VALID_UNSAMPLED_VALUES = [0, '0', 'false', false]; +const VALID_SAMPLED_VALUES = new Set([true, 'true', 'True', '1', 1]); +const VALID_UNSAMPLED_VALUES = new Set([false, 'false', 'False', '0', 0]); function isValidTraceId(traceId: string): boolean { return VALID_TRACEID_REGEX.test(traceId) && !INVALID_ID_REGEX.test(traceId); @@ -52,78 +52,78 @@ function isValidParentSpanID(spanId: string | undefined): boolean { return spanId === undefined || isValidSpanId(spanId); } -function isValidSampledValue(sampled: number | undefined): boolean { - return ( - sampled === undefined || - VALID_SAMPLED_VALUES.includes(sampled) || - VALID_UNSAMPLED_VALUES.includes(sampled) - ); +function isValidSampledValue(sampled: TraceFlags | undefined): boolean { + return sampled === TraceFlags.SAMPLED || sampled === TraceFlags.NONE; } function parseHeader(header: unknown) { return Array.isArray(header) ? header[0] : header; } -/** - * Propagator for the B3 HTTP header format. - * Based on: https://github.com/openzipkin/b3-propagation - */ -export class B3Propagator implements HttpTextPropagator { - _getHeaderValue(carrier: unknown, getter: GetterFunction, key: string) { - const header = getter(carrier, key); - return parseHeader(header); - } +function getHeaderValue(carrier: unknown, getter: GetterFunction, key: string) { + const header = getter(carrier, key); + return parseHeader(header); +} - _getTraceId(carrier: unknown, getter: GetterFunction): string { - const traceId = this._getHeaderValue(carrier, getter, X_B3_TRACE_ID); - if (typeof traceId === 'string') { - return traceId.padStart(32, '0'); - } - return ''; +function getTraceId(carrier: unknown, getter: GetterFunction): string { + const traceId = getHeaderValue(carrier, getter, X_B3_TRACE_ID); + if (typeof traceId === 'string') { + return traceId.padStart(32, '0'); } + return ''; +} - _getSpanId(carrier: unknown, getter: GetterFunction): string { - const spanId = this._getHeaderValue(carrier, getter, X_B3_SPAN_ID); - if (typeof spanId === 'string') { - return spanId; - } - return ''; +function getSpanId(carrier: unknown, getter: GetterFunction): string { + const spanId = getHeaderValue(carrier, getter, X_B3_SPAN_ID); + if (typeof spanId === 'string') { + return spanId; } + return ''; +} - _getParentSpanId( - carrier: unknown, - getter: GetterFunction - ): string | undefined { - const spanId = this._getHeaderValue(carrier, getter, X_B3_PARENT_SPAN_ID); - if (typeof spanId === 'string') { - return spanId; - } - return; +function getParentSpanId( + carrier: unknown, + getter: GetterFunction +): string | undefined { + const spanId = getHeaderValue(carrier, getter, X_B3_PARENT_SPAN_ID); + if (typeof spanId === 'string') { + return spanId; } + return; +} - _getDebug(carrier: unknown, getter: GetterFunction): string | undefined { - const debug = this._getHeaderValue(carrier, getter, X_B3_FLAGS); - return debug === '1' ? '1' : undefined; - } +function getDebug( + carrier: unknown, + getter: GetterFunction +): string | undefined { + const debug = getHeaderValue(carrier, getter, X_B3_FLAGS); + return debug === '1' ? '1' : undefined; +} - _getTraceFlags(carrier: unknown, getter: GetterFunction): number | undefined { - const traceFlags = this._getHeaderValue(carrier, getter, X_B3_SAMPLED); - const debug = this._getDebug(carrier, getter); - if (debug === '1') { - return TraceFlags.SAMPLED; - } else if (traceFlags !== undefined) { - if (VALID_SAMPLED_VALUES.includes(traceFlags)) { - return TraceFlags.SAMPLED; - } else if (VALID_UNSAMPLED_VALUES.includes(traceFlags)) { - return TraceFlags.NONE; - } else { - // Invalid traceflag - return 2; - } - } - return; +function getTraceFlags( + carrier: unknown, + getter: GetterFunction +): TraceFlags | undefined { + const traceFlags = getHeaderValue(carrier, getter, X_B3_SAMPLED); + const debug = getDebug(carrier, getter); + if (debug === '1' || VALID_SAMPLED_VALUES.has(traceFlags)) { + return TraceFlags.SAMPLED; + } + if (VALID_UNSAMPLED_VALUES.has(traceFlags)) { + return TraceFlags.NONE; + } + if (traceFlags === undefined) { + return TraceFlags.NONE; } + // This indicates to isValidSampledValue that this is not valid + return; +} +/** + * Propagator for the B3 HTTP header format. + * Based on: https://github.com/openzipkin/b3-propagation + */ +export class B3Propagator implements HttpTextPropagator { inject(context: Context, carrier: unknown, setter: SetterFunction) { const spanContext = getParentSpanContext(context); if (!spanContext) return; @@ -160,11 +160,11 @@ export class B3Propagator implements HttpTextPropagator { } extract(context: Context, carrier: unknown, getter: GetterFunction): Context { - const traceId = this._getTraceId(carrier, getter); - const spanId = this._getSpanId(carrier, getter); - const parentSpanId = this._getParentSpanId(carrier, getter); - const traceFlags = this._getTraceFlags(carrier, getter); - const debug = this._getDebug(carrier, getter); + const traceId = getTraceId(carrier, getter); + const spanId = getSpanId(carrier, getter); + const parentSpanId = getParentSpanId(carrier, getter); + const traceFlags = getTraceFlags(carrier, getter) as TraceFlags; + const debug = getDebug(carrier, getter); if ( isValidTraceId(traceId) && diff --git a/packages/opentelemetry-core/src/trace/sampler/ParentOrElseSampler.ts b/packages/opentelemetry-core/src/trace/sampler/ParentOrElseSampler.ts index c3ff5d752f..71495a3c70 100644 --- a/packages/opentelemetry-core/src/trace/sampler/ParentOrElseSampler.ts +++ b/packages/opentelemetry-core/src/trace/sampler/ParentOrElseSampler.ts @@ -41,7 +41,7 @@ export class ParentOrElseSampler implements Sampler { links: Link[] ): SamplingResult { // Respect the parent sampling decision if there is one - if (parentContext && parentContext.traceFlags !== undefined) { + if (parentContext) { return { decision: (TraceFlags.SAMPLED & parentContext.traceFlags) === TraceFlags.SAMPLED diff --git a/packages/opentelemetry-core/src/trace/sampler/ProbabilitySampler.ts b/packages/opentelemetry-core/src/trace/sampler/ProbabilitySampler.ts index 83b334834d..bec3df6f91 100644 --- a/packages/opentelemetry-core/src/trace/sampler/ProbabilitySampler.ts +++ b/packages/opentelemetry-core/src/trace/sampler/ProbabilitySampler.ts @@ -31,7 +31,7 @@ export class ProbabilitySampler implements Sampler { shouldSample(parentContext?: SpanContext): SamplingResult { // Respect the parent sampling decision if there is one. // TODO(#1284): add an option to ignore parent regarding to spec. - if (parentContext && parentContext.traceFlags !== undefined) { + if (parentContext) { return { decision: (TraceFlags.SAMPLED & parentContext.traceFlags) === TraceFlags.SAMPLED diff --git a/packages/opentelemetry-core/test/context/B3Propagator.test.ts b/packages/opentelemetry-core/test/context/B3Propagator.test.ts index 1a00e98bf4..d79dd0422d 100644 --- a/packages/opentelemetry-core/test/context/B3Propagator.test.ts +++ b/packages/opentelemetry-core/test/context/B3Propagator.test.ts @@ -142,6 +142,7 @@ describe('B3Propagator', () => { assert.deepStrictEqual(carrier[X_B3_PARENT_SPAN_ID], 'f4592dc481026a8c'); assert.deepStrictEqual(carrier[X_B3_SPAN_ID], '6e0c63257de34c92'); assert.deepStrictEqual(carrier[X_B3_FLAGS], undefined); + assert.deepStrictEqual(carrier[X_B3_SAMPLED], '0'); }); it('should not inject empty spancontext', () => { @@ -176,7 +177,7 @@ describe('B3Propagator', () => { spanId: 'b7ad6b7169203331', traceId: '0af7651916cd43dd8448eb211c80319c', isRemote: true, - traceFlags: undefined, + traceFlags: TraceFlags.NONE, }); assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); From 55304c7a965a2f0777cff4ade08912859377286f Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 3 Aug 2020 14:17:19 -0400 Subject: [PATCH 09/10] style: rename and add describes to some b3 tests --- .../test/context/B3Propagator.test.ts | 486 +++++++++--------- 1 file changed, 256 insertions(+), 230 deletions(-) diff --git a/packages/opentelemetry-core/test/context/B3Propagator.test.ts b/packages/opentelemetry-core/test/context/B3Propagator.test.ts index d79dd0422d..567fcc6778 100644 --- a/packages/opentelemetry-core/test/context/B3Propagator.test.ts +++ b/packages/opentelemetry-core/test/context/B3Propagator.test.ts @@ -183,186 +183,202 @@ describe('B3Propagator', () => { assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); - describe('when sampled flag is set', () => { - it('should extract context of a sampled span from carrier', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_SAMPLED] = '1'; - 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, + describe('when sampled flag is valid', () => { + describe('AND sampled flag is 1', () => { + it('should extract context of a sampled span from carrier', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_SAMPLED] = '1'; + 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), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); - assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); - assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); - it('should extract context of a sampled span from carrier when sampled is mentioned as boolean true flag', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_SAMPLED] = true; - 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, + describe('AND sampled flag is true', () => { + it('should extract context of a sampled span from carrier', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_SAMPLED] = true; + 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), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); - assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); - assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); - it('should extract context of a sampled span from carrier when sampled is mentioned as boolean false flag', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_SAMPLED] = false; - 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, + describe('AND sampled flag is false', () => { + it('should extract context of a sampled span from carrier', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_SAMPLED] = false; + 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); }); - assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); - assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); }); describe('when debug flag is valid', () => { - it('should extract context of a debug span from carrier when debug flag is valid', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_FLAGS] = '1'; - 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, + describe('AND debug flag is 1', () => { + it('should extract context of a debug span from carrier', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_FLAGS] = '1'; + 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.strictEqual(context.getValue(DEBUG_FLAG_KEY), '1'); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); - assert.strictEqual(context.getValue(DEBUG_FLAG_KEY), '1'); - assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); }); describe('when debug flag is invalid', () => { - it('should extract context of a span from carrier when debug flag is invalidly set as 0', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_FLAGS] = '0'; - carrier[X_B3_SAMPLED] = '1'; - 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, + describe('AND debug flag is 0', () => { + it('should extract context of a span from carrier', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_FLAGS] = '0'; + carrier[X_B3_SAMPLED] = '1'; + 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), undefined); + assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); - 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, + describe('AND debug flag is false', () => { + it('should extract context of a span from carrier', () => { + 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); }); - 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, + describe('AND debug flag is true', () => { + it('should extract context of a span from carrier', () => { + 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); }); - 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, + describe('AND debug flag is 2', () => { + it('should extract context of a span from carrier', () => { + 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); }); - assert.equal(context.getValue(DEBUG_FLAG_KEY), undefined); - assert.equal(context.getValue(PARENT_SPAN_ID_KEY), undefined); }); }); - describe('when parent span id is set', () => { - it('should extract context of a span from carrier with a parent span id', () => { + describe('when parent span id is valid', () => { + it('should extract context of a span from carrier', () => { carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; carrier[X_B3_PARENT_SPAN_ID] = 'f4592dc481026a8c'; @@ -385,102 +401,112 @@ 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, + describe('AND debug is 1', () => { + it('should extract context of a span from carrier', () => { + 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' + ); }); - assert.equal(context.getValue(DEBUG_FLAG_KEY), '1'); - assert.equal(context.getValue(PARENT_SPAN_ID_KEY), 'f4592dc481026a8c'); }); }); describe('when headers are invalid', () => { - it('should return undefined when traceId is undefined', () => { - carrier[X_B3_TRACE_ID] = undefined; - carrier[X_B3_SPAN_ID] = undefined; - const context = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ); - assert.deepStrictEqual(context, undefined); - }); - - it('should return undefined when spanId is undefined', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = undefined; - const context = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ); - assert.deepStrictEqual(context, undefined); + describe('AND traceId is undefined', () => { + it('should return undefined', () => { + carrier[X_B3_TRACE_ID] = undefined; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + assert.deepStrictEqual(context, undefined); + }); }); - it('should return undefined when parentSpanId is invalid', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_PARENT_SPAN_ID] = 'invalid'; - const context = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ); - assert.deepStrictEqual(context, undefined); + describe('AND spanId is undefined', () => { + it('should return undefined', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = undefined; + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + 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); + describe('AND parentSpanId is invalid', () => { + it('should return undefined', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_PARENT_SPAN_ID] = 'invalid'; + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + 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); + describe('AND parentSpanId is a trace id', () => { + it('should return undefined', () => { + 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('should return undefined when sample is invalid', () => { - carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; - carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; - carrier[X_B3_SAMPLED] = '2'; - const context = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ); - assert.deepStrictEqual(context, undefined); + describe('AND sample is 2', () => { + it('should return undefined', () => { + carrier[X_B3_TRACE_ID] = '0af7651916cd43dd8448eb211c80319c'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + carrier[X_B3_SAMPLED] = '2'; + 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) - ); - assert.deepStrictEqual(context, undefined); + describe('AND b3 header is missing', () => { + it('should return undefined', () => { + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + assert.deepStrictEqual(context, undefined); + }); }); - it('returns undefined if b3 header is invalid', () => { - carrier[X_B3_TRACE_ID] = 'invalid!'; - const context = getExtractedSpanContext( - b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) - ); - assert.deepStrictEqual(context, undefined); + describe('AND trace id is invalid', () => { + it('should return undefined', () => { + carrier[X_B3_TRACE_ID] = 'invalid!'; + carrier[X_B3_SPAN_ID] = 'b7ad6b7169203331'; + const context = getExtractedSpanContext( + b3Propagator.extract(Context.ROOT_CONTEXT, carrier, defaultGetter) + ); + assert.deepStrictEqual(context, undefined); + }); }); }); From 9e1c33714091d9a9294ef269360b36316d694fc5 Mon Sep 17 00:00:00 2001 From: Steven Date: Tue, 4 Aug 2020 14:04:08 -0400 Subject: [PATCH 10/10] style: combine traceFlags none condition --- .../src/context/propagation/B3Propagator.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts index fb577f9f90..129e457cb6 100644 --- a/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts +++ b/packages/opentelemetry-core/src/context/propagation/B3Propagator.ts @@ -109,10 +109,7 @@ function getTraceFlags( if (debug === '1' || VALID_SAMPLED_VALUES.has(traceFlags)) { return TraceFlags.SAMPLED; } - if (VALID_UNSAMPLED_VALUES.has(traceFlags)) { - return TraceFlags.NONE; - } - if (traceFlags === undefined) { + if (traceFlags === undefined || VALID_UNSAMPLED_VALUES.has(traceFlags)) { return TraceFlags.NONE; } // This indicates to isValidSampledValue that this is not valid