forked from open-telemetry/opentelemetry-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add GlobalTracer API (open-telemetry#118)
* add GlobalTracer * remove extra tslint rule * update format types * refactor to add globaltracer-utils * rename: GlobalTracer to GlobalTracerDelegate * remove 1st arg from Delegate constructor * rename GlobalTracerDelegate to TracerDelegate * refactor TracerDelegate tracer as runtime readonly * refactor globaltracer-utils * fix new lint issues * add missing linter fix * move no-any disabler * delegate: add start/stop to use fallback * core: reorder exports * delegate: use constructor initializers
- Loading branch information
1 parent
a15ccb9
commit 081469f
Showing
5 changed files
with
337 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
packages/opentelemetry-core/src/trace/TracerDelegate.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/** | ||
* 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 types from '@opentelemetry/types'; | ||
import { NoopTracer } from './NoopTracer'; | ||
|
||
// Acts a bridge to the global tracer that can be safely called before the | ||
// global tracer is initialized. The purpose of the delegation is to avoid the | ||
// sometimes nearly intractible initialization order problems that can arise in | ||
// applications with a complex set of dependencies. Also allows for the tracer | ||
// to be changed/disabled during runtime without needing to change reference | ||
// to the global tracer | ||
export class TracerDelegate implements types.Tracer { | ||
private _currentTracer: types.Tracer; | ||
|
||
// Wrap a tracer with a TracerDelegate. Provided tracer becomes the default | ||
// fallback tracer for when a global tracer has not been initialized | ||
constructor( | ||
private readonly tracer: types.Tracer | null = null, | ||
private readonly fallbackTracer: types.Tracer = new NoopTracer() | ||
) { | ||
this._currentTracer = tracer || fallbackTracer; // equivalent to this.start() | ||
} | ||
|
||
// Begin using the user provided tracer. Stop always falling back to fallback tracer | ||
start(): void { | ||
this._currentTracer = this.tracer || this.fallbackTracer; | ||
} | ||
|
||
// Stop the delegate from using the provided tracer. Begin to use the fallback tracer | ||
stop(): void { | ||
this._currentTracer = this.fallbackTracer; | ||
} | ||
|
||
// -- Tracer interface implementation below -- // | ||
|
||
getCurrentSpan(): types.Span { | ||
return this._currentTracer.getCurrentSpan.apply( | ||
this._currentTracer, | ||
// tslint:disable-next-line:no-any | ||
arguments as any | ||
); | ||
} | ||
|
||
startSpan(name: string, options?: types.SpanOptions | undefined): types.Span { | ||
return this._currentTracer.startSpan.apply( | ||
this._currentTracer, | ||
// tslint:disable-next-line:no-any | ||
arguments as any | ||
); | ||
} | ||
|
||
withSpan<T extends (...args: unknown[]) => unknown>( | ||
span: types.Span, | ||
fn: T | ||
): ReturnType<T> { | ||
return this._currentTracer.withSpan.apply( | ||
this._currentTracer, | ||
// tslint:disable-next-line:no-any | ||
arguments as any | ||
) as ReturnType<T>; | ||
} | ||
|
||
recordSpanData(span: types.Span): void { | ||
return this._currentTracer.recordSpanData.apply( | ||
this._currentTracer, | ||
// tslint:disable-next-line:no-any | ||
arguments as any | ||
); | ||
} | ||
|
||
getBinaryFormat(): types.BinaryFormat { | ||
return this._currentTracer.getBinaryFormat.apply( | ||
this._currentTracer, | ||
// tslint:disable-next-line:no-any | ||
arguments as any | ||
); | ||
} | ||
|
||
getHttpTextFormat(): types.HttpTextFormat { | ||
return this._currentTracer.getHttpTextFormat.apply( | ||
this._currentTracer, | ||
// tslint:disable-next-line:no-any | ||
arguments as any | ||
); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
packages/opentelemetry-core/src/trace/globaltracer-utils.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/** | ||
* 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 types from '@opentelemetry/types'; | ||
import { TracerDelegate } from './TracerDelegate'; | ||
|
||
let globalTracerDelegate = new TracerDelegate(); | ||
|
||
/** | ||
* Set the current global tracer. Returns the initialized global tracer | ||
*/ | ||
export function initGlobalTracer(tracer: types.Tracer): types.Tracer { | ||
return (globalTracerDelegate = new TracerDelegate(tracer)); | ||
} | ||
|
||
/** | ||
* Returns the global tracer | ||
*/ | ||
export function getTracer(): types.Tracer { | ||
// Return the global tracer delegate | ||
return globalTracerDelegate; | ||
} |
117 changes: 117 additions & 0 deletions
117
packages/opentelemetry-core/test/trace/TracerDelegate.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/** | ||
* 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 * as types from '@opentelemetry/types'; | ||
import { TracerDelegate } from '../../src/trace/TracerDelegate'; | ||
import { NoopTracer, NoopSpan } from '../../src'; | ||
import { TraceOptions } from '@opentelemetry/types'; | ||
|
||
describe('TracerDelegate', () => { | ||
const functions = [ | ||
'getCurrentSpan', | ||
'startSpan', | ||
'withSpan', | ||
'recordSpanData', | ||
'getBinaryFormat', | ||
'getHttpTextFormat', | ||
]; | ||
const spanContext = { | ||
traceId: 'd4cda95b652f4a1592b449d5929fda1b', | ||
spanId: '6e0c63257de34c92', | ||
traceOptions: TraceOptions.UNSAMPLED, | ||
}; | ||
|
||
describe('#constructor(...)', () => { | ||
it('should not crash with default constructor', () => { | ||
functions.forEach(fn => { | ||
const tracer = new TracerDelegate(); | ||
try { | ||
((tracer as unknown) as { [fn: string]: Function })[fn](); // Try to run the function | ||
assert.ok(true, fn); | ||
} catch (err) { | ||
if (err.message !== 'Method not implemented.') { | ||
assert.ok(false, fn); | ||
} | ||
} | ||
}); | ||
}); | ||
|
||
it('should allow fallback tracer to be set', () => { | ||
const dummyTracer = new DummyTracer(); | ||
const tracerDelegate = new TracerDelegate(dummyTracer); | ||
|
||
tracerDelegate.startSpan('foo'); | ||
assert.deepStrictEqual(dummyTracer.spyCounter, 1); | ||
}); | ||
|
||
it('should use user provided tracer if provided', () => { | ||
const dummyTracer = new DummyTracer(); | ||
const tracerDelegate = new TracerDelegate(dummyTracer); | ||
|
||
tracerDelegate.startSpan('foo'); | ||
assert.deepStrictEqual(dummyTracer.spyCounter, 1); | ||
}); | ||
|
||
describe('#start/stop()', () => { | ||
it('should use the fallback tracer when stop is called', () => { | ||
const dummyTracerUser = new DummyTracer(); | ||
const dummyTracerFallback = new DummyTracer(); | ||
const tracerDelegate = new TracerDelegate( | ||
dummyTracerUser, | ||
dummyTracerFallback | ||
); | ||
|
||
tracerDelegate.stop(); | ||
tracerDelegate.startSpan('fallback'); | ||
assert.deepStrictEqual(dummyTracerUser.spyCounter, 0); | ||
assert.deepStrictEqual(dummyTracerFallback.spyCounter, 1); | ||
}); | ||
|
||
it('should use the user tracer when start is called', () => { | ||
const dummyTracerUser = new DummyTracer(); | ||
const dummyTracerFallback = new DummyTracer(); | ||
const tracerDelegate = new TracerDelegate( | ||
dummyTracerUser, | ||
dummyTracerFallback | ||
); | ||
|
||
tracerDelegate.stop(); | ||
tracerDelegate.startSpan('fallback'); | ||
assert.deepStrictEqual(dummyTracerUser.spyCounter, 0); | ||
assert.deepStrictEqual(dummyTracerFallback.spyCounter, 1); | ||
|
||
tracerDelegate.start(); | ||
tracerDelegate.startSpan('user'); | ||
assert.deepStrictEqual(dummyTracerUser.spyCounter, 1); | ||
assert.deepStrictEqual( | ||
dummyTracerFallback.spyCounter, | ||
1, | ||
'Only user tracer counter is incremented' | ||
); | ||
}); | ||
}); | ||
}); | ||
|
||
class DummyTracer extends NoopTracer { | ||
spyCounter = 0; | ||
|
||
startSpan(name: string, options?: types.SpanOptions | undefined) { | ||
this.spyCounter = this.spyCounter + 1; | ||
return new NoopSpan(spanContext); | ||
} | ||
} | ||
}); |
83 changes: 83 additions & 0 deletions
83
packages/opentelemetry-core/test/trace/globaltracer-utils.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/** | ||
* 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 * as types from '@opentelemetry/types'; | ||
import { | ||
getTracer, | ||
initGlobalTracer, | ||
} from '../../src/trace/globaltracer-utils'; | ||
import { NoopTracer, NoopSpan } from '../../src'; | ||
import { TraceOptions } from '@opentelemetry/types'; | ||
|
||
describe('globaltracer-utils', () => { | ||
const functions = [ | ||
'getCurrentSpan', | ||
'startSpan', | ||
'withSpan', | ||
'recordSpanData', | ||
'getBinaryFormat', | ||
'getHttpTextFormat', | ||
]; | ||
|
||
it('should expose a tracer via getTracer', () => { | ||
const tracer = getTracer(); | ||
assert.ok(tracer); | ||
assert.strictEqual(typeof tracer, 'object'); | ||
}); | ||
|
||
describe('GlobalTracer', () => { | ||
const spanContext = { | ||
traceId: 'd4cda95b652f4a1592b449d5929fda1b', | ||
spanId: '6e0c63257de34c92', | ||
traceOptions: TraceOptions.UNSAMPLED, | ||
}; | ||
const dummySpan = new NoopSpan(spanContext); | ||
|
||
afterEach(() => { | ||
initGlobalTracer(new NoopTracer()); | ||
}); | ||
|
||
it('should not crash', () => { | ||
functions.forEach(fn => { | ||
const tracer = getTracer(); | ||
try { | ||
((tracer as unknown) as { [fn: string]: Function })[fn](); // Try to run the function | ||
assert.ok(true, fn); | ||
} catch (err) { | ||
if (err.message !== 'Method not implemented.') { | ||
assert.ok(false, fn); | ||
} | ||
} | ||
}); | ||
}); | ||
|
||
it('should use the global tracer', () => { | ||
const tracer = initGlobalTracer(new TestTracer()); | ||
const span = tracer.startSpan('test'); | ||
assert.deepStrictEqual(span, dummySpan); | ||
}); | ||
|
||
class TestTracer extends NoopTracer { | ||
startSpan( | ||
name: string, | ||
options?: types.SpanOptions | undefined | ||
): types.Span { | ||
return dummySpan; | ||
} | ||
} | ||
}); | ||
}); |