Skip to content

Commit

Permalink
chore: use interface for context types (open-telemetry#1515)
Browse files Browse the repository at this point in the history
  • Loading branch information
dyladan committed Feb 18, 2021
1 parent 2f1686b commit 68f49a7
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 41 deletions.
4 changes: 2 additions & 2 deletions 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
10 changes: 5 additions & 5 deletions api/src/context-base/NoopContextManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@
* limitations under the License.
*/

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

export class NoopContextManager implements types.ContextManager {
active(): Context {
return Context.ROOT_CONTEXT;
active(): types.Context {
return 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
33 changes: 14 additions & 19 deletions api/src/context-base/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,18 @@
* 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();

/**
* 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;
import { Context } from './types';

/** Get a key to uniquely identify a context value */
public static createKey(description: string) {
return Symbol.for(description);
}
export class BaseContext implements Context {
private _currentContext: Map<symbol, unknown>;

/**
* Construct a new context which inherits values from an optional parent context.
*
* @param parentContext a context from which to inherit values
*/
private constructor(parentContext?: Map<symbol, unknown>) {
constructor(parentContext?: Map<symbol, unknown>) {
this._currentContext = parentContext ? new Map(parentContext) : new Map();
}

Expand All @@ -58,7 +45,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 +57,16 @@ 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;
}
}

/** The root context is used as the default parent context when there is no active context */
export const ROOT_CONTEXT: Context = new BaseContext();

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

export * from './types';
export * from './context';
export { createContextKey, ROOT_CONTEXT } from './context';
export * from './NoopContextManager';
export * from './types';
26 changes: 25 additions & 1 deletion api/src/context-base/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,31 @@
* limitations under the License.
*/

import { Context } from './context';
export interface Context {
/**
* Get a value from the context.
*
* @param key key which identifies a context value
*/
getValue(key: symbol): unknown;

/**
* Create a new context which inherits from this context and has
* the given key set to the given value.
*
* @param key context key for which to set the value
* @param value value to set for the given key
*/
setValue(key: symbol, value: unknown): Context;

/**
* Return a new context which inherits from this context but does
* not contain a value for the given key.
*
* @param key context key for which to clear a value
*/
deleteValue(key: symbol): Context;
}

export interface ContextManager {
/**
Expand Down
7 changes: 6 additions & 1 deletion 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
23 changes: 12 additions & 11 deletions api/test/context-base/NoopContextManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
*/

import * as assert from 'assert';
import { NoopContextManager, Context } from '../src';
import { NoopContextManager, ROOT_CONTEXT } from '../src';
import { createContextKey } from '../src/context';

describe('NoopContextManager', () => {
let contextManager: NoopContextManager;
Expand Down Expand Up @@ -45,17 +46,17 @@ describe('NoopContextManager', () => {
});

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

it('should run the callback (object as target)', done => {
const key = Context.createKey('test key 1');
const test = Context.ROOT_CONTEXT.setValue(key, 1);
const key = createContextKey('test key 1');
const test = ROOT_CONTEXT.setValue(key, 1);
contextManager.with(test, () => {
assert.strictEqual(
contextManager.active(),
Context.ROOT_CONTEXT,
ROOT_CONTEXT,
'should not have context'
);
return done();
Expand All @@ -64,27 +65,27 @@ describe('NoopContextManager', () => {

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

describe('.active()', () => {
it('should always return Context.ROOT_CONTEXT (when enabled)', () => {
it('should always return ROOT_CONTEXT (when enabled)', () => {
assert.strictEqual(
contextManager.active(),
Context.ROOT_CONTEXT,
ROOT_CONTEXT,
'should not have context'
);
});

it('should always return Context.ROOT_CONTEXT (when disabled)', () => {
it('should always return ROOT_CONTEXT (when disabled)', () => {
contextManager.disable();
assert.strictEqual(
contextManager.active(),
Context.ROOT_CONTEXT,
ROOT_CONTEXT,
'should not have context'
);
contextManager.enable();
Expand Down

0 comments on commit 68f49a7

Please sign in to comment.