diff --git a/integration-tests/propagation-validation-server/validation-server.js b/integration-tests/propagation-validation-server/validation-server.js index badcddb7693..a84312e15f7 100644 --- a/integration-tests/propagation-validation-server/validation-server.js +++ b/integration-tests/propagation-validation-server/validation-server.js @@ -7,17 +7,14 @@ const { } = require("@opentelemetry/context-async-hooks"); const bodyParser = require("body-parser"); -// set global propagator -propagation.setGlobalPropagator(new HttpTraceContext()); - -// set global context manager -context.setGlobalContextManager(new AsyncHooksContextManager()); - // Create a provider for activating and tracking spans const tracerProvider = new BasicTracerProvider(); // Register the tracer -tracerProvider.register(); +tracerProvider.register({ + propagator: new HttpTraceContext(), + contextManager: new AsyncHooksContextManager().enable(), +}); // Get a tracer const tracer = trace.getTracer("w3c-tests"); diff --git a/packages/opentelemetry-api/src/api/context.ts b/packages/opentelemetry-api/src/api/context.ts index ac5aff2cdd1..f9bd115012c 100644 --- a/packages/opentelemetry-api/src/api/context.ts +++ b/packages/opentelemetry-api/src/api/context.ts @@ -20,12 +20,12 @@ import { NoopContextManager, } from '@opentelemetry/context-base'; import { - API_BACKWARDS_COMPATIBILITY_VERSION, - GLOBAL_CONTEXT_MANAGER_API_KEY, - makeGetter, - _global, -} from './global-utils'; + getGlobal, + registerGlobal, + unregisterGlobal, +} from '../internal/global-utils'; +const API_NAME = 'context'; const NOOP_CONTEXT_MANAGER = new NoopContextManager(); /** @@ -52,17 +52,7 @@ export class ContextAPI { public setGlobalContextManager( contextManager: ContextManager ): ContextManager { - if (_global[GLOBAL_CONTEXT_MANAGER_API_KEY]) { - // global context manager has already been set - return this._getContextManager(); - } - - _global[GLOBAL_CONTEXT_MANAGER_API_KEY] = makeGetter( - API_BACKWARDS_COMPATIBILITY_VERSION, - contextManager, - NOOP_CONTEXT_MANAGER - ); - + registerGlobal(API_NAME, contextManager); return contextManager; } @@ -97,16 +87,12 @@ export class ContextAPI { } private _getContextManager(): ContextManager { - return ( - _global[GLOBAL_CONTEXT_MANAGER_API_KEY]?.( - API_BACKWARDS_COMPATIBILITY_VERSION - ) ?? NOOP_CONTEXT_MANAGER - ); + return getGlobal(API_NAME) || NOOP_CONTEXT_MANAGER; } /** Disable and remove the global context manager */ public disable() { this._getContextManager().disable(); - delete _global[GLOBAL_CONTEXT_MANAGER_API_KEY]; + unregisterGlobal(API_NAME); } } diff --git a/packages/opentelemetry-api/src/api/global-utils.ts b/packages/opentelemetry-api/src/api/global-utils.ts deleted file mode 100644 index 5d6ad7de3e0..00000000000 --- a/packages/opentelemetry-api/src/api/global-utils.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ContextManager } from '@opentelemetry/context-base'; -import { TextMapPropagator } from '../context/propagation/TextMapPropagator'; -import { MeterProvider } from '../metrics/MeterProvider'; -import { TracerProvider } from '../trace/tracer_provider'; -import { _globalThis } from '../platform'; - -export const GLOBAL_CONTEXT_MANAGER_API_KEY = Symbol.for( - 'io.opentelemetry.js.api.context' -); -export const GLOBAL_METRICS_API_KEY = Symbol.for( - 'io.opentelemetry.js.api.metrics' -); -export const GLOBAL_PROPAGATION_API_KEY = Symbol.for( - 'io.opentelemetry.js.api.propagation' -); -export const GLOBAL_TRACE_API_KEY = Symbol.for('io.opentelemetry.js.api.trace'); - -type Get = (version: number) => T; -type OtelGlobal = Partial<{ - [GLOBAL_CONTEXT_MANAGER_API_KEY]: Get; - [GLOBAL_METRICS_API_KEY]: Get; - [GLOBAL_PROPAGATION_API_KEY]: Get; - [GLOBAL_TRACE_API_KEY]: Get; -}>; - -export const _global = _globalThis as OtelGlobal; - -/** - * Make a function which accepts a version integer and returns the instance of an API if the version - * is compatible, or a fallback version (usually NOOP) if it is not. - * - * @param requiredVersion Backwards compatibility version which is required to return the instance - * @param instance Instance which should be returned if the required version is compatible - * @param fallback Fallback instance, usually NOOP, which will be returned if the required version is not compatible - */ -export function makeGetter( - requiredVersion: number, - instance: T, - fallback: T -): Get { - return (version: number): T => - version === requiredVersion ? instance : fallback; -} - -/** - * A number which should be incremented each time a backwards incompatible - * change is made to the API. This number is used when an API package - * attempts to access the global API to ensure it is getting a compatible - * version. If the global API is not compatible with the API package - * attempting to get it, a NOOP API implementation will be returned. - */ -export const API_BACKWARDS_COMPATIBILITY_VERSION = 3; diff --git a/packages/opentelemetry-api/src/api/metrics.ts b/packages/opentelemetry-api/src/api/metrics.ts index f06b09fa367..7bbe28b02b0 100644 --- a/packages/opentelemetry-api/src/api/metrics.ts +++ b/packages/opentelemetry-api/src/api/metrics.ts @@ -18,11 +18,12 @@ import { Meter } from '../metrics/Meter'; import { MeterProvider } from '../metrics/MeterProvider'; import { NOOP_METER_PROVIDER } from '../metrics/NoopMeterProvider'; import { - API_BACKWARDS_COMPATIBILITY_VERSION, - GLOBAL_METRICS_API_KEY, - makeGetter, - _global, -} from './global-utils'; + getGlobal, + registerGlobal, + unregisterGlobal, +} from '../internal/global-utils'; + +const API_NAME = 'metrics'; /** * Singleton object which represents the entry point to the OpenTelemetry Metrics API @@ -46,17 +47,7 @@ export class MetricsAPI { * Set the current global meter. Returns the initialized global meter provider. */ public setGlobalMeterProvider(provider: MeterProvider): MeterProvider { - if (_global[GLOBAL_METRICS_API_KEY]) { - // global meter provider has already been set - return this.getMeterProvider(); - } - - _global[GLOBAL_METRICS_API_KEY] = makeGetter( - API_BACKWARDS_COMPATIBILITY_VERSION, - provider, - NOOP_METER_PROVIDER - ); - + registerGlobal(API_NAME, provider); return provider; } @@ -64,10 +55,7 @@ export class MetricsAPI { * Returns the global meter provider. */ public getMeterProvider(): MeterProvider { - return ( - _global[GLOBAL_METRICS_API_KEY]?.(API_BACKWARDS_COMPATIBILITY_VERSION) ?? - NOOP_METER_PROVIDER - ); + return getGlobal(API_NAME) || NOOP_METER_PROVIDER; } /** @@ -79,6 +67,6 @@ export class MetricsAPI { /** Remove the global meter provider */ public disable() { - delete _global[GLOBAL_METRICS_API_KEY]; + unregisterGlobal(API_NAME); } } diff --git a/packages/opentelemetry-api/src/api/propagation.ts b/packages/opentelemetry-api/src/api/propagation.ts index a07b88b94d2..ff3f24be743 100644 --- a/packages/opentelemetry-api/src/api/propagation.ts +++ b/packages/opentelemetry-api/src/api/propagation.ts @@ -24,11 +24,12 @@ import { TextMapSetter, } from '../context/propagation/TextMapPropagator'; import { - API_BACKWARDS_COMPATIBILITY_VERSION, - GLOBAL_PROPAGATION_API_KEY, - makeGetter, - _global, -} from './global-utils'; + getGlobal, + registerGlobal, + unregisterGlobal, +} from '../internal/global-utils'; + +const API_NAME = 'propagation'; /** * Singleton object which represents the entry point to the OpenTelemetry Propagation API @@ -52,17 +53,7 @@ export class PropagationAPI { * Set the current propagator. Returns the initialized propagator */ public setGlobalPropagator(propagator: TextMapPropagator): TextMapPropagator { - if (_global[GLOBAL_PROPAGATION_API_KEY]) { - // global propagator has already been set - return this._getGlobalPropagator(); - } - - _global[GLOBAL_PROPAGATION_API_KEY] = makeGetter( - API_BACKWARDS_COMPATIBILITY_VERSION, - propagator, - NOOP_TEXT_MAP_PROPAGATOR - ); - + registerGlobal(API_NAME, propagator); return propagator; } @@ -98,14 +89,10 @@ export class PropagationAPI { /** Remove the global propagator */ public disable() { - delete _global[GLOBAL_PROPAGATION_API_KEY]; + unregisterGlobal(API_NAME); } private _getGlobalPropagator(): TextMapPropagator { - return ( - _global[GLOBAL_PROPAGATION_API_KEY]?.( - API_BACKWARDS_COMPATIBILITY_VERSION - ) ?? NOOP_TEXT_MAP_PROPAGATOR - ); + return getGlobal(API_NAME) || NOOP_TEXT_MAP_PROPAGATOR; } } diff --git a/packages/opentelemetry-api/src/api/trace.ts b/packages/opentelemetry-api/src/api/trace.ts index f0c2005577a..f9beba0cab9 100644 --- a/packages/opentelemetry-api/src/api/trace.ts +++ b/packages/opentelemetry-api/src/api/trace.ts @@ -14,17 +14,17 @@ * limitations under the License. */ -import { NOOP_TRACER_PROVIDER } from '../trace/NoopTracerProvider'; import { ProxyTracerProvider } from '../trace/ProxyTracerProvider'; import { Tracer } from '../trace/tracer'; import { TracerProvider } from '../trace/tracer_provider'; import { isSpanContextValid } from '../trace/spancontext-utils'; import { - API_BACKWARDS_COMPATIBILITY_VERSION, - GLOBAL_TRACE_API_KEY, - makeGetter, - _global, -} from './global-utils'; + getGlobal, + registerGlobal, + unregisterGlobal, +} from '../internal/global-utils'; + +const API_NAME = 'trace'; /** * Singleton object which represents the entry point to the OpenTelemetry Tracing API @@ -50,30 +50,16 @@ export class TraceAPI { * Set the current global tracer. Returns the initialized global tracer provider */ public setGlobalTracerProvider(provider: TracerProvider): TracerProvider { - if (_global[GLOBAL_TRACE_API_KEY]) { - // global tracer provider has already been set - return this.getTracerProvider(); - } - this._proxyTracerProvider.setDelegate(provider); - - _global[GLOBAL_TRACE_API_KEY] = makeGetter( - API_BACKWARDS_COMPATIBILITY_VERSION, - this._proxyTracerProvider, - NOOP_TRACER_PROVIDER - ); - - return this.getTracerProvider(); + registerGlobal(API_NAME, this._proxyTracerProvider); + return this._proxyTracerProvider; } /** * Returns the global tracer provider. */ public getTracerProvider(): TracerProvider { - return ( - _global[GLOBAL_TRACE_API_KEY]?.(API_BACKWARDS_COMPATIBILITY_VERSION) ?? - this._proxyTracerProvider - ); + return getGlobal(API_NAME) || this._proxyTracerProvider; } /** @@ -85,7 +71,7 @@ export class TraceAPI { /** Remove the global tracer provider */ public disable() { - delete _global[GLOBAL_TRACE_API_KEY]; + unregisterGlobal(API_NAME); this._proxyTracerProvider = new ProxyTracerProvider(); } diff --git a/packages/opentelemetry-api/src/internal/global-utils.ts b/packages/opentelemetry-api/src/internal/global-utils.ts new file mode 100644 index 00000000000..6771982845e --- /dev/null +++ b/packages/opentelemetry-api/src/internal/global-utils.ts @@ -0,0 +1,86 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ContextManager } from '@opentelemetry/context-base'; +import type { TextMapPropagator } from '../context/propagation/TextMapPropagator'; +import type { MeterProvider } from '../metrics/MeterProvider'; +import { _globalThis } from '../platform'; +import type { TracerProvider } from '../trace/tracer_provider'; +import { VERSION } from '../version'; +import { isCompatible } from './semver'; + +const GLOBAL_OPENTELEMETRY_API_KEY = Symbol.for('io.opentelemetry.js.api'); + +const _global = _globalThis as OTelGlobal; + +export function registerGlobal( + type: Type, + instance: OTelGlobalAPI[Type] +): void { + _global[GLOBAL_OPENTELEMETRY_API_KEY] = _global[ + GLOBAL_OPENTELEMETRY_API_KEY + ] ?? { + version: VERSION, + }; + + const api = _global[GLOBAL_OPENTELEMETRY_API_KEY]!; + if (api[type]) { + // already registered an API of this type + throw new Error( + `@opentelemetry/api: Attempted duplicate registration of API: ${type}` + ); + } + + if (api.version != VERSION) { + // All registered APIs must be of the same version exactly + throw new Error( + '@opentelemetry/api: All API registration versions must match' + ); + } + + api[type] = instance; +} + +export function getGlobal( + type: Type +): OTelGlobalAPI[Type] | undefined { + const version = _global[GLOBAL_OPENTELEMETRY_API_KEY]?.version; + if (!version || !isCompatible(version)) { + return; + } + return _global[GLOBAL_OPENTELEMETRY_API_KEY]?.[type]; +} + +export function unregisterGlobal(type: keyof OTelGlobalAPI) { + const api = _global[GLOBAL_OPENTELEMETRY_API_KEY]; + + if (api) { + delete api[type]; + } +} + +type OTelGlobal = { + [GLOBAL_OPENTELEMETRY_API_KEY]?: OTelGlobalAPI; +}; + +type OTelGlobalAPI = { + version: string; + + trace?: TracerProvider; + metrics?: MeterProvider; + context?: ContextManager; + propagation?: TextMapPropagator; +}; diff --git a/packages/opentelemetry-api/src/internal/semver.ts b/packages/opentelemetry-api/src/internal/semver.ts new file mode 100644 index 00000000000..fba640d4eb6 --- /dev/null +++ b/packages/opentelemetry-api/src/internal/semver.ts @@ -0,0 +1,113 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { VERSION } from '../version'; + +const re = /^(\d+)\.(\d+)\.(\d+)(?:-(.*))?$/; + +/** + * Create a function to test an API version to see if it is compatible with the provided ownVersion. + * + * The returned function has the following semantics: + * - Exact match is always compatible + * - Major versions must always match + * - The minor version of the API module requesting access to the global API must be greater or equal to the minor version of this API + * - Patch and build tag differences are not considered at this time + * + * @param ownVersion version which should be checked against + */ +export function _makeCompatibilityCheck( + ownVersion: string +): (version: string) => boolean { + const acceptedVersions = new Set([ownVersion]); + const rejectedVersions = new Set(); + + const myVersionMatch = ownVersion.match(re); + if (!myVersionMatch) { + throw new Error('Cannot parse own version'); + } + + const ownVersionParsed = { + major: +myVersionMatch[1], + minor: +myVersionMatch[2], + patch: +myVersionMatch[3], + }; + + return function isCompatible(version: string): boolean { + if (acceptedVersions.has(version)) { + return true; + } + + if (rejectedVersions.has(version)) { + return false; + } + + const m = version.match(re); + if (!m) { + // cannot parse other version + rejectedVersions.add(version); + return false; + } + + const otherVersionParsed = { + major: +m[1], + minor: +m[2], + patch: +m[3], + }; + + // major versions must match + if (ownVersionParsed.major != otherVersionParsed.major) { + rejectedVersions.add(version); + return false; + } + + // if major version is 0, minor is treated like major and patch is treated like minor + if (ownVersionParsed.major === 0) { + if (ownVersionParsed.minor != otherVersionParsed.minor) { + rejectedVersions.add(version); + return false; + } + + if (ownVersionParsed.patch < otherVersionParsed.patch) { + rejectedVersions.add(version); + return false; + } + + acceptedVersions.add(version); + return true; + } + + if (ownVersionParsed.minor < otherVersionParsed.minor) { + rejectedVersions.add(version); + return false; + } + + acceptedVersions.add(version); + return true; + }; +} + +/** + * Test an API version to see if it is compatible with this API. + * + * - Exact match is always compatible + * - Major versions must always match + * - The minor version of the API module requesting access to the global API must be greater or equal to the minor version of this API + * - Patch and build tag differences are not considered at this time + * + * @param version version of the API requesting an instance of the global API + */ +export const isCompatible = _makeCompatibilityCheck(VERSION); diff --git a/packages/opentelemetry-api/test/api/global.test.ts b/packages/opentelemetry-api/test/internal/global.test.ts similarity index 80% rename from packages/opentelemetry-api/test/api/global.test.ts rename to packages/opentelemetry-api/test/internal/global.test.ts index 7d9ea5b9caa..13c7e82d690 100644 --- a/packages/opentelemetry-api/test/api/global.test.ts +++ b/packages/opentelemetry-api/test/internal/global.test.ts @@ -16,10 +16,8 @@ import * as assert from 'assert'; import { NoopContextManager } from '@opentelemetry/context-base'; -import { - _global, - GLOBAL_CONTEXT_MANAGER_API_KEY, -} from '../../src/api/global-utils'; +import { getGlobal } from '../../src/internal/global-utils'; +import { _globalThis } from '../../src/platform'; const api1 = require('../../src') as typeof import('../../src'); @@ -73,9 +71,17 @@ describe('Global Utils', () => { it('should return the module NoOp implementation if the version is a mismatch', () => { const original = api1.context['_getContextManager'](); - api1.context.setGlobalContextManager(new NoopContextManager()); - const afterSet = _global[GLOBAL_CONTEXT_MANAGER_API_KEY]!(-1); - assert.strictEqual(original, afterSet); + const newContextManager = new NoopContextManager(); + api1.context.setGlobalContextManager(newContextManager); + + assert.strictEqual(api1.context['_getContextManager'](), newContextManager); + + const globalInstance = getGlobal('context'); + assert.ok(globalInstance); + // @ts-ignore we are modifying internals for testing purposes here + _globalThis[Symbol.for('io.opentelemetry.js.api')].version = '0.0.1'; + + assert.strictEqual(api1.context['_getContextManager'](), original); }); }); diff --git a/packages/opentelemetry-api/test/internal/semver.test.ts b/packages/opentelemetry-api/test/internal/semver.test.ts new file mode 100644 index 00000000000..6020723b5cd --- /dev/null +++ b/packages/opentelemetry-api/test/internal/semver.test.ts @@ -0,0 +1,101 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as assert from 'assert'; +import { + isCompatible, + _makeCompatibilityCheck, +} from '../../src/internal/semver'; +import { VERSION } from '../../src/version'; + +describe('Version Compatibility', () => { + it('should be compatible if versions are equal', () => { + assert.ok(isCompatible(VERSION)); + }); + + describe('throws if own version cannot be parsed', () => { + assert.throws(() => { + _makeCompatibilityCheck('this is not semver'); + }); + }); + + describe('incompatible if other version cannot be parsed', () => { + const check = _makeCompatibilityCheck('0.1.2'); + assert.ok(!check('this is not semver')); + }); + + describe('>= 1.x', () => { + it('should be compatible if major and minor versions are equal', () => { + const check = _makeCompatibilityCheck('1.2.3'); + assert.ok(check('1.2.2')); + assert.ok(check('1.2.2-alpha')); + assert.ok(check('1.2.4')); + assert.ok(check('1.2.4-alpha')); + }); + + it('should be compatible if major versions are equal and minor version is lesser', () => { + const check = _makeCompatibilityCheck('1.2.3'); + assert.ok(check('1.1.2')); + assert.ok(check('1.1.2-alpha')); + assert.ok(check('1.1.4')); + assert.ok(check('1.1.4-alpha')); + }); + + it('should be incompatible if major versions do not match', () => { + const check = _makeCompatibilityCheck('3.3.3'); + assert.ok(!check('0.3.3')); + assert.ok(!check('0.3.3')); + }); + + it('should be incompatible if major versions match but other minor version is greater than our minor version', () => { + const check = _makeCompatibilityCheck('1.2.3'); + assert.ok(!check('1.3.3-alpha')); + assert.ok(!check('1.3.3')); + }); + }); + + describe('0.x', () => { + it('should be compatible if minor and patch versions are equal', () => { + const check = _makeCompatibilityCheck('0.1.2'); + assert.ok(check('0.1.2')); + assert.ok(check('0.1.2-alpha')); + }); + + it('should be compatible if minor versions are equal and patch version is lesser', () => { + const check = _makeCompatibilityCheck('0.1.2'); + assert.ok(check('0.1.1')); + assert.ok(check('0.1.1-alpha')); + }); + + it('should be incompatible if minor versions do not match', () => { + const check = _makeCompatibilityCheck('0.3.3'); + assert.ok(!check('0.2.3')); + assert.ok(!check('0.4.3')); + }); + + it('should be incompatible if minor versions do not match', () => { + const check = _makeCompatibilityCheck('0.3.3'); + assert.ok(!check('0.2.3')); + assert.ok(!check('0.4.3')); + }); + + it('should be incompatible if minor versions match but other patch version is greater than our patch version', () => { + const check = _makeCompatibilityCheck('0.3.3'); + assert.ok(!check('0.3.4-alpha')); + assert.ok(!check('0.3.4')); + }); + }); +}); diff --git a/packages/opentelemetry-grpc-utils/test/grpcUtils.test.ts b/packages/opentelemetry-grpc-utils/test/grpcUtils.test.ts index f53055e620e..db785e99d25 100644 --- a/packages/opentelemetry-grpc-utils/test/grpcUtils.test.ts +++ b/packages/opentelemetry-grpc-utils/test/grpcUtils.test.ts @@ -397,6 +397,10 @@ export const runTests = ( propagation.setGlobalPropagator(new HttpTraceContext()); }); + after(() => { + propagation.disable(); + }); + beforeEach(() => { contextManager = new AsyncHooksContextManager().enable(); context.setGlobalContextManager(contextManager); diff --git a/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts b/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts index 4cf1c175fa4..055b279fb88 100644 --- a/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts +++ b/packages/opentelemetry-instrumentation-http/test/functionals/http-enable.test.ts @@ -67,7 +67,6 @@ const provider = new NodeTracerProvider({ }); provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); instrumentation.setTracerProvider(provider); -propagation.setGlobalPropagator(new DummyPropagation()); function doNock( hostname: string, @@ -104,6 +103,14 @@ export const responseHookFunction = ( describe('HttpInstrumentation', () => { let contextManager: ContextManager; + before(() => { + propagation.setGlobalPropagator(new DummyPropagation()); + }); + + after(() => { + propagation.disable(); + }); + beforeEach(() => { contextManager = new AsyncHooksContextManager().enable(); context.setGlobalContextManager(contextManager); diff --git a/packages/opentelemetry-instrumentation-http/test/functionals/http-package.test.ts b/packages/opentelemetry-instrumentation-http/test/functionals/http-package.test.ts index 4ea82d27655..3249ba531cd 100644 --- a/packages/opentelemetry-instrumentation-http/test/functionals/http-package.test.ts +++ b/packages/opentelemetry-instrumentation-http/test/functionals/http-package.test.ts @@ -67,12 +67,12 @@ describe('Packages', () => { }); provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); instrumentation.setTracerProvider(provider); - propagation.setGlobalPropagator(new DummyPropagation()); beforeEach(() => { memoryExporter.reset(); }); before(() => { + propagation.setGlobalPropagator(new DummyPropagation()); instrumentation.setConfig({ applyCustomAttributesOnSpan: customAttributeFunction, }); @@ -81,6 +81,7 @@ describe('Packages', () => { after(() => { // back to normal + propagation.disable(); nock.cleanAll(); nock.enableNetConnect(); }); diff --git a/packages/opentelemetry-instrumentation-http/test/functionals/https-enable.test.ts b/packages/opentelemetry-instrumentation-http/test/functionals/https-enable.test.ts index 7e5c6a4ef2c..811daa3a17f 100644 --- a/packages/opentelemetry-instrumentation-http/test/functionals/https-enable.test.ts +++ b/packages/opentelemetry-instrumentation-http/test/functionals/https-enable.test.ts @@ -69,7 +69,6 @@ const provider = new BasicTracerProvider({ instrumentation.setTracerProvider(provider); const tracer = provider.getTracer('test-https'); provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); -propagation.setGlobalPropagator(new DummyPropagation()); function doNock( hostname: string, @@ -94,12 +93,14 @@ describe('HttpsInstrumentation', () => { beforeEach(() => { contextManager = new AsyncHooksContextManager().enable(); + propagation.setGlobalPropagator(new DummyPropagation()); context.setGlobalContextManager(contextManager); }); afterEach(() => { contextManager.disable(); context.disable(); + propagation.disable(); }); describe('enable()', () => { diff --git a/packages/opentelemetry-instrumentation-http/test/functionals/https-package.test.ts b/packages/opentelemetry-instrumentation-http/test/functionals/https-package.test.ts index 6169ff1b329..c2779afa284 100644 --- a/packages/opentelemetry-instrumentation-http/test/functionals/https-package.test.ts +++ b/packages/opentelemetry-instrumentation-http/test/functionals/https-package.test.ts @@ -68,12 +68,12 @@ describe('Packages', () => { }); provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); instrumentation.setTracerProvider(provider); - propagation.setGlobalPropagator(new DummyPropagation()); beforeEach(() => { memoryExporter.reset(); }); before(() => { + propagation.setGlobalPropagator(new DummyPropagation()); instrumentation.setConfig({ applyCustomAttributesOnSpan: customAttributeFunction, }); @@ -84,6 +84,7 @@ describe('Packages', () => { // back to normal nock.cleanAll(); nock.enableNetConnect(); + propagation.disable(); }); let resHeaders: http.IncomingHttpHeaders; diff --git a/packages/opentelemetry-instrumentation-http/test/integrations/http-enable.test.ts b/packages/opentelemetry-instrumentation-http/test/integrations/http-enable.test.ts index f0ba3ec005b..ee0f23e04cc 100644 --- a/packages/opentelemetry-instrumentation-http/test/integrations/http-enable.test.ts +++ b/packages/opentelemetry-instrumentation-http/test/integrations/http-enable.test.ts @@ -58,11 +58,16 @@ const customAttributeFunction = (span: Span): void => { describe('HttpInstrumentation Integration tests', () => { beforeEach(() => { memoryExporter.reset(); + }); + + before(() => { + propagation.setGlobalPropagator(new DummyPropagation()); context.setGlobalContextManager(new AsyncHooksContextManager().enable()); }); - afterEach(() => { + after(() => { context.disable(); + propagation.disable(); }); describe('enable()', () => { before(function (done) { @@ -85,7 +90,6 @@ describe('HttpInstrumentation Integration tests', () => { const provider = new NodeTracerProvider({ logger, }); - propagation.setGlobalPropagator(new DummyPropagation()); provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); instrumentation.setTracerProvider(provider); beforeEach(() => { diff --git a/packages/opentelemetry-instrumentation-http/test/integrations/https-enable.test.ts b/packages/opentelemetry-instrumentation-http/test/integrations/https-enable.test.ts index 880c2ec0f6a..7ee13b7d635 100644 --- a/packages/opentelemetry-instrumentation-http/test/integrations/https-enable.test.ts +++ b/packages/opentelemetry-instrumentation-http/test/integrations/https-enable.test.ts @@ -86,7 +86,6 @@ describe('HttpsInstrumentation Integration tests', () => { const provider = new NodeTracerProvider({ logger, }); - propagation.setGlobalPropagator(new DummyPropagation()); provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); instrumentation.setTracerProvider(provider); beforeEach(() => { @@ -99,6 +98,7 @@ describe('HttpsInstrumentation Integration tests', () => { /\/ignored\/regexp$/i, (url: string) => url.endsWith('/ignored/function'), ]; + propagation.setGlobalPropagator(new DummyPropagation()); instrumentation.setConfig({ ignoreIncomingPaths: ignoreConfig, ignoreOutgoingUrls: ignoreConfig, @@ -109,6 +109,7 @@ describe('HttpsInstrumentation Integration tests', () => { after(() => { instrumentation.disable(); + propagation.disable(); }); it('should create a rootSpan for GET requests and add propagation headers', async () => { diff --git a/packages/opentelemetry-instrumentation-xml-http-request/test/xhr.test.ts b/packages/opentelemetry-instrumentation-xml-http-request/test/xhr.test.ts index f5acb4ebf89..799a115fc59 100644 --- a/packages/opentelemetry-instrumentation-xml-http-request/test/xhr.test.ts +++ b/packages/opentelemetry-instrumentation-xml-http-request/test/xhr.test.ts @@ -150,6 +150,10 @@ describe('xhr', () => { ); }); + after(() => { + api.propagation.disable(); + }); + describe('when request is successful', () => { let webTracerWithZone: api.Tracer; let webTracerProviderWithZone: WebTracerProvider; diff --git a/packages/opentelemetry-plugin-fetch/test/fetch.test.ts b/packages/opentelemetry-plugin-fetch/test/fetch.test.ts index 80c3000b1f7..23ec87d217f 100644 --- a/packages/opentelemetry-plugin-fetch/test/fetch.test.ts +++ b/packages/opentelemetry-plugin-fetch/test/fetch.test.ts @@ -232,6 +232,10 @@ describe('fetch', () => { ); }); + after(() => { + api.propagation.disable(); + }); + describe('when request is successful', () => { beforeEach(done => { const propagateTraceHeaderCorsUrls = [url]; diff --git a/packages/opentelemetry-plugin-http/test/functionals/http-enable.test.ts b/packages/opentelemetry-plugin-http/test/functionals/http-enable.test.ts index b34816f76ab..a134e096feb 100644 --- a/packages/opentelemetry-plugin-http/test/functionals/http-enable.test.ts +++ b/packages/opentelemetry-plugin-http/test/functionals/http-enable.test.ts @@ -60,7 +60,6 @@ const provider = new NodeTracerProvider({ logger, }); provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); -propagation.setGlobalPropagator(new DummyPropagation()); function doNock( hostname: string, @@ -97,6 +96,14 @@ export const responseHookFunction = ( describe('HttpPlugin', () => { let contextManager: ContextManager; + before(() => { + propagation.setGlobalPropagator(new DummyPropagation()); + }); + + after(() => { + propagation.disable(); + }); + beforeEach(() => { contextManager = new AsyncHooksContextManager().enable(); context.setGlobalContextManager(contextManager); diff --git a/packages/opentelemetry-plugin-http/test/functionals/http-package.test.ts b/packages/opentelemetry-plugin-http/test/functionals/http-package.test.ts index 31bb06f48ab..75c9fc0d1d9 100644 --- a/packages/opentelemetry-plugin-http/test/functionals/http-package.test.ts +++ b/packages/opentelemetry-plugin-http/test/functionals/http-package.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { context, SpanKind, NoopLogger } from '@opentelemetry/api'; +import { context, NoopLogger, propagation, SpanKind } from '@opentelemetry/api'; import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; import { NodeTracerProvider } from '@opentelemetry/node'; import { @@ -42,9 +42,11 @@ const protocol = 'http'; describe('Packages', () => { beforeEach(() => { context.setGlobalContextManager(new AsyncHooksContextManager().enable()); + propagation.setGlobalPropagator(new DummyPropagation()); }); afterEach(() => { + propagation.disable(); context.disable(); }); describe('get', () => { diff --git a/packages/opentelemetry-plugin-http/test/integrations/http-enable.test.ts b/packages/opentelemetry-plugin-http/test/integrations/http-enable.test.ts index 383a4b3b456..0d6c051499c 100644 --- a/packages/opentelemetry-plugin-http/test/integrations/http-enable.test.ts +++ b/packages/opentelemetry-plugin-http/test/integrations/http-enable.test.ts @@ -14,26 +14,33 @@ * limitations under the License. */ -import { SpanKind, Span, context, NoopLogger } from '@opentelemetry/api'; import { - HttpAttribute, + context, + NoopLogger, + propagation, + Span, + SpanKind, +} from '@opentelemetry/api'; +import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; +import { NodeTracerProvider } from '@opentelemetry/node'; +import { GeneralAttribute, + HttpAttribute, } from '@opentelemetry/semantic-conventions'; +import { + InMemorySpanExporter, + SimpleSpanProcessor, +} from '@opentelemetry/tracing'; import * as assert from 'assert'; import * as http from 'http'; import * as url from 'url'; import { plugin } from '../../src/http'; +import { HttpPluginConfig } from '../../src/types'; import { assertSpan } from '../utils/assertSpan'; import { DummyPropagation } from '../utils/DummyPropagation'; import { httpRequest } from '../utils/httpRequest'; import * as utils from '../utils/utils'; -import { NodeTracerProvider } from '@opentelemetry/node'; -import { - InMemorySpanExporter, - SimpleSpanProcessor, -} from '@opentelemetry/tracing'; -import { HttpPluginConfig } from '../../src/types'; -import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; + const protocol = 'http'; const serverPort = 32345; const hostname = 'localhost'; @@ -46,11 +53,16 @@ export const customAttributeFunction = (span: Span): void => { describe('HttpPlugin Integration tests', () => { beforeEach(() => { memoryExporter.reset(); + }); + + before(() => { context.setGlobalContextManager(new AsyncHooksContextManager().enable()); + propagation.setGlobalPropagator(new DummyPropagation()); }); - afterEach(() => { + after(() => { context.disable(); + propagation.disable(); }); describe('enable()', () => { before(function (done) { diff --git a/packages/opentelemetry-plugin-https/test/functionals/https-enable.test.ts b/packages/opentelemetry-plugin-https/test/functionals/https-enable.test.ts index 4123a046a6a..871dd9e92d7 100644 --- a/packages/opentelemetry-plugin-https/test/functionals/https-enable.test.ts +++ b/packages/opentelemetry-plugin-https/test/functionals/https-enable.test.ts @@ -62,7 +62,6 @@ const provider = new NodeTracerProvider({ }); const tracer = provider.getTracer('test-https'); provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); -propagation.setGlobalPropagator(new DummyPropagation()); function doNock( hostname: string, @@ -85,6 +84,14 @@ export const customAttributeFunction = (span: ISpan): void => { describe('HttpsPlugin', () => { let contextManager: ContextManager; + before(() => { + propagation.setGlobalPropagator(new DummyPropagation()); + }); + + after(() => { + propagation.disable(); + }); + beforeEach(() => { contextManager = new AsyncHooksContextManager().enable(); context.setGlobalContextManager(contextManager); diff --git a/packages/opentelemetry-plugin-https/test/functionals/https-package.test.ts b/packages/opentelemetry-plugin-https/test/functionals/https-package.test.ts index daf3ac7e9ee..8d227b16d2e 100644 --- a/packages/opentelemetry-plugin-https/test/functionals/https-package.test.ts +++ b/packages/opentelemetry-plugin-https/test/functionals/https-package.test.ts @@ -14,7 +14,13 @@ * limitations under the License. */ -import { context, Span, SpanKind, NoopLogger } from '@opentelemetry/api'; +import { + context, + NoopLogger, + propagation, + Span, + SpanKind, +} from '@opentelemetry/api'; import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; import { NodeTracerProvider } from '@opentelemetry/node'; import { Http } from '@opentelemetry/plugin-http'; @@ -45,11 +51,16 @@ export const customAttributeFunction = (span: Span): void => { describe('Packages', () => { beforeEach(() => { memoryExporter.reset(); + }); + + before(() => { context.setGlobalContextManager(new AsyncHooksContextManager().enable()); + propagation.setGlobalPropagator(new DummyPropagation()); }); - afterEach(() => { + after(() => { context.disable(); + propagation.disable(); }); describe('get', () => { const logger = new NoopLogger(); diff --git a/packages/opentelemetry-plugin-https/test/integrations/https-enable.test.ts b/packages/opentelemetry-plugin-https/test/integrations/https-enable.test.ts index 3fc48cdcadf..f362a522547 100644 --- a/packages/opentelemetry-plugin-https/test/integrations/https-enable.test.ts +++ b/packages/opentelemetry-plugin-https/test/integrations/https-enable.test.ts @@ -14,27 +14,33 @@ * limitations under the License. */ -import { HttpPluginConfig, Http } from '@opentelemetry/plugin-http'; -import { SpanKind, Span, context, NoopLogger } from '@opentelemetry/api'; import { - HttpAttribute, + context, + NoopLogger, + propagation, + Span, + SpanKind, +} from '@opentelemetry/api'; +import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; +import { NodeTracerProvider } from '@opentelemetry/node'; +import { Http, HttpPluginConfig } from '@opentelemetry/plugin-http'; +import { GeneralAttribute, + HttpAttribute, } from '@opentelemetry/semantic-conventions'; +import { + InMemorySpanExporter, + SimpleSpanProcessor, +} from '@opentelemetry/tracing'; import * as assert from 'assert'; import * as http from 'http'; import * as https from 'https'; +import * as url from 'url'; import { plugin } from '../../src/https'; import { assertSpan } from '../utils/assertSpan'; import { DummyPropagation } from '../utils/DummyPropagation'; import { httpsRequest } from '../utils/httpsRequest'; -import * as url from 'url'; import * as utils from '../utils/utils'; -import { NodeTracerProvider } from '@opentelemetry/node'; -import { - InMemorySpanExporter, - SimpleSpanProcessor, -} from '@opentelemetry/tracing'; -import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks'; const protocol = 'https'; const serverPort = 42345; @@ -48,11 +54,16 @@ export const customAttributeFunction = (span: Span): void => { describe('HttpsPlugin Integration tests', () => { beforeEach(() => { memoryExporter.reset(); + }); + + before(() => { context.setGlobalContextManager(new AsyncHooksContextManager().enable()); + propagation.setGlobalPropagator(new DummyPropagation()); }); - afterEach(() => { + after(() => { context.disable(); + propagation.disable(); }); describe('enable()', () => { diff --git a/packages/opentelemetry-shim-opentracing/test/Shim.test.ts b/packages/opentelemetry-shim-opentracing/test/Shim.test.ts index ba0b3b461d1..698eeee17fa 100644 --- a/packages/opentelemetry-shim-opentracing/test/Shim.test.ts +++ b/packages/opentelemetry-shim-opentracing/test/Shim.test.ts @@ -37,7 +37,13 @@ describe('OpenTracing Shim', () => { propagators: [new HttpTraceContext(), new HttpBaggage()], }); - propagation.setGlobalPropagator(compositePropagator); + before(() => { + propagation.setGlobalPropagator(compositePropagator); + }); + + after(() => { + propagation.disable(); + }); describe('TracerShim', () => { let span: opentracing.Span;