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: paths:
- ./node_modules - ./node_modules
- ./package-lock.json - ./package-lock.json
- packages/opentelemetry-base/node_modules
- packages/opentelemetry-scope-base/node_modules
- packages/opentelemetry-api/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-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-jaeger/node_modules
- packages/opentelemetry-exporter-prometheus/node_modules
- packages/opentelemetry-exporter-zipkin/node_modules - packages/opentelemetry-exporter-zipkin/node_modules
- packages/opentelemetry-metrics/node_modules
- packages/opentelemetry-node/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-plugin-dns/node_modules
- packages/opentelemetry-shim-opentracing/node_modules
- packages/opentelemetry-tracing/node_modules
- packages/opentelemetry-web/node_modules
cache_2: &cache_2 cache_2: &cache_2
key: npm-cache-02-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/checksums.txt" }}-F267A71D 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 Example of using Web Tracer with document load plugin with console exporter and collector exporter
<script type="text/javascript" src="document-load.js"></script> <script type="text/javascript" src="document-load.js"></script>
<br/> <br/>
<button id="button1">Test WebTracer with ZoneScopeManager - async</button> <button id="button1">Test WebTracer with ZoneContextManager - async</button>
</body> </body>

View File

@ -1,7 +1,7 @@
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing'; import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracerProvider } from '@opentelemetry/web'; import { WebTracerProvider } from '@opentelemetry/web';
import { DocumentLoad } from '@opentelemetry/plugin-document-load'; 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'; import { CollectorExporter } from '@opentelemetry/exporter-collector';
const provider = new WebTracerProvider({ const provider = new WebTracerProvider({
@ -12,7 +12,7 @@ const provider = new WebTracerProvider({
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter())); provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
const providerWithZone = new WebTracerProvider({ const providerWithZone = new WebTracerProvider({
scopeManager: new ZoneScopeManager(), contextManager: new ZoneContextManager(),
plugins: [ plugins: [
new DocumentLoad(), 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 prepareClickEvent = () => {
const url1 = 'https://raw.githubusercontent.com/open-telemetry/opentelemetry-js/master/package.json'; 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'; 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 { WebTracerProvider } from '@opentelemetry/web';
import { XMLHttpRequestPlugin } from '@opentelemetry/plugin-xml-http-request'; import { XMLHttpRequestPlugin } from '@opentelemetry/plugin-xml-http-request';
import { UserInteractionPlugin } from '@opentelemetry/plugin-user-interaction'; 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 { CollectorExporter } from '@opentelemetry/exporter-collector';
import { B3Propagator } from '@opentelemetry/core'; import { B3Propagator } from '@opentelemetry/core';
const providerWithZone = new WebTracerProvider({ const providerWithZone = new WebTracerProvider({
HttpTextPropagator: new B3Propagator(),
scopeManager: new ZoneScopeManager(),
plugins: [ plugins: [
new UserInteractionPlugin(), new UserInteractionPlugin(),
new XMLHttpRequestPlugin({ new XMLHttpRequestPlugin({
@ -23,6 +21,11 @@ const providerWithZone = new WebTracerProvider({
providerWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter())); providerWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
providerWithZone.addSpanProcessor(new SimpleSpanProcessor(new CollectorExporter())); providerWithZone.addSpanProcessor(new SimpleSpanProcessor(new CollectorExporter()));
providerWithZone.register({
contextManager: new ZoneContextManager(),
propagator: new B3Propagator(),
});
let lastButtonId = 0; let lastButtonId = 0;
function btnAddClick() { function btnAddClick() {

View File

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

View File

@ -39,7 +39,7 @@
"@opentelemetry/plugin-document-load": "^0.4.0", "@opentelemetry/plugin-document-load": "^0.4.0",
"@opentelemetry/plugin-user-interaction": "^0.4.0", "@opentelemetry/plugin-user-interaction": "^0.4.0",
"@opentelemetry/plugin-xml-http-request": "^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/tracing": "^0.4.0",
"@opentelemetry/web": "^0.4.0" "@opentelemetry/web": "^0.4.0"
}, },

View File

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

View File

@ -15,22 +15,22 @@
*/ */
import { import {
ScopeManager, ContextManager,
NoopScopeManager, NoopContextManager,
Context, Context,
} from '@opentelemetry/scope-base'; } from '@opentelemetry/context-base';
/** /**
* Singleton object which represents the entry point to the OpenTelemetry Context API * Singleton object which represents the entry point to the OpenTelemetry Context API
*/ */
export class ContextAPI { export class ContextAPI {
private static _instance?: 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 */ /** Empty private constructor prevents end users from constructing a new instance of the API */
private constructor() {} private constructor() {}
/** Get the singleton instance of the Scope API */ /** Get the singleton instance of the Context API */
public static getInstance(): ContextAPI { public static getInstance(): ContextAPI {
if (!this._instance) { if (!this._instance) {
this._instance = new ContextAPI(); this._instance = new ContextAPI();
@ -42,16 +42,18 @@ export class ContextAPI {
/** /**
* Set the current context manager. Returns the initialized context manager * Set the current context manager. Returns the initialized context manager
*/ */
public setGlobalContextManager(scopeManager: ScopeManager): ScopeManager { public setGlobalContextManager(
this._scopeManager = scopeManager; contextManager: ContextManager
return scopeManager; ): ContextManager {
this._contextManager = contextManager;
return contextManager;
} }
/** /**
* Get the currently active context * Get the currently active context
*/ */
public active(): Context { public active(): Context {
return this._scopeManager.active(); return this._contextManager.active();
} }
/** /**
@ -64,7 +66,7 @@ export class ContextAPI {
context: Context, context: Context,
fn: T fn: T
): ReturnType<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 * @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 { 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. * limitations under the License.
*/ */
import { Context } from '@opentelemetry/scope-base'; import { Context } from '@opentelemetry/context-base';
import { defaultGetter, GetterFunction } from '../context/propagation/getter'; import { defaultGetter, GetterFunction } from '../context/propagation/getter';
import { HttpTextPropagator } from '../context/propagation/HttpTextPropagator'; import { HttpTextPropagator } from '../context/propagation/HttpTextPropagator';
import { NOOP_HTTP_TEXT_PROPAGATOR } from '../context/propagation/NoopHttpTextPropagator'; import { NOOP_HTTP_TEXT_PROPAGATOR } from '../context/propagation/NoopHttpTextPropagator';

View File

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

View File

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

View File

@ -35,7 +35,7 @@ export interface EntryValue {
*/ */
export enum EntryTtl { 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. * process it created.
*/ */
NO_PROPAGATION = 0, NO_PROPAGATION = 0,

View File

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

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { Context } from '@opentelemetry/scope-base'; import { Context } from '@opentelemetry/context-base';
import { Span } from './span'; import { Span } from './span';
import { SpanOptions } from './SpanOptions'; import { SpanOptions } from './SpanOptions';
@ -58,9 +58,9 @@ export interface Tracer {
): ReturnType<T>; ): 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 * @param [context] Optionally specify the context which you want to bind
*/ */
bind<T>(target: T, context?: Span): T; 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] [![Gitter chat][gitter-image]][gitter-url]
[![NPM Published Version][npm-img]][npm-url] [![NPM Published Version][npm-img]][npm-url]
[![dependencies][dependencies-image]][dependencies-url] [![dependencies][dependencies-image]][dependencies-url]
[![devDependencies][devDependencies-image]][devDependencies-url] [![devDependencies][devDependencies-image]][devDependencies-url]
[![Apache License][license-image]][license-image] [![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 ### 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. This package only handle storing a specific object for a given async hooks context.
### Limitations ### 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 ### 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 [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-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 [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-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-scope-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-scope-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-scope-async-hooks&type=dev [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 [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 [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 [opentracing-scope]: https://github.com/opentracing/opentracing-javascript/pull/113
[diag-team-scope-discussion]: https://github.com/nodejs/diagnostics/issues/300 [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 [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-url]: https://www.npmjs.com/package/@opentelemetry/context-async-hooks
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fscope-async-hooks.svg [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", "version": "0.4.0",
"description": "OpenTelemetry AsyncHooks-based Scope Manager", "description": "OpenTelemetry AsyncHooks-based Context Manager",
"main": "build/src/index.js", "main": "build/src/index.js",
"types": "build/src/index.d.ts", "types": "build/src/index.d.ts",
"repository": "open-telemetry/opentelemetry-js", "repository": "open-telemetry/opentelemetry-js",
@ -56,6 +56,6 @@
"typescript": "3.7.2" "typescript": "3.7.2"
}, },
"dependencies": { "dependencies": {
"@opentelemetry/scope-base": "^0.4.0" "@opentelemetry/context-base": "^0.4.0"
} }
} }

View File

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

View File

@ -14,4 +14,4 @@
* limitations under the License. * 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] [![Gitter chat][gitter-image]][gitter-url]
[![NPM Published Version][npm-img]][npm-url] [![NPM Published Version][npm-img]][npm-url]
[![dependencies][dependencies-image]][dependencies-url] [![dependencies][dependencies-image]][dependencies-url]
[![devDependencies][devDependencies-image]][devDependencies-url] [![devDependencies][devDependencies-image]][devDependencies-url]
[![Apache License][license-image]][license-image] [![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. 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. 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.
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.
## Useful links ## Useful links
- For more information on OpenTelemetry, visit: <https://opentelemetry.io/> - 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 [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-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 [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-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-scope-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-scope-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-scope-base&type=dev [devDependencies-url]: https://david-dm.org/open-telemetry/opentelemetry-js?path=packages%2Fopentelemetry-context-base&type=dev
[ah-scope-manager]: https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-scope-async-hooks [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/scope-base [npm-url]: https://www.npmjs.com/package/@opentelemetry/context-base
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fscope-base.svg [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", "version": "0.4.0",
"description": "OpenTelemetry Base Scope Manager", "description": "OpenTelemetry Base Context Manager",
"main": "build/src/index.js", "main": "build/src/index.js",
"types": "build/src/index.d.ts", "types": "build/src/index.d.ts",
"repository": "open-telemetry/opentelemetry-js", "repository": "open-telemetry/opentelemetry-js",

View File

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

View File

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

View File

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

View File

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

View File

@ -1,33 +1,33 @@
# OpenTelemetry Scope Zone Peer Dependency # OpenTelemetry Context Zone Peer Dependency
[![Gitter chat][gitter-image]][gitter-url] [![Gitter chat][gitter-image]][gitter-url]
[![NPM Published Version][npm-img]][npm-url] [![NPM Published Version][npm-img]][npm-url]
[![dependencies][dependencies-image]][dependencies-url] [![dependencies][dependencies-image]][dependencies-url]
[![devDependencies][devDependencies-image]][devDependencies-url] [![devDependencies][devDependencies-image]][devDependencies-url]
[![Apache License][license-image]][license-image] [![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 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 ## Installation
```bash ```bash
npm install --save @opentelemetry/scope-zone-peer-dep npm install --save @opentelemetry/context-zone-peer-dep
``` ```
## Usage ## Usage
```js ```js
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing'; import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracer } from '@opentelemetry/web'; 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({ const webTracerWithZone = new WebTracer({
scopeManager: new ZoneScopeManager() contextManager: new ZoneContextManager()
}); });
webTracerWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter())); 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'); const span1 = webTracerWithZone.startSpan('foo1');
webTracerWithZone.withSpan(span1, () => { webTracerWithZone.withSpan(span1, () => {
console.log('Current span is span1', webTracerWithZone.getCurrentSpan() === 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 [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-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 [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-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-scope-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-scope-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 [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-url]: https://www.npmjs.com/package/@opentelemetry/context-zone-peer-dep
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fscope-zone-peer-dep.svg [npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fcontext-zone-peer-dep.svg
[zone-js]: https://www.npmjs.com/package/zone.js [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", "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", "main": "build/src/index.js",
"types": "build/src/index.d.ts", "types": "build/src/index.d.ts",
"repository": "open-telemetry/opentelemetry-js", "repository": "open-telemetry/opentelemetry-js",
@ -72,7 +72,7 @@
"zone.js": "^0.10.2" "zone.js": "^0.10.2"
}, },
"dependencies": { "dependencies": {
"@opentelemetry/scope-base": "^0.4.0" "@opentelemetry/context-base": "^0.4.0"
}, },
"peerDependencies": { "peerDependencies": {
"zone.js": "^0.10.2" "zone.js": "^0.10.2"

View File

@ -14,25 +14,25 @@
* limitations under the License. * limitations under the License.
*/ */
import { ScopeManager, Context } from '@opentelemetry/scope-base'; import { ContextManager, Context } from '@opentelemetry/context-base';
import { Func, TargetWithEvents } from './types'; import { Func, TargetWithEvents } from './types';
import { isListenerObject } from './util'; import { isListenerObject } from './util';
/* Key name to be used to save a scope reference in Zone */ /* Key name to be used to save a context reference in Zone */
const ZONE_SCOPE_KEY = 'OT_ZONE_SCOPE'; const ZONE_CONTEXT_KEY = 'OT_ZONE_CONTEXT';
/** /**
* ZoneScopeManager * ZoneContextManager
* This module provides an easy functionality for tracing action between asynchronous operations in web. * 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 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". * 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. * 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; private _enabled = false;
@ -42,23 +42,23 @@ export class ZoneScopeManager implements ScopeManager {
private _zoneCounter = 0; private _zoneCounter = 0;
/** /**
* Returns the active scope from certain zone name * Returns the active context from certain zone name
* @param activeZone * @param activeZone
*/ */
private _activeScopeFromZone(activeZone: Zone | undefined): Context { private _activeContextFromZone(activeZone: Zone | undefined): Context {
return ( 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 target Function to be executed within the context
* @param scope A scope (span) to be executed within target function * @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 manager = this;
const contextWrapper = function(this: any, ...args: unknown[]) { 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', { Object.defineProperty(contextWrapper, 'length', {
enumerable: false, enumerable: false,
@ -71,9 +71,9 @@ export class ZoneScopeManager implements ScopeManager {
/** /**
* @param obj target object on which the listeners will be patched * @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; const target = (obj as unknown) as TargetWithEvents;
if (target.__ot_listeners !== undefined) { if (target.__ot_listeners !== undefined) {
return obj; return obj;
@ -84,7 +84,7 @@ export class ZoneScopeManager implements ScopeManager {
target.addEventListener = this._patchAddEventListener( target.addEventListener = this._patchAddEventListener(
target, target,
target.addEventListener, target.addEventListener,
scope context
); );
} }
@ -110,13 +110,13 @@ export class ZoneScopeManager implements ScopeManager {
/** /**
* Creates a new zone * Creates a new zone
* @param zoneName zone name * @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({ return Zone.root.fork({
name: zoneName, name: zoneName,
properties: { properties: {
[ZONE_SCOPE_KEY]: scope, [ZONE_CONTEXT_KEY]: context,
}, },
}); });
} }
@ -132,14 +132,14 @@ export class ZoneScopeManager implements ScopeManager {
* Patches addEventListener method * Patches addEventListener method
* @param target any target that has "addEventListener" method * @param target any target that has "addEventListener" method
* @param original reference to the patched 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( private _patchAddEventListener(
target: TargetWithEvents, target: TargetWithEvents,
original: Function, original: Function,
scope: Context context: Context
) { ) {
const scopeManager = this; const contextManager = this;
return function(this: {}, event: string, listener: Func<void>, opts?: any) { return function(this: {}, event: string, listener: Func<void>, opts?: any) {
if (target.__ot_listeners === undefined) { if (target.__ot_listeners === undefined) {
@ -150,7 +150,7 @@ export class ZoneScopeManager implements ScopeManager {
listeners = new WeakMap(); listeners = new WeakMap();
target.__ot_listeners[event] = listeners; 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 // store a weak reference of the user listener to ours
listeners.set(listener, patchedListener); listeners.set(listener, patchedListener);
return original.call(this, event, patchedListener, opts); 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 { active(): Context {
if (!this._enabled) { if (!this._enabled) {
@ -189,7 +189,7 @@ export class ZoneScopeManager implements ScopeManager {
} }
const activeZone = this._getActiveZone(); const activeZone = this._getActiveZone();
const active = this._activeScopeFromZone(activeZone); const active = this._activeContextFromZone(activeZone);
if (active) { if (active) {
return 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 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 { bind<T>(target: T | TargetWithEvents, context: Context): T {
// if no specific scope to propagate is given, we use the current one // if no specific context to propagate is given, we use the current one
if (scope === undefined) { if (context === undefined) {
scope = this.active(); context = this.active();
} }
if (typeof target === 'function') { if (typeof target === 'function') {
return this._bindFunction(target, scope); return this._bindFunction(target, context);
} else if (isListenerObject(target)) { } else if (isListenerObject(target)) {
this._bindListener(target, scope); this._bindListener(target, context);
} }
return (target as unknown) as T; return (target as unknown) as T;
} }
/** /**
* Disable the scope manager (clears all the scopes) * Disable the context manager (clears all the contexts)
*/ */
disable(): this { disable(): this {
this._enabled = false; 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 { enable(): this {
this._enabled = true; this._enabled = true;
@ -232,20 +232,20 @@ export class ZoneScopeManager implements ScopeManager {
} }
/** /**
* Calls the callback function [fn] with the provided [scope]. * Calls the callback function [fn] with the provided [context].
* If [scope] is undefined then it will use the active scope. * If [context] is undefined then it will use the active context.
* The scope will be set as active * The context will be set as active
* @param scope A scope (span) to be called with provided callback * @param context A context (span) to be called with provided callback
* @param fn Callback function * @param fn Callback function
*/ */
with<T extends (...args: unknown[]) => ReturnType<T>>( with<T extends (...args: unknown[]) => ReturnType<T>>(
scope: Context | null, context: Context | null,
fn: () => ReturnType<T> fn: () => ReturnType<T>
): ReturnType<T> { ): ReturnType<T> {
const zoneName = this._createZoneName(); 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. * limitations under the License.
*/ */
export * from './ZoneScopeManager'; export * from './ZoneContextManager';
export * from './types'; export * from './types';

View File

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

View File

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

View File

@ -1,33 +1,33 @@
# OpenTelemetry Scope Zone # OpenTelemetry Context Zone
[![Gitter chat][gitter-image]][gitter-url] [![Gitter chat][gitter-image]][gitter-url]
[![NPM Published Version][npm-img]][npm-url] [![NPM Published Version][npm-img]][npm-url]
[![dependencies][dependencies-image]][dependencies-url] [![dependencies][dependencies-image]][dependencies-url]
[![devDependencies][devDependencies-image]][devDependencies-url] [![devDependencies][devDependencies-image]][devDependencies-url]
[![Apache License][license-image]][license-image] [![Apache License][license-image]][license-image]
This module provides *Zone Scope Manager with bundled [zone-js]* for Web applications. This module provides *Zone Context Manager with bundled [zone-js]* for Web applications.
If you have your own [zone-js] please use [@opentelemetry/scope-zone-peer-dep] 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/scope-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 ## Installation
```bash ```bash
npm install --save @opentelemetry/scope-zone npm install --save @opentelemetry/context-zone
``` ```
## Usage ## Usage
```js ```js
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing'; import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracer } from '@opentelemetry/web'; import { WebTracer } from '@opentelemetry/web';
import { ZoneScopeManager } from '@opentelemetry/scope-zone'; import { ZoneContextManager } from '@opentelemetry/context-zone';
const webTracerWithZone = new WebTracer({ const webTracerWithZone = new WebTracer({
scopeManager: new ZoneScopeManager() contextManager: new ZoneContextManager()
}); });
webTracerWithZone.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter())); 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'); const span1 = webTracerWithZone.startSpan('foo1');
webTracerWithZone.withSpan(span1, () => { webTracerWithZone.withSpan(span1, () => {
console.log('Current span is span1', webTracerWithZone.getCurrentSpan() === 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 [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-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 [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-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-scope-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-scope-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 [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-url]: https://www.npmjs.com/package/@opentelemetry/context-zone
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fscope-zone.svg [npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fcontext-zone.svg
[zone-js]: https://www.npmjs.com/package/zone.js [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", "version": "0.4.0",
"description": "OpenTelemetry Scope Zone", "description": "OpenTelemetry Context Zone",
"main": "build/src/index.js", "main": "build/src/index.js",
"types": "build/src/index.d.ts", "types": "build/src/index.d.ts",
"repository": "open-telemetry/opentelemetry-js", "repository": "open-telemetry/opentelemetry-js",
@ -66,7 +66,7 @@
"webpack-merge": "^4.2.2" "webpack-merge": "^4.2.2"
}, },
"dependencies": { "dependencies": {
"@opentelemetry/scope-zone-peer-dep": "^0.4.0", "@opentelemetry/context-zone-peer-dep": "^0.4.0",
"zone.js": "^0.10.2" "zone.js": "^0.10.2"
}, },
"sideEffects": true "sideEffects": true

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -27,7 +27,7 @@ This is done by wrapping all tracing-relevant functions.
This instrumentation code will automatically This instrumentation code will automatically
- extract a trace-context identifier from inbound requests to allow distributed tracing (if applicable) - 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) - add this trace-context identifier to outbound requests to allow continuing the distributed trace on the next hop (if applicable)
- create and end spans - create and end spans

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -158,7 +158,7 @@ export class ExpressPlugin extends BasePlugin<typeof express> {
} as any; } 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) { private _applyPatch(layer: ExpressLayer, layerPath?: string) {
const plugin = this; const plugin = this;
if (layer[kLayerPatched] === true) return; if (layer[kLayerPatched] === true) return;

View File

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

View File

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

View File

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

View File

@ -42,8 +42,8 @@
}, },
"devDependencies": { "devDependencies": {
"@opentelemetry/node": "^0.4.0", "@opentelemetry/node": "^0.4.0",
"@opentelemetry/scope-async-hooks": "^0.4.0", "@opentelemetry/context-async-hooks": "^0.4.0",
"@opentelemetry/scope-base": "^0.4.0", "@opentelemetry/context-base": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0", "@opentelemetry/tracing": "^0.4.0",
"@types/got": "^9.6.7", "@types/got": "^9.6.7",
"@types/mocha": "^5.2.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 { assertSpan } from '../utils/assertSpan';
import { DummyPropagation } from '../utils/DummyPropagation'; import { DummyPropagation } from '../utils/DummyPropagation';
import { httpRequest } from '../utils/httpRequest'; import { httpRequest } from '../utils/httpRequest';
import { ScopeManager } from '@opentelemetry/scope-base'; import { ContextManager } from '@opentelemetry/context-base';
import { AsyncHooksScopeManager } from '@opentelemetry/scope-async-hooks'; import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
const applyCustomAttributesOnSpanErrorMessage = const applyCustomAttributesOnSpanErrorMessage =
'bad applyCustomAttributesOnSpan function'; 'bad applyCustomAttributesOnSpan function';
@ -77,15 +77,15 @@ export const customAttributeFunction = (span: ISpan): void => {
}; };
describe('HttpPlugin', () => { describe('HttpPlugin', () => {
let scopeManger: ScopeManager; let contextManager: ContextManager;
beforeEach(() => { beforeEach(() => {
scopeManger = new AsyncHooksScopeManager().enable(); contextManager = new AsyncHooksContextManager().enable();
context.setGlobalContextManager(scopeManger); context.setGlobalContextManager(contextManager);
}); });
afterEach(() => { afterEach(() => {
scopeManger.disable(); contextManager.disable();
}); });
it('should return a plugin', () => { it('should return a plugin', () => {

View File

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

View File

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

View File

@ -45,7 +45,7 @@
}, },
"devDependencies": { "devDependencies": {
"@opentelemetry/node": "^0.4.0", "@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/test-utils": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0", "@opentelemetry/tracing": "^0.4.0",
"@types/ioredis": "^4.14.3", "@types/ioredis": "^4.14.3",

View File

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

View File

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

View File

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

View File

@ -42,7 +42,7 @@
}, },
"devDependencies": { "devDependencies": {
"@opentelemetry/node": "^0.4.0", "@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/test-utils": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0", "@opentelemetry/tracing": "^0.4.0",
"@types/mocha": "^5.2.7", "@types/mocha": "^5.2.7",

View File

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

View File

@ -47,7 +47,7 @@
}, },
"devDependencies": { "devDependencies": {
"@opentelemetry/plugin-pg": "^0.4.0", "@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", "@opentelemetry/test-utils": "^0.4.0",
"@types/mocha": "^5.2.7", "@types/mocha": "^5.2.7",
"@types/node": "^12.6.9", "@types/node": "^12.6.9",

View File

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

View File

@ -46,7 +46,7 @@
}, },
"devDependencies": { "devDependencies": {
"@opentelemetry/node": "^0.4.0", "@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/test-utils": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0", "@opentelemetry/tracing": "^0.4.0",
"@types/mocha": "^5.2.7", "@types/mocha": "^5.2.7",

View File

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

View File

@ -44,7 +44,7 @@
}, },
"devDependencies": { "devDependencies": {
"@opentelemetry/node": "^0.4.0", "@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/test-utils": "^0.4.0",
"@opentelemetry/tracing": "^0.4.0", "@opentelemetry/tracing": "^0.4.0",
"@types/mocha": "^5.2.7", "@types/mocha": "^5.2.7",

View File

@ -17,7 +17,7 @@
import { CanonicalCode, context, SpanKind, Status } from '@opentelemetry/api'; import { CanonicalCode, context, SpanKind, Status } from '@opentelemetry/api';
import { NoopLogger } from '@opentelemetry/core'; import { NoopLogger } from '@opentelemetry/core';
import { NodeTracerProvider } from '@opentelemetry/node'; 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 * as testUtils from '@opentelemetry/test-utils';
import { import {
InMemorySpanExporter, InMemorySpanExporter,
@ -55,18 +55,18 @@ describe('redis@2.x', () => {
const shouldTestLocal = process.env.RUN_REDIS_TESTS_LOCAL; const shouldTestLocal = process.env.RUN_REDIS_TESTS_LOCAL;
const shouldTest = process.env.RUN_REDIS_TESTS || shouldTestLocal; const shouldTest = process.env.RUN_REDIS_TESTS || shouldTestLocal;
let scopeManager: AsyncHooksScopeManager; let contextManager: AsyncHooksContextManager;
beforeEach(() => { beforeEach(() => {
scopeManager = new AsyncHooksScopeManager().enable(); contextManager = new AsyncHooksContextManager().enable();
context.setGlobalContextManager(scopeManager); context.setGlobalContextManager(contextManager);
}); });
afterEach(() => { afterEach(() => {
scopeManager.disable(); contextManager.disable();
}); });
before(function() { before(function() {
// needs to be "function" to have MochaContext "this" scope // needs to be "function" to have MochaContext "this" context
if (!shouldTest) { if (!shouldTest) {
// this.skip() workaround // this.skip() workaround
// https://github.com/mochajs/mocha/issues/2683#issuecomment-375629901 // 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 provides auto instrumentation of user interaction for web.
This module can work either with [zone-js] or without it. This module can work either with [zone-js] or without it.
With [zone-js] and ZoneScopeManager it will fully support the async operations. 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/scope-zone]. 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. Without [zone-js] it will still work but with limited support.
## Installation ## Installation
@ -23,12 +23,12 @@ npm install --save @opentelemetry/plugin-user-interaction
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing'; import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/tracing';
import { WebTracerProvider } from '@opentelemetry/web'; import { WebTracerProvider } from '@opentelemetry/web';
import { UserInteractionPlugin } from '@opentelemetry/plugin-user-interaction'; 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 // 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({ const provider = new WebTracerProvider({
scopeManager: new ZoneScopeManager(), // optional contextManager: new ZoneContextManager(), // optional
plugins: [ plugins: [
new UserInteractionPlugin() 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-url]: https://www.npmjs.com/package/@opentelemetry/plugin-user-interaction
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fplugin-user-interaction.svg [npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fplugin-user-interaction.svg
[zone-js]: https://www.npmjs.com/package/zone.js [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": { "devDependencies": {
"@babel/core": "^7.6.0", "@babel/core": "^7.6.0",
"@opentelemetry/plugin-xml-http-request": "^0.4.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", "@opentelemetry/tracing": "^0.4.0",
"@types/jquery": "^3.3.31", "@types/jquery": "^3.3.31",
"@types/mocha": "^5.2.5", "@types/mocha": "^5.2.5",

View File

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

View File

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

View File

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

View File

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

View File

@ -22,7 +22,7 @@ import {
X_B3_SPAN_ID, X_B3_SPAN_ID,
X_B3_TRACE_ID, X_B3_TRACE_ID,
} from '@opentelemetry/core'; } from '@opentelemetry/core';
import { ZoneScopeManager } from '@opentelemetry/scope-zone'; import { ZoneContextManager } from '@opentelemetry/context-zone';
import * as tracing from '@opentelemetry/tracing'; import * as tracing from '@opentelemetry/tracing';
import { import {
PerformanceTimingNames as PTN, PerformanceTimingNames as PTN,
@ -97,15 +97,15 @@ describe('xhr', () => {
let requests: any[] = []; let requests: any[] = [];
let prepareData: any; let prepareData: any;
let clearData: any; let clearData: any;
let scopeManager: ZoneScopeManager; let contextManager: ZoneContextManager;
beforeEach(() => { beforeEach(() => {
scopeManager = new ZoneScopeManager().enable(); contextManager = new ZoneContextManager().enable();
types.context.setGlobalContextManager(scopeManager); types.context.setGlobalContextManager(contextManager);
}); });
afterEach(() => { afterEach(() => {
scopeManager.disable(); contextManager.disable();
}); });
before(() => { 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/base": "^0.4.0",
"@opentelemetry/core": "^0.4.0", "@opentelemetry/core": "^0.4.0",
"@opentelemetry/resources": "^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>>( withSpan<T extends (...args: unknown[]) => ReturnType<T>>(
span: api.Span, 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 { bind<T>(target: T, span?: api.Span): T {
return api.context.bind( return api.context.bind(

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