-
Notifications
You must be signed in to change notification settings - Fork 835
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add no-op implementations of Tracer API #98
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 { SpanContext, BinaryFormat } from '@opentelemetry/types'; | ||
|
||
/** | ||
* No-op implementations of {@link BinaryFormat}. | ||
*/ | ||
class NoopBinaryFormat implements BinaryFormat { | ||
private readonly _buff = new ArrayBuffer(0); | ||
// By default does nothing | ||
toBytes(spanContext: SpanContext): ArrayBuffer { | ||
return this._buff; | ||
} | ||
|
||
// By default does nothing | ||
fromBytes(buf: ArrayBuffer): SpanContext | null { | ||
return null; | ||
} | ||
} | ||
|
||
export const NOOP_BINARY_FORMAT = new NoopBinaryFormat(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/** | ||
* 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 { HttpTextFormat, SpanContext } from '@opentelemetry/types'; | ||
|
||
/** | ||
* No-op implementations of {@link HttpTextFormat}. | ||
*/ | ||
class NoopHttpTextFormat implements HttpTextFormat { | ||
// By default does nothing | ||
inject(spanContext: SpanContext, format: string, carrier: unknown): void {} | ||
// By default does nothing | ||
extract(format: string, carrier: unknown): SpanContext | null { | ||
return null; | ||
} | ||
} | ||
|
||
export const NOOP_HTTP_TEXT_FORMAT = new NoopHttpTextFormat(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/** | ||
* 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 { | ||
Tracer, | ||
SpanOptions, | ||
Span, | ||
HttpTextFormat, | ||
BinaryFormat, | ||
} from '@opentelemetry/types'; | ||
import { NOOP_HTTP_TEXT_FORMAT } from '../context/propagation/NoopHttpTextFormat'; | ||
import { NOOP_BINARY_FORMAT } from '../context/propagation/NoopBinaryFormat'; | ||
import { NoopSpan } from './NoopSpan'; | ||
import { INVALID_SPAN_CONTEXT } from './spancontext-utils'; | ||
|
||
export const NOOP_SPAN = new NoopSpan(INVALID_SPAN_CONTEXT); | ||
|
||
/** | ||
* No-op implementations of {@link Tracer}. | ||
*/ | ||
export class NoopTracer implements Tracer { | ||
getCurrentSpan(): Span { | ||
return NOOP_SPAN; | ||
} | ||
|
||
// startSpan starts a noop span. | ||
startSpan(name: string, options?: SpanOptions): Span { | ||
return NOOP_SPAN; | ||
} | ||
|
||
// @todo: dependency on https://github.com/open-telemetry/opentelemetry-js/pull/100, Use new return type. | ||
withSpan<T extends (...args: unknown[]) => unknown>( | ||
span: Span, | ||
fn: T | ||
): ReturnType<T> { | ||
throw new Error('Method not implemented.'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The tracer should never throw. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, added There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should discuss it on our next SIG the similar conversation here: |
||
} | ||
|
||
// By default does nothing | ||
recordSpanData(span: Span): void {} | ||
|
||
// By default does nothing | ||
getBinaryFormat(): BinaryFormat { | ||
return NOOP_BINARY_FORMAT; | ||
} | ||
|
||
// By default does nothing | ||
getHttpTextFormat(): HttpTextFormat { | ||
return NOOP_HTTP_TEXT_FORMAT; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { SpanContext } from '@opentelemetry/types'; | ||
|
||
/** | ||
* 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. | ||
*/ | ||
|
||
export const INVALID_SPANID = '0'; | ||
export const INVALID_TRACEID = '0'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should these be fully padded values? To my knowledge, there aren't many ways a single There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the idea was if we are not able to extract the Just noticed, in the HTTP plugin we are using _emptySpanContext, ideally we should have used INVALID_SPAN_CONTEXT there. |
||
export const INVALID_SPAN_CONTEXT: SpanContext = { | ||
traceId: INVALID_TRACEID, | ||
spanId: INVALID_SPANID, | ||
}; | ||
|
||
/** | ||
* Returns true if this {@link SpanContext} is valid. | ||
* @return true if this {@link SpanContext} is valid. | ||
*/ | ||
export function isValid(spanContext: SpanContext): boolean { | ||
return ( | ||
spanContext.traceId !== INVALID_TRACEID && | ||
spanContext.spanId !== INVALID_SPANID | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/** | ||
* 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 { NoopTracer, NOOP_SPAN } from '../../src/trace/NoopTracer'; | ||
import { SpanKind } from '@opentelemetry/types'; | ||
|
||
describe('NoopTracer', () => { | ||
it('does not crash', () => { | ||
const spanContext = { traceId: '', spanId: '' }; | ||
const tracer = new NoopTracer(); | ||
|
||
assert.deepStrictEqual(tracer.startSpan('span-name'), NOOP_SPAN); | ||
assert.deepStrictEqual( | ||
tracer.startSpan('span-name1', { kind: SpanKind.CLIENT }), | ||
NOOP_SPAN | ||
); | ||
assert.deepStrictEqual( | ||
tracer.startSpan('span-name2', { | ||
kind: SpanKind.CLIENT, | ||
isRecordingEvents: true, | ||
}), | ||
NOOP_SPAN | ||
); | ||
|
||
tracer.recordSpanData(NOOP_SPAN); | ||
|
||
assert.deepStrictEqual(tracer.getCurrentSpan(), NOOP_SPAN); | ||
const httpTextFormat = tracer.getHttpTextFormat(); | ||
assert.ok(httpTextFormat); | ||
httpTextFormat.inject(spanContext, 'HttpTextFormat', {}); | ||
assert.deepStrictEqual(httpTextFormat.extract('HttpTextFormat', {}), null); | ||
|
||
const binaryFormat = tracer.getBinaryFormat(); | ||
assert.ok(binaryFormat); | ||
assert.ok(binaryFormat.toBytes(spanContext), typeof ArrayBuffer); | ||
assert.deepStrictEqual(binaryFormat.fromBytes(new ArrayBuffer(0)), null); | ||
|
||
assert.throws(() => { | ||
tracer.withSpan(NOOP_SPAN, () => {}); | ||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that
NOOP_SPAN
is useful to return for non-sampled cases, but what would be the use case forNoopTracer
?If it's intended to just get some code started, what would you think about calling this TracerBase or similar? Would this be the class that eventually takes a scope storage in the constructor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main reason for
NoopTracer
, at least for us, is when users disable the tracer then the implementation is switched to the noop to avoid unnecessary overhead. The noop tracer then uses only noop classes for the entire API surface.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, makes sense!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on @rochdev comment (#98 (comment))
And In OpenTracing there is a concept of Global tracer (which user can set using
initGlobalTracer()
function). AFAIK Global tracer (global.Tracer()
) should return minimal Tracer -NoopTracer
if the app chooses to NOT use the SDK like basic-tracer or auto-tracer or vendor specific.