From 3e66c666416db9498f127df3b0cb002d78b19a6d Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Fri, 24 Jan 2025 09:26:38 -0800 Subject: [PATCH] docs(api): clarify `TextMapPropagator` API requirements The current interface places the generic paramter on the interface itself. This implies that the implementors of `TextMapPropagator` can specify what carrier types it accepts (and that each implementor only work with one specific type of carrier). ```ts interface TextMapPropagator { inject(context: Context, carrier: Carrier, setter: TextMapSetter): void; extract(context: Context, carrier: Carrier, getter: TextMapGetter): void; } ``` In reality, this is not the case. The propagator API is designed to be called by participating code around the various transport layers (such as the `fetch` inst on the browser, or integration with the HTTP server library on the backend), and it is these callers that ultimately controls what carrier type the currently configured propagator is called with. Therefore, a correct implementation of this interface must treat the carrier as an opaque value, and only work with it using the provided getter/setter. Ideally, the interface should look like this instead: ```ts interface TextMapPropagator { inject(context: Context, carrier: Carrier, setter: TextMapSetter): void; extract(context: Context, carrier: Carrier, getter: TextMapGetter): void; } ``` This communicates and enforces the contract. Unfortunately, that would be a breking change we are not currently prepared to make. Instead, this commit updates the documentation to explicitly document the discrapancy and advice implemntors the correct way forward. It also updates our own implementations to follow the recommended pattern, as well as updating the tests to be more well-behaved around this, as some of them are written to rely on this exact behavior that would be problematic in the real world. Ref #5365 Ref #5368 --- api/CHANGELOG.md | 2 + api/src/propagation/TextMapPropagator.ts | 47 +++++++++--- api/test/common/api/api.test.ts | 73 ++++++++----------- doc/propagation.md | 14 +++- .../test/utils/DummyPropagation.ts | 43 +++++++++-- .../propagation/W3CBaggagePropagator.ts | 14 +++- .../src/propagation/composite.ts | 14 +++- .../src/trace/W3CTraceContextPropagator.ts | 14 +++- .../test/propagation/composite.test.ts | 55 +++++++++++--- .../src/B3MultiPropagator.ts | 39 +++++++--- .../src/B3Propagator.ts | 16 +++- .../src/B3SinglePropagator.ts | 14 +++- .../test/B3Propagator.test.ts | 2 +- .../src/JaegerPropagator.ts | 14 +++- .../test/common/BasicTracerProvider.test.ts | 8 +- .../test/NodeTracerProvider.test.ts | 12 +-- 16 files changed, 264 insertions(+), 117 deletions(-) diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 758829935e1..05f536dfd08 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -13,6 +13,8 @@ All notable changes to this project will be documented in this file. ### :books: (Refine Doc) +* docs(api): Clarify `TextMapPropagator` interface implementation requirements around the `Carrier` type [#5370](https://github.com/open-telemetry/opentelemetry-js/pull/5370) @chancancode + ### :house: (Internal) * refactor(api): remove "export *" in favor of explicit named exports [#4880](https://github.com/open-telemetry/opentelemetry-js/pull/4880) @robbkidd diff --git a/api/src/propagation/TextMapPropagator.ts b/api/src/propagation/TextMapPropagator.ts index 0abc79f0da7..b2a641c59fc 100644 --- a/api/src/propagation/TextMapPropagator.ts +++ b/api/src/propagation/TextMapPropagator.ts @@ -22,13 +22,36 @@ import { Context } from '../context/types'; * HTTP Header Field semantics. Values are often encoded as RPC/HTTP request * headers. * - * The carrier of propagated data on both the client (injector) and server - * (extractor) side is usually an object such as http headers. Propagation is - * usually implemented via library-specific request interceptors, where the - * client-side injects values and the server-side extracts them. + * Propagation is usually implemented via library-specific request + * interceptors, where the client-side injects values and the server-side + * extracts them. + * + * @template Carrier **It is strongly recommended to set the `Carrier` type + * parameter to `unknown`, as it is the only correct type here.** + * + * The carrier is the medium for communicating propagated data between the + * client (injector) and server (extractor) side, such as HTTP headers. To + * work with `TextMapPropagator`, the carrier type must semantically function + * as an abstract map data structure, supporting string keys and values. + * + * This type parameter exists on the interface for historical reasons. While + * it may be suggest that implementors have a choice over what type of carrier + * medium it accepts, this is not true in practice. + * + * The propagator API is designed to be called by participating code around the + * various transport layers (such as the `fetch` instrumentation on the browser + * client, or integration with the HTTP server library on the backend), and it + * is these callers that ultimately controls what carrier type your propagator + * is called with. + * + * Therefore, a correct implementation of this interface must treat the carrier + * as an opaque value, and only work with it using the provided getter/setter. * * @since 1.0.0 */ +// TODO: move this generic parameter into the methods in API 2.0 and remove +// the default to `any` +// eslint-disable-next-line @typescript-eslint/no-explicit-any export interface TextMapPropagator { /** * Injects values from a given `Context` into a carrier. @@ -38,10 +61,10 @@ export interface TextMapPropagator { * * @param context the Context from which to extract values to transmit over * the wire. - * @param carrier the carrier of propagation fields, such as http request + * @param carrier the carrier of propagation fields, such as HTTP request * headers. - * @param setter an optional {@link TextMapSetter}. If undefined, values will be - * set by direct object assignment. + * @param setter a {@link TextMapSetter} guaranteed to work with the given + * carrier, implementors must use this to set values on the carrier. */ inject( context: Context, @@ -56,10 +79,10 @@ export interface TextMapPropagator { * * @param context the Context from which to extract values to transmit over * the wire. - * @param carrier the carrier of propagation fields, such as http request + * @param carrier the carrier of propagation fields, such as HTTP request * headers. - * @param getter an optional {@link TextMapGetter}. If undefined, keys will be all - * own properties, and keys will be accessed by direct object access. + * @param getter a {@link TextMapGetter} guaranteed to work with the given + * carrier, implementors must use this to read values from the carrier. */ extract( context: Context, @@ -79,6 +102,8 @@ export interface TextMapPropagator { * * @since 1.0.0 */ +// TODO: remove the default to `any` in API 2.0 +// eslint-disable-next-line @typescript-eslint/no-explicit-any export interface TextMapSetter { /** * Callback used to set a key/value pair on an object. @@ -99,6 +124,8 @@ export interface TextMapSetter { * * @since 1.0.0 */ +// TODO: remove the default to `any` in API 2.0 +// eslint-disable-next-line @typescript-eslint/no-explicit-any export interface TextMapGetter { /** * Get a list of all keys available on the carrier. diff --git a/api/test/common/api/api.test.ts b/api/test/common/api/api.test.ts index 23ffcf57325..a86a347c7bc 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 { + class TestTextMapPropagation implements TextMapPropagator { inject( context: Context, - carrier: Carrier, - setter: TextMapSetter + carrier: unknown, + 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: unknown, + 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..4f2ea6be51a 100644 --- a/doc/propagation.md +++ b/doc/propagation.md @@ -32,9 +32,13 @@ import { isTracingSuppressed } from '@opentelemetry/core'; // Example header, the content format can be `:` const MyHeader = 'my-header'; -export class MyPropagator implements TextMapPropagator { +export class MyPropagator implements TextMapPropagator { // Inject the header to the outgoing request. - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { + inject( + context: Context, + carrier: unknown, + 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: unknown, + 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..3db517caf80 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/test/utils/DummyPropagation.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/test/utils/DummyPropagation.ts @@ -15,33 +15,60 @@ */ import { Context, + TextMapGetter, TextMapPropagator, + TextMapSetter, trace, TraceFlags, } from '@opentelemetry/api'; -import type * as http from 'http'; -export class DummyPropagation implements TextMapPropagator { +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) { + + extract(context: Context, carrier: unknown, getter: TextMapGetter) { + const traceId = getter.get(carrier, DummyPropagation.TRACE_CONTEXT_KEY); + + if (typeof traceId !== 'string') { + throw new Error('expecting traceId to be a string'); + } + + const spanId = getter.get(carrier, DummyPropagation.SPAN_CONTEXT_KEY); + + if (typeof spanId !== 'string') { + throw new Error('expecting spanId to be a string'); + } + const extractedSpanContext = { - traceId: carrier[DummyPropagation.TRACE_CONTEXT_KEY] as string, - spanId: carrier[DummyPropagation.SPAN_CONTEXT_KEY] as string, + traceId, + spanId, traceFlags: TraceFlags.SAMPLED, isRemote: true, }; + if (extractedSpanContext.traceId && extractedSpanContext.spanId) { return trace.setSpanContext(context, extractedSpanContext); } + return context; } - inject(context: Context, headers: { [custom: string]: string }): void { + + inject( + context: Context, + carrier: unknown, + 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..cc49cf1343b 100644 --- a/packages/opentelemetry-core/src/baggage/propagation/W3CBaggagePropagator.ts +++ b/packages/opentelemetry-core/src/baggage/propagation/W3CBaggagePropagator.ts @@ -38,8 +38,12 @@ import { getKeyPairs, parsePairKeyValue, serializeKeyPairs } from '../utils'; * Based on the Baggage specification: * https://w3c.github.io/baggage/ */ -export class W3CBaggagePropagator implements TextMapPropagator { - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { +export class W3CBaggagePropagator implements TextMapPropagator { + inject( + context: Context, + carrier: unknown, + 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: unknown, + 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..764db4bdcc0 100644 --- a/packages/opentelemetry-core/src/propagation/composite.ts +++ b/packages/opentelemetry-core/src/propagation/composite.ts @@ -33,7 +33,7 @@ export interface CompositePropagatorConfig { } /** Combines multiple propagators into a single propagator. */ -export class CompositePropagator implements TextMapPropagator { +export class CompositePropagator implements TextMapPropagator { private readonly _propagators: TextMapPropagator[]; private readonly _fields: string[]; @@ -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: unknown, + 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: unknown, + 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..33a5ef609a5 100644 --- a/packages/opentelemetry-core/src/trace/W3CTraceContextPropagator.ts +++ b/packages/opentelemetry-core/src/trace/W3CTraceContextPropagator.ts @@ -71,8 +71,12 @@ export function parseTraceParent(traceParent: string): SpanContext | null { * Based on the Trace Context specification: * https://www.w3.org/TR/trace-context/ */ -export class W3CTraceContextPropagator implements TextMapPropagator { - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { +export class W3CTraceContextPropagator implements TextMapPropagator { + inject( + context: Context, + carrier: unknown, + 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: unknown, + 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..1866138aee9 100644 --- a/packages/opentelemetry-core/test/propagation/composite.test.ts +++ b/packages/opentelemetry-core/test/propagation/composite.test.ts @@ -32,24 +32,53 @@ import { } from '../../src/trace/W3CTraceContextPropagator'; import { TraceState } from '../../src/trace/TraceState'; -class DummyPropagator implements TextMapPropagator { - inject(context: Context, carrier: any, setter: TextMapSetter): void { - carrier['dummy'] = trace.getSpanContext(context); +class DummyPropagator implements TextMapPropagator { + inject( + context: Context, + carrier: unknown, + 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: unknown, + 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', }; @@ -213,7 +246,7 @@ describe('Composite Propagator', () => { }); }); -class ThrowingPropagator implements TextMapPropagator { +class ThrowingPropagator implements TextMapPropagator { inject(context: Context, carrier: unknown) { throw new Error('this propagator throws'); } diff --git a/packages/opentelemetry-propagator-b3/src/B3MultiPropagator.ts b/packages/opentelemetry-propagator-b3/src/B3MultiPropagator.ts index 63189e1578c..f99780646f8 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); @@ -92,8 +105,12 @@ function getTraceFlags( * Propagator for the B3 multiple-header HTTP format. * Based on: https://github.com/openzipkin/b3-propagation */ -export class B3MultiPropagator implements TextMapPropagator { - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { +export class B3MultiPropagator implements TextMapPropagator { + inject( + context: Context, + carrier: unknown, + 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: unknown, + 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..22f3e88ecba 100644 --- a/packages/opentelemetry-propagator-b3/src/B3Propagator.ts +++ b/packages/opentelemetry-propagator-b3/src/B3Propagator.ts @@ -33,7 +33,7 @@ import { B3InjectEncoding, B3PropagatorConfig } from './types'; * be implemented as a composite propagator. * Based on: https://github.com/openzipkin/b3-propagation */ -export class B3Propagator implements TextMapPropagator { +export class B3Propagator implements TextMapPropagator { private readonly _b3MultiPropagator: B3MultiPropagator = new B3MultiPropagator(); private readonly _b3SinglePropagator: B3SinglePropagator = @@ -41,7 +41,7 @@ export class B3Propagator implements TextMapPropagator { private readonly _inject: ( context: Context, carrier: unknown, - setter: TextMapSetter + 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: unknown, + setter: TextMapSetter + ): void { if (isTracingSuppressed(context)) { return; } this._inject(context, carrier, setter); } - extract(context: Context, carrier: unknown, getter: TextMapGetter): Context { + extract( + context: Context, + carrier: unknown, + 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..68663d41393 100644 --- a/packages/opentelemetry-propagator-b3/src/B3SinglePropagator.ts +++ b/packages/opentelemetry-propagator-b3/src/B3SinglePropagator.ts @@ -50,8 +50,12 @@ function convertToTraceFlags(samplingState: string | undefined): TraceFlags { * Propagator for the B3 single-header HTTP format. * Based on: https://github.com/openzipkin/b3-propagation */ -export class B3SinglePropagator implements TextMapPropagator { - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { +export class B3SinglePropagator implements TextMapPropagator { + inject( + context: Context, + carrier: unknown, + 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: unknown, + 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..96c78768750 100644 --- a/packages/opentelemetry-propagator-b3/test/B3Propagator.test.ts +++ b/packages/opentelemetry-propagator-b3/test/B3Propagator.test.ts @@ -154,7 +154,7 @@ describe('B3Propagator', () => { it('extracts multi header b3 using array getter', () => { const context = propagator.extract(ROOT_CONTEXT, b3MultiCarrier, { - get(carrier, key) { + get(carrier: Record, key) { if (carrier == null || carrier[key] === undefined) { return []; } diff --git a/packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts b/packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts index 7b11d7290b5..9aeb389b007 100644 --- a/packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts +++ b/packages/opentelemetry-propagator-jaeger/src/JaegerPropagator.ts @@ -45,7 +45,7 @@ export const UBER_BAGGAGE_HEADER_PREFIX = 'uberctx'; * One byte bitmap, as two hex digits. * Inspired by jaeger-client-node project. */ -export class JaegerPropagator implements TextMapPropagator { +export class JaegerPropagator implements TextMapPropagator { private readonly _jaegerTraceHeader: string; private readonly _jaegerBaggageHeaderPrefix: string; @@ -63,7 +63,11 @@ export class JaegerPropagator implements TextMapPropagator { } } - inject(context: Context, carrier: unknown, setter: TextMapSetter): void { + inject( + context: Context, + carrier: unknown, + 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: unknown, + getter: TextMapGetter + ): Context { const uberTraceIdHeader = getter.get(carrier, this._jaegerTraceHeader); const uberTraceId = Array.isArray(uberTraceIdHeader) ? uberTraceIdHeader[0] 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..389de0610e4 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'; @@ -44,11 +42,11 @@ import { import { SpanImpl } from '../../src/Span'; import { MultiSpanProcessor } from '../../src/MultiSpanProcessor'; -class DummyPropagator implements TextMapPropagator { - inject(context: Context, carrier: any, setter: TextMapSetter): void { +class DummyPropagator implements TextMapPropagator { + 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..c8674388fe5 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'; @@ -246,15 +244,11 @@ describe('NodeTracerProvider', () => { }); describe('Custom TracerProvider through inheritance', () => { - class DummyPropagator implements TextMapPropagator { - inject(context: Context, carrier: any, setter: TextMapSetter): void { + class DummyPropagator implements TextMapPropagator { + 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[] {