Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: use interface for context types #1515

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/opentelemetry-api/src/api/propagation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class PropagationAPI {
public inject<Carrier>(
carrier: Carrier,
setter: SetterFunction<Carrier> = defaultSetter,
context = contextApi.active()
context: Context = contextApi.active()
): void {
return this._getGlobalPropagator().inject(context, carrier, setter);
}
Expand All @@ -90,7 +90,7 @@ export class PropagationAPI {
public extract<Carrier>(
carrier: Carrier,
getter: GetterFunction<Carrier> = defaultGetter,
context = contextApi.active()
context: Context = contextApi.active()
): Context {
return this._getGlobalPropagator().extract(context, carrier, getter);
}
Expand Down
7 changes: 6 additions & 1 deletion packages/opentelemetry-api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ export {
INVALID_SPAN_CONTEXT,
} from './trace/spancontext-utils';

export { Context } from '@opentelemetry/context-base';
export {
Context,
ROOT_CONTEXT,
createContextKey,
ContextManager,
} from '@opentelemetry/context-base';

import { ContextAPI } from './api/context';
/** Entrypoint for context API */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { Context } from '@opentelemetry/context-base';
import { Context, ROOT_CONTEXT } from '@opentelemetry/context-base';
import * as asyncHooks from 'async_hooks';
import { AbstractAsyncHooksContextManager } from './AbstractAsyncHooksContextManager';

Expand All @@ -35,7 +35,7 @@ export class AsyncHooksContextManager extends AbstractAsyncHooksContextManager {
}

active(): Context {
return this._stack[this._stack.length - 1] ?? Context.ROOT_CONTEXT;
return this._stack[this._stack.length - 1] ?? ROOT_CONTEXT;
}

with<T extends (...args: unknown[]) => ReturnType<T>>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { Context } from '@opentelemetry/context-base';
import { Context, ROOT_CONTEXT } from '@opentelemetry/context-base';
import { AsyncLocalStorage } from 'async_hooks';
import { AbstractAsyncHooksContextManager } from './AbstractAsyncHooksContextManager';

Expand All @@ -27,7 +27,7 @@ export class AsyncLocalStorageContextManager extends AbstractAsyncHooksContextMa
}

active(): Context {
return this._asyncLocalStorage.getStore() ?? Context.ROOT_CONTEXT;
return this._asyncLocalStorage.getStore() ?? ROOT_CONTEXT;
}

with<T extends (...args: unknown[]) => ReturnType<T>>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
AsyncLocalStorageContextManager,
} from '../src';
import { EventEmitter } from 'events';
import { Context } from '@opentelemetry/context-base';
import { createContextKey, ROOT_CONTEXT } from '@opentelemetry/context-base';

