From c188ac1a6b900aea8ff7473dc810fb8927efa212 Mon Sep 17 00:00:00 2001 From: Erwin van der Koogh <890386+evanderkoogh@users.noreply.github.com> Date: Sat, 10 Aug 2024 13:55:08 +1000 Subject: [PATCH 1/3] Fix instances where config was available in the context --- src/config.ts | 4 ++-- src/instrumentation/fetch.ts | 5 ++++- src/spanprocessor.ts | 4 ++-- src/tracer.ts | 4 +++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/config.ts b/src/config.ts index 129c959..649d3cb 100644 --- a/src/config.ts +++ b/src/config.ts @@ -9,7 +9,7 @@ export function setConfig(config: ResolvedTraceConfig, ctx = context.active()) { return ctx.setValue(configSymbol, config) } -export function getActiveConfig(): ResolvedTraceConfig { +export function getActiveConfig(): ResolvedTraceConfig | undefined { const config = context.active().getValue(configSymbol) as ResolvedTraceConfig - return config + return config || undefined } diff --git a/src/instrumentation/fetch.ts b/src/instrumentation/fetch.ts index 2641275..bfc33c3 100644 --- a/src/instrumentation/fetch.ts +++ b/src/instrumentation/fetch.ts @@ -112,7 +112,7 @@ export function getParentContextFromHeaders(headers: Headers): Context { } function getParentContextFromRequest(request: Request) { - const workerConfig = getActiveConfig() + const workerConfig = getActiveConfig() as ResolvedTraceConfig //Config should always be available const acceptTraceContext = typeof workerConfig.handlers.fetch.acceptTraceContext === 'function' ? workerConfig.handlers.fetch.acceptTraceContext(request) @@ -208,6 +208,9 @@ export function instrumentClientFetch( } const workerConfig = getActiveConfig() + if (!workerConfig) { + return Reflect.apply(target, thisArg, [request]) + } const config = configFn(workerConfig) const tracer = trace.getTracer('fetcher') diff --git a/src/spanprocessor.ts b/src/spanprocessor.ts index c6f40e4..9bd5b8d 100644 --- a/src/spanprocessor.ts +++ b/src/spanprocessor.ts @@ -5,7 +5,7 @@ import { Action, State, stateMachine } from './vendor/ts-checked-fsm/StateMachin import { getActiveConfig } from './config.js' import { TailSampleFn } from './sampling.js' -import { PostProcessorFn } from './types.js' +import { PostProcessorFn, ResolvedTraceConfig } from './types.js' type CompletedTrace = { traceId: string @@ -131,7 +131,7 @@ export class BatchTraceSpanProcessor implements SpanProcessor { } private export(localRootSpanId: string) { - const { sampling, postProcessor } = getActiveConfig() + const { sampling, postProcessor } = getActiveConfig() as ResolvedTraceConfig //Config should always be available const exportArgs = { exporter: this.exporter, tailSampler: sampling.tailSampler, postProcessor } const newState = this.action(localRootSpanId, { actionName: 'startExport', args: exportArgs }) if (newState.stateName === 'exporting') { diff --git a/src/tracer.ts b/src/tracer.ts index 5140b19..c79e88c 100644 --- a/src/tracer.ts +++ b/src/tracer.ts @@ -14,6 +14,7 @@ import { SpanProcessor, RandomIdGenerator, ReadableSpan, SamplingDecision } from import { SpanImpl } from './span.js' import { getActiveConfig } from './config.js' +import { ResolvedTraceConfig } from './types.js' export class WorkerTracer implements Tracer { private readonly _spanProcessors: SpanProcessor[] @@ -44,7 +45,8 @@ export class WorkerTracer implements Tracer { const spanKind = options.kind || SpanKind.INTERNAL const sanitisedAttrs = sanitizeAttributes(options.attributes) - const sampler = getActiveConfig().sampling.headSampler + const config = getActiveConfig() as ResolvedTraceConfig //Config should always be available + const sampler = config.sampling.headSampler const samplingDecision = sampler.shouldSample(context, traceId, name, spanKind, sanitisedAttrs, []) const { decision, traceState, attributes: attrs } = samplingDecision const attributes = Object.assign({}, sanitisedAttrs, attrs) From 892ad26d2a0897d63613df33ca2052ded411fc0e Mon Sep 17 00:00:00 2001 From: Erwin van der Koogh <890386+evanderkoogh@users.noreply.github.com> Date: Sat, 10 Aug 2024 14:05:57 +1000 Subject: [PATCH 2/3] Fixed it better --- src/instrumentation/fetch.ts | 7 ++++++- src/spanprocessor.ts | 5 ++++- src/tracer.ts | 4 +++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/instrumentation/fetch.ts b/src/instrumentation/fetch.ts index bfc33c3..80a54ad 100644 --- a/src/instrumentation/fetch.ts +++ b/src/instrumentation/fetch.ts @@ -112,7 +112,12 @@ export function getParentContextFromHeaders(headers: Headers): Context { } function getParentContextFromRequest(request: Request) { - const workerConfig = getActiveConfig() as ResolvedTraceConfig //Config should always be available + const workerConfig = getActiveConfig() + + if (workerConfig === undefined) { + return api_context.active() + } + const acceptTraceContext = typeof workerConfig.handlers.fetch.acceptTraceContext === 'function' ? workerConfig.handlers.fetch.acceptTraceContext(request) diff --git a/src/spanprocessor.ts b/src/spanprocessor.ts index 9bd5b8d..10e88d4 100644 --- a/src/spanprocessor.ts +++ b/src/spanprocessor.ts @@ -131,7 +131,10 @@ export class BatchTraceSpanProcessor implements SpanProcessor { } private export(localRootSpanId: string) { - const { sampling, postProcessor } = getActiveConfig() as ResolvedTraceConfig //Config should always be available + const config = getActiveConfig() + if (!config) throw new Error('Config is undefined. This is a bug in the instrumentation logic') + + const { sampling, postProcessor } = config const exportArgs = { exporter: this.exporter, tailSampler: sampling.tailSampler, postProcessor } const newState = this.action(localRootSpanId, { actionName: 'startExport', args: exportArgs }) if (newState.stateName === 'exporting') { diff --git a/src/tracer.ts b/src/tracer.ts index c79e88c..a82ba3d 100644 --- a/src/tracer.ts +++ b/src/tracer.ts @@ -45,7 +45,9 @@ export class WorkerTracer implements Tracer { const spanKind = options.kind || SpanKind.INTERNAL const sanitisedAttrs = sanitizeAttributes(options.attributes) - const config = getActiveConfig() as ResolvedTraceConfig //Config should always be available + const config = getActiveConfig() + if (!config) throw new Error('Config is undefined. This is a bug in the instrumentation logic') + const sampler = config.sampling.headSampler const samplingDecision = sampler.shouldSample(context, traceId, name, spanKind, sanitisedAttrs, []) const { decision, traceState, attributes: attrs } = samplingDecision From d530e90886606581f5d59eda95af694899c14465 Mon Sep 17 00:00:00 2001 From: Erwin van der Koogh <890386+evanderkoogh@users.noreply.github.com> Date: Sat, 10 Aug 2024 14:13:58 +1000 Subject: [PATCH 3/3] Fix imports --- src/spanprocessor.ts | 2 +- src/tracer.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/spanprocessor.ts b/src/spanprocessor.ts index 10e88d4..55779e7 100644 --- a/src/spanprocessor.ts +++ b/src/spanprocessor.ts @@ -5,7 +5,7 @@ import { Action, State, stateMachine } from './vendor/ts-checked-fsm/StateMachin import { getActiveConfig } from './config.js' import { TailSampleFn } from './sampling.js' -import { PostProcessorFn, ResolvedTraceConfig } from './types.js' +import { PostProcessorFn } from './types.js' type CompletedTrace = { traceId: string diff --git a/src/tracer.ts b/src/tracer.ts index a82ba3d..c000aac 100644 --- a/src/tracer.ts +++ b/src/tracer.ts @@ -14,7 +14,6 @@ import { SpanProcessor, RandomIdGenerator, ReadableSpan, SamplingDecision } from import { SpanImpl } from './span.js' import { getActiveConfig } from './config.js' -import { ResolvedTraceConfig } from './types.js' export class WorkerTracer implements Tracer { private readonly _spanProcessors: SpanProcessor[]