From bf99144ad4e4fa38120e896d70e9e5bcfaf27054 Mon Sep 17 00:00:00 2001 From: Marc Bachmann <marc.brookman@gmail.com> Date: Mon, 25 Jan 2021 18:03:31 +0100 Subject: [PATCH] chore(http-propagation): reduce complexity of traceparent parsing (#1837) Co-authored-by: Valentin Marchaud <contact@vmarchaud.fr> Co-authored-by: Daniel Dyla <dyladan@users.noreply.github.com> --- .../context/propagation/HttpTraceContext.ts | 46 +++++++------------ 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/packages/opentelemetry-core/src/context/propagation/HttpTraceContext.ts b/packages/opentelemetry-core/src/context/propagation/HttpTraceContext.ts index 5957b2228d8..735e8d2e443 100644 --- a/packages/opentelemetry-core/src/context/propagation/HttpTraceContext.ts +++ b/packages/opentelemetry-core/src/context/propagation/HttpTraceContext.ts @@ -30,12 +30,13 @@ export const TRACE_PARENT_HEADER = 'traceparent'; export const TRACE_STATE_HEADER = 'tracestate'; const VERSION = '00'; -const VERSION_PART_COUNT = 4; // Version 00 only allows the specific 4 fields. - -const VERSION_REGEX = /^(?!ff)[\da-f]{2}$/; -const TRACE_ID_REGEX = /^(?![0]{32})[\da-f]{32}$/; -const PARENT_ID_REGEX = /^(?![0]{16})[\da-f]{16}$/; -const FLAGS_REGEX = /^[\da-f]{2}$/; +const VERSION_PART = '(?!ff)[\\da-f]{2}'; +const TRACE_ID_PART = '(?![0]{32})[\\da-f]{32}'; +const PARENT_ID_PART = '(?![0]{16})[\\da-f]{16}'; +const FLAGS_PART = '[\\da-f]{2}'; +const TRACE_PARENT_REGEX = new RegExp( + `^\\s?(${VERSION_PART})-(${TRACE_ID_PART})-(${PARENT_ID_PART})-(${FLAGS_PART})(-.*)?\\s?$` +); /** * Parses information from the [traceparent] span tag and converts it into {@link SpanContext} @@ -48,33 +49,18 @@ const FLAGS_REGEX = /^[\da-f]{2}$/; * For more information see {@link https://www.w3.org/TR/trace-context/} */ export function parseTraceParent(traceParent: string): SpanContext | null { - const trimmed = traceParent.trim(); - const traceParentParts = trimmed.split('-'); - - // Current version must be structured correctly. - // For future versions, we can grab just the parts we do support. - if ( - traceParentParts[0] === VERSION && - traceParentParts.length !== VERSION_PART_COUNT - ) { - return null; - } + const match = TRACE_PARENT_REGEX.exec(traceParent); + if (!match) return null; - const [version, traceId, parentId, flags] = traceParentParts; - const isValidParent = - VERSION_REGEX.test(version) && - TRACE_ID_REGEX.test(traceId) && - PARENT_ID_REGEX.test(parentId) && - FLAGS_REGEX.test(flags); - - if (!isValidParent) { - return null; - } + // According to the specification the implementation should be compatible + // with future versions. If there are more parts, we only reject it if it's using version 00 + // See https://www.w3.org/TR/trace-context/#versioning-of-traceparent + if (match[1] === '00' && match[5]) return null; return { - traceId: traceId, - spanId: parentId, - traceFlags: parseInt(flags, 16), + traceId: match[2], + spanId: match[3], + traceFlags: parseInt(match[4], 16), }; }