Skip to content

Commit 12755a7

Browse files
committed
style: refactor extract and tests
1 parent bbc08dc commit 12755a7

File tree

5 files changed

+363
-280
lines changed

5 files changed

+363
-280
lines changed

packages/opentelemetry-api/src/trace/span_context.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export interface SpanContext {
4949
*
5050
* SAMPLED = 0x1 and NONE = 0x0;
5151
*/
52-
traceFlags: TraceFlags;
52+
traceFlags?: TraceFlags;
5353
/**
5454
* Tracing-system-specific info to propagate.
5555
*

packages/opentelemetry-core/src/context/propagation/B3Propagator.ts

+87-36
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ export const DEBUG_FLAG_KEY = Context.createKey(
3737
const VALID_TRACEID_REGEX = /^([0-9a-f]{16}){1,2}$/i;
3838
const VALID_SPANID_REGEX = /^[0-9a-f]{16}$/i;
3939
const INVALID_ID_REGEX = /^0+$/i;
40-
const VALID_SAMPLED_VALUES = [true, 'true', '1'];
40+
const VALID_SAMPLED_VALUES = [true, 'true', '1', 1];
41+
const VALID_UNSAMPLED_VALUES = [0, '0', 'false', false];
4142

4243
function isValidTraceId(traceId: string): boolean {
4344
return VALID_TRACEID_REGEX.test(traceId) && !INVALID_ID_REGEX.test(traceId);
@@ -47,6 +48,18 @@ function isValidSpanId(spanId: string): boolean {
4748
return VALID_SPANID_REGEX.test(spanId) && !INVALID_ID_REGEX.test(spanId);
4849
}
4950

51+
function isValidParentSpanID(spanId: string | undefined): boolean {
52+
return spanId === undefined || isValidSpanId(spanId);
53+
}
54+
55+
function isValidSampledValue(sampled: string | undefined): boolean {
56+
return (
57+
sampled === undefined ||
58+
VALID_SAMPLED_VALUES.includes(sampled) ||
59+
VALID_UNSAMPLED_VALUES.includes(sampled)
60+
);
61+
}
62+
5063
function parseHeader(header: unknown) {
5164
return Array.isArray(header) ? header[0] : header;
5265
}
@@ -56,24 +69,78 @@ function parseHeader(header: unknown) {
5669
* Based on: https://github.com/openzipkin/b3-propagation
5770
*/
5871
export class B3Propagator implements HttpTextPropagator {
72+
_getHeaderValue(carrier: unknown, getter: GetterFunction, key: string) {
73+
const header = getter(carrier, key);
74+
return parseHeader(header);
75+
}
76+
77+
_getTraceId(carrier: unknown, getter: GetterFunction): string {
78+
const traceId = this._getHeaderValue(carrier, getter, X_B3_TRACE_ID);
79+
if (typeof traceId === 'string') {
80+
return traceId.padStart(32, '0');
81+
}
82+
return '';
83+
}
84+
85+
_getSpanId(carrier: unknown, getter: GetterFunction): string {
86+
const spanId = this._getHeaderValue(carrier, getter, X_B3_SPAN_ID);
87+
if (typeof spanId === 'string') {
88+
return spanId;
89+
}
90+
return '';
91+
}
92+
93+
_getParentSpanId(
94+
carrier: unknown,
95+
getter: GetterFunction
96+
): string | undefined {
97+
const spanId = this._getHeaderValue(carrier, getter, X_B3_PARENT_SPAN_ID);
98+
if (typeof spanId === 'string') {
99+
return spanId;
100+
}
101+
return;
102+
}
103+
104+
_getDebug(carrier: unknown, getter: GetterFunction): string | undefined {
105+
const debug = this._getHeaderValue(carrier, getter, X_B3_FLAGS);
106+
return debug === '1' ? '1' : undefined;
107+
}
108+
109+
_getTraceFlags(
110+
carrier: unknown,
111+
getter: GetterFunction
112+
): TraceFlags | string | undefined {
113+
const traceFlags = this._getHeaderValue(carrier, getter, X_B3_SAMPLED);
114+
const debug = this._getDebug(carrier, getter);
115+
if (debug === '1') {
116+
return TraceFlags.SAMPLED;
117+
} else if (traceFlags !== undefined) {
118+
if (VALID_SAMPLED_VALUES.includes(traceFlags)) {
119+
return TraceFlags.SAMPLED;
120+
} else if (VALID_UNSAMPLED_VALUES.includes(traceFlags)) {
121+
return TraceFlags.NONE;
122+
} else {
123+
return '';
124+
}
125+
}
126+
return;
127+
}
128+
59129
inject(context: Context, carrier: unknown, setter: SetterFunction) {
60130
const spanContext = getParentSpanContext(context);
61131
if (!spanContext) return;
62132
const parentSpanId = context.getValue(PARENT_SPAN_ID_KEY);
63133
if (
64134
isValidTraceId(spanContext.traceId) &&
65-
isValidSpanId(spanContext.spanId)
135+
isValidSpanId(spanContext.spanId) &&
136+
isValidParentSpanID(parentSpanId)
66137
) {
67-
if (parentSpanId) {
68-
if (isValidSpanId(parentSpanId as string)) {
69-
setter(carrier, X_B3_PARENT_SPAN_ID, parentSpanId);
70-
} else {
71-
return;
72-
}
73-
}
74138
const debug = context.getValue(DEBUG_FLAG_KEY);
75139
setter(carrier, X_B3_TRACE_ID, spanContext.traceId);
76140
setter(carrier, X_B3_SPAN_ID, spanContext.spanId);
141+
if (parentSpanId) {
142+
setter(carrier, X_B3_PARENT_SPAN_ID, parentSpanId);
143+
}
77144
// According to the B3 spec, if the debug flag is set,
78145
// the sampled flag shouldn't be propagated as well.
79146
if (debug === '1') {
@@ -93,36 +160,20 @@ export class B3Propagator implements HttpTextPropagator {
93160
}
94161

95162
extract(context: Context, carrier: unknown, getter: GetterFunction): Context {
96-
const traceIdHeader = getter(carrier, X_B3_TRACE_ID);
97-
const spanIdHeader = getter(carrier, X_B3_SPAN_ID);
98-
const parentSpanIdHeader = getter(carrier, X_B3_PARENT_SPAN_ID);
99-
const sampledHeader = getter(carrier, X_B3_SAMPLED);
100-
const flagsHeader = getter(carrier, X_B3_FLAGS);
101-
102-
const traceIdHeaderValue = parseHeader(traceIdHeader);
103-
const spanId = parseHeader(spanIdHeader);
104-
const parentSpanId = parseHeader(parentSpanIdHeader);
105-
const options = parseHeader(sampledHeader);
106-
const debugHeaderValue = parseHeader(flagsHeader);
107-
const debug = debugHeaderValue === '1';
108-
const isSampled = VALID_SAMPLED_VALUES.includes(options);
109-
const traceFlags =
110-
debug || isSampled ? TraceFlags.SAMPLED : TraceFlags.NONE;
163+
const traceId = this._getTraceId(carrier, getter);
164+
const spanId = this._getSpanId(carrier, getter);
165+
const parentSpanId = this._getParentSpanId(carrier, getter);
166+
const traceFlags = this._getTraceFlags(carrier, getter);
167+
const debug = this._getDebug(carrier, getter);
111168

112169
if (
113-
typeof traceIdHeaderValue !== 'string' ||
114-
typeof spanId !== 'string' ||
115-
(typeof parentSpanIdHeader === 'string' && !isValidSpanId(parentSpanId))
170+
isValidTraceId(traceId) &&
171+
isValidSpanId(spanId) &&
172+
isValidParentSpanID(parentSpanId) &&
173+
isValidSampledValue(traceFlags)
116174
) {
117-
return context;
118-
}
119-
120-
context = context.setValue(PARENT_SPAN_ID_KEY, parentSpanId);
121-
context = context.setValue(DEBUG_FLAG_KEY, debug ? '1' : undefined);
122-
123-
const traceId = traceIdHeaderValue.padStart(32, '0');
124-
125-
if (isValidTraceId(traceId) && isValidSpanId(spanId)) {
175+
context = context.setValue(PARENT_SPAN_ID_KEY, parentSpanId);
176+
context = context.setValue(DEBUG_FLAG_KEY, debug);
126177
return setExtractedSpanContext(context, {
127178
traceId,
128179
spanId,

packages/opentelemetry-core/src/trace/sampler/ParentOrElseSampler.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export class ParentOrElseSampler implements Sampler {
4141
links: Link[]
4242
): SamplingResult {
4343
// Respect the parent sampling decision if there is one
44-
if (parentContext) {
44+
if (parentContext && parentContext.traceFlags !== undefined) {
4545
return {
4646
decision:
4747
(TraceFlags.SAMPLED & parentContext.traceFlags) === TraceFlags.SAMPLED

packages/opentelemetry-core/src/trace/sampler/ProbabilitySampler.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class ProbabilitySampler implements Sampler {
3131
shouldSample(parentContext?: SpanContext): SamplingResult {
3232
// Respect the parent sampling decision if there is one.
3333
// TODO(#1284): add an option to ignore parent regarding to spec.
34-
if (parentContext) {
34+
if (parentContext && parentContext.traceFlags !== undefined) {
3535
return {
3636
decision:
3737
(TraceFlags.SAMPLED & parentContext.traceFlags) === TraceFlags.SAMPLED

0 commit comments

Comments
 (0)