Skip to content

Commit

Permalink
chore: share context utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
dyladan committed Apr 24, 2020
1 parent 8f377e7 commit a1c408e
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 63 deletions.
33 changes: 15 additions & 18 deletions packages/opentelemetry-api/src/api/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,17 @@
*/

import {
Context,
ContextManager,
NoopContextManager,
Context,
} from '@opentelemetry/context-base';
import {
GLOBAL_CONTEXT_MANAGER_API_KEY,
makeGetter,
_global,
} from './global-utils';

const NOOP_CONTEXT_MANAGER = new NoopContextManager();

const GLOBAL_CONTEXT_MANAGER_API_KEY = Symbol.for(
'io.opentelemetry.js.api.context'
);
const API_VERSION = 0;

/**
Expand All @@ -51,20 +52,16 @@ export class ContextAPI {
public setGlobalContextManager(
contextManager: ContextManager
): ContextManager {
if ((global as any)[GLOBAL_CONTEXT_MANAGER_API_KEY]) {
if (_global[GLOBAL_CONTEXT_MANAGER_API_KEY]) {
// global context manager has already been set
return NOOP_CONTEXT_MANAGER;
}

(global as any)[GLOBAL_CONTEXT_MANAGER_API_KEY] = function getTraceApi(
version: number
) {
if (version !== API_VERSION) {
return NOOP_CONTEXT_MANAGER;
}

return contextManager;
};
_global[GLOBAL_CONTEXT_MANAGER_API_KEY] = makeGetter(
API_VERSION,
contextManager,
NOOP_CONTEXT_MANAGER
);

return contextManager;
}
Expand Down Expand Up @@ -100,16 +97,16 @@ export class ContextAPI {
}

private _getContextManager(): ContextManager {
if (!(global as any)[GLOBAL_CONTEXT_MANAGER_API_KEY]) {
if (!_global[GLOBAL_CONTEXT_MANAGER_API_KEY]) {
return NOOP_CONTEXT_MANAGER;
}

return (global as any)[GLOBAL_CONTEXT_MANAGER_API_KEY](API_VERSION);
return _global[GLOBAL_CONTEXT_MANAGER_API_KEY]!(API_VERSION);
}

/** Disable and remove the global context manager */
public disable() {
this._getContextManager().disable();
delete (global as any)[GLOBAL_CONTEXT_MANAGER_API_KEY];
delete _global[GLOBAL_CONTEXT_MANAGER_API_KEY];
}
}
50 changes: 50 additions & 0 deletions packages/opentelemetry-api/src/api/global-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*!
* Copyright 2020, 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 { HttpTextPropagator } from '../context/propagation/HttpTextPropagator';
import { MeterProvider } from '../metrics/MeterProvider';
import { TracerProvider } from '../trace/tracer_provider';

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<T> = (version: number) => T;
type MyGlobals = Partial<{
[GLOBAL_CONTEXT_MANAGER_API_KEY]: Get<ContextManager>;
[GLOBAL_METRICS_API_KEY]: Get<MeterProvider>;
[GLOBAL_PROPAGATION_API_KEY]: Get<HttpTextPropagator>;
[GLOBAL_TRACE_API_KEY]: Get<TracerProvider>;
}>;

export const _global = global as typeof global & MyGlobals;

export function makeGetter<T>(
requiredVersion: number,
instance: T,
fallback: T
): Get<T> {
return (version: number): T =>
version === requiredVersion ? instance : fallback;
}
24 changes: 10 additions & 14 deletions packages/opentelemetry-api/src/api/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
import { Meter } from '../metrics/Meter';
import { MeterProvider } from '../metrics/MeterProvider';
import { NOOP_METER_PROVIDER } from '../metrics/NoopMeterProvider';
import { GLOBAL_METRICS_API_KEY, makeGetter, _global } from './global-utils';

const GLOBAL_METRICS_API_KEY = Symbol.for('io.opentelemetry.js.api.metrics');
const API_VERSION = 0;

