From 483f2a09796278bbae12d2154d17ff250c6f7d58 Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Thu, 23 Jan 2025 20:34:06 -0800 Subject: [PATCH] feat(api)!: Revamp `TextMapPropagator` TypeScript interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous interface placed the generic paramter on the interface itself. This implies that the implementors of `TextMapPropagator` can specify what carrier types it accepts. As far as I can tell, this has never been the case. The propagator API is designed to be called from the transport layers. The transport layer (caller of `inject`/`extract`) is the one who has control over what the carrier type is. The constraint is that the carrier must semantically behave as an abstract map data structure that supports setting and getting string keys/values, and the caller must supply a matching getter/setter that works with the given carrier type. For example, the fetch instrumentation calls the propogation API with one of many carrier types – POJOs, `Headers`, `Map`, etc. Therefore, a _correct_ implementation of `TextMapPropagator` must treat the carrier as opaque and only work with it using the supplied getter/setter. Unfortunately, the previous interface definition allowed a lot of sloppiness in the implementations that would cause problems in the real world. Fortunately, it seems like these all happen in tests, and all the production propagators are already compliant with the spirit of the API. This commit moves the generic parameter from the interface into the `inject` and `extract` methods. This forces implementors to comply with the API more rigiously. This is a breaking change even for compliant implementations, as it requires adjusting the method signatures to match. If an implementation supplied a custom type for the generic parameter previously existed on the interface, then that probably represents a case where it wouldn't have worked in the real world and should be refactored/rewritten to work with the abstracted carrier type as intended. Ref #5365 --- api/CHANGELOG.md | 5 ++ api/src/api/propagation.ts | 30 +++++++- api/src/propagation/NoopTextMapPropagator.ts | 4 +- api/src/propagation/TextMapPropagator.ts | 18 ++--- api/test/common/api/api.test.ts | 75 ++++++++----------- doc/propagation.md | 12 ++- .../test/utils/DummyPropagation.ts | 54 ++++++++++--- .../propagation/W3CBaggagePropagator.ts | 12 ++- .../src/propagation/composite.ts | 12 ++- .../src/trace/W3CTraceContextPropagator.ts | 12 ++- .../test/propagation/composite.test.ts | 51 ++++++++++--- .../src/B3MultiPropagator.ts | 37 +++++++-- .../src/B3Propagator.ts | 18 +++-- .../src/B3SinglePropagator.ts | 12 ++- .../test/B3Propagator.test.ts | 24 +++--- .../src/JaegerPropagator.ts | 12 ++- .../test/JaegerPropagator.test.ts | 2 +- .../test/common/BasicTracerProvider.test.ts | 6 +- .../test/NodeTracerProvider.test.ts | 10 +-- 19 files changed, 281 insertions(+), 125 deletions(-) diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 758829935e1..261a3b6b063 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -7,6 +7,11 @@ All notable changes to this project will be documented in this file. ### :boom: Breaking Change +* feat(api): revamped `TextMapPropagator` TypeScript interface [#5368](https://github.com/open-telemetry/opentelemetry-js/pull/5368) @chancancode + * Removed generic parameter from the `TextMapPropagator` interface + * Introduced a new `Carrier` generic parameter on its `inject` and `extract` methods + * The previous interface implies the implementor of `TextMapPropagator` can specify what carrier type it accepts, this has never been the case in practice; instead, they must treat the carrier as opaque and use the provided getter/setter. + ### :rocket: (Enhancement) ### :bug: (Bug Fix) diff --git a/api/src/api/propagation.ts b/api/src/api/propagation.ts index 42026d0bc20..05ddc854a99 100644 --- a/api/src/api/propagation.ts +++ b/api/src/api/propagation.ts @@ -76,10 +76,23 @@ export class PropagationAPI { * @param carrier carrier to inject context into * @param setter Function used to set values on the carrier */ + public inject( + context: Context, + carrier: Carrier, + setter?: TextMapSetter + ): void; + public inject( + context: Context, + carrier: Carrier, + setter: TextMapSetter + ): void; public inject( context: Context, carrier: Carrier, - setter: TextMapSetter = defaultTextMapSetter + // Note: this is only safe as long as the TypeScript overloads are enforced. + // If an incompatible `Carrier` is paired with `defaultTextMapSetter`, it + // will error at runtime when the operation is performed. + setter: TextMapSetter = defaultTextMapSetter as TextMapSetter ): void { return this._getGlobalPropagator().inject(context, carrier, setter); } @@ -91,10 +104,23 @@ export class PropagationAPI { * @param carrier Carrier to extract context from * @param getter Function used to extract keys from a carrier */ + public extract( + context: Context, + carrier: Carrier, + getter?: TextMapGetter + ): Context; + public extract( + context: Context, + carrier: Carrier, + getter: TextMapGetter + ): Context; public extract( context: Context, carrier: Carrier, - getter: TextMapGetter = defaultTextMapGetter + // Note: this is only safe as long as the TypeScript overloads are enforced. + // If an incompatible `Carrier` is paired with `defaultTextMapSetter`, it + // will error at runtime when the operation is performed. + getter: TextMapGetter = defaultTextMapGetter as TextMapGetter ): Context { return this._getGlobalPropagator().extract(context, carrier, getter); } diff --git a/api/src/propagation/NoopTextMapPropagator.ts b/api/src/propagation/NoopTextMapPropagator.ts index 16d90cf9700..56adc7d3eb9 100644 --- a/api/src/propagation/NoopTextMapPropagator.ts +++ b/api/src/propagation/NoopTextMapPropagator.ts @@ -22,9 +22,9 @@ import { TextMapPropagator } from './TextMapPropagator'; */ export class NoopTextMapPropagator implements TextMapPropagator { /** Noop inject function does nothing */ - inject(_context: Context, _carrier: unknown): void {} + inject(): void {} /** Noop extract function does nothing and returns the input context */ - extract(context: Context, _carrier: unknown): Context { + extract(context: Context): Context { return context; } fields(): string[] { diff --git a/api/src/propagation/TextMapPropagator.ts b/api/src/propagation/TextMapPropagator.ts index 0abc79f0da7..fa7438f6faf 100644 --- a/api/src/propagation/TextMapPropagator.ts +++ b/api/src/propagation/TextMapPropagator.ts @@ -29,7 +29,7 @@ import { Context } from '../context/types'; * * @since 1.0.0 */ -export interface TextMapPropagator { +export interface TextMapPropagator { /** * Injects values from a given `Context` into a carrier. * @@ -43,7 +43,7 @@ export interface TextMapPropagator { * @param setter an optional {@link TextMapSetter}. If undefined, values will be * set by direct object assignment. */ - inject( + inject( context: Context, carrier: Carrier, setter: TextMapSetter @@ -61,7 +61,7 @@ export interface TextMapPropagator { * @param getter an optional {@link TextMapGetter}. If undefined, keys will be all * own properties, and keys will be accessed by direct object access. */ - extract( + extract( context: Context, carrier: Carrier, getter: TextMapGetter @@ -79,7 +79,7 @@ export interface TextMapPropagator { * * @since 1.0.0 */ -export interface TextMapSetter { +export interface TextMapSetter { /** * Callback used to set a key/value pair on an object. * @@ -99,7 +99,7 @@ export interface TextMapSetter { * * @since 1.0.0 */ -export interface TextMapGetter { +export interface TextMapGetter { /** * Get a list of all keys available on the carrier. * @@ -119,12 +119,12 @@ export interface TextMapGetter { /** * @since 1.0.0 */ -export const defaultTextMapGetter: TextMapGetter = { +export const defaultTextMapGetter: TextMapGetter = { get(carrier, key) { if (carrier == null) { return undefined; } - return carrier[key]; + return (carrier as Record)[key]; }, keys(carrier) { @@ -138,12 +138,12 @@ export const defaultTextMapGetter: TextMapGetter = { /** * @since 1.0.0 */ -export const defaultTextMapSetter: TextMapSetter = { +export const defaultTextMapSetter: TextMapSetter = { set(carrier, key, value) { if (carrier == null) { return; } - carrier[key] = value; + (carrier as Record)[key] = value; }, }; diff --git a/api/test/common/api/api.test.ts b/api/test/common/api/api.test.ts index 23ffcf57325..41369fb487d 100644 --- a/api/test/common/api/api.test.ts +++ b/api/test/common/api/api.test.ts @@ -18,8 +18,6 @@ import * as assert from 'assert'; import api, { context, Context, - defaultTextMapGetter, - defaultTextMapSetter, diag, metrics, propagation, @@ -137,31 +135,23 @@ describe('API', () => { describe('should use the global propagation', () => { const testKey = Symbol('kTestKey'); - interface Carrier { - context?: Context; - setter?: TextMapSetter; - } + type Carrier = Record; - class TestTextMapPropagation implements TextMapPropagator { - inject( + class TestTextMapPropagation implements TextMapPropagator { + inject( context: Context, - carrier: Carrier, - setter: TextMapSetter + carrier: C, + setter: TextMapSetter ): void { - carrier.context = context; - carrier.setter = setter; + setter.set(carrier, 'TestField', String(context.getValue(testKey))); } - extract( + extract( context: Context, - carrier: Carrier, - getter: TextMapGetter + carrier: C, + getter: TextMapGetter ): Context { - return context.setValue(testKey, { - context, - carrier, - getter, - }); + return context.setValue(testKey, getter.get(carrier, 'TestField')); } fields(): string[] { @@ -172,41 +162,40 @@ describe('API', () => { it('inject', () => { api.propagation.setGlobalPropagator(new TestTextMapPropagation()); - const context = ROOT_CONTEXT.setValue(testKey, 15); + const context = ROOT_CONTEXT.setValue(testKey, 'test-value'); const carrier: Carrier = {}; api.propagation.inject(context, carrier); - assert.strictEqual(carrier.context, context); - assert.strictEqual(carrier.setter, defaultTextMapSetter); + assert.strictEqual(carrier['TestField'], 'test-value'); - const setter: TextMapSetter = { - set: () => {}, + const setter: TextMapSetter = { + set: (carrier, key, value) => { + carrier[key.toLowerCase()] = value.toUpperCase(); + }, }; api.propagation.inject(context, carrier, setter); - assert.strictEqual(carrier.context, context); - assert.strictEqual(carrier.setter, setter); + assert.strictEqual(carrier['testfield'], 'TEST-VALUE'); }); it('extract', () => { api.propagation.setGlobalPropagator(new TestTextMapPropagation()); - const carrier: Carrier = {}; - let context = api.propagation.extract(ROOT_CONTEXT, carrier); - let data: any = context.getValue(testKey); - assert.ok(data != null); - assert.strictEqual(data.context, ROOT_CONTEXT); - assert.strictEqual(data.carrier, carrier); - assert.strictEqual(data.getter, defaultTextMapGetter); - - const getter: TextMapGetter = { - keys: () => [], - get: () => undefined, + let context = api.propagation.extract(ROOT_CONTEXT, { + TestField: 'test-value', + }); + let data = context.getValue(testKey); + assert.strictEqual(data, 'test-value'); + + const getter: TextMapGetter = { + keys: carrier => Object.keys(carrier), + get: (carrier, key) => carrier[key.toLowerCase()], }; - context = api.propagation.extract(ROOT_CONTEXT, carrier, getter); + context = api.propagation.extract( + ROOT_CONTEXT, + { testfield: 'TEST-VALUE' }, + getter + ); data = context.getValue(testKey); - assert.ok(data != null); - assert.strictEqual(data.context, ROOT_CONTEXT); - assert.strictEqual(data.carrier, carrier); - assert.strictEqual(data.getter, getter); + assert.strictEqual(data, 'TEST-VALUE'); }); it('fields', () => { diff --git a/doc/propagation.md b/doc/propagation.md index c3d246c0fcf..bebe09ca4ad 100644 --- a/doc/propagation.md +++ b/doc/propagation.md @@ -34,7 +34,11 @@ const MyHeader = 'my-header'; export class MyPropagator implements TextMapPropagator { // Inject the header to the outgoing request. - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { + inject( + context: Context, + carrier: Carrier, + setter: TextMapSetter + ): void { const spanContext = trace.getSpanContext(context); // Skip if the current span context is not valid or suppressed. if ( @@ -51,7 +55,11 @@ export class MyPropagator implements TextMapPropagator { } // Extract the header from the incoming request. - extract(context: Context, carrier: unknown, getter: TextMapGetter): Context { + extract( + context: Context, + carrier: Carrier, + getter: TextMapGetter + ): Context { const headers = getter.get(carrier, MyHeader); const header = Array.isArray(headers) ? headers[0] : headers; if (typeof header !== 'string') return context; diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/utils/DummyPropagation.ts b/experimental/packages/opentelemetry-instrumentation-http/test/utils/DummyPropagation.ts index d5206813fa5..35292cd9db0 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/test/utils/DummyPropagation.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/test/utils/DummyPropagation.ts @@ -15,33 +15,63 @@ */ import { Context, + TextMapGetter, TextMapPropagator, + TextMapSetter, trace, TraceFlags, } from '@opentelemetry/api'; -import type * as http from 'http'; export class DummyPropagation implements TextMapPropagator { static TRACE_CONTEXT_KEY = 'x-dummy-trace-id'; static SPAN_CONTEXT_KEY = 'x-dummy-span-id'; - extract(context: Context, carrier: http.OutgoingHttpHeaders) { - const extractedSpanContext = { - traceId: carrier[DummyPropagation.TRACE_CONTEXT_KEY] as string, - spanId: carrier[DummyPropagation.SPAN_CONTEXT_KEY] as string, - traceFlags: TraceFlags.SAMPLED, - isRemote: true, - }; - if (extractedSpanContext.traceId && extractedSpanContext.spanId) { + + extract( + context: Context, + carrier: Carrier, + getter: TextMapGetter + ) { + const traceId = getter.get(carrier, DummyPropagation.TRACE_CONTEXT_KEY); + const spanId = getter.get(carrier, DummyPropagation.SPAN_CONTEXT_KEY); + + if (traceId && spanId) { + if (typeof traceId !== 'string') { + throw new Error('expecting traceId to be a string'); + } + + if (typeof spanId !== 'string') { + throw new Error('expecting spanId to be a string'); + } + + const extractedSpanContext = { + traceId, + spanId, + traceFlags: TraceFlags.SAMPLED, + isRemote: true, + }; + return trace.setSpanContext(context, extractedSpanContext); } + return context; } - inject(context: Context, headers: { [custom: string]: string }): void { + + inject( + context: Context, + carrier: Carrier, + setter: TextMapSetter + ): void { const spanContext = trace.getSpanContext(context); if (!spanContext) return; - headers[DummyPropagation.TRACE_CONTEXT_KEY] = spanContext.traceId; - headers[DummyPropagation.SPAN_CONTEXT_KEY] = spanContext.spanId; + + setter.set( + carrier, + DummyPropagation.TRACE_CONTEXT_KEY, + spanContext.traceId + ); + setter.set(carrier, DummyPropagation.SPAN_CONTEXT_KEY, spanContext.spanId); } + fields(): string[] { return [ DummyPropagation.TRACE_CONTEXT_KEY, diff --git a/packages/opentelemetry-core/src/baggage/propagation/W3CBaggagePropagator.ts b/packages/opentelemetry-core/src/baggage/propagation/W3CBaggagePropagator.ts index 8a20dedcaaf..83ccdfbf7b8 100644 --- a/packages/opentelemetry-core/src/baggage/propagation/W3CBaggagePropagator.ts +++ b/packages/opentelemetry-core/src/baggage/propagation/W3CBaggagePropagator.ts @@ -39,7 +39,11 @@ import { getKeyPairs, parsePairKeyValue, serializeKeyPairs } from '../utils'; * https://w3c.github.io/baggage/ */ export class W3CBaggagePropagator implements TextMapPropagator { - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { + inject( + context: Context, + carrier: Carrier, + setter: TextMapSetter + ): void { const baggage = propagation.getBaggage(context); if (!baggage || isTracingSuppressed(context)) return; const keyPairs = getKeyPairs(baggage) @@ -53,7 +57,11 @@ export class W3CBaggagePropagator implements TextMapPropagator { } } - extract(context: Context, carrier: unknown, getter: TextMapGetter): Context { + extract( + context: Context, + carrier: Carrier, + getter: TextMapGetter + ): Context { const headerValue = getter.get(carrier, BAGGAGE_HEADER); const baggageString = Array.isArray(headerValue) ? headerValue.join(BAGGAGE_ITEMS_SEPARATOR) diff --git a/packages/opentelemetry-core/src/propagation/composite.ts b/packages/opentelemetry-core/src/propagation/composite.ts index 0654dfa031a..a27585d3978 100644 --- a/packages/opentelemetry-core/src/propagation/composite.ts +++ b/packages/opentelemetry-core/src/propagation/composite.ts @@ -64,7 +64,11 @@ export class CompositePropagator implements TextMapPropagator { * @param context Context to inject * @param carrier Carrier into which context will be injected */ - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { + inject( + context: Context, + carrier: Carrier, + setter: TextMapSetter + ): void { for (const propagator of this._propagators) { try { propagator.inject(context, carrier, setter); @@ -85,7 +89,11 @@ export class CompositePropagator implements TextMapPropagator { * @param context Context to add values to * @param carrier Carrier from which to extract context */ - extract(context: Context, carrier: unknown, getter: TextMapGetter): Context { + extract( + context: Context, + carrier: Carrier, + getter: TextMapGetter + ): Context { return this._propagators.reduce((ctx, propagator) => { try { return propagator.extract(ctx, carrier, getter); diff --git a/packages/opentelemetry-core/src/trace/W3CTraceContextPropagator.ts b/packages/opentelemetry-core/src/trace/W3CTraceContextPropagator.ts index 7925e74814a..d8866e0b734 100644 --- a/packages/opentelemetry-core/src/trace/W3CTraceContextPropagator.ts +++ b/packages/opentelemetry-core/src/trace/W3CTraceContextPropagator.ts @@ -72,7 +72,11 @@ export function parseTraceParent(traceParent: string): SpanContext | null { * https://www.w3.org/TR/trace-context/ */ export class W3CTraceContextPropagator implements TextMapPropagator { - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { + inject( + context: Context, + carrier: Carrier, + setter: TextMapSetter + ): void { const spanContext = trace.getSpanContext(context); if ( !spanContext || @@ -95,7 +99,11 @@ export class W3CTraceContextPropagator implements TextMapPropagator { } } - extract(context: Context, carrier: unknown, getter: TextMapGetter): Context { + extract( + context: Context, + carrier: Carrier, + getter: TextMapGetter + ): Context { const traceParentHeader = getter.get(carrier, TRACE_PARENT_HEADER); if (!traceParentHeader) return context; const traceParent = Array.isArray(traceParentHeader) diff --git a/packages/opentelemetry-core/test/propagation/composite.test.ts b/packages/opentelemetry-core/test/propagation/composite.test.ts index 7dfa8f7a328..717d3779c5c 100644 --- a/packages/opentelemetry-core/test/propagation/composite.test.ts +++ b/packages/opentelemetry-core/test/propagation/composite.test.ts @@ -33,23 +33,52 @@ import { import { TraceState } from '../../src/trace/TraceState'; class DummyPropagator implements TextMapPropagator { - inject(context: Context, carrier: any, setter: TextMapSetter): void { - carrier['dummy'] = trace.getSpanContext(context); + inject( + context: Context, + carrier: Carrier, + setter: TextMapSetter + ): void { + const spanContext = trace.getSpanContext(context); + + if (spanContext) { + const { traceId, spanId, traceFlags } = spanContext; + setter.set(carrier, 'dummy-trace-id', traceId); + setter.set(carrier, 'dummy-span-id', spanId); + setter.set(carrier, 'dummy-trace-flags', String(traceFlags)); + } } - extract(context: Context, carrier: any, getter: TextMapGetter): Context { - if (carrier['dummy']) { - return trace.setSpanContext(context, carrier['dummy']); + extract( + context: Context, + carrier: Carrier, + getter: TextMapGetter + ): Context { + const traceId = getter.get(carrier, 'dummy-trace-id'); + const spanId = getter.get(carrier, 'dummy-span-id'); + const traceFlags = getter.get(carrier, 'dummy-trace-flags'); + + if ( + typeof traceId === 'string' && + typeof spanId === 'string' && + typeof traceFlags === 'string' + ) { + return trace.setSpanContext(context, { + traceId, + spanId, + traceFlags: parseInt(traceFlags), + }); } + return context; } fields(): string[] { - return ['dummy']; + return ['dummy-trace-id', 'dummy-span-id', 'dummy-trace-flags']; } } describe('Composite Propagator', () => { const traceId = 'd4cda95b652f4a1592b449d5929fda1b'; const spanId = '6e0c63257de34c92'; + const traceFlags = 1; describe('inject', () => { let carrier: { [key: string]: unknown }; @@ -61,7 +90,7 @@ describe('Composite Propagator', () => { spanContext = { spanId, traceId, - traceFlags: 1, + traceFlags, traceState: new TraceState('foo=bar'), }; ctxWithSpanContext = trace.setSpanContext(ROOT_CONTEXT, spanContext); @@ -73,7 +102,9 @@ describe('Composite Propagator', () => { }); composite.inject(ctxWithSpanContext, carrier, defaultTextMapSetter); - assert.strictEqual(carrier['dummy'], spanContext); + assert.strictEqual(carrier['dummy-trace-id'], traceId); + assert.strictEqual(carrier['dummy-span-id'], spanId); + assert.strictEqual(carrier['dummy-trace-flags'], String(traceFlags)); assert.strictEqual( carrier[TRACE_PARENT_HEADER], `00-${traceId}-${spanId}-01` @@ -102,7 +133,9 @@ describe('Composite Propagator', () => { beforeEach(() => { carrier = { - ['dummy']: { traceId, spanId }, + ['dummy-trace-id']: traceId, + ['dummy-span-id']: spanId, + ['dummy-trace-flags']: String(traceFlags), [TRACE_PARENT_HEADER]: `00-${traceId}-${spanId}-01`, [TRACE_STATE_HEADER]: 'foo=bar', }; diff --git a/packages/opentelemetry-propagator-b3/src/B3MultiPropagator.ts b/packages/opentelemetry-propagator-b3/src/B3MultiPropagator.ts index 63189e1578c..fb508b8b1e5 100644 --- a/packages/opentelemetry-propagator-b3/src/B3MultiPropagator.ts +++ b/packages/opentelemetry-propagator-b3/src/B3MultiPropagator.ts @@ -46,12 +46,19 @@ function parseHeader(header: unknown) { return Array.isArray(header) ? header[0] : header; } -function getHeaderValue(carrier: unknown, getter: TextMapGetter, key: string) { +function getHeaderValue( + carrier: Carrier, + getter: TextMapGetter, + key: string +) { const header = getter.get(carrier, key); return parseHeader(header); } -function getTraceId(carrier: unknown, getter: TextMapGetter): string { +function getTraceId( + carrier: Carrier, + getter: TextMapGetter +): string { const traceId = getHeaderValue(carrier, getter, X_B3_TRACE_ID); if (typeof traceId === 'string') { return traceId.padStart(32, '0'); @@ -59,7 +66,10 @@ function getTraceId(carrier: unknown, getter: TextMapGetter): string { return ''; } -function getSpanId(carrier: unknown, getter: TextMapGetter): string { +function getSpanId( + carrier: Carrier, + getter: TextMapGetter +): string { const spanId = getHeaderValue(carrier, getter, X_B3_SPAN_ID); if (typeof spanId === 'string') { return spanId; @@ -67,14 +77,17 @@ function getSpanId(carrier: unknown, getter: TextMapGetter): string { return ''; } -function getDebug(carrier: unknown, getter: TextMapGetter): string | undefined { +function getDebug( + carrier: Carrier, + getter: TextMapGetter +): string | undefined { const debug = getHeaderValue(carrier, getter, X_B3_FLAGS); return debug === '1' ? '1' : undefined; } -function getTraceFlags( +function getTraceFlags( carrier: unknown, - getter: TextMapGetter + getter: TextMapGetter ): TraceFlags | undefined { const traceFlags = getHeaderValue(carrier, getter, X_B3_SAMPLED); const debug = getDebug(carrier, getter); @@ -93,7 +106,11 @@ function getTraceFlags( * Based on: https://github.com/openzipkin/b3-propagation */ export class B3MultiPropagator implements TextMapPropagator { - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { + inject( + context: Context, + carrier: Carrier, + setter: TextMapSetter + ): void { const spanContext = trace.getSpanContext(context); if ( !spanContext || @@ -122,7 +139,11 @@ export class B3MultiPropagator implements TextMapPropagator { } } - extract(context: Context, carrier: unknown, getter: TextMapGetter): Context { + extract( + context: Context, + carrier: Carrier, + getter: TextMapGetter + ): Context { const traceId = getTraceId(carrier, getter); const spanId = getSpanId(carrier, getter); const traceFlags = getTraceFlags(carrier, getter) as TraceFlags; diff --git a/packages/opentelemetry-propagator-b3/src/B3Propagator.ts b/packages/opentelemetry-propagator-b3/src/B3Propagator.ts index 0997fcdb18d..18b8f8da712 100644 --- a/packages/opentelemetry-propagator-b3/src/B3Propagator.ts +++ b/packages/opentelemetry-propagator-b3/src/B3Propagator.ts @@ -38,10 +38,10 @@ export class B3Propagator implements TextMapPropagator { new B3MultiPropagator(); private readonly _b3SinglePropagator: B3SinglePropagator = new B3SinglePropagator(); - private readonly _inject: ( + private readonly _inject: ( context: Context, - carrier: unknown, - setter: TextMapSetter + carrier: Carrier, + setter: TextMapSetter ) => void; public readonly _fields: string[]; @@ -55,14 +55,22 @@ export class B3Propagator implements TextMapPropagator { } } - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { + inject( + context: Context, + carrier: Carrier, + setter: TextMapSetter + ): void { if (isTracingSuppressed(context)) { return; } this._inject(context, carrier, setter); } - extract(context: Context, carrier: unknown, getter: TextMapGetter): Context { + extract( + context: Context, + carrier: Carrier, + getter: TextMapGetter + ): Context { const header = getter.get(carrier, B3_CONTEXT_HEADER); const b3Context = Array.isArray(header) ? header[0] : header; diff --git a/packages/opentelemetry-propagator-b3/src/B3SinglePropagator.ts b/packages/opentelemetry-propagator-b3/src/B3SinglePropagator.ts index 83d21ec6ddb..bbebf2edd65 100644 --- a/packages/opentelemetry-propagator-b3/src/B3SinglePropagator.ts +++ b/packages/opentelemetry-propagator-b3/src/B3SinglePropagator.ts @@ -51,7 +51,11 @@ function convertToTraceFlags(samplingState: string | undefined): TraceFlags { * Based on: https://github.com/openzipkin/b3-propagation */ export class B3SinglePropagator implements TextMapPropagator { - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { + inject( + context: Context, + carrier: Carrier, + setter: TextMapSetter + ): void { const spanContext = trace.getSpanContext(context); if ( !spanContext || @@ -66,7 +70,11 @@ export class B3SinglePropagator implements TextMapPropagator { setter.set(carrier, B3_CONTEXT_HEADER, value); } - extract(context: Context, carrier: unknown, getter: TextMapGetter): Context { + extract( + context: Context, + carrier: Carrier, + getter: TextMapGetter + ): Context { const header = getter.get(carrier, B3_CONTEXT_HEADER); const b3Context = Array.isArray(header) ? header[0] : header; if (typeof b3Context !== 'string') return context; diff --git a/packages/opentelemetry-propagator-b3/test/B3Propagator.test.ts b/packages/opentelemetry-propagator-b3/test/B3Propagator.test.ts index 20ebcf3cdd9..e09910f4079 100644 --- a/packages/opentelemetry-propagator-b3/test/B3Propagator.test.ts +++ b/packages/opentelemetry-propagator-b3/test/B3Propagator.test.ts @@ -153,16 +153,20 @@ describe('B3Propagator', () => { }); it('extracts multi header b3 using array getter', () => { - const context = propagator.extract(ROOT_CONTEXT, b3MultiCarrier, { - get(carrier, key) { - if (carrier == null || carrier[key] === undefined) { - return []; - } - return [carrier[key]]; - }, - - keys: defaultTextMapGetter.keys, - }); + const context = propagator.extract>( + ROOT_CONTEXT, + b3MultiCarrier, + { + get(carrier, key) { + if (carrier == null || carrier[key] === undefined) { + return []; + } + return [carrier[key]]; + }, + + keys: defaultTextMapGetter.keys, + } + ); const extractedSpanContext = trace.getSpanContext(context); assert.deepStrictEqual(extractedSpanContext, { diff --git a/packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts b/packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts index 7b11d7290b5..74887920d59 100644 --- a/packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts +++ b/packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts @@ -63,7 +63,11 @@ export class JaegerPropagator implements TextMapPropagator { } } - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { + inject( + context: Context, + carrier: Carrier, + setter: TextMapSetter + ): void { const spanContext = trace.getSpanContext(context); const baggage = propagation.getBaggage(context); if (spanContext && isTracingSuppressed(context) === false) { @@ -89,7 +93,11 @@ export class JaegerPropagator implements TextMapPropagator { } } - extract(context: Context, carrier: unknown, getter: TextMapGetter): Context { + extract( + context: Context, + carrier: Carrier, + getter: TextMapGetter + ): Context { const uberTraceIdHeader = getter.get(carrier, this._jaegerTraceHeader); const uberTraceId = Array.isArray(uberTraceIdHeader) ? uberTraceIdHeader[0] diff --git a/packages/opentelemetry-propagator-jaeger/test/JaegerPropagator.test.ts b/packages/opentelemetry-propagator-jaeger/test/JaegerPropagator.test.ts index c7a6b155fff..9f18493f9ba 100644 --- a/packages/opentelemetry-propagator-jaeger/test/JaegerPropagator.test.ts +++ b/packages/opentelemetry-propagator-jaeger/test/JaegerPropagator.test.ts @@ -377,7 +377,7 @@ describe('JaegerPropagator', () => { }); function makeGetter(value: any) { - const getter: TextMapGetter = { + const getter: TextMapGetter = { get(carrier, key) { return value; }, diff --git a/packages/opentelemetry-sdk-trace-base/test/common/BasicTracerProvider.test.ts b/packages/opentelemetry-sdk-trace-base/test/common/BasicTracerProvider.test.ts index b6762b3c3cc..815e4c34df9 100644 --- a/packages/opentelemetry-sdk-trace-base/test/common/BasicTracerProvider.test.ts +++ b/packages/opentelemetry-sdk-trace-base/test/common/BasicTracerProvider.test.ts @@ -21,9 +21,7 @@ import { TraceFlags, ROOT_CONTEXT, TextMapPropagator, - TextMapSetter, Context, - TextMapGetter, propagation, diag, } from '@opentelemetry/api'; @@ -45,10 +43,10 @@ import { SpanImpl } from '../../src/Span'; import { MultiSpanProcessor } from '../../src/MultiSpanProcessor'; class DummyPropagator implements TextMapPropagator { - inject(context: Context, carrier: any, setter: TextMapSetter): void { + inject(): void { throw new Error('Method not implemented.'); } - extract(context: Context, carrier: any, getter: TextMapGetter): Context { + extract(): Context { throw new Error('Method not implemented.'); } fields(): string[] { diff --git a/packages/opentelemetry-sdk-trace-node/test/NodeTracerProvider.test.ts b/packages/opentelemetry-sdk-trace-node/test/NodeTracerProvider.test.ts index e076ad0c71d..3dd78962a21 100644 --- a/packages/opentelemetry-sdk-trace-node/test/NodeTracerProvider.test.ts +++ b/packages/opentelemetry-sdk-trace-node/test/NodeTracerProvider.test.ts @@ -23,9 +23,7 @@ import { ContextManager, propagation, ROOT_CONTEXT, - TextMapGetter, TextMapPropagator, - TextMapSetter, trace, TraceFlags, } from '@opentelemetry/api'; @@ -247,14 +245,10 @@ describe('NodeTracerProvider', () => { describe('Custom TracerProvider through inheritance', () => { class DummyPropagator implements TextMapPropagator { - inject(context: Context, carrier: any, setter: TextMapSetter): void { + inject(): void { throw new Error('Method not implemented.'); } - extract( - context: Context, - carrier: any, - getter: TextMapGetter - ): Context { + extract(): Context { throw new Error('Method not implemented.'); } fields(): string[] {