Skip to content

Commit

Permalink
chore: change withSpanAsync return to void and add tsdoc
Browse files Browse the repository at this point in the history
  • Loading branch information
vmarchaud committed May 17, 2020
1 parent 128cdad commit 3308204
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 34 deletions.
22 changes: 11 additions & 11 deletions packages/opentelemetry-api/test/api/global.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ describe('Global Utils', () => {
assert.notEqual(api1, api2);
// that return separate noop instances to start
assert.notStrictEqual(
api1.context['getContextManager'](),
api2.context['getContextManager']()
api1.context.getContextManager(),
api2.context.getContextManager()
);

beforeEach(() => {
Expand All @@ -46,33 +46,33 @@ describe('Global Utils', () => {
});

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

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

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

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

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

it('should return the module NoOp implementation if the version is a mismatch', () => {
const original = api1.context['getContextManager']();
const original = api1.context.getContextManager();
api1.context.setGlobalContextManager(new NoopContextManager());
const afterSet = _global[GLOBAL_CONTEXT_MANAGER_API_KEY]!(-1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,7 @@ export class AsyncHooksContextManager implements ContextManager {
return ref === undefined ? Context.ROOT_CONTEXT : ref.get();
}

with<T extends (...args: unknown[]) => ReturnType<T>>(
context: Context,
fn: T
): ReturnType<T> {
with<T extends () => ReturnType<T>>(context: Context, fn: T): ReturnType<T> {
const uid = asyncHooks.executionAsyncId();
let ref = this._contextRefs.get(uid);
let oldContext: Context | undefined = undefined;
Expand All @@ -94,10 +91,10 @@ export class AsyncHooksContextManager implements ContextManager {
}
}

async withAsync<T extends Promise<any>, U extends (...args: unknown[]) => T>(
async withAsync<T extends any, U extends () => Promise<T>>(
context: Context,
fn: U
): Promise<T> {
): Promise<void> {
const uid = asyncHooks.executionAsyncId();
let ref = this._contextRefs.get(uid);
let oldContext: Context | undefined = undefined;
Expand All @@ -109,7 +106,7 @@ export class AsyncHooksContextManager implements ContextManager {
ref.set(context);
}
try {
return await fn();
await fn();
} catch (err) {
throw err;
} finally {
Expand Down
44 changes: 28 additions & 16 deletions packages/opentelemetry-node/src/NodeTracer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,51 @@

import * as api from '@opentelemetry/api';
import { setActiveSpan } from '@opentelemetry/core';
import {
BasicTracerProvider,
Tracer,
TracerConfig,
} from '@opentelemetry/tracing';
import { Tracer } from '@opentelemetry/tracing';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';

export type Parameters<T> = T extends (...args: infer T) => any ? T : unknown[];
// Used to get return type from patched function used for type our memoize function
// (we remove the promise, the original function should be an async function)
export type ReturnType<T> = T extends (...args: any[]) => infer T
? Unpromisify<T>
: string | object;
// Used to type the patched function (with the promise)
export type OriginalReturnType<T> = Promise<ReturnType<T>>;
// Type of the original function with params and promise as result
export type Func<T> = (...args: Parameters<T>) => OriginalReturnType<T>;
// Type of our memoize function with original params and promise with original returns types
// we need to remove promise from the original function and set it again to be sure to only
// have one level of promise (avoid Promise<Promise<string>>)
export type AsyncFunc<T> = () => Promise<ReturnType<T>>;
// Used to remove promise from a type
export type Unpromisify<T> = T extends Promise<infer R> ? R : T;

/**
* This class represents a nodejs-specific tracer.
*/
export class NodeTracer extends Tracer {
/**
* Constructs a new NodeTracer instance.
* Execute the provided function with the given span in the current context.
*
* **NOTE**: This function is experimental, refer to to
* https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-node#withspanasync
*/
constructor(config: TracerConfig, _tracerProvider: BasicTracerProvider) {
super(config, _tracerProvider);
}

async withSpanAsync<
T extends Promise<any>,
U extends (...args: unknown[]) => T
>(span: api.Span, fn: U): Promise<T> {
async withSpanAsync<T extends any, U extends () => Promise<T>>(
span: api.Span,
fn: U
): Promise<void> {
const contextManager = api.context.getContextManager();
if (contextManager instanceof AsyncHooksContextManager) {
return contextManager.withAsync(
await contextManager.withAsync(
setActiveSpan(api.context.active(), span),
fn
);
} else {
this.logger.warn(
`Using withAsync without AsyncHookContextManager doesn't work, please refer to https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-node#withspanasync`
);
return await fn();
await fn();
}
}
}

0 comments on commit 3308204

Please sign in to comment.