/**
Expand All @@ -43,20 +43,16 @@ export class MetricsAPI {
* Set the current global meter. Returns the initialized global meter provider.
*/
public setGlobalMeterProvider(provider: MeterProvider): MeterProvider {
if ((global as any)[GLOBAL_METRICS_API_KEY]) {
if (_global[GLOBAL_METRICS_API_KEY]) {
// global meter provider has already been set
return NOOP_METER_PROVIDER;
}

(global as any)[GLOBAL_METRICS_API_KEY] = function getTraceApi(
version: number
) {
if (version !== API_VERSION) {
return NOOP_METER_PROVIDER;
}

return provider;
};
_global[GLOBAL_METRICS_API_KEY] = makeGetter(
API_VERSION,
provider,
NOOP_METER_PROVIDER
);

return provider;
}
Expand All @@ -65,11 +61,11 @@ export class MetricsAPI {
* Returns the global meter provider.
*/
public getMeterProvider(): MeterProvider {
if (!(global as any)[GLOBAL_METRICS_API_KEY]) {
if (!_global[GLOBAL_METRICS_API_KEY]) {
return NOOP_METER_PROVIDER;
}

return (global as any)[GLOBAL_METRICS_API_KEY](API_VERSION);
return _global[GLOBAL_METRICS_API_KEY]!(API_VERSION);
}

/**
Expand All @@ -81,6 +77,6 @@ export class MetricsAPI {

/** Remove the global meter provider */
public disable() {
delete (global as any)[GLOBAL_METRICS_API_KEY];
delete _global[GLOBAL_METRICS_API_KEY];
}
}
30 changes: 14 additions & 16 deletions packages/opentelemetry-api/src/api/propagation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ import { HttpTextPropagator } from '../context/propagation/HttpTextPropagator';
import { NOOP_HTTP_TEXT_PROPAGATOR } from '../context/propagation/NoopHttpTextPropagator';
import { defaultSetter, SetterFunction } from '../context/propagation/setter';
import { ContextAPI } from './context';
import {
GLOBAL_PROPAGATION_API_KEY,
makeGetter,
_global,
} from './global-utils';

const contextApi = ContextAPI.getInstance();

const GLOBAL_PROPAGATION_API_KEY = Symbol.for(
'io.opentelemetry.js.api.propagation'
);
const API_VERSION = 0;

/**
Expand All @@ -52,20 +54,16 @@ export class PropagationAPI {
public setGlobalPropagator(
propagator: HttpTextPropagator
): HttpTextPropagator {
if ((global as any)[GLOBAL_PROPAGATION_API_KEY]) {
if (_global[GLOBAL_PROPAGATION_API_KEY]) {
// global propagator has already been set
return NOOP_HTTP_TEXT_PROPAGATOR;
}

(global as any)[GLOBAL_PROPAGATION_API_KEY] = function getTraceApi(
version: number
) {
if (version !== API_VERSION) {
return NOOP_HTTP_TEXT_PROPAGATOR;
}

return propagator;
};
_global[GLOBAL_PROPAGATION_API_KEY] = makeGetter(
API_VERSION,
propagator,
NOOP_HTTP_TEXT_PROPAGATOR
);

return propagator;
}
Expand Down Expand Up @@ -102,14 +100,14 @@ export class PropagationAPI {

/** Remove the global propagator */
public disable() {
delete (global as any)[GLOBAL_PROPAGATION_API_KEY];
delete _global[GLOBAL_PROPAGATION_API_KEY];
}

private _getGlobalPropagator(): HttpTextPropagator {
if (!(global as any)[GLOBAL_PROPAGATION_API_KEY]) {
if (!_global[GLOBAL_PROPAGATION_API_KEY]) {
return NOOP_HTTP_TEXT_PROPAGATOR;
}

return (global as any)[GLOBAL_PROPAGATION_API_KEY](API_VERSION);
return _global[GLOBAL_PROPAGATION_API_KEY]!(API_VERSION);
}
}
26 changes: 11 additions & 15 deletions packages/opentelemetry-api/src/api/trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
*/

import { NOOP_TRACER_PROVIDER } from '../trace/NoopTracerProvider';
import { TracerProvider } from '../trace/tracer_provider';
import { Tracer } from '../trace/tracer';
import { TracerProvider } from '../trace/tracer_provider';
import { GLOBAL_TRACE_API_KEY, makeGetter, _global } from './global-utils';

const GLOBAL_TRACE_API_KEY = Symbol.for('io.opentelemetry.js.api.trace');
const API_VERSION = 0;

/**
Expand All @@ -43,20 +43,16 @@ export class TraceAPI {
* Set the current global tracer. Returns the initialized global tracer provider
*/
public setGlobalTracerProvider(provider: TracerProvider): TracerProvider {
if ((global as any)[GLOBAL_TRACE_API_KEY]) {
if (_global[GLOBAL_TRACE_API_KEY]) {
// global tracer provider has already been set
return NOOP_TRACER_PROVIDER;
}

(global as any)[GLOBAL_TRACE_API_KEY] = function getTraceApi(
version: number
) {
if (version !== API_VERSION) {
return NOOP_TRACER_PROVIDER;
}

return provider;
};
_global[GLOBAL_TRACE_API_KEY] = makeGetter(
API_VERSION,
provider,
NOOP_TRACER_PROVIDER
);

return this.getTracerProvider();
}
Expand All @@ -65,12 +61,12 @@ export class TraceAPI {
* Returns the global tracer provider.
*/
public getTracerProvider(): TracerProvider {
if (!(global as any)[GLOBAL_TRACE_API_KEY]) {
if (!_global[GLOBAL_TRACE_API_KEY]) {
// global tracer provider has already been set
return NOOP_TRACER_PROVIDER;
}

return (global as any)[GLOBAL_TRACE_API_KEY](API_VERSION);
return _global[GLOBAL_TRACE_API_KEY]!(API_VERSION);
}

/**
Expand All @@ -82,6 +78,6 @@ export class TraceAPI {

/** Remove the global tracer provider */
public disable() {
delete (global as any)[GLOBAL_TRACE_API_KEY];
delete _global[GLOBAL_TRACE_API_KEY];
}
}
81 changes: 81 additions & 0 deletions packages/opentelemetry-api/test/api/global.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*!
* Copyright 2020, 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 { NoopContextManager } from '@opentelemetry/context-base';
import {
_global,
GLOBAL_CONTEXT_MANAGER_API_KEY,
} from '../../src/api/global-utils';

const api1 = require('../../src') as typeof import('../../src');

// clear cache and load a second instance of the api
for (const key of Object.keys(require.cache)) {
delete require.cache[key];
}
const api2 = require('../../src') as typeof import('../../src');

describe('Global Utils', () => {
// prove they are separate instances
assert.notEqual(api1, api2);
// that return separate noop instances to start
assert.notStrictEqual(
api1.context['_getContextManager'](),
api2.context['_getContextManager']()
);

beforeEach(() => {
api1.context.disable();
api1.propagation.disable();
api1.trace.disable();
api1.metrics.disable();
});

it('should change the global context manager', () => {
const original = api1.context['_getContextManager']();
const newContextManager = new NoopContextManager();
api1.context.setGlobalContextManager(newContextManager);
assert.notStrictEqual(api1.context['_getContextManager'](), original);
assert.strictEqual(api1.context['_getContextManager'](), newContextManager);
});

it('should load an instance from one which was set in the other', () => {
api1.context.setGlobalContextManager(new NoopContextManager());
assert.strictEqual(
api1.context['_getContextManager'](),
api2.context['_getContextManager']()
);
});

it('should disable both if one is disabled', () => {
const original = api1.context['_getContextManager']();

api1.context.setGlobalContextManager(new NoopContextManager());

assert.notStrictEqual(original, api1.context['_getContextManager']());
api2.context.disable();
assert.strictEqual(original, api1.context['_getContextManager']());
});

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);
});
});

0 comments on commit a1c408e

Please sign in to comment.