for (const contextManagerClass of [
AsyncHooksContextManager,
Expand All @@ -30,7 +30,7 @@ for (const contextManagerClass of [
let contextManager:
| AsyncHooksContextManager
| AsyncLocalStorageContextManager;
const key1 = Context.createKey('test key 1');
const key1 = createContextKey('test key 1');

before(function () {
if (
Expand Down Expand Up @@ -77,11 +77,11 @@ for (const contextManagerClass of [

describe('.with()', () => {
it('should run the callback (null as target)', done => {
contextManager.with(Context.ROOT_CONTEXT, done);
contextManager.with(ROOT_CONTEXT, done);
});

it('should run the callback (object as target)', done => {
const test = Context.ROOT_CONTEXT.setValue(key1, 1);
const test = ROOT_CONTEXT.setValue(key1, 1);
contextManager.with(test, () => {
assert.strictEqual(
contextManager.active(),
Expand All @@ -94,24 +94,24 @@ for (const contextManagerClass of [

it('should run the callback (when disabled)', done => {
contextManager.disable();
contextManager.with(Context.ROOT_CONTEXT, () => {
contextManager.with(ROOT_CONTEXT, () => {
contextManager.enable();
return done();
});
});

it('should rethrow errors', done => {
assert.throws(() => {
contextManager.with(Context.ROOT_CONTEXT, () => {
contextManager.with(ROOT_CONTEXT, () => {
throw new Error('This should be rethrown');
});
});
return done();
});

it('should finally restore an old context', done => {
const ctx1 = Context.ROOT_CONTEXT.setValue(key1, 'ctx1');
const ctx2 = Context.ROOT_CONTEXT.setValue(key1, 'ctx2');
const ctx1 = ROOT_CONTEXT.setValue(key1, 'ctx1');
const ctx2 = ROOT_CONTEXT.setValue(key1, 'ctx2');
contextManager.with(ctx1, () => {
assert.strictEqual(contextManager.active(), ctx1);
contextManager.with(ctx2, () => {
Expand All @@ -123,7 +123,7 @@ for (const contextManagerClass of [
});

it('should finally restore an old context', done => {
const ctx1 = Context.ROOT_CONTEXT.setValue(key1, 'ctx1');
const ctx1 = ROOT_CONTEXT.setValue(key1, 'ctx1');
contextManager.with(ctx1, () => {
assert.strictEqual(contextManager.active(), ctx1);
setTimeout(() => {
Expand All @@ -150,7 +150,7 @@ for (const contextManagerClass of [
);
assert.strictEqual(contextManager.active(), scope1);
});
assert.strictEqual(contextManager.active(), Context.ROOT_CONTEXT);
assert.strictEqual(contextManager.active(), ROOT_CONTEXT);
});

it('should not loose the context', done => {
Expand All @@ -162,7 +162,7 @@ for (const contextManagerClass of [
assert.strictEqual(contextManager.active(), scope1);
return done();
});
assert.strictEqual(contextManager.active(), Context.ROOT_CONTEXT);
assert.strictEqual(contextManager.active(), ROOT_CONTEXT);
});

it('should correctly restore context using async/await', async () => {
Expand All @@ -186,7 +186,7 @@ for (const contextManagerClass of [
});
assert.strictEqual(contextManager.active(), scope1);
});
assert.strictEqual(contextManager.active(), Context.ROOT_CONTEXT);
assert.strictEqual(contextManager.active(), ROOT_CONTEXT);
});

it('should works with multiple concurrent operations', done => {
Expand All @@ -208,7 +208,7 @@ for (const contextManagerClass of [
}, 100);
assert.strictEqual(contextManager.active(), scope1);
});
assert.strictEqual(contextManager.active(), Context.ROOT_CONTEXT);
assert.strictEqual(contextManager.active(), ROOT_CONTEXT);
contextManager.with(scope2, async () => {
assert.strictEqual(contextManager.active(), scope2);
setTimeout(() => {
Expand All @@ -220,31 +220,25 @@ for (const contextManagerClass of [
}, 20);
assert.strictEqual(contextManager.active(), scope2);
});
assert.strictEqual(contextManager.active(), Context.ROOT_CONTEXT);
assert.strictEqual(contextManager.active(), ROOT_CONTEXT);
});
});

describe('.bind(function)', () => {
it('should return the same target (when enabled)', () => {
const test = { a: 1 };
assert.deepStrictEqual(
contextManager.bind(test, Context.ROOT_CONTEXT),
test
);
assert.deepStrictEqual(contextManager.bind(test, ROOT_CONTEXT), test);
});

it('should return the same target (when disabled)', () => {
contextManager.disable();
const test = { a: 1 };
assert.deepStrictEqual(
contextManager.bind(test, Context.ROOT_CONTEXT),
test
);
assert.deepStrictEqual(contextManager.bind(test, ROOT_CONTEXT), test);
contextManager.enable();
});

it('should return current context (when enabled)', done => {
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const context = ROOT_CONTEXT.setValue(key1, 1);
const fn = contextManager.bind(() => {
assert.strictEqual(
contextManager.active(),
Expand All @@ -262,7 +256,7 @@ for (const contextManagerClass of [
*/
it('should return current context (when disabled)', done => {
contextManager.disable();
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const context = ROOT_CONTEXT.setValue(key1, 1);
const fn = contextManager.bind(() => {
assert.strictEqual(
contextManager.active(),
Expand All @@ -275,7 +269,7 @@ for (const contextManagerClass of [
});

it('should fail to return current context with async op', done => {
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const context = ROOT_CONTEXT.setValue(key1, 1);
const fn = contextManager.bind(() => {
assert.strictEqual(contextManager.active(), context);
setTimeout(() => {
Expand All @@ -294,24 +288,18 @@ for (const contextManagerClass of [
describe('.bind(event-emitter)', () => {
it('should return the same target (when enabled)', () => {
const ee = new EventEmitter();
assert.deepStrictEqual(
contextManager.bind(ee, Context.ROOT_CONTEXT),
ee
);
assert.deepStrictEqual(contextManager.bind(ee, ROOT_CONTEXT), ee);
});

it('should return the same target (when disabled)', () => {
const ee = new EventEmitter();
contextManager.disable();
assert.deepStrictEqual(
contextManager.bind(ee, Context.ROOT_CONTEXT),
ee
);
assert.deepStrictEqual(contextManager.bind(ee, ROOT_CONTEXT), ee);
});

it('should return current context and removeListener (when enabled)', done => {
const ee = new EventEmitter();
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const context = ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = contextManager.bind(ee, context);
const handler = () => {
assert.deepStrictEqual(contextManager.active(), context);
Expand All @@ -326,7 +314,7 @@ for (const contextManagerClass of [

it('should return current context and removeAllListener (when enabled)', done => {
const ee = new EventEmitter();
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const context = ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = contextManager.bind(ee, context);
const handler = () => {
assert.deepStrictEqual(contextManager.active(), context);
Expand All @@ -346,7 +334,7 @@ for (const contextManagerClass of [
it('should return context (when disabled)', done => {
contextManager.disable();
const ee = new EventEmitter();
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const context = ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = contextManager.bind(ee, context);
const handler = () => {
assert.deepStrictEqual(contextManager.active(), context);
Expand All @@ -361,7 +349,7 @@ for (const contextManagerClass of [

it('should not return current context with async op', done => {
const ee = new EventEmitter();
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const context = ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = contextManager.bind(ee, context);
const handler = () => {
assert.deepStrictEqual(contextManager.active(), context);
Expand Down
10 changes: 5 additions & 5 deletions packages/opentelemetry-context-base/src/NoopContextManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@
*/

import * as types from './types';
import { Context } from './context';
import { BaseContext } from './context';

export class NoopContextManager implements types.ContextManager {
active(): Context {
return Context.ROOT_CONTEXT;
active(): types.Context {
return BaseContext.ROOT_CONTEXT;
}

with<T extends (...args: unknown[]) => ReturnType<T>>(
context: Context,
context: types.Context,
fn: T
): ReturnType<T> {
return fn();
}

bind<T>(target: T, context?: Context): T {
bind<T>(target: T, context?: types.Context): T {
return target;
}

Expand Down
29 changes: 12 additions & 17 deletions packages/opentelemetry-context-base/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export class Context {
private _currentContext: Map<symbol, unknown>;

/** The root context is used as the default parent context when there is no active context */
public static readonly ROOT_CONTEXT = new Context();
import { Context } from './types';

/**
* This is another identifier to the root context which allows developers to easily search the
* codebase for direct uses of context which need to be removed in later PRs.
*
* It's existence is temporary and it should be removed when all references are fixed.
*/
public static readonly TODO = Context.ROOT_CONTEXT;
export class BaseContext implements Context {
private _currentContext: Map<symbol, unknown>;

/** Get a key to uniquely identify a context value */
public static createKey(description: string) {
return Symbol.for(description);
}
/** The root context is used as the default parent context when there is no active context */
public static readonly ROOT_CONTEXT = new BaseContext();

/**
* Construct a new context which inherits values from an optional parent context.
Expand Down Expand Up @@ -58,7 +48,7 @@ export class Context {
* @param value value to set for the given key
*/
setValue(key: symbol, value: unknown): Context {
const context = new Context(this._currentContext);
const context = new BaseContext(this._currentContext);
context._currentContext.set(key, value);
return context;
}
Expand All @@ -70,8 +60,13 @@ export class Context {
* @param key context key for which to clear a value
*/
deleteValue(key: symbol): Context {
const context = new Context(this._currentContext);
const context = new BaseContext(this._currentContext);
context._currentContext.delete(key);
return context;
}
}

/** Get a key to uniquely identify a context value */
export function createContextKey(description: string) {
return Symbol.for(description);
}
7 changes: 5 additions & 2 deletions packages/opentelemetry-context-base/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
* limitations under the License.
*/

export * from './types';
export * from './context';
export * from './NoopContextManager';
export * from './types';
import { BaseContext } from './context';
import { Context } from './types';
dyladan marked this conversation as resolved.
Show resolved Hide resolved
export { createContextKey } from './context';
export const ROOT_CONTEXT: Context = BaseContext.ROOT_CONTEXT;
dyladan marked this conversation as resolved.
Show resolved Hide resolved
Loading