Rename scope to context (#853)

This commit is contained in:
Daniel Dyla 2020-03-13 15:01:07 -04:00 committed by GitHub
parent 6b9d3afff9
commit 9a3fd7b560
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
111 changed files with 1048 additions and 975 deletions

View File

@ -44,20 +44,22 @@ cache_1: &cache_1
paths:
- ./node_modules
- ./package-lock.json
- packages/opentelemetry-base/node_modules
- packages/opentelemetry-scope-base/node_modules
- packages/opentelemetry-api/node_modules
- packages/opentelemetry-scope-async-hooks/node_modules
- packages/opentelemetry-base/node_modules
- packages/opentelemetry-context-async-hooks/node_modules
- packages/opentelemetry-context-base/node_modules
- packages/opentelemetry-context-zone/node_modules
- packages/opentelemetry-context-zone-peer-dep/node_modules
- packages/opentelemetry-core/node_modules
- packages/opentelemetry-exporter-prometheus/node_modules
- packages/opentelemetry-metrics/node_modules
- packages/opentelemetry-tracing/node_modules
- packages/opentelemetry-exporter-jaeger/node_modules
- packages/opentelemetry-exporter-prometheus/node_modules
- packages/opentelemetry-exporter-zipkin/node_modules
- packages/opentelemetry-metrics/node_modules
- packages/opentelemetry-node/node_modules
- packages/opentelemetry-shim-opentracing/node_modules
- packages/opentelemetry-web/node_modules
- packages/opentelemetry-plugin-dns/node_modules
- packages/opentelemetry-shim-opentracing/node_modules
- packages/opentelemetry-tracing/node_modules
- packages/opentelemetry-web/node_modules
cache_2: &cache_2
key: npm-cache-02-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/checksums.txt" }}-F267A71D

View File

@ -24,7 +24,7 @@
Example of using Web Tracer with document load plugin with console exporter and collector exporter
<script type="text/javascript" src="document-load.js"></script>
<br/>
<button id="button1">Test WebTracer with ZoneScopeManager - async</button>
<button id="button1">Test WebTracer with ZoneContextManager - async</button>
</body>

View File

@ -1,7 +1,7 @@
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracerProvider } from '@opentelemetry/web';
import { DocumentLoad } from '@opentelemetry/plugin-document-load';
import { ZoneScopeManager } from '@opentelemetry/scope-zone';
import { ZoneContextManager } from '@opentelemetry/context-zone';
import { CollectorExporter } from '@opentelemetry/exporter-collector';
const provider = new WebTracerProvider({
@ -12,7 +12,7 @@ const provider = new WebTracerProvider({
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
const providerWithZone = new WebTracerProvider({
scopeManager: new ZoneScopeManager(),
contextManager: new ZoneContextManager(),
plugins: [
new DocumentLoad(),
],
@ -40,7 +40,7 @@ const getData = (url) => new Promise((resolve, reject) => {
};
});
// example of keeping track of scope between async operations
// example of keeping track of context between async operations
const prepareClickEvent = () => {
const url1 = 'https://raw.githubusercontent.com/open-telemetry/opentelemetry-js/master/package.json';
const url2 = 'https://raw.githubusercontent.com/open-telemetry/opentelemetry-js/master/packages/opentelemetry-web/package.json';

View File

@ -2,13 +2,11 @@ import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing
import { WebTracerProvider } from '@opentelemetry/web';
import { XMLHttpRequestPlugin } from '@opentelemetry/plugin-xml-http-request';
import { UserInteractionPlugin } from '@opentelemetry/plugin-user-interaction';
import { ZoneScopeManager } from '@opentelemetry/scope-zone';
import { ZoneContextManager } from '@opentelemetry/context-zone';
import { CollectorExporter } from '@opentelemetry/exporter-collector';
import { B3Propagator } from '@opentelemetry/core';
const providerWithZone = new WebTracerProvider({
HttpTextPropagator: new B3Propagator(),
scopeManager: new ZoneScopeManager(),
plugins: [
new UserInteractionPlugin(),
new XMLHttpRequestPlugin({
@ -23,6 +21,11 @@ const providerWithZone = new WebTracerProvider({
providerWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
providerWithZone.addSpanProcessor(new SimpleSpanProcessor(new CollectorExporter()));
providerWithZone.register({
contextManager: new ZoneContextManager(),
propagator: new B3Propagator(),
});
let lastButtonId = 0;
function btnAddClick() {

View File

@ -1,13 +1,11 @@
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracerProvider } from '@opentelemetry/web';
import { XMLHttpRequestPlugin } from '@opentelemetry/plugin-xml-http-request';
import { ZoneScopeManager } from '@opentelemetry/scope-zone';
import { ZoneContextManager } from '@opentelemetry/context-zone';
import { CollectorExporter } from '@opentelemetry/exporter-collector';
import { B3Propagator } from '@opentelemetry/core';
const providerWithZone = new WebTracerProvider({
HttpTextPropagator: new B3Propagator(),
scopeManager: new ZoneScopeManager(),
plugins: [
new XMLHttpRequestPlugin({
ignoreUrls: [/localhost:8090\/sockjs-node/],
@ -21,6 +19,11 @@ const providerWithZone = new WebTracerProvider({
providerWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
providerWithZone.addSpanProcessor(new SimpleSpanProcessor(new CollectorExporter()));
providerWithZone.register({
contextManager: new ZoneContextManager(),
propagator: new B3Propagator(),
});
const webTracerWithZone = providerWithZone.getTracer('example-tracer-web');
const getData = (url) => new Promise((resolve, _reject) => {
@ -35,7 +38,7 @@ const getData = (url) => new Promise((resolve, _reject) => {
};
});
// example of keeping track of scope between async operations
// example of keeping track of context between async operations
const prepareClickEvent = () => {
const url1 = 'https://httpbin.org/get';

View File

@ -39,7 +39,7 @@
"@opentelemetry/plugin-document-load": "^0.4.0",
"@opentelemetry/plugin-user-interaction": "^0.4.0",
"@opentelemetry/plugin-xml-http-request": "^0.4.0",
"@opentelemetry/scope-zone": "^0.4.0",
"@opentelemetry/context-zone": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0",
"@opentelemetry/web": "^0.4.0"
},

View File

@ -47,7 +47,7 @@
"access": "public"
},
"dependencies": {
"@opentelemetry/scope-base": "^0.4.0"
"@opentelemetry/context-base": "^0.4.0"
},
"devDependencies": {
"@types/mocha": "^5.2.7",

View File

@ -15,22 +15,22 @@
*/
import {
ScopeManager,
NoopScopeManager,
ContextManager,
NoopContextManager,
Context,
} from '@opentelemetry/scope-base';
} from '@opentelemetry/context-base';
/**
* Singleton object which represents the entry point to the OpenTelemetry Context API
*/
export class ContextAPI {
private static _instance?: ContextAPI;
private _scopeManager: ScopeManager = new NoopScopeManager();
private _contextManager: ContextManager = new NoopContextManager();
/** Empty private constructor prevents end users from constructing a new instance of the API */
private constructor() {}
/** Get the singleton instance of the Scope API */
/** Get the singleton instance of the Context API */
public static getInstance(): ContextAPI {
if (!this._instance) {
this._instance = new ContextAPI();
@ -42,16 +42,18 @@ export class ContextAPI {
/**
* Set the current context manager. Returns the initialized context manager
*/
public setGlobalContextManager(scopeManager: ScopeManager): ScopeManager {
this._scopeManager = scopeManager;
return scopeManager;
public setGlobalContextManager(
contextManager: ContextManager
): ContextManager {
this._contextManager = contextManager;
return contextManager;
}
/**
* Get the currently active context
*/
public active(): Context {
return this._scopeManager.active();
return this._contextManager.active();
}
/**
@ -64,7 +66,7 @@ export class ContextAPI {
context: Context,
fn: T
): ReturnType<T> {
return this._scopeManager.with(context, fn);
return this._contextManager.with(context, fn);
}
/**
@ -74,6 +76,6 @@ export class ContextAPI {
* @param context context to bind to the event emitter or function. Defaults to the currently active context
*/
public bind<T>(target: T, context: Context = this.active()): T {
return this._scopeManager.bind(target, context);
return this._contextManager.bind(target, context);
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { Context } from '@opentelemetry/scope-base';
import { Context } from '@opentelemetry/context-base';
import { defaultGetter, GetterFunction } from '../context/propagation/getter';
import { HttpTextPropagator } from '../context/propagation/HttpTextPropagator';
import { NOOP_HTTP_TEXT_PROPAGATOR } from '../context/propagation/NoopHttpTextPropagator';

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { Context } from '@opentelemetry/scope-base';
import { Context } from '@opentelemetry/context-base';
import { SetterFunction } from './setter';
import { GetterFunction } from './getter';

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { Context } from '@opentelemetry/scope-base';
import { Context } from '@opentelemetry/context-base';
import { HttpTextPropagator } from './HttpTextPropagator';
/**

View File

@ -35,7 +35,7 @@ export interface EntryValue {
*/
export enum EntryTtl {
/**
* NO_PROPAGATION is considered to have local scope and is used within the
* NO_PROPAGATION is considered to have local context and is used within the
* process it created.
*/
NO_PROPAGATION = 0,

View File

@ -49,7 +49,7 @@ export * from './trace/trace_state';
export * from './trace/tracer_provider';
export * from './trace/tracer';
export { Context } from '@opentelemetry/scope-base';
export { Context } from '@opentelemetry/context-base';
import { ContextAPI } from './api/context';
/** Entrypoint for context API */

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { Context } from '@opentelemetry/scope-base';
import { Context } from '@opentelemetry/context-base';
import { Span } from './span';
import { SpanOptions } from './SpanOptions';
@ -58,9 +58,9 @@ export interface Tracer {
): ReturnType<T>;
/**
* Bind a span as the target's scope or propagate the current one.
* Bind a span as the target's context or propagate the current one.
*
* @param target Any object to which a scope need to be set
* @param target Any object to which a context need to be set
* @param [context] Optionally specify the context which you want to bind
*/
bind<T>(target: T, context?: Span): T;

View File

@ -1,26 +1,26 @@
# OpenTelemetry AsyncHooks-based Scope Manager
# OpenTelemetry AsyncHooks-based Context Manager
[![Gitter chat][gitter-image]][gitter-url]
[![NPM Published Version][npm-img]][npm-url]
[![dependencies][dependencies-image]][dependencies-url]
[![devDependencies][devDependencies-image]][devDependencies-url]
[![Apache License][license-image]][license-image]
This package provides [async-hooks][async-hooks-doc] based scope manager which is used internally by OpenTelemetry plugins to propagate specific scope between function calls and async operations. It only targets NodeJS since async-hooks is only available there.
This package provides [async-hooks][async-hooks-doc] based context manager which is used internally by OpenTelemetry plugins to propagate specific context between function calls and async operations. It only targets NodeJS since async-hooks is only available there.
## What is a ScopeManager ?
## What is a ContextManager ?
The definition and why they exist is available on [the readme of the scope-base package][def-scope-manager].
The definition and why they exist is available on [the readme of the context-base package][def-context-manager].
### Implementation in NodeJS
NodeJS has a specific API to track async scope: [async-hooks][async-hooks-doc], it allows to track creation of new async operation and their respective parent.
NodeJS has a specific API to track async context: [async-hooks][async-hooks-doc], it allows to track creation of new async operation and their respective parent.
This package only handle storing a specific object for a given async hooks context.
### Limitations
Even if the API is native to NodeJS, it doesn't cover all possible cases of scope propagation but there is a big effort from the NodeJS team to fix those. That's why we generally advise to be on the latest LTS to benefit from performance and bug fixes.
Even if the API is native to NodeJS, it doesn't cover all possible cases of context propagation but there is a big effort from the NodeJS team to fix those. That's why we generally advise to be on the latest LTS to benefit from performance and bug fixes.
There are known modules that break scope propagation ([some of them are listed there][pkgs-that-break-ah]), so it's possible that the scope manager doesn't work with them.
There are known modules that break context propagation ([some of them are listed there][pkgs-that-break-ah]), so it's possible that the context manager doesn't work with them.
### Prior arts
@ -44,15 +44,15 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[gitter-url]: https://gitter.im/open-telemetry/opentelemetry-node?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/master/LICENSE
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/status.svg?path=packages/opentelemetry-scope-async-hooks
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-scope-async-hooks
[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-scope-async-hooks
[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-scope-async-hooks&type=dev
[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/status.svg?path=packages/opentelemetry-context-async-hooks
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-context-async-hooks
[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-context-async-hooks
[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-context-async-hooks&type=dev
[async-hooks-doc]: http://nodejs.org/dist/latest/docs/api/async_hooks.html
[def-scope-manager]: https://github.com/open-telemetry/opentelemetry-js/blob/master/packages/opentelemetry-scope-base/README.md
[def-context-manager]: https://github.com/open-telemetry/opentelemetry-js/blob/master/packages/opentelemetry-context-base/README.md
[dd-js-tracer-scope]: https://github.com/DataDog/dd-trace-js/tree/master/packages/dd-trace/src/scope
[opentracing-scope]: https://github.com/opentracing/opentracing-javascript/pull/113
[diag-team-scope-discussion]: https://github.com/nodejs/diagnostics/issues/300
[pkgs-that-break-ah]: https://github.com/nodejs/diagnostics/blob/master/tracing/AsyncHooks/problematic-modules.md
[npm-url]: https://www.npmjs.com/package/@opentelemetry/scope-async-hooks
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fscope-async-hooks.svg
[npm-url]: https://www.npmjs.com/package/@opentelemetry/context-async-hooks
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fcontext-async-hooks.svg

View File

@ -1,7 +1,7 @@
{
"name": "@opentelemetry/scope-async-hooks",
"name": "@opentelemetry/context-async-hooks",
"version": "0.4.0",
"description": "OpenTelemetry AsyncHooks-based Scope Manager",
"description": "OpenTelemetry AsyncHooks-based Context Manager",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
"repository": "open-telemetry/opentelemetry-js",
@ -56,6 +56,6 @@
"typescript": "3.7.2"
},
"dependencies": {
"@opentelemetry/scope-base": "^0.4.0"
"@opentelemetry/context-base": "^0.4.0"
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { ScopeManager, Context } from '@opentelemetry/scope-base';
import { ContextManager, Context } from '@opentelemetry/context-base';
import * as asyncHooks from 'async_hooks';
import { EventEmitter } from 'events';
@ -37,9 +37,9 @@ const ADD_LISTENER_METHODS = [
'prependOnceListener' as 'prependOnceListener',
];
export class AsyncHooksScopeManager implements ScopeManager {
export class AsyncHooksContextManager implements ContextManager {
private _asyncHook: asyncHooks.AsyncHook;
private _scopes: {
private _contexts: {
[uid: number]: Context | undefined | null;
} = Object.create(null);
@ -52,38 +52,40 @@ export class AsyncHooksScopeManager implements ScopeManager {
}
active(): Context {
return this._scopes[asyncHooks.executionAsyncId()] || Context.ROOT_CONTEXT;
return (
this._contexts[asyncHooks.executionAsyncId()] || Context.ROOT_CONTEXT
);
}
with<T extends (...args: unknown[]) => ReturnType<T>>(
scope: Context,
context: Context,
fn: T
): ReturnType<T> {
const uid = asyncHooks.executionAsyncId();
const oldScope = this._scopes[uid];
this._scopes[uid] = scope;
const oldContext = this._contexts[uid];
this._contexts[uid] = context;
try {
return fn();
} catch (err) {
throw err;
} finally {
if (oldScope === undefined) {
if (oldContext === undefined) {
this._destroy(uid);
} else {
this._scopes[uid] = oldScope;
this._contexts[uid] = oldContext;
}
}
}
bind<T>(target: T, scope: Context): T {
// if no specific scope to propagate is given, we use the current one
if (scope === undefined) {
scope = this.active();
bind<T>(target: T, context: Context): T {
// if no specific context to propagate is given, we use the current one
if (context === undefined) {
context = this.active();
}
if (target instanceof EventEmitter) {
return this._bindEventEmitter(target, scope);
return this._bindEventEmitter(target, context);
} else if (typeof target === 'function') {
return this._bindFunction(target, scope);
return this._bindFunction(target, context);
}
return target;
}
@ -95,14 +97,14 @@ export class AsyncHooksScopeManager implements ScopeManager {
disable(): this {
this._asyncHook.disable();
this._scopes = {};
this._contexts = {};
return this;
}
private _bindFunction<T extends Function>(target: T, scope: Context): T {
private _bindFunction<T extends Function>(target: T, context: Context): T {
const manager = this;
const contextWrapper = function(this: {}, ...args: unknown[]) {
return manager.with(scope, () => target.apply(this, args));
return manager.with(context, () => target.apply(this, args));
};
Object.defineProperty(contextWrapper, 'length', {
enumerable: false,
@ -119,24 +121,24 @@ export class AsyncHooksScopeManager implements ScopeManager {
}
/**
* By default, EventEmitter call their callback with their scope, which we do
* not want, instead we will bind a specific scope to all callbacks that
* By default, EventEmitter call their callback with their context, which we do
* not want, instead we will bind a specific context to all callbacks that
* go through it.
* @param target EventEmitter a instance of EventEmitter to patch
* @param scope the scope we want to bind
* @param context the context we want to bind
*/
private _bindEventEmitter<T extends EventEmitter>(
target: T,
scope: Context
context: Context
): T {
const ee = (target as unknown) as PatchedEventEmitter;
if (ee.__ot_listeners !== undefined) return target;
ee.__ot_listeners = {};
// patch methods that add a listener to propagate scope
// patch methods that add a listener to propagate context
ADD_LISTENER_METHODS.forEach(methodName => {
if (ee[methodName] === undefined) return;
ee[methodName] = this._patchAddListener(ee, ee[methodName], scope);
ee[methodName] = this._patchAddListener(ee, ee[methodName], context);
});
// patch methods that remove a listener
if (typeof ee.removeListener === 'function') {
@ -202,14 +204,14 @@ export class AsyncHooksScopeManager implements ScopeManager {
* can force them to propagate a given context.
* @param ee EventEmitter instance
* @param original reference to the patched method
* @param [scope] scope to propagate when calling listeners
* @param [context] context to propagate when calling listeners
*/
private _patchAddListener(
ee: PatchedEventEmitter,
original: Function,
scope: Context
context: Context
) {
const scopeManager = this;
const contextManager = this;
return function(this: {}, event: string, listener: Func<void>) {
if (ee.__ot_listeners === undefined) ee.__ot_listeners = {};
let listeners = ee.__ot_listeners[event];
@ -217,7 +219,7 @@ export class AsyncHooksScopeManager implements ScopeManager {
listeners = new WeakMap();
ee.__ot_listeners[event] = listeners;
}
const patchedListener = scopeManager.bind(listener, scope);
const patchedListener = contextManager.bind(listener, context);
// store a weak reference of the user listener to ours
listeners.set(listener, patchedListener);
return original.call(this, event, patchedListener);
@ -225,20 +227,20 @@ export class AsyncHooksScopeManager implements ScopeManager {
}
/**
* Init hook will be called when userland create a async scope, setting the
* scope as the current one if it exist.
* @param uid id of the async scope
* Init hook will be called when userland create a async context, setting the
* context as the current one if it exist.
* @param uid id of the async context
*/
private _init(uid: number) {
this._scopes[uid] = this._scopes[asyncHooks.executionAsyncId()];
this._contexts[uid] = this._contexts[asyncHooks.executionAsyncId()];
}
/**
* Destroy hook will be called when a given scope is no longer used so we can
* remove its attached scope.
* @param uid uid of the async scope
* Destroy hook will be called when a given context is no longer used so we can
* remove its attached context.
* @param uid uid of the async context
*/
private _destroy(uid: number) {
delete this._scopes[uid];
delete this._contexts[uid];
}
}

View File

@ -14,4 +14,4 @@
* limitations under the License.
*/
export * from './AsyncHooksScopeManager';
export * from './AsyncHooksContextManager';

View File

@ -0,0 +1,290 @@
/*!
* Copyright 2019, 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 { AsyncHooksContextManager } from '../src';
import { EventEmitter } from 'events';
import { Context } from '@opentelemetry/context-base';
describe('AsyncHooksContextManager', () => {
let contextManager: AsyncHooksContextManager;
const key1 = Context.createKey('test key 1');
beforeEach(() => {
contextManager = new AsyncHooksContextManager();
contextManager.enable();
});
afterEach(() => {
contextManager.disable();
});
describe('.enable()', () => {
it('should work', () => {
assert.doesNotThrow(() => {
contextManager = new AsyncHooksContextManager();
assert(
contextManager.enable() === contextManager,
'should return this'
);
});
});
});
describe('.disable()', () => {
it('should work', () => {
assert.doesNotThrow(() => {
assert(
contextManager.disable() === contextManager,
'should return this'
);
});
contextManager.enable();
});
});
describe('.with()', () => {
it('should run the callback (null as target)', done => {
contextManager.with(Context.ROOT_CONTEXT, done);
});
it('should run the callback (object as target)', done => {
const test = Context.ROOT_CONTEXT.setValue(key1, 1);
contextManager.with(test, () => {
assert.strictEqual(
contextManager.active(),
test,
'should have context'
);
return done();
});
});
it('should run the callback (when disabled)', done => {
contextManager.disable();
contextManager.with(Context.ROOT_CONTEXT, () => {
contextManager.enable();
return done();
});
});
it('should rethrow errors', done => {
assert.throws(() => {
contextManager.with(Context.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');
contextManager.with(ctx1, () => {
assert.strictEqual(contextManager.active(), ctx1);
contextManager.with(ctx2, () => {
assert.strictEqual(contextManager.active(), ctx2);
});
assert.strictEqual(contextManager.active(), ctx1);
return done();
});
});
});
describe('.bind(function)', () => {
it('should return the same target (when enabled)', () => {
const test = { a: 1 };
assert.deepStrictEqual(
contextManager.bind(test, Context.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
);
contextManager.enable();
});
it('should return current context (when enabled)', done => {
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const fn = contextManager.bind(() => {
assert.strictEqual(
contextManager.active(),
context,
'should have context'
);
return done();
}, context);
fn();
});
/**
* Even if asynchooks is disabled, the context propagation will
* still works but it might be lost after any async op.
*/
it('should return current context (when disabled)', done => {
contextManager.disable();
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const fn = contextManager.bind(() => {
assert.strictEqual(
contextManager.active(),
context,
'should have context'
);
return done();
}, context);
fn();
});
it('should fail to return current context (when disabled + async op)', done => {
contextManager.disable();
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const fn = contextManager.bind(() => {
setTimeout(() => {
assert.strictEqual(
contextManager.active(),
Context.ROOT_CONTEXT,
'should have no context'
);
return done();
}, 100);
}, context);
fn();
});
it('should return current context (when re-enabled + async op)', done => {
contextManager.enable();
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const fn = contextManager.bind(() => {
setTimeout(() => {
assert.strictEqual(
contextManager.active(),
context,
'should have context'
);
return done();
}, 100);
}, context);
fn();
});
});
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);
});
it('should return the same target (when disabled)', () => {
const ee = new EventEmitter();
contextManager.disable();
assert.deepStrictEqual(contextManager.bind(ee, Context.ROOT_CONTEXT), ee);
contextManager.enable();
});
it('should return current context and removeListener (when enabled)', done => {
const ee = new EventEmitter();
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = contextManager.bind(ee, context);
const handler = () => {
assert.deepStrictEqual(contextManager.active(), context);
patchedEe.removeListener('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 0);
return done();
};
patchedEe.on('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 1);
patchedEe.emit('test');
});
it('should return current context and removeAllListener (when enabled)', done => {
const ee = new EventEmitter();
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = contextManager.bind(ee, context);
const handler = () => {
assert.deepStrictEqual(contextManager.active(), context);
patchedEe.removeAllListeners('test');
assert.strictEqual(patchedEe.listeners('test').length, 0);
return done();
};
patchedEe.on('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 1);
patchedEe.emit('test');
});
/**
* Even if asynchooks is disabled, the context propagation will
* still works but it might be lost after any async op.
*/
it('should return context (when disabled)', done => {
contextManager.disable();
const ee = new EventEmitter();
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = contextManager.bind(ee, context);
const handler = () => {
assert.deepStrictEqual(contextManager.active(), context);
patchedEe.removeListener('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 0);
contextManager.enable();
return done();
};
patchedEe.on('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 1);
patchedEe.emit('test');
});
it('should not return current context (when disabled + async op)', done => {
contextManager.disable();
const ee = new EventEmitter();
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = contextManager.bind(ee, context);
const handler = () => {
setImmediate(() => {
assert.deepStrictEqual(contextManager.active(), Context.ROOT_CONTEXT);
patchedEe.removeAllListeners('test');
assert.strictEqual(patchedEe.listeners('test').length, 0);
return done();
});
};
patchedEe.on('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 1);
patchedEe.emit('test');
});
it('should return current context (when enabled + async op)', done => {
contextManager.enable();
const ee = new EventEmitter();
const context = Context.ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = contextManager.bind(ee, context);
const handler = () => {
setImmediate(() => {
assert.deepStrictEqual(contextManager.active(), context);
patchedEe.removeAllListeners('test');
assert.strictEqual(patchedEe.listeners('test').length, 0);
return done();
});
};
patchedEe.on('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 1);
patchedEe.emit('test');
});
});
});

View File

@ -1,23 +1,21 @@
# OpenTelemetry Base Scope Manager
# OpenTelemetry Base Context Manager
[![Gitter chat][gitter-image]][gitter-url]
[![NPM Published Version][npm-img]][npm-url]
[![dependencies][dependencies-image]][dependencies-url]
[![devDependencies][devDependencies-image]][devDependencies-url]
[![Apache License][license-image]][license-image]
This package provides the ScopeManager interface (which is used by concrete implementations) and a no-op implementation (which is used internally when no scope propagation is defined). It's intended for use both on the server and in the browser.
This package provides the ContextManager interface (which is used by concrete implementations) and a no-op implementation (which is used internally when no context propagation is defined). It's intended for use both on the server and in the browser.
## What is a Scope Manager ?
## What is a Context Manager ?
To understand why they exists, we'll need to understand how Javascript works: when you make native function call (networks, setInterval etc) you generally call C++ code that will later callback your own code.
A common issue when tracing a request in javascript is to link the function that have made the native call to the callback that the native code called when the response is there. Imagine you want to track for which user you made the request, you need some sort of "context/scope aware storage".
A common issue when tracing a request in javascript is to link the function that have made the native call to the callback that the native code called when the response is there. Imagine you want to track for which user you made the request, you need some sort of "context/context aware storage".
ScopeManager's aim to offer exactly that, it's API offer to store an object in the current scope (`with()`) and if needed, `bind()` to a specific function call to find it back when the callback fire, which can later get retrieved using `active()`.
ContextManager's aim to offer exactly that, it's API offer to store an object in the current context (`with()`) and if needed, `bind()` to a specific function call to find it back when the callback fire, which can later get retrieved using `active()`.
This package only include the interface and a Noop implementation, for more information please see the [async-hooks based ScopeManager][ah-scope-manager] for NodeJS.
Note: You will sometimes read about **context** management, which is sometimes also used for talking about **scope** management. However in OpenTelemetry, **context** was already heavily used as a concept in the Trace API so we named this package with **scope** to avoid confusion.
This package only include the interface and a Noop implementation, for more information please see the [async-hooks based ContextManager][ah-context-manager] for NodeJS.
## Useful links
- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>
@ -32,10 +30,10 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[gitter-url]: https://gitter.im/open-telemetry/opentelemetry-node?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/master/LICENSE
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/status.svg?path=packages/opentelemetry-scope-base
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-scope-base
[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-scope-base
[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-scope-base&type=dev
[ah-scope-manager]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-scope-async-hooks
[npm-url]: https://www.npmjs.com/package/@opentelemetry/scope-base
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fscope-base.svg
[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/status.svg?path=packages/opentelemetry-context-base
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-context-base
[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-context-base
[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-context-base&type=dev
[ah-context-manager]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-context-async-hooks
[npm-url]: https://www.npmjs.com/package/@opentelemetry/context-base
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fcontext-base.svg

View File

@ -1,7 +1,7 @@
{
"name": "@opentelemetry/scope-base",
"name": "@opentelemetry/context-base",
"version": "0.4.0",
"description": "OpenTelemetry Base Scope Manager",
"description": "OpenTelemetry Base Context Manager",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
"repository": "open-telemetry/opentelemetry-js",

View File

@ -17,19 +17,19 @@
import * as types from './types';
import { Context } from './context';
export class NoopScopeManager implements types.ScopeManager {
export class NoopContextManager implements types.ContextManager {
active(): Context {
return Context.ROOT_CONTEXT;
}
with<T extends (...args: unknown[]) => ReturnType<T>>(
scope: Context,
context: Context,
fn: T
): ReturnType<T> {
return fn();
}
bind<T>(target: T, scope?: Context): T {
bind<T>(target: T, context?: Context): T {
return target;
}

View File

@ -16,4 +16,4 @@
export * from './types';
export * from './context';
export * from './NoopScopeManager';
export * from './NoopContextManager';

View File

@ -16,36 +16,36 @@
import { Context } from './context';
export interface ScopeManager {
export interface ContextManager {
/**
* Get the current active scope
* Get the current active context
*/
active(): Context;
/**
* Run the fn callback with object set as the current active scope
* @param scope Any object to set as the current active scope
* @param fn A callback to be immediately run within a specific scope
* Run the fn callback with object set as the current active context
* @param context Any object to set as the current active context
* @param fn A callback to be immediately run within a specific context
*/
with<T extends (...args: unknown[]) => ReturnType<T>>(
scope: Context,
context: Context,
fn: T
): ReturnType<T>;
/**
* Bind an object as the current scope (or a specific one)
* @param target Any object to which a scope need to be set
* @param [scope] Optionally specify the scope which you want to assign
* Bind an object as the current context (or a specific one)
* @param target Any object to which a context need to be set
* @param [context] Optionally specify the context which you want to assign
*/
bind<T>(target: T, scope?: Context): T;
bind<T>(target: T, context?: Context): T;
/**
* Enable scope management
* Enable context management
*/
enable(): this;
/**
* Disable scope management
* Disable context management
*/
disable(): this;
}

View File

@ -15,16 +15,19 @@
*/
import * as assert from 'assert';
import { NoopScopeManager, Context } from '../src';
import { NoopContextManager, Context } from '../src';
describe('NoopScopeManager', () => {
let scopeManager: NoopScopeManager;
describe('NoopContextManager', () => {
let contextManager: NoopContextManager;
describe('.enable()', () => {
it('should work', () => {
assert.doesNotThrow(() => {
scopeManager = new NoopScopeManager();
assert(scopeManager.enable() === scopeManager, 'should return this');
contextManager = new NoopContextManager();
assert(
contextManager.enable() === contextManager,
'should return this'
);
});
});
});
@ -32,34 +35,37 @@ describe('NoopScopeManager', () => {
describe('.disable()', () => {
it('should work', () => {
assert.doesNotThrow(() => {
assert(scopeManager.disable() === scopeManager, 'should return this');
assert(
contextManager.disable() === contextManager,
'should return this'
);
});
scopeManager.enable();
contextManager.enable();
});
});
describe('.with()', () => {
it('should run the callback (Context.ROOT_CONTEXT as target)', done => {
scopeManager.with(Context.ROOT_CONTEXT, done);
contextManager.with(Context.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);
scopeManager.with(test, () => {
contextManager.with(test, () => {
assert.strictEqual(
scopeManager.active(),
contextManager.active(),
Context.ROOT_CONTEXT,
'should not have scope'
'should not have context'
);
return done();
});
});
it('should run the callback (when disabled)', done => {
scopeManager.disable();
scopeManager.with(Context.ROOT_CONTEXT, () => {
scopeManager.enable();
contextManager.disable();
contextManager.with(Context.ROOT_CONTEXT, () => {
contextManager.enable();
return done();
});
});
@ -68,34 +74,34 @@ describe('NoopScopeManager', () => {
describe('.active()', () => {
it('should always return Context.ROOT_CONTEXT (when enabled)', () => {
assert.strictEqual(
scopeManager.active(),
contextManager.active(),
Context.ROOT_CONTEXT,
'should not have scope'
'should not have context'
);
});
it('should always return Context.ROOT_CONTEXT (when disabled)', () => {
scopeManager.disable();
contextManager.disable();
assert.strictEqual(
scopeManager.active(),
contextManager.active(),
Context.ROOT_CONTEXT,
'should not have scope'
'should not have context'
);
scopeManager.enable();
contextManager.enable();
});
});
describe('.bind()', () => {
it('should return the same target (when enabled)', () => {
const test = { a: 1 };
assert.deepStrictEqual(scopeManager.bind(test), test);
assert.deepStrictEqual(contextManager.bind(test), test);
});
it('should return the same target (when disabled)', () => {
scopeManager.disable();
contextManager.disable();
const test = { a: 1 };
assert.deepStrictEqual(scopeManager.bind(test), test);
scopeManager.enable();
assert.deepStrictEqual(contextManager.bind(test), test);
contextManager.enable();
});
});
});

View File

@ -1,33 +1,33 @@
# OpenTelemetry Scope Zone Peer Dependency
# OpenTelemetry Context Zone Peer Dependency
[![Gitter chat][gitter-image]][gitter-url]
[![NPM Published Version][npm-img]][npm-url]
[![dependencies][dependencies-image]][dependencies-url]
[![devDependencies][devDependencies-image]][devDependencies-url]
[![Apache License][license-image]][license-image]
This module provides *Zone Scope Manager with a peer dependency for [zone-js]* for Web applications.
This module provides *Zone Context Manager with a peer dependency for [zone-js]* for Web applications.
If you use Angular you already have the [zone-js] and you should use this package.
If you don't have your own [zone-js] please use [@opentelemetry/scope-zone]
If you don't have your own [zone-js] please use [@opentelemetry/context-zone]
## Installation
```bash
npm install --save @opentelemetry/scope-zone-peer-dep
npm install --save @opentelemetry/context-zone-peer-dep
```
## Usage
```js
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracer } from '@opentelemetry/web';
import { ZoneScopeManager } from '@opentelemetry/scope-zone-peer-dep';
import { ZoneContextManager } from '@opentelemetry/context-zone-peer-dep';
const webTracerWithZone = new WebTracer({
scopeManager: new ZoneScopeManager()
contextManager: new ZoneContextManager()
});
webTracerWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
// Example how the ZoneScopeManager keeps the reference to the correct scope during async operations
// Example how the ZoneContextManager keeps the reference to the correct context during async operations
const span1 = webTracerWithZone.startSpan('foo1');
webTracerWithZone.withSpan(span1, () => {
console.log('Current span is span1', webTracerWithZone.getCurrentSpan() === span1);
@ -61,11 +61,11 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[gitter-url]: https://gitter.im/open-telemetry/opentelemetry-node?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/master/LICENSE
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/status.svg?path=packages/opentelemetry-scope-zone-peer-dep
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-scope-zone-peer-dep
[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-scope-zone-peer-dep
[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/status.svg?path=packages/opentelemetry-context-zone-peer-dep
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-context-zone-peer-dep
[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-context-zone-peer-dep
[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-web&type=dev
[npm-url]: https://www.npmjs.com/package/@opentelemetry/scope-zone-peer-dep
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fscope-zone-peer-dep.svg
[npm-url]: https://www.npmjs.com/package/@opentelemetry/context-zone-peer-dep
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fcontext-zone-peer-dep.svg
[zone-js]: https://www.npmjs.com/package/zone.js
[@opentelemetry/scope-zone]: https://www.npmjs.com/package/@opentelemetry/scope-zone
[@opentelemetry/context-zone]: https://www.npmjs.com/package/@opentelemetry/context-zone

View File

@ -1,7 +1,7 @@
{
"name": "@opentelemetry/scope-zone-peer-dep",
"name": "@opentelemetry/context-zone-peer-dep",
"version": "0.4.0",
"description": "OpenTelemetry Scope Zone with peer dependency for zone.js",
"description": "OpenTelemetry Context Zone with peer dependency for zone.js",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
"repository": "open-telemetry/opentelemetry-js",
@ -72,7 +72,7 @@
"zone.js": "^0.10.2"
},
"dependencies": {
"@opentelemetry/scope-base": "^0.4.0"
"@opentelemetry/context-base": "^0.4.0"
},
"peerDependencies": {
"zone.js": "^0.10.2"

View File

@ -14,25 +14,25 @@
* limitations under the License.
*/
import { ScopeManager, Context } from '@opentelemetry/scope-base';
import { ContextManager, Context } from '@opentelemetry/context-base';
import { Func, TargetWithEvents } from './types';
import { isListenerObject } from './util';
/* Key name to be used to save a scope reference in Zone */
const ZONE_SCOPE_KEY = 'OT_ZONE_SCOPE';
/* Key name to be used to save a context reference in Zone */
const ZONE_CONTEXT_KEY = 'OT_ZONE_CONTEXT';
/**
* ZoneScopeManager
* ZoneContextManager
* This module provides an easy functionality for tracing action between asynchronous operations in web.
* It was not possible with standard [StackScopeManager]{@link https://github.com/open-telemetry/opentelemetry-js/blob/master/packages/opentelemetry-web/src/StackScopeManager.ts}.
* It was not possible with standard [StackContextManager]{@link https://github.com/open-telemetry/opentelemetry-js/blob/master/packages/opentelemetry-web/src/StackContextManager.ts}.
* It heavily depends on [zone.js]{@link https://www.npmjs.com/package/zone.js}.
* It stores the information about scope in zone. Each Scope will have always new Zone;
* It stores the information about context in zone. Each Context will have always new Zone;
* It also supports binding a certain Span to a target that has "addEventListener" and "removeEventListener".
* When this happens a new zone is being created and the provided Span is being assigned to this zone.
*/
export class ZoneScopeManager implements ScopeManager {
export class ZoneContextManager implements ContextManager {
/**
* whether the scope manager is enabled or not
* whether the context manager is enabled or not
*/
private _enabled = false;
@ -42,23 +42,23 @@ export class ZoneScopeManager implements ScopeManager {
private _zoneCounter = 0;
/**
* Returns the active scope from certain zone name
* Returns the active context from certain zone name
* @param activeZone
*/
private _activeScopeFromZone(activeZone: Zone | undefined): Context {
private _activeContextFromZone(activeZone: Zone | undefined): Context {
return (
(activeZone && activeZone.get(ZONE_SCOPE_KEY)) || Context.ROOT_CONTEXT
(activeZone && activeZone.get(ZONE_CONTEXT_KEY)) || Context.ROOT_CONTEXT
);
}
/**
* @param target Function to be executed within the scope
* @param scope A scope (span) to be executed within target function
* @param target Function to be executed within the context
* @param context A context (span) to be executed within target function
*/
private _bindFunction<T extends Function>(target: T, scope: Context): T {
private _bindFunction<T extends Function>(target: T, context: Context): T {
const manager = this;
const contextWrapper = function(this: any, ...args: unknown[]) {
return manager.with(scope, () => target.apply(this, args));
return manager.with(context, () => target.apply(this, args));
};
Object.defineProperty(contextWrapper, 'length', {
enumerable: false,
@ -71,9 +71,9 @@ export class ZoneScopeManager implements ScopeManager {
/**
* @param obj target object on which the listeners will be patched
* @param scope A scope (span) to be bind to target
* @param context A context (span) to be bind to target
*/
private _bindListener<T>(obj: T, scope: Context): T {
private _bindListener<T>(obj: T, context: Context): T {
const target = (obj as unknown) as TargetWithEvents;
if (target.__ot_listeners !== undefined) {
return obj;
@ -84,7 +84,7 @@ export class ZoneScopeManager implements ScopeManager {
target.addEventListener = this._patchAddEventListener(
target,
target.addEventListener,
scope
context
);
}
@ -110,13 +110,13 @@ export class ZoneScopeManager implements ScopeManager {
/**
* Creates a new zone
* @param zoneName zone name
* @param scope A scope (span) to be bind with Zone
* @param context A context (span) to be bind with Zone
*/
private _createZone(zoneName: string, scope: unknown): Zone {
private _createZone(zoneName: string, context: unknown): Zone {
return Zone.root.fork({
name: zoneName,
properties: {
[ZONE_SCOPE_KEY]: scope,
[ZONE_CONTEXT_KEY]: context,
},
});
}
@ -132,14 +132,14 @@ export class ZoneScopeManager implements ScopeManager {
* Patches addEventListener method
* @param target any target that has "addEventListener" method
* @param original reference to the patched method
* @param [scope] scope to be bind to the listener
* @param [context] context to be bind to the listener
*/
private _patchAddEventListener(
target: TargetWithEvents,
original: Function,
scope: Context
context: Context
) {
const scopeManager = this;
const contextManager = this;
return function(this: {}, event: string, listener: Func<void>, opts?: any) {
if (target.__ot_listeners === undefined) {
@ -150,7 +150,7 @@ export class ZoneScopeManager implements ScopeManager {
listeners = new WeakMap();
target.__ot_listeners[event] = listeners;
}
const patchedListener = scopeManager.bind(listener, scope);
const patchedListener = contextManager.bind(listener, context);
// store a weak reference of the user listener to ours
listeners.set(listener, patchedListener);
return original.call(this, event, patchedListener, opts);
@ -181,7 +181,7 @@ export class ZoneScopeManager implements ScopeManager {
}
/**
* Returns the active scope
* Returns the active context
*/
active(): Context {
if (!this._enabled) {
@ -189,7 +189,7 @@ export class ZoneScopeManager implements ScopeManager {
}
const activeZone = this._getActiveZone();
const active = this._activeScopeFromZone(activeZone);
const active = this._activeContextFromZone(activeZone);
if (active) {
return active;
}
@ -198,25 +198,25 @@ export class ZoneScopeManager implements ScopeManager {
}
/**
* Binds a the certain scope or the active one to the target function and then returns the target
* Binds a the certain context or the active one to the target function and then returns the target
* @param target
* @param scope A scope (span) to be bind to target
* @param context A context (span) to be bind to target
*/
bind<T>(target: T | TargetWithEvents, scope: Context): T {
// if no specific scope to propagate is given, we use the current one
if (scope === undefined) {
scope = this.active();
bind<T>(target: T | TargetWithEvents, context: Context): T {
// if no specific context to propagate is given, we use the current one
if (context === undefined) {
context = this.active();
}
if (typeof target === 'function') {
return this._bindFunction(target, scope);
return this._bindFunction(target, context);
} else if (isListenerObject(target)) {
this._bindListener(target, scope);
this._bindListener(target, context);
}
return (target as unknown) as T;
}
/**
* Disable the scope manager (clears all the scopes)
* Disable the context manager (clears all the contexts)
*/
disable(): this {
this._enabled = false;
@ -224,7 +224,7 @@ export class ZoneScopeManager implements ScopeManager {
}
/**
* Enables the scope manager and creates a default(root) scope
* Enables the context manager and creates a default(root) context
*/
enable(): this {
this._enabled = true;
@ -232,20 +232,20 @@ export class ZoneScopeManager implements ScopeManager {
}
/**
* Calls the callback function [fn] with the provided [scope].
* If [scope] is undefined then it will use the active scope.
* The scope will be set as active
* @param scope A scope (span) to be called with provided callback
* Calls the callback function [fn] with the provided [context].
* If [context] is undefined then it will use the active context.
* The context will be set as active
* @param context A context (span) to be called with provided callback
* @param fn Callback function
*/
with<T extends (...args: unknown[]) => ReturnType<T>>(
scope: Context | null,
context: Context | null,
fn: () => ReturnType<T>
): ReturnType<T> {
const zoneName = this._createZoneName();
const newZone = this._createZone(zoneName, scope);
const newZone = this._createZone(zoneName, context);
return newZone.run(fn, scope);
return newZone.run(fn, context);
}
}

View File

@ -14,5 +14,5 @@
* limitations under the License.
*/
export * from './ZoneScopeManager';
export * from './ZoneContextManager';
export * from './types';

View File

@ -17,34 +17,37 @@
import 'zone.js';
import * as sinon from 'sinon';
import * as assert from 'assert';
import { ZoneScopeManager } from '../src';
import { Context } from '@opentelemetry/scope-base';
import { ZoneContextManager } from '../src';
import { Context } from '@opentelemetry/context-base';
let clock: any;
describe('ZoneScopeManager', () => {
let scopeManager: ZoneScopeManager;
describe('ZoneContextManager', () => {
let contextManager: ZoneContextManager;
const key1 = Context.createKey('test key 1');
const key2 = Context.createKey('test key 2');
beforeEach(() => {
clock = sinon.useFakeTimers();
scopeManager = new ZoneScopeManager();
scopeManager.enable();
contextManager = new ZoneContextManager();
contextManager.enable();
});
afterEach(() => {
clock.restore();
scopeManager.disable();
contextManager.disable();
});
describe('.enable()', () => {
it('should work', () => {
const ctx = Context.ROOT_CONTEXT.setValue(key1, 1);
assert.doesNotThrow(() => {
assert(scopeManager.enable() === scopeManager, 'should return this');
scopeManager.with(ctx, () => {
assert(scopeManager.active() === ctx, 'should have root scope');
assert(
contextManager.enable() === contextManager,
'should return this'
);
contextManager.with(ctx, () => {
assert(contextManager.active() === ctx, 'should have root context');
});
});
});
@ -54,11 +57,14 @@ describe('ZoneScopeManager', () => {
it('should work', () => {
const ctx = Context.ROOT_CONTEXT.setValue(key1, 1);
assert.doesNotThrow(() => {
assert(scopeManager.disable() === scopeManager, 'should return this');
scopeManager.with(ctx, () => {
assert(
contextManager.disable() === contextManager,
'should return this'
);
contextManager.with(ctx, () => {
assert(
scopeManager.active() === Context.ROOT_CONTEXT,
'should have root scope'
contextManager.active() === Context.ROOT_CONTEXT,
'should have root context'
);
});
});
@ -67,85 +73,89 @@ describe('ZoneScopeManager', () => {
describe('.with()', () => {
it('should run the callback (null as target)', done => {
scopeManager.with(null, done);
contextManager.with(null, done);
});
it('should run the callback (object as target)', done => {
const test = Context.ROOT_CONTEXT.setValue(key1, 1);
scopeManager.with(test, () => {
assert.strictEqual(scopeManager.active(), test, 'should have scope');
contextManager.with(test, () => {
assert.strictEqual(
contextManager.active(),
test,
'should have context'
);
return done();
});
});
it('should run the callback (when disabled)', done => {
scopeManager.disable();
scopeManager.with(null, () => {
scopeManager.enable();
contextManager.disable();
contextManager.with(null, () => {
contextManager.enable();
return done();
});
});
it('should rethrow errors', done => {
assert.throws(() => {
scopeManager.with(null, () => {
contextManager.with(null, () => {
throw new Error('This should be rethrown');
});
});
return done();
});
it('should finally restore an old scope, including the async task', done => {
const scope1 = Context.ROOT_CONTEXT.setValue(key1, 'scope1');
const scope2 = Context.ROOT_CONTEXT.setValue(key1, 'scope2');
const scope3 = Context.ROOT_CONTEXT.setValue(key1, 'scope3');
it('should finally restore an old context, including the async task', done => {
const ctx1 = Context.ROOT_CONTEXT.setValue(key1, 'ctx1');
const ctx2 = Context.ROOT_CONTEXT.setValue(key1, 'ctx2');
const ctx3 = Context.ROOT_CONTEXT.setValue(key1, 'ctx3');
scopeManager.with(scope1, () => {
assert.strictEqual(scopeManager.active(), scope1);
scopeManager.with(scope2, () => {
assert.strictEqual(scopeManager.active(), scope2);
scopeManager.with(scope3, () => {
assert.strictEqual(scopeManager.active(), scope3);
contextManager.with(ctx1, () => {
assert.strictEqual(contextManager.active(), ctx1);
contextManager.with(ctx2, () => {
assert.strictEqual(contextManager.active(), ctx2);
contextManager.with(ctx3, () => {
assert.strictEqual(contextManager.active(), ctx3);
});
assert.strictEqual(scopeManager.active(), scope2);
assert.strictEqual(contextManager.active(), ctx2);
});
assert.strictEqual(scopeManager.active(), scope1);
assert.strictEqual(contextManager.active(), ctx1);
setTimeout(() => {
assert.strictEqual(scopeManager.active(), scope1);
assert.strictEqual(contextManager.active(), ctx1);
done();
}, 500);
clock.tick(500);
});
assert.strictEqual(scopeManager.active(), window);
assert.strictEqual(contextManager.active(), window);
});
it('should finally restore an old scope when scope is an object, including the async task', done => {
const scope1 = Context.ROOT_CONTEXT.setValue(key1, 1);
const scope2 = Context.ROOT_CONTEXT.setValue(key1, 2);
const scope3 = Context.ROOT_CONTEXT.setValue(key1, 3);
scopeManager.with(scope1, () => {
assert.strictEqual(scopeManager.active(), scope1);
scopeManager.with(scope2, () => {
assert.strictEqual(scopeManager.active(), scope2);
scopeManager.with(scope3, () => {
assert.strictEqual(scopeManager.active(), scope3);
it('should finally restore an old context when context is an object, including the async task', done => {
const ctx1 = Context.ROOT_CONTEXT.setValue(key1, 1);
const ctx2 = Context.ROOT_CONTEXT.setValue(key1, 2);
const ctx3 = Context.ROOT_CONTEXT.setValue(key1, 3);
contextManager.with(ctx1, () => {
assert.strictEqual(contextManager.active(), ctx1);
contextManager.with(ctx2, () => {
assert.strictEqual(contextManager.active(), ctx2);
contextManager.with(ctx3, () => {
assert.strictEqual(contextManager.active(), ctx3);
});
assert.strictEqual(scopeManager.active(), scope2);
assert.strictEqual(contextManager.active(), ctx2);
});
assert.strictEqual(scopeManager.active(), scope1);
assert.strictEqual(contextManager.active(), ctx1);
setTimeout(() => {
assert.strictEqual(scopeManager.active(), scope1);
assert.strictEqual(contextManager.active(), ctx1);
done();
}, 500);
clock.tick(500);
});
assert.strictEqual(scopeManager.active(), window);
assert.strictEqual(contextManager.active(), window);
});
it('should correctly return the scopes for 3 parallel actions', () => {
it('should correctly return the contexts for 3 parallel actions', () => {
const rootSpan = Context.ROOT_CONTEXT.setValue(key1, 'root');
scopeManager.with(rootSpan, () => {
contextManager.with(rootSpan, () => {
assert.ok(
scopeManager.active().getValue(key1) === 'root',
contextManager.active().getValue(key1) === 'root',
'Current span is rootSpan'
);
const concurrentSpan1 = Context.ROOT_CONTEXT.setValue(
@ -161,28 +171,28 @@ describe('ZoneScopeManager', () => {
'concurrentSpan3'
);
scopeManager.with(concurrentSpan1, () => {
contextManager.with(concurrentSpan1, () => {
setTimeout(() => {
assert.ok(
scopeManager.active().getValue(key2) === concurrentSpan1,
contextManager.active().getValue(key2) === concurrentSpan1,
'Current span is concurrentSpan1'
);
}, 10);
});
scopeManager.with(concurrentSpan2, () => {
contextManager.with(concurrentSpan2, () => {
setTimeout(() => {
assert.ok(
scopeManager.active().getValue(key2) === concurrentSpan2,
contextManager.active().getValue(key2) === concurrentSpan2,
'Current span is concurrentSpan2'
);
}, 20);
});
scopeManager.with(concurrentSpan3, () => {
contextManager.with(concurrentSpan3, () => {
setTimeout(() => {
assert.ok(
scopeManager.active().getValue(key2) === concurrentSpan3,
contextManager.active().getValue(key2) === concurrentSpan3,
'Current span is concurrentSpan3'
);
}, 30);
@ -192,7 +202,7 @@ describe('ZoneScopeManager', () => {
});
describe('.bind(function)', () => {
it('should call the function with previously assigned scope', () => {
it('should call the function with previously assigned context', () => {
class Obj {
title: string;
@ -201,7 +211,7 @@ describe('ZoneScopeManager', () => {
}
getTitle() {
return (scopeManager.active().getValue(key1) as Obj).title;
return (contextManager.active().getValue(key1) as Obj).title;
}
}
@ -209,61 +219,65 @@ describe('ZoneScopeManager', () => {
const ctx = Context.ROOT_CONTEXT.setValue(key1, obj1);
obj1.title = 'a2';
const obj2 = new Obj('b1');
const wrapper: any = scopeManager.bind(obj2.getTitle, ctx);
const wrapper: any = contextManager.bind(obj2.getTitle, ctx);
assert.ok(wrapper(), 'a2');
});
it('should return the same target (when enabled)', () => {
const test = { a: 1 };
assert.deepStrictEqual(
scopeManager.bind(test, Context.ROOT_CONTEXT),
contextManager.bind(test, Context.ROOT_CONTEXT),
test
);
});
it('should return the same target (when disabled)', () => {
scopeManager.disable();
contextManager.disable();
const test = { a: 1 };
assert.deepStrictEqual(
scopeManager.bind(test, Context.ROOT_CONTEXT),
contextManager.bind(test, Context.ROOT_CONTEXT),
test
);
scopeManager.enable();
contextManager.enable();
});
it('should return current scope (when enabled)', done => {
const scope = Context.ROOT_CONTEXT.setValue(key1, { a: 1 });
const fn: any = scopeManager.bind(() => {
assert.strictEqual(scopeManager.active(), scope, 'should have scope');
return done();
}, scope);
fn();
});
it('should return root scope (when disabled)', done => {
scopeManager.disable();
const scope = Context.ROOT_CONTEXT.setValue(key1, { a: 1 });
const fn: any = scopeManager.bind(() => {
it('should return current context (when enabled)', done => {
const context = Context.ROOT_CONTEXT.setValue(key1, { a: 1 });
const fn: any = contextManager.bind(() => {
assert.strictEqual(
scopeManager.active(),
Context.ROOT_CONTEXT,
'should have scope'
contextManager.active(),
context,
'should have context'
);
return done();
}, scope);
}, context);
fn();
});
it('should bind the the certain scope to the target "addEventListener" function', done => {
const scope1 = Context.ROOT_CONTEXT.setValue(key1, 1);
it('should return root context (when disabled)', done => {
contextManager.disable();
const context = Context.ROOT_CONTEXT.setValue(key1, { a: 1 });
const fn: any = contextManager.bind(() => {
assert.strictEqual(
contextManager.active(),
Context.ROOT_CONTEXT,
'should have context'
);
return done();
}, context);
fn();
});
it('should bind the the certain context to the target "addEventListener" function', done => {
const ctx1 = Context.ROOT_CONTEXT.setValue(key1, 1);
const element = document.createElement('div');
scopeManager.bind(element, scope1);
contextManager.bind(element, ctx1);
element.addEventListener('click', () => {
assert.strictEqual(scopeManager.active(), scope1);
assert.strictEqual(contextManager.active(), ctx1);
setTimeout(() => {
assert.strictEqual(scopeManager.active(), scope1);
assert.strictEqual(contextManager.active(), ctx1);
done();
}, 500);
clock.tick(500);
@ -279,21 +293,21 @@ describe('ZoneScopeManager', () => {
});
it('should preserve zone when creating new click event inside zone', done => {
const scope1 = Context.ROOT_CONTEXT.setValue(key1, 1);
const ctx1 = Context.ROOT_CONTEXT.setValue(key1, 1);
const element = document.createElement('div');
scopeManager.bind(element, scope1);
contextManager.bind(element, ctx1);
element.addEventListener('click', () => {
assert.strictEqual(scopeManager.active(), scope1);
assert.strictEqual(contextManager.active(), ctx1);
setTimeout(() => {
assert.strictEqual(scopeManager.active(), scope1);
assert.strictEqual(contextManager.active(), ctx1);
const element2 = document.createElement('div');
element2.addEventListener('click', () => {
assert.strictEqual(scopeManager.active(), scope1);
assert.strictEqual(contextManager.active(), ctx1);
setTimeout(() => {
assert.strictEqual(scopeManager.active(), scope1);
assert.strictEqual(contextManager.active(), ctx1);
done();
}, 500);
clock.tick(500);

View File

@ -17,7 +17,7 @@
import * as assert from 'assert';
import * as utils from '../src/util';
describe('ZoneScopeManager utils', () => {
describe('ZoneContextManager utils', () => {
describe('isListenerObject', () => {
describe('when object contains "addEventListener" and "removeEventListener"', () => {
it('should return true', () => {

View File

@ -1,33 +1,33 @@
# OpenTelemetry Scope Zone
# OpenTelemetry Context Zone
[![Gitter chat][gitter-image]][gitter-url]
[![NPM Published Version][npm-img]][npm-url]
[![dependencies][dependencies-image]][dependencies-url]
[![devDependencies][devDependencies-image]][devDependencies-url]
[![Apache License][license-image]][license-image]
This module provides *Zone Scope Manager with bundled [zone-js]* for Web applications.
If you have your own [zone-js] please use [@opentelemetry/scope-zone-peer-dep]
If you use Angular it means you already have the [zone-js] and you should use [@opentelemetry/scope-zone-peer-dep]
This module provides *Zone Context Manager with bundled [zone-js]* for Web applications.
If you have your own [zone-js] please use [@opentelemetry/context-zone-peer-dep]
If you use Angular it means you already have the [zone-js] and you should use [@opentelemetry/context-zone-peer-dep]
## Installation
```bash
npm install --save @opentelemetry/scope-zone
npm install --save @opentelemetry/context-zone
```
## Usage
```js
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracer } from '@opentelemetry/web';
import { ZoneScopeManager } from '@opentelemetry/scope-zone';
import { ZoneContextManager } from '@opentelemetry/context-zone';
const webTracerWithZone = new WebTracer({
scopeManager: new ZoneScopeManager()
contextManager: new ZoneContextManager()
});
webTracerWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
// Example how the ZoneScopeManager keeps the reference to the correct scope during async operations
// Example how the ZoneContextManager keeps the reference to the correct context during async operations
const span1 = webTracerWithZone.startSpan('foo1');
webTracerWithZone.withSpan(span1, () => {
console.log('Current span is span1', webTracerWithZone.getCurrentSpan() === span1);
@ -61,11 +61,11 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[gitter-url]: https://gitter.im/open-telemetry/opentelemetry-node?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/master/LICENSE
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/status.svg?path=packages/opentelemetry-scope-zone
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-scope-zone
[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-scope-zone
[dependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/status.svg?path=packages/opentelemetry-context-zone
[dependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-context-zone
[devDependencies-image]: https://david-dm.org/open-telemetry/opentelemetry-js/dev-status.svg?path=packages/opentelemetry-context-zone
[devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-web&type=dev
[npm-url]: https://www.npmjs.com/package/@opentelemetry/scope-zone
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fscope-zone.svg
[npm-url]: https://www.npmjs.com/package/@opentelemetry/context-zone
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fcontext-zone.svg
[zone-js]: https://www.npmjs.com/package/zone.js
[@opentelemetry/scope-zone-peer-dep]: https://www.npmjs.com/package/@opentelemetry/scope-zone-peer-dep
[@opentelemetry/context-zone-peer-dep]: https://www.npmjs.com/package/@opentelemetry/context-zone-peer-dep

View File

@ -1,7 +1,7 @@
{
"name": "@opentelemetry/scope-zone",
"name": "@opentelemetry/context-zone",
"version": "0.4.0",
"description": "OpenTelemetry Scope Zone",
"description": "OpenTelemetry Context Zone",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
"repository": "open-telemetry/opentelemetry-js",
@ -66,7 +66,7 @@
"webpack-merge": "^4.2.2"
},
"dependencies": {
"@opentelemetry/scope-zone-peer-dep": "^0.4.0",
"@opentelemetry/context-zone-peer-dep": "^0.4.0",
"zone.js": "^0.10.2"
},
"sideEffects": true

View File

@ -14,5 +14,5 @@
* limitations under the License.
*/
export * from '@opentelemetry/scope-zone-peer-dep';
export * from '@opentelemetry/context-zone-peer-dep';
import 'zone.js';

View File

@ -79,7 +79,7 @@
},
"dependencies": {
"@opentelemetry/api": "^0.4.0",
"@opentelemetry/scope-base": "^0.4.0",
"@opentelemetry/context-base": "^0.4.0",
"semver": "^7.1.3"
}
}

View File

@ -15,7 +15,7 @@
*/
import { Span, SpanContext } from '@opentelemetry/api';
import { Context } from '@opentelemetry/scope-base';
import { Context } from '@opentelemetry/context-base';
const ACTIVE_SPAN_KEY = Context.createKey(
'OpenTelemetry Context Key ACTIVE_SPAN'

View File

@ -20,7 +20,7 @@ import {
SpanContext,
TraceFlags,
} from '@opentelemetry/api';
import { Context } from '@opentelemetry/scope-base';
import { Context } from '@opentelemetry/context-base';
import * as assert from 'assert';
import {
getExtractedSpanContext,

View File

@ -20,7 +20,7 @@ import {
SpanContext,
TraceFlags,
} from '@opentelemetry/api';
import { Context } from '@opentelemetry/scope-base';
import { Context } from '@opentelemetry/context-base';
import * as assert from 'assert';
import {
getExtractedSpanContext,

View File

@ -20,7 +20,7 @@ import {
HttpTextPropagator,
SpanContext,
} from '@opentelemetry/api';
import { Context } from '@opentelemetry/scope-base';
import { Context } from '@opentelemetry/context-base';
import * as assert from 'assert';
import {
CompositePropagator,

View File

@ -27,7 +27,7 @@ This is done by wrapping all tracing-relevant functions.
This instrumentation code will automatically
- extract a trace-context identifier from inbound requests to allow distributed tracing (if applicable)
- make sure that this current trace-context is propagated while the transaction traverses an application (see [@opentelemetry/opentelemetry-scope-base](https://github.com/open-telemetry/opentelemetry-js/blob/master/packages/opentelemetry-scope-base/README.md) for an in-depth explanation)
- make sure that this current trace-context is propagated while the transaction traverses an application (see [@opentelemetry/opentelemetry-context-base](https://github.com/open-telemetry/opentelemetry-js/blob/master/packages/opentelemetry-context-base/README.md) for an in-depth explanation)
- add this trace-context identifier to outbound requests to allow continuing the distributed trace on the next hop (if applicable)
- create and end spans

View File

@ -44,7 +44,7 @@
"@opentelemetry/resources": "^0.4.0",
"@types/mocha": "^5.2.5",
"@types/node": "^12.6.8",
"@opentelemetry/scope-base": "^0.4.0",
"@opentelemetry/context-base": "^0.4.0",
"@types/semver": "^6.0.1",
"@types/shimmer": "^1.0.1",
"codecov": "^3.6.1",
@ -62,7 +62,7 @@
"dependencies": {
"@opentelemetry/api": "^0.4.0",
"@opentelemetry/core": "^0.4.0",
"@opentelemetry/scope-async-hooks": "^0.4.0",
"@opentelemetry/context-async-hooks": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0",
"require-in-the-middle": "^5.0.0",
"semver": "^7.1.3"

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import {
BasicTracerProvider,
SDKRegistrationConfig,
@ -48,7 +48,7 @@ export class NodeTracerProvider extends BasicTracerProvider {
register(config: SDKRegistrationConfig = {}) {
if (config.contextManager === undefined) {
config.contextManager = new AsyncHooksScopeManager();
config.contextManager = new AsyncHooksContextManager();
config.contextManager.enable();
}

View File

@ -22,12 +22,12 @@ import {
NoRecordingSpan,
setActiveSpan,
} from '@opentelemetry/core';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import { Span } from '@opentelemetry/tracing';
import { Resource, TELEMETRY_SDK_RESOURCE } from '@opentelemetry/resources';
import * as assert from 'assert';
import * as path from 'path';
import { ScopeManager } from '../../opentelemetry-scope-base/build/src';
import { ContextManager } from '@opentelemetry/context-base';
import { NodeTracerProvider } from '../src/NodeTracerProvider';
const sleep = (time: number) =>
@ -43,21 +43,21 @@ const INSTALLED_PLUGINS_PATH = path.join(
describe('NodeTracerProvider', () => {
let provider: NodeTracerProvider;
let scopeManager: ScopeManager;
let contextManager: ContextManager;
before(() => {
module.paths.push(INSTALLED_PLUGINS_PATH);
});
beforeEach(() => {
scopeManager = new AsyncHooksScopeManager();
context.setGlobalContextManager(scopeManager.enable());
contextManager = new AsyncHooksContextManager();
context.setGlobalContextManager(contextManager.enable());
});
afterEach(() => {
// clear require cache
Object.keys(require.cache).forEach(key => delete require.cache[key]);
provider.stop();
scopeManager.disable();
contextManager.disable();
});
describe('constructor', () => {
@ -175,7 +175,7 @@ describe('NodeTracerProvider', () => {
});
describe('.getCurrentSpan()', () => {
it('should return undefined with AsyncHooksScopeManager when no span started', () => {
it('should return undefined with AsyncHooksContextManager when no span started', () => {
provider = new NodeTracerProvider({});
assert.deepStrictEqual(
provider.getTracer('default').getCurrentSpan(),
@ -185,7 +185,7 @@ describe('NodeTracerProvider', () => {
});
describe('.withSpan()', () => {
it('should run scope with AsyncHooksScopeManager scope manager', done => {
it('should run context with AsyncHooksContextManager context manager', done => {
provider = new NodeTracerProvider({});
const span = provider.getTracer('default').startSpan('my-span');
provider.getTracer('default').withSpan(span, () => {
@ -201,7 +201,7 @@ describe('NodeTracerProvider', () => {
);
});
it('should run scope with AsyncHooksScopeManager scope manager with multiple spans', done => {
it('should run context with AsyncHooksContextManager context manager with multiple spans', done => {
provider = new NodeTracerProvider({});
const span = provider.getTracer('default').startSpan('my-span');
provider.getTracer('default').withSpan(span, () => {
@ -232,7 +232,7 @@ describe('NodeTracerProvider', () => {
);
});
it('should find correct scope with promises', async () => {
it('should find correct context with promises', async () => {
provider = new NodeTracerProvider();
const span = provider.getTracer('default').startSpan('my-span');
await provider.getTracer('default').withSpan(span, async () => {
@ -253,7 +253,7 @@ describe('NodeTracerProvider', () => {
});
describe('.bind()', () => {
it('should bind scope with AsyncHooksScopeManager scope manager', done => {
it('should bind context with AsyncHooksContextManager context manager', done => {
const provider = new NodeTracerProvider({});
const span = provider.getTracer('default').startSpan('my-span');
const fn = () => {

View File

@ -22,14 +22,14 @@ import {
trace,
} from '@opentelemetry/api';
import { HttpTraceContext } from '@opentelemetry/core';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { NoopScopeManager } from '@opentelemetry/scope-base';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import { NoopContextManager } from '@opentelemetry/context-base';
import * as assert from 'assert';
import { NodeTracerProvider } from '../src';
describe('API registration', () => {
beforeEach(() => {
context.setGlobalContextManager(new NoopScopeManager());
context.setGlobalContextManager(new NoopContextManager());
propagation.setGlobalPropagator(new NoopHttpTextPropagator());
trace.setGlobalTracerProvider(new NoopTracerProvider());
});
@ -38,7 +38,7 @@ describe('API registration', () => {
const tracerProvider = new NodeTracerProvider();
tracerProvider.register();
assert.ok(context['_scopeManager'] instanceof AsyncHooksScopeManager);
assert.ok(context['_contextManager'] instanceof AsyncHooksContextManager);
assert.ok(propagation['_propagator'] instanceof HttpTraceContext);
assert.ok(trace['_tracerProvider'] === tracerProvider);
});
@ -46,7 +46,7 @@ describe('API registration', () => {
it('should register configured implementations', () => {
const tracerProvider = new NodeTracerProvider();
const contextManager = new NoopScopeManager();
const contextManager = new NoopContextManager();
const propagator = new NoopHttpTextPropagator();
tracerProvider.register({
@ -54,7 +54,7 @@ describe('API registration', () => {
propagator,
});
assert.ok(context['_scopeManager'] === contextManager);
assert.ok(context['_contextManager'] === contextManager);
assert.ok(propagation['_propagator'] === propagator);
assert.ok(trace['_tracerProvider'] === tracerProvider);
@ -66,7 +66,7 @@ describe('API registration', () => {
contextManager: null,
});
assert.ok(context['_scopeManager'] instanceof NoopScopeManager);
assert.ok(context['_contextManager'] instanceof NoopContextManager);
assert.ok(propagation['_propagator'] instanceof HttpTraceContext);
assert.ok(trace['_tracerProvider'] === tracerProvider);
@ -80,7 +80,7 @@ describe('API registration', () => {
assert.ok(propagation['_propagator'] instanceof NoopHttpTextPropagator);
assert.ok(context['_scopeManager'] instanceof AsyncHooksScopeManager);
assert.ok(context['_contextManager'] instanceof AsyncHooksContextManager);
assert.ok(trace['_tracerProvider'] === tracerProvider);
});
});

View File

@ -38,7 +38,7 @@ import {
} from '@opentelemetry/tracing';
import {
PerformanceTimingNames as PTN,
StackScopeManager,
StackContextManager,
} from '@opentelemetry/web';
import * as assert from 'assert';
import * as sinon from 'sinon';
@ -209,11 +209,11 @@ describe('DocumentLoad Plugin', () => {
let config: PluginConfig;
let spanProcessor: SimpleSpanProcessor;
let dummyExporter: DummyExporter;
let scopeManager: StackScopeManager;
let contextManager: StackContextManager;
beforeEach(() => {
scopeManager = new StackScopeManager().enable();
context.setGlobalContextManager(scopeManager);
contextManager = new StackContextManager().enable();
context.setGlobalContextManager(contextManager);
Object.defineProperty(window.document, 'readyState', {
writable: true,
value: 'complete',
@ -229,7 +229,7 @@ describe('DocumentLoad Plugin', () => {
});
afterEach(() => {
scopeManager.disable();
contextManager.disable();
Object.defineProperty(window.document, 'readyState', {
writable: true,
value: 'complete',

View File

@ -42,7 +42,7 @@
},
"devDependencies": {
"@opentelemetry/node": "^0.4.0",
"@opentelemetry/scope-async-hooks": "^0.4.0",
"@opentelemetry/context-async-hooks": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0",
"@types/express": "^4.17.2",
"@types/mocha": "^5.2.7",

View File

@ -158,7 +158,7 @@ export class ExpressPlugin extends BasePlugin<typeof express> {
} as any;
}
/** Patch each express layer to create span and propagate scope */
/** Patch each express layer to create span and propagate context */
private _applyPatch(layer: ExpressLayer, layerPath?: string) {
const plugin = this;
if (layer[kLayerPatched] === true) return;

View File

@ -17,7 +17,7 @@
import { context } from '@opentelemetry/api';
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracerProvider } from '@opentelemetry/node';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
@ -59,20 +59,20 @@ describe('Express Plugin', () => {
const spanProcessor = new SimpleSpanProcessor(memoryExporter);
provider.addSpanProcessor(spanProcessor);
const tracer = provider.getTracer('default');
let scopeManager: AsyncHooksScopeManager;
let contextManager: AsyncHooksContextManager;
before(() => {
plugin.enable(express, provider, logger);
});
beforeEach(() => {
scopeManager = new AsyncHooksScopeManager();
context.setGlobalContextManager(scopeManager.enable());
contextManager = new AsyncHooksContextManager();
context.setGlobalContextManager(contextManager.enable());
});
afterEach(() => {
memoryExporter.reset();
scopeManager.disable();
contextManager.disable();
});
describe('Instrumenting normal get operations', () => {

View File

@ -42,8 +42,8 @@
},
"devDependencies": {
"@opentelemetry/node": "^0.4.0",
"@opentelemetry/scope-async-hooks": "^0.4.0",
"@opentelemetry/scope-base": "^0.4.0",
"@opentelemetry/context-async-hooks": "^0.4.0",
"@opentelemetry/context-base": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0",
"@types/mocha": "^5.2.7",
"@types/node": "^12.6.9",

View File

@ -22,8 +22,8 @@ import {
} from '@opentelemetry/api';
import { NoopLogger, HttpTraceContext } from '@opentelemetry/core';
import { NodeTracerProvider } from '@opentelemetry/node';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { ScopeManager } from '@opentelemetry/scope-base';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import { ContextManager } from '@opentelemetry/context-base';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
@ -300,19 +300,19 @@ function createClient(grpc: GrpcModule, proto: any) {
}
describe('GrpcPlugin', () => {
let scopeManger: ScopeManager;
let contextManager: ContextManager;
before(() => {
propagation.setGlobalPropagator(new HttpTraceContext());
});
beforeEach(() => {
scopeManger = new AsyncHooksScopeManager().enable();
context.setGlobalContextManager(scopeManger);
contextManager = new AsyncHooksContextManager().enable();
context.setGlobalContextManager(contextManager);
});
afterEach(() => {
scopeManger.disable();
contextManager.disable();
});
it('should return a plugin', () => {

View File

@ -42,8 +42,8 @@
},
"devDependencies": {
"@opentelemetry/node": "^0.4.0",
"@opentelemetry/scope-async-hooks": "^0.4.0",
"@opentelemetry/scope-base": "^0.4.0",
"@opentelemetry/context-async-hooks": "^0.4.0",
"@opentelemetry/context-base": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0",
"@types/got": "^9.6.7",
"@types/mocha": "^5.2.7",

View File

@ -38,8 +38,8 @@ import { OT_REQUEST_HEADER } from '../../src/utils';
import { assertSpan } from '../utils/assertSpan';
import { DummyPropagation } from '../utils/DummyPropagation';
import { httpRequest } from '../utils/httpRequest';
import { ScopeManager } from '@opentelemetry/scope-base';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { ContextManager } from '@opentelemetry/context-base';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
const applyCustomAttributesOnSpanErrorMessage =
'bad applyCustomAttributesOnSpan function';
@ -77,15 +77,15 @@ export const customAttributeFunction = (span: ISpan): void => {
};
describe('HttpPlugin', () => {
let scopeManger: ScopeManager;
let contextManager: ContextManager;
beforeEach(() => {
scopeManger = new AsyncHooksScopeManager().enable();
context.setGlobalContextManager(scopeManger);
contextManager = new AsyncHooksContextManager().enable();
context.setGlobalContextManager(contextManager);
});
afterEach(() => {
scopeManger.disable();
contextManager.disable();
});
it('should return a plugin', () => {

View File

@ -42,8 +42,8 @@
},
"devDependencies": {
"@opentelemetry/node": "^0.4.0",
"@opentelemetry/scope-async-hooks": "^0.4.0",
"@opentelemetry/scope-base": "^0.4.0",
"@opentelemetry/context-async-hooks": "^0.4.0",
"@opentelemetry/context-base": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0",
"@types/got": "^9.6.7",
"@types/mocha": "^5.2.7",

View File

@ -29,8 +29,8 @@ import {
HttpPluginConfig,
OT_REQUEST_HEADER,
} from '@opentelemetry/plugin-http';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { ScopeManager } from '@opentelemetry/scope-base';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import { ContextManager } from '@opentelemetry/context-base';
import {
InMemorySpanExporter,
SimpleSpanProcessor,
@ -83,15 +83,15 @@ export const customAttributeFunction = (span: ISpan): void => {
};
describe('HttpsPlugin', () => {
let scopeManger: ScopeManager;
let contextManager: ContextManager;
beforeEach(() => {
scopeManger = new AsyncHooksScopeManager().enable();
context.setGlobalContextManager(scopeManger);
contextManager = new AsyncHooksContextManager().enable();
context.setGlobalContextManager(contextManager);
});
afterEach(() => {
scopeManger.disable();
contextManager.disable();
});
it('should return a plugin', () => {

View File

@ -45,7 +45,7 @@
},
"devDependencies": {
"@opentelemetry/node": "^0.4.0",
"@opentelemetry/scope-async-hooks": "^0.4.0",
"@opentelemetry/context-async-hooks": "^0.4.0",
"@opentelemetry/test-utils": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0",
"@types/ioredis": "^4.14.3",

View File

@ -17,7 +17,7 @@
import { CanonicalCode, context, SpanKind, Status } from '@opentelemetry/api';
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracerProvider } from '@opentelemetry/node';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import * as testUtils from '@opentelemetry/test-utils';
import {
InMemorySpanExporter,
@ -55,18 +55,18 @@ describe('ioredis', () => {
const shouldTestLocal = process.env.RUN_REDIS_TESTS_LOCAL;
const shouldTest = process.env.RUN_REDIS_TESTS || shouldTestLocal;
let scopeManager: AsyncHooksScopeManager;
let contextManager: AsyncHooksContextManager;
beforeEach(() => {
scopeManager = new AsyncHooksScopeManager().enable();
context.setGlobalContextManager(scopeManager);
contextManager = new AsyncHooksContextManager().enable();
context.setGlobalContextManager(contextManager);
});
afterEach(() => {
scopeManager.disable();
contextManager.disable();
});
before(function() {
// needs to be "function" to have MochaContext "this" scope
// needs to be "function" to have MochaContext "this" context
if (!shouldTest) {
// this.skip() workaround
// https://github.com/mochajs/mocha/issues/2683#issuecomment-375629901

View File

@ -42,7 +42,7 @@
},
"devDependencies": {
"@opentelemetry/node": "^0.4.0",
"@opentelemetry/scope-async-hooks": "^0.4.0",
"@opentelemetry/context-async-hooks": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0",
"@types/mocha": "^5.2.7",
"@types/mongodb": "^3.2.3",

View File

@ -17,7 +17,7 @@
import { CanonicalCode, context, SpanKind } from '@opentelemetry/api';
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracerProvider } from '@opentelemetry/node';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import {
InMemorySpanExporter,
ReadableSpan,
@ -103,7 +103,7 @@ describe('MongoDBPlugin', () => {
const DB_NAME = process.env.MONGODB_DB || 'opentelemetry-tests';
const COLLECTION_NAME = 'test';
let scopeManager: AsyncHooksScopeManager;
let contextManager: AsyncHooksContextManager;
let client: mongodb.MongoClient;
let collection: mongodb.Collection;
const logger = new NoopLogger();
@ -142,13 +142,13 @@ describe('MongoDBPlugin', () => {
collection.insertMany(insertData, (err, result) => {
done();
});
scopeManager = new AsyncHooksScopeManager().enable();
context.setGlobalContextManager(scopeManager);
contextManager = new AsyncHooksContextManager().enable();
context.setGlobalContextManager(contextManager);
});
afterEach(done => {
collection.deleteOne({}, done);
scopeManager.disable();
contextManager.disable();
});
after(() => {

View File

@ -42,7 +42,7 @@
},
"devDependencies": {
"@opentelemetry/node": "^0.4.0",
"@opentelemetry/scope-async-hooks": "^0.4.0",
"@opentelemetry/context-async-hooks": "^0.4.0",
"@opentelemetry/test-utils": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0",
"@types/mocha": "^5.2.7",

View File

@ -17,7 +17,7 @@
import { CanonicalCode, context } from '@opentelemetry/api';
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracerProvider } from '@opentelemetry/node';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import * as testUtils from '@opentelemetry/test-utils';
import {
InMemorySpanExporter,
@ -36,7 +36,7 @@ const user = process.env.MYSQL_USER || 'otel';
const password = process.env.MYSQL_PASSWORD || 'secret';
describe('mysql@2.x', () => {
let scopeManager: AsyncHooksScopeManager;
let contextManager: AsyncHooksContextManager;
let connection: mysql.Connection;
let pool: mysql.Pool;
let poolCluster: mysql.PoolCluster;
@ -73,8 +73,8 @@ describe('mysql@2.x', () => {
});
beforeEach(function() {
scopeManager = new AsyncHooksScopeManager().enable();
context.setGlobalContextManager(scopeManager);
contextManager = new AsyncHooksContextManager().enable();
context.setGlobalContextManager(contextManager);
plugin.enable(mysql, provider, logger);
connection = mysql.createConnection({
port,
@ -101,7 +101,7 @@ describe('mysql@2.x', () => {
});
afterEach(done => {
scopeManager.disable();
contextManager.disable();
memoryExporter.reset();
plugin.disable();
connection.end(() => {

View File

@ -47,7 +47,7 @@
},
"devDependencies": {
"@opentelemetry/plugin-pg": "^0.4.0",
"@opentelemetry/scope-async-hooks": "^0.4.0",
"@opentelemetry/context-async-hooks": "^0.4.0",
"@opentelemetry/test-utils": "^0.4.0",
"@types/mocha": "^5.2.7",
"@types/node": "^12.6.9",

View File

@ -26,7 +26,7 @@ import {
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracerProvider } from '@opentelemetry/node';
import { plugin as pgPlugin, PostgresPlugin } from '@opentelemetry/plugin-pg';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import * as testUtils from '@opentelemetry/test-utils';
import {
InMemorySpanExporter,
@ -94,7 +94,7 @@ const runCallbackTest = (
describe('pg-pool@2.x', () => {
let pool: pgPool<pg.Client>;
let scopeManager: AsyncHooksScopeManager;
let contextManager: AsyncHooksContextManager;
const provider = new NodeTracerProvider();
const logger = new NoopLogger();
const testPostgres = process.env.RUN_POSTGRES_TESTS; // For CI: assumes local postgres db is already available
@ -128,15 +128,15 @@ describe('pg-pool@2.x', () => {
beforeEach(function() {
plugin.enable(pgPool, provider, logger);
pgPlugin.enable(pg, provider, logger);
scopeManager = new AsyncHooksScopeManager().enable();
context.setGlobalContextManager(scopeManager);
contextManager = new AsyncHooksContextManager().enable();
context.setGlobalContextManager(contextManager);
});
afterEach(() => {
memoryExporter.reset();
plugin.disable();
pgPlugin.disable();
scopeManager.disable();
contextManager.disable();
});
it('should return a plugin', () => {

View File

@ -46,7 +46,7 @@
},
"devDependencies": {
"@opentelemetry/node": "^0.4.0",
"@opentelemetry/scope-async-hooks": "^0.4.0",
"@opentelemetry/context-async-hooks": "^0.4.0",
"@opentelemetry/test-utils": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0",
"@types/mocha": "^5.2.7",

View File

@ -25,7 +25,7 @@ import {
} from '@opentelemetry/api';
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracerProvider } from '@opentelemetry/node';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import * as testUtils from '@opentelemetry/test-utils';
import {
InMemorySpanExporter,
@ -83,7 +83,7 @@ const runCallbackTest = (
describe('pg@7.x', () => {
let client: pg.Client;
let scopeManager: AsyncHooksScopeManager;
let contextManager: AsyncHooksContextManager;
const provider = new NodeTracerProvider();
const tracer = provider.getTracer('external');
const logger = new NoopLogger();
@ -120,14 +120,14 @@ describe('pg@7.x', () => {
beforeEach(function() {
plugin.enable(pg, provider, logger);
scopeManager = new AsyncHooksScopeManager().enable();
context.setGlobalContextManager(scopeManager);
contextManager = new AsyncHooksContextManager().enable();
context.setGlobalContextManager(contextManager);
});
afterEach(() => {
memoryExporter.reset();
plugin.disable();
scopeManager.disable();
contextManager.disable();
});
it('should return a plugin', () => {

View File

@ -44,7 +44,7 @@
},
"devDependencies": {
"@opentelemetry/node": "^0.4.0",
"@opentelemetry/scope-async-hooks": "^0.4.0",
"@opentelemetry/context-async-hooks": "^0.4.0",
"@opentelemetry/test-utils": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0",
"@types/mocha": "^5.2.7",

View File

@ -17,7 +17,7 @@
import { CanonicalCode, context, SpanKind, Status } from '@opentelemetry/api';
import { NoopLogger } from '@opentelemetry/core';
import { NodeTracerProvider } from '@opentelemetry/node';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import * as testUtils from '@opentelemetry/test-utils';
import {
InMemorySpanExporter,
@ -55,18 +55,18 @@ describe('redis@2.x', () => {
const shouldTestLocal = process.env.RUN_REDIS_TESTS_LOCAL;
const shouldTest = process.env.RUN_REDIS_TESTS || shouldTestLocal;
let scopeManager: AsyncHooksScopeManager;
let contextManager: AsyncHooksContextManager;
beforeEach(() => {
scopeManager = new AsyncHooksScopeManager().enable();
context.setGlobalContextManager(scopeManager);
contextManager = new AsyncHooksContextManager().enable();
context.setGlobalContextManager(contextManager);
});
afterEach(() => {
scopeManager.disable();
contextManager.disable();
});
before(function() {
// needs to be "function" to have MochaContext "this" scope
// needs to be "function" to have MochaContext "this" context
if (!shouldTest) {
// this.skip() workaround
// https://github.com/mochajs/mocha/issues/2683#issuecomment-375629901

View File

@ -7,8 +7,8 @@
This module provides auto instrumentation of user interaction for web.
This module can work either with [zone-js] or without it.
With [zone-js] and ZoneScopeManager it will fully support the async operations.
If you use Angular you already have the [zone-js]. It will be the same if you use [@opentelemetry/scope-zone].
With [zone-js] and ZoneContextManager it will fully support the async operations.
If you use Angular you already have the [zone-js]. It will be the same if you use [@opentelemetry/context-zone].
Without [zone-js] it will still work but with limited support.
## Installation
@ -23,12 +23,12 @@ npm install --save @opentelemetry/plugin-user-interaction
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracerProvider } from '@opentelemetry/web';
import { UserInteractionPlugin } from '@opentelemetry/plugin-user-interaction';
import { ZoneScopeManager } from '@opentelemetry/scope-zone';
import { ZoneContextManager } from '@opentelemetry/context-zone';
// or if you already have zone.js
// import { ZoneScopeManager } from '@opentelemetry/scope-zone-peer-dep';
// import { ZoneContextManager } from '@opentelemetry/context-zone-peer-dep';
const provider = new WebTracerProvider({
scopeManager: new ZoneScopeManager(), // optional
contextManager: new ZoneContextManager(), // optional
plugins: [
new UserInteractionPlugin()
]
@ -101,4 +101,4 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[npm-url]: https://www.npmjs.com/package/@opentelemetry/plugin-user-interaction
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fplugin-user-interaction.svg
[zone-js]: https://www.npmjs.com/package/zone.js
[@opentelemetry/scope-zone]: https://www.npmjs.com/package/@opentelemetry/scope-zone
[@opentelemetry/context-zone]: https://www.npmjs.com/package/@opentelemetry/context-zone

View File

@ -44,7 +44,7 @@
"devDependencies": {
"@babel/core": "^7.6.0",
"@opentelemetry/plugin-xml-http-request": "^0.4.0",
"@opentelemetry/scope-zone-peer-dep": "^0.4.0",
"@opentelemetry/context-zone-peer-dep": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0",
"@types/jquery": "^3.3.31",
"@types/mocha": "^5.2.5",

View File

@ -28,7 +28,7 @@ import {
import { AttributeNames } from './enums/AttributeNames';
import { VERSION } from './version';
const ZONE_SCOPE_KEY = 'OT_ZONE_SCOPE';
const ZONE_CONTEXT_KEY = 'OT_ZONE_CONTEXT';
const EVENT_CLICK_NAME = 'event_click:';
const EVENT_NAVIGATION_NAME = 'Navigation:';
@ -246,7 +246,7 @@ export class UserInteractionPlugin extends BasePlugin<unknown> {
task: AsyncTask
) {
const currentZone = Zone.current;
const currentSpan = currentZone.get(ZONE_SCOPE_KEY);
const currentSpan = currentZone.get(ZONE_CONTEXT_KEY);
if (currentSpan && plugin._shouldCountTask(task, currentZone)) {
plugin._decrementTask(currentSpan);
}
@ -269,7 +269,7 @@ export class UserInteractionPlugin extends BasePlugin<unknown> {
task: AsyncTask
) {
const currentZone = Zone.current;
const currentSpan: types.Span = currentZone.get(ZONE_SCOPE_KEY);
const currentSpan: types.Span = currentZone.get(ZONE_CONTEXT_KEY);
if (currentSpan && plugin._shouldCountTask(task, currentZone)) {
plugin._incrementTask(currentSpan);
plugin._checkForTimeout(task, currentSpan);
@ -310,7 +310,7 @@ export class UserInteractionPlugin extends BasePlugin<unknown> {
}
}
} else {
span = this.get(ZONE_SCOPE_KEY);
span = this.get(ZONE_CONTEXT_KEY);
}
try {
@ -337,7 +337,7 @@ export class UserInteractionPlugin extends BasePlugin<unknown> {
if (!currentZone || !task.data || task.data.isPeriodic) {
return false;
}
const currentSpan = currentZone.get(ZONE_SCOPE_KEY);
const currentSpan = currentZone.get(ZONE_CONTEXT_KEY);
if (!currentSpan) {
return false;
}

View File

@ -21,7 +21,7 @@ const originalSetTimeout = window.setTimeout;
import { context } from '@opentelemetry/api';
import { isWrapped, LogLevel } from '@opentelemetry/core';
import { XMLHttpRequestPlugin } from '@opentelemetry/plugin-xml-http-request';
import { ZoneScopeManager } from '@opentelemetry/scope-zone-peer-dep';
import { ZoneContextManager } from '@opentelemetry/context-zone-peer-dep';
import * as tracing from '@opentelemetry/tracing';
import { WebTracerProvider } from '@opentelemetry/web';
import * as assert from 'assert';
@ -39,7 +39,7 @@ const FILE_URL =
describe('UserInteractionPlugin', () => {
describe('when zone.js is NOT available', () => {
let scopeManager: ZoneScopeManager;
let contextManager: ZoneContextManager;
let userInteractionPlugin: UserInteractionPlugin;
let sandbox: sinon.SinonSandbox;
let webTracerProvider: WebTracerProvider;
@ -47,8 +47,8 @@ describe('UserInteractionPlugin', () => {
let exportSpy: sinon.SinonSpy;
let requests: sinon.SinonFakeXMLHttpRequest[] = [];
beforeEach(() => {
scopeManager = new ZoneScopeManager().enable();
context.setGlobalContextManager(scopeManager);
contextManager = new ZoneContextManager().enable();
context.setGlobalContextManager(contextManager);
sandbox = sinon.createSandbox();
const fakeXhr = sandbox.useFakeXMLHttpRequest();
fakeXhr.onCreate = function(xhr: sinon.SinonFakeXMLHttpRequest) {
@ -81,7 +81,7 @@ describe('UserInteractionPlugin', () => {
new tracing.SimpleSpanProcessor(dummySpanExporter)
);
// this is needed as window is treated as scope and karma is adding
// this is needed as window is treated as context and karma is adding
// context which is then detected as spanContext
(window as { context?: {} }).context = undefined;
});
@ -89,7 +89,7 @@ describe('UserInteractionPlugin', () => {
requests = [];
sandbox.restore();
exportSpy.restore();
scopeManager.disable();
contextManager.disable();
});
it('should handle task without async operation', () => {

View File

@ -21,7 +21,7 @@ const originalSetTimeout = window.setTimeout;
import { context } from '@opentelemetry/api';
import { isWrapped, LogLevel } from '@opentelemetry/core';
import { XMLHttpRequestPlugin } from '@opentelemetry/plugin-xml-http-request';
import { ZoneScopeManager } from '@opentelemetry/scope-zone-peer-dep';
import { ZoneContextManager } from '@opentelemetry/context-zone-peer-dep';
import * as tracing from '@opentelemetry/tracing';
import { WebTracerProvider } from '@opentelemetry/web';
import * as assert from 'assert';
@ -42,7 +42,7 @@ const FILE_URL =
describe('UserInteractionPlugin', () => {
describe('when zone.js is available', () => {
let scopeManager: ZoneScopeManager;
let contextManager: ZoneContextManager;
let userInteractionPlugin: UserInteractionPlugin;
let sandbox: sinon.SinonSandbox;
let webTracerProvider: WebTracerProvider;
@ -50,8 +50,8 @@ describe('UserInteractionPlugin', () => {
let exportSpy: sinon.SinonSpy;
let requests: sinon.SinonFakeXMLHttpRequest[] = [];
beforeEach(() => {
scopeManager = new ZoneScopeManager().enable();
context.setGlobalContextManager(scopeManager);
contextManager = new ZoneContextManager().enable();
context.setGlobalContextManager(contextManager);
sandbox = sinon.createSandbox();
history.pushState({ test: 'testing' }, '', `${location.pathname}`);
const fakeXhr = sandbox.useFakeXMLHttpRequest();
@ -79,7 +79,7 @@ describe('UserInteractionPlugin', () => {
new tracing.SimpleSpanProcessor(dummySpanExporter)
);
// this is needed as window is treated as scope and karma is adding
// this is needed as window is treated as context and karma is adding
// context which is then detected as spanContext
(window as { context?: {} }).context = undefined;
});
@ -87,7 +87,7 @@ describe('UserInteractionPlugin', () => {
requests = [];
sandbox.restore();
exportSpy.restore();
scopeManager.disable();
contextManager.disable();
});
it('should handle task without async operation', () => {

View File

@ -19,10 +19,10 @@ npm install --save @opentelemetry/plugin-xml-http-request
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracer } from '@opentelemetry/web';
import { XMLHttpRequestPlugin } from '@opentelemetry/plugin-xml-http-request';
import { ZoneScopeManager } from '@opentelemetry/scope-zone';
import { ZoneContextManager } from '@opentelemetry/context-zone';
const webTracerWithZone = new WebTracer({
scopeManager: new ZoneScopeManager(),
contextManager: new ZoneContextManager(),
plugins: [
new XMLHttpRequestPlugin({
propagateTraceHeaderCorsUrls: ['http://localhost:8090']

View File

@ -44,7 +44,7 @@
},
"devDependencies": {
"@babel/core": "^7.6.0",
"@opentelemetry/scope-zone": "^0.4.0",
"@opentelemetry/context-zone": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0",
"@types/mocha": "^5.2.5",
"@types/node": "^12.6.8",

View File

@ -22,7 +22,7 @@ import {
X_B3_SPAN_ID,
X_B3_TRACE_ID,
} from '@opentelemetry/core';
import { ZoneScopeManager } from '@opentelemetry/scope-zone';
import { ZoneContextManager } from '@opentelemetry/context-zone';
import * as tracing from '@opentelemetry/tracing';
import {
PerformanceTimingNames as PTN,
@ -97,15 +97,15 @@ describe('xhr', () => {
let requests: any[] = [];
let prepareData: any;
let clearData: any;
let scopeManager: ZoneScopeManager;
let contextManager: ZoneContextManager;
beforeEach(() => {
scopeManager = new ZoneScopeManager().enable();
types.context.setGlobalContextManager(scopeManager);
contextManager = new ZoneContextManager().enable();
types.context.setGlobalContextManager(contextManager);
});
afterEach(() => {
scopeManager.disable();
contextManager.disable();
});
before(() => {

View File

@ -1,268 +0,0 @@
/*!
* Copyright 2019, 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 { AsyncHooksScopeManager } from '../src';
import { EventEmitter } from 'events';
import { Context } from '@opentelemetry/scope-base';
describe('AsyncHooksScopeManager', () => {
let scopeManager: AsyncHooksScopeManager;
const key1 = Context.createKey('test key 1');
beforeEach(() => {
scopeManager = new AsyncHooksScopeManager();
scopeManager.enable();
});
afterEach(() => {
scopeManager.disable();
});
describe('.enable()', () => {
it('should work', () => {
assert.doesNotThrow(() => {
scopeManager = new AsyncHooksScopeManager();
assert(scopeManager.enable() === scopeManager, 'should return this');
});
});
});
describe('.disable()', () => {
it('should work', () => {
assert.doesNotThrow(() => {
assert(scopeManager.disable() === scopeManager, 'should return this');
});
scopeManager.enable();
});
});
describe('.with()', () => {
it('should run the callback (null as target)', done => {
scopeManager.with(Context.ROOT_CONTEXT, done);
});
it('should run the callback (object as target)', done => {
const test = Context.ROOT_CONTEXT.setValue(key1, 1);
scopeManager.with(test, () => {
assert.strictEqual(scopeManager.active(), test, 'should have scope');
return done();
});
});
it('should run the callback (when disabled)', done => {
scopeManager.disable();
scopeManager.with(Context.ROOT_CONTEXT, () => {
scopeManager.enable();
return done();
});
});
it('should rethrow errors', done => {
assert.throws(() => {
scopeManager.with(Context.ROOT_CONTEXT, () => {
throw new Error('This should be rethrown');
});
});
return done();
});
it('should finally restore an old scope', done => {
const scope1 = Context.ROOT_CONTEXT.setValue(key1, 'scope1');
const scope2 = Context.ROOT_CONTEXT.setValue(key1, 'scope2');
scopeManager.with(scope1, () => {
assert.strictEqual(scopeManager.active(), scope1);
scopeManager.with(scope2, () => {
assert.strictEqual(scopeManager.active(), scope2);
});
assert.strictEqual(scopeManager.active(), scope1);
return done();
});
});
});
describe('.bind(function)', () => {
it('should return the same target (when enabled)', () => {
const test = { a: 1 };
assert.deepStrictEqual(
scopeManager.bind(test, Context.ROOT_CONTEXT),
test
);
});
it('should return the same target (when disabled)', () => {
scopeManager.disable();
const test = { a: 1 };
assert.deepStrictEqual(
scopeManager.bind(test, Context.ROOT_CONTEXT),
test
);
scopeManager.enable();
});
it('should return current scope (when enabled)', done => {
const scope = Context.ROOT_CONTEXT.setValue(key1, 1);
const fn = scopeManager.bind(() => {
assert.strictEqual(scopeManager.active(), scope, 'should have scope');
return done();
}, scope);
fn();
});
/**
* Even if asynchooks is disabled, the scope propagation will
* still works but it might be lost after any async op.
*/
it('should return current scope (when disabled)', done => {
scopeManager.disable();
const scope = Context.ROOT_CONTEXT.setValue(key1, 1);
const fn = scopeManager.bind(() => {
assert.strictEqual(scopeManager.active(), scope, 'should have scope');
return done();
}, scope);
fn();
});
it('should fail to return current scope (when disabled + async op)', done => {
scopeManager.disable();
const scope = Context.ROOT_CONTEXT.setValue(key1, 1);
const fn = scopeManager.bind(() => {
setTimeout(() => {
assert.strictEqual(
scopeManager.active(),
Context.ROOT_CONTEXT,
'should have no scope'
);
return done();
}, 100);
}, scope);
fn();
});
it('should return current scope (when re-enabled + async op)', done => {
scopeManager.enable();
const scope = Context.ROOT_CONTEXT.setValue(key1, 1);
const fn = scopeManager.bind(() => {
setTimeout(() => {
assert.strictEqual(scopeManager.active(), scope, 'should have scope');
return done();
}, 100);
}, scope);
fn();
});
});
describe('.bind(event-emitter)', () => {
it('should return the same target (when enabled)', () => {
const ee = new EventEmitter();
assert.deepStrictEqual(scopeManager.bind(ee, Context.ROOT_CONTEXT), ee);
});
it('should return the same target (when disabled)', () => {
const ee = new EventEmitter();
scopeManager.disable();
assert.deepStrictEqual(scopeManager.bind(ee, Context.ROOT_CONTEXT), ee);
scopeManager.enable();
});
it('should return current scope and removeListener (when enabled)', done => {
const ee = new EventEmitter();
const scope = Context.ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = scopeManager.bind(ee, scope);
const handler = () => {
assert.deepStrictEqual(scopeManager.active(), scope);
patchedEe.removeListener('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 0);
return done();
};
patchedEe.on('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 1);
patchedEe.emit('test');
});
it('should return current scope and removeAllListener (when enabled)', done => {
const ee = new EventEmitter();
const scope = Context.ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = scopeManager.bind(ee, scope);
const handler = () => {
assert.deepStrictEqual(scopeManager.active(), scope);
patchedEe.removeAllListeners('test');
assert.strictEqual(patchedEe.listeners('test').length, 0);
return done();
};
patchedEe.on('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 1);
patchedEe.emit('test');
});
/**
* Even if asynchooks is disabled, the scope propagation will
* still works but it might be lost after any async op.
*/
it('should return scope (when disabled)', done => {
scopeManager.disable();
const ee = new EventEmitter();
const scope = Context.ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = scopeManager.bind(ee, scope);
const handler = () => {
assert.deepStrictEqual(scopeManager.active(), scope);
patchedEe.removeListener('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 0);
scopeManager.enable();
return done();
};
patchedEe.on('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 1);
patchedEe.emit('test');
});
it('should not return current scope (when disabled + async op)', done => {
scopeManager.disable();
const ee = new EventEmitter();
const scope = Context.ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = scopeManager.bind(ee, scope);
const handler = () => {
setImmediate(() => {
assert.deepStrictEqual(scopeManager.active(), Context.ROOT_CONTEXT);
patchedEe.removeAllListeners('test');
assert.strictEqual(patchedEe.listeners('test').length, 0);
return done();
});
};
patchedEe.on('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 1);
patchedEe.emit('test');
});
it('should return current scope (when enabled + async op)', done => {
scopeManager.enable();
const ee = new EventEmitter();
const scope = Context.ROOT_CONTEXT.setValue(key1, 1);
const patchedEe = scopeManager.bind(ee, scope);
const handler = () => {
setImmediate(() => {
assert.deepStrictEqual(scopeManager.active(), scope);
patchedEe.removeAllListeners('test');
assert.strictEqual(patchedEe.listeners('test').length, 0);
return done();
});
};
patchedEe.on('test', handler);
assert.strictEqual(patchedEe.listeners('test').length, 1);
patchedEe.emit('test');
});
});
});

View File

@ -77,6 +77,6 @@
"@opentelemetry/base": "^0.4.0",
"@opentelemetry/core": "^0.4.0",
"@opentelemetry/resources": "^0.4.0",
"@opentelemetry/scope-base": "^0.4.0"
"@opentelemetry/context-base": "^0.4.0"
}
}

View File

@ -119,7 +119,7 @@ export class Tracer implements api.Tracer {
}
/**
* Enters the scope of code where the given Span is in the current context.
* Enters the context of code where the given Span is in the current context.
*/
withSpan<T extends (...args: unknown[]) => ReturnType<T>>(
span: api.Span,
@ -130,7 +130,7 @@ export class Tracer implements api.Tracer {
}
/**
* Bind a span (or the current one) to the target's scope
* Bind a span (or the current one) to the target's context
*/
bind<T>(target: T, span?: api.Span): T {
return api.context.bind(

Some files were not shown because too many files have changed in this diff Show More