From c1f21f2612f76a5c8f953a2a38b9ce9b6fa6316e Mon Sep 17 00:00:00 2001 From: vmarchaud Date: Sun, 13 Sep 2020 15:57:53 +0200 Subject: [PATCH] feat(api): propagate spanContext only using API #1456 --- .../src/metrics/NoopMeter.ts | 12 ++---- .../opentelemetry-api/src/trace/NoopTracer.ts | 38 ++++++++++++++++-- .../noop-implementations/noop-tracer.test.ts | 40 ++++++++++++++++++- 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/packages/opentelemetry-api/src/metrics/NoopMeter.ts b/packages/opentelemetry-api/src/metrics/NoopMeter.ts index 765a0fd8ae3..f3c8feeddd1 100644 --- a/packages/opentelemetry-api/src/metrics/NoopMeter.ts +++ b/packages/opentelemetry-api/src/metrics/NoopMeter.ts @@ -131,24 +131,21 @@ export class NoopMetric implements UnboundMetric { } } -export class NoopCounterMetric - extends NoopMetric +export class NoopCounterMetric extends NoopMetric implements Counter { add(value: number, labels: Labels) { this.bind(labels).add(value); } } -export class NoopValueRecorderMetric - extends NoopMetric +export class NoopValueRecorderMetric extends NoopMetric implements ValueRecorder { record(value: number, labels: Labels) { this.bind(labels).record(value); } } -export class NoopBaseObserverMetric - extends NoopMetric +export class NoopBaseObserverMetric extends NoopMetric implements BaseObserver { observation() { return { @@ -158,8 +155,7 @@ export class NoopBaseObserverMetric } } -export class NoopBatchObserverMetric - extends NoopMetric +export class NoopBatchObserverMetric extends NoopMetric implements BatchObserver {} export class NoopBoundCounter implements BoundCounter { diff --git a/packages/opentelemetry-api/src/trace/NoopTracer.ts b/packages/opentelemetry-api/src/trace/NoopTracer.ts index 2fdc4dc3104..8c2d22defeb 100644 --- a/packages/opentelemetry-api/src/trace/NoopTracer.ts +++ b/packages/opentelemetry-api/src/trace/NoopTracer.ts @@ -14,8 +14,17 @@ * limitations under the License. */ -import { Span, SpanOptions, Tracer } from '..'; -import { NOOP_SPAN } from './NoopSpan'; +import { Span, SpanOptions, Tracer, SpanContext } from '..'; +import { Context } from '@opentelemetry/context-base'; +import { NoopSpan, NOOP_SPAN } from './NoopSpan'; +import { isSpanContextValid } from './spancontext-utils'; + +/** + * Internal key used by the core to store spanContext in the global context + */ +export const _EXTRACTED_SPAN_CONTEXT_KEY = Context.createKey( + 'OpenTelemetry Context Key EXTRACTED_SPAN_CONTEXT' +); /** * No-op implementations of {@link Tracer}. @@ -26,8 +35,20 @@ export class NoopTracer implements Tracer { } // startSpan starts a noop span. - startSpan(name: string, options?: SpanOptions): Span { - return NOOP_SPAN; + startSpan(name: string, options?: SpanOptions, context?: Context): Span { + const parent = options?.parent; + const parentFromContext = + context && context.getValue(_EXTRACTED_SPAN_CONTEXT_KEY); + if (isSpanContext(parent) && isSpanContextValid(parent)) { + return new NoopSpan(parent); + } else if ( + isSpanContext(parentFromContext) && + isSpanContextValid(parentFromContext) + ) { + return new NoopSpan(parentFromContext); + } else { + return NOOP_SPAN; + } } withSpan ReturnType>( @@ -42,4 +63,13 @@ export class NoopTracer implements Tracer { } } +function isSpanContext(spanContext: any): spanContext is SpanContext { + return ( + typeof spanContext === 'object' && + typeof spanContext['spanId'] === 'string' && + typeof spanContext['traceId'] === 'string' && + typeof spanContext['traceFlags'] === 'number' + ); +} + export const NOOP_TRACER = new NoopTracer(); diff --git a/packages/opentelemetry-api/test/noop-implementations/noop-tracer.test.ts b/packages/opentelemetry-api/test/noop-implementations/noop-tracer.test.ts index 62ed24bb8ee..c6bbe7d0cd2 100644 --- a/packages/opentelemetry-api/test/noop-implementations/noop-tracer.test.ts +++ b/packages/opentelemetry-api/test/noop-implementations/noop-tracer.test.ts @@ -15,7 +15,15 @@ */ import * as assert from 'assert'; -import { NoopTracer, NOOP_SPAN, SpanKind } from '../../src'; +import { + NoopTracer, + NOOP_SPAN, + SpanContext, + SpanKind, + TraceFlags, + context, + _EXTRACTED_SPAN_CONTEXT_KEY, +} from '../../src'; describe('NoopTracer', () => { it('should not crash', () => { @@ -51,4 +59,34 @@ describe('NoopTracer', () => { const patchedFn = tracer.bind(fn, NOOP_SPAN); return patchedFn(); }); + + it('should propagate valid spanContext on the span (from parent)', () => { + const tracer = new NoopTracer(); + const parent: SpanContext = { + traceId: 'd4cda95b652f4a1592b449d5929fda1b', + spanId: '6e0c63257de34c92', + traceFlags: TraceFlags.NONE, + }; + const span = tracer.startSpan('test-1', { parent }); + assert(span.context().traceId === parent.traceId); + assert(span.context().spanId === parent.spanId); + assert(span.context().traceFlags === parent.traceFlags); + }); + + it('should propagate valid spanContext on the span (from context)', () => { + const tracer = new NoopTracer(); + const parent: SpanContext = { + traceId: 'd4cda95b652f4a1592b449dd92ffda3b', + spanId: '6e0c63ffe4e34c42', + traceFlags: TraceFlags.NONE, + }; + const span = tracer.startSpan( + 'test-1', + {}, + context.active().setValue(_EXTRACTED_SPAN_CONTEXT_KEY, parent) + ); + assert(span.context().traceId === parent.traceId); + assert(span.context().spanId === parent.spanId); + assert(span.context().traceFlags === parent.traceFlags); + }); });