Skip to content

Commit

Permalink
feat(tracer): expose bind method from scope manager
Browse files Browse the repository at this point in the history
  • Loading branch information
vmarchaud committed Aug 14, 2019
1 parent b498ba2 commit b99c2cd
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 4 deletions.
20 changes: 18 additions & 2 deletions packages/opentelemetry-basic-tracer/src/BasicTracer.ts
Expand Up @@ -24,6 +24,7 @@ import {
randomSpanId,
NoRecordingSpan,
NoopLogger,
NoopSpan,
} from '@opentelemetry/core';
import {
BinaryFormat,
Expand Down Expand Up @@ -103,10 +104,18 @@ export class BasicTracer implements types.Tracer {

/**
* Returns the current Span from the current context.
*
* If there is no Span associated with the current context, a default Span
* with invalid SpanContext is returned.
*/
getCurrentSpan(): types.Span {
// Get the current Span from the context.
return this._scopeManager.active() as types.Span;
// Get the current Span from the context or NoopSpan if none found.
const current = this._scopeManager.active();
if (current === null) {
return new NoopSpan();
} else {
return current as types.Span;
}
}

/**
Expand All @@ -120,6 +129,13 @@ export class BasicTracer implements types.Tracer {
return this._scopeManager.with(span, fn);
}

/**
* Bind a span (or the current one) to the target's scope
*/
bind<T>(target: T, span?: types.Span): T {
return this._scopeManager.bind(target, span);
}

/**
* Records a SpanData.
*/
Expand Down
21 changes: 19 additions & 2 deletions packages/opentelemetry-basic-tracer/test/BasicTracer.test.ts
Expand Up @@ -23,6 +23,7 @@ import {
NoopLogger,
TraceState,
NoRecordingSpan,
NoopSpan,
} from '@opentelemetry/core';
import { BasicTracer } from '../src/BasicTracer';
import { NoopScopeManager } from '@opentelemetry/scope-base';
Expand Down Expand Up @@ -224,12 +225,12 @@ describe('BasicTracer', () => {
});

describe('.getCurrentSpan()', () => {
it('should return null with NoopScopeManager', () => {
it('should return NoopSpan with NoopScopeManager', () => {
const tracer = new BasicTracer({
scopeManager: new NoopScopeManager(),
});
const currentSpan = tracer.getCurrentSpan();
assert.deepStrictEqual(currentSpan, null);
assert.ok(currentSpan instanceof NoopSpan);
});
});

Expand All @@ -240,11 +241,27 @@ describe('BasicTracer', () => {
});
const span = tracer.startSpan('my-span');
tracer.withSpan(span, () => {
assert.ok(tracer.getCurrentSpan() instanceof NoopSpan);
return done();
});
});
});

describe('.bind()', () => {
it('should bind scope with NoopScopeManager scope manager', done => {
const tracer = new BasicTracer({
scopeManager: new NoopScopeManager(),
});
const span = tracer.startSpan('my-span');
const fn = () => {
assert.ok(tracer.getCurrentSpan() instanceof NoopSpan);
return done();
};
const patchedFn = tracer.bind(fn, span);
return patchedFn();
});
});

describe('.recordSpanData()', () => {
// @todo: implement
it('should call exporters with span data');
Expand Down
4 changes: 4 additions & 0 deletions packages/opentelemetry-core/src/trace/NoopTracer.ts
Expand Up @@ -45,6 +45,10 @@ export class NoopTracer implements Tracer {
return fn();
}

bind<T>(target: T, span?: Span): T {
return target;
}

// By default does nothing
recordSpanData(span: Span): void {}

Expand Down
9 changes: 9 additions & 0 deletions packages/opentelemetry-core/src/trace/TracerDelegate.ts
Expand Up @@ -55,6 +55,15 @@ export class TracerDelegate implements types.Tracer {
);
}

bind<T>(target: T, span?: types.Span): T {
return this._currentTracer.bind.apply(
this._currentTracer,
// tslint:disable-next-line:no-any
arguments as any
// tslint:disable-next-line:no-any
) as any;
}

startSpan(name: string, options?: types.SpanOptions): types.Span {
return this._currentTracer.startSpan.apply(
this._currentTracer,
Expand Down
9 changes: 9 additions & 0 deletions packages/opentelemetry-core/test/trace/NoopTracer.test.ts
Expand Up @@ -57,4 +57,13 @@ describe('NoopTracer', () => {
return done();
});
});

it('should not crash when .bind()', done => {
const tracer = new NoopTracer();
const fn = () => {
return done();
};
const patchedFn = tracer.bind(fn, NOOP_SPAN);
return patchedFn();
});
});
Expand Up @@ -25,6 +25,7 @@ describe('TracerDelegate', () => {
'getCurrentSpan',
'startSpan',
'withSpan',
'bind',
'recordSpanData',
'getBinaryFormat',
'getHttpTextFormat',
Expand Down
15 changes: 15 additions & 0 deletions packages/opentelemetry-node-tracer/test/NodeTracer.test.ts
Expand Up @@ -158,6 +158,21 @@ describe('NodeTracer', () => {
});
});

describe('.bind()', () => {
it('should bind scope with AsyncHooksScopeManager scope manager', done => {
const tracer = new NodeTracer({
scopeManager: new AsyncHooksScopeManager(),
});
const span = tracer.startSpan('my-span');
const fn = () => {
assert.deepStrictEqual(tracer.getCurrentSpan(), span);
return done();
};
const patchedFn = tracer.bind(fn, span);
return patchedFn();
});
});

describe('.recordSpanData()', () => {
// @todo: implement
it('should call exporters with span data');
Expand Down
8 changes: 8 additions & 0 deletions packages/opentelemetry-types/src/trace/tracer.ts
Expand Up @@ -58,6 +58,14 @@ export interface Tracer {
fn: T
): ReturnType<T>;

/**
* Bind a span as the target's scope or propagate the current one.
*
* @param target Any object to which a scope need to be set
* @param [span] Optionally specify the span which you want to assign
*/
bind<T>(target: T, span?: Span): T;

/**
* Send a pre-populated span object to the exporter.
* Sampling and recording decisions as well as other collection optimizations
Expand Down

0 comments on commit b99c2cd

Please sign in to comment.