Skip to content

Commit

Permalink
WIP 1
Browse files Browse the repository at this point in the history
  • Loading branch information
mydea committed Nov 26, 2024
1 parent b59ce07 commit a4c84aa
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 49 deletions.
34 changes: 3 additions & 31 deletions packages/opentelemetry/src/trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import type { Client, DynamicSamplingContext, Scope, Span as SentrySpan, TraceCo
import { continueTraceAsRemoteSpan } from './propagator';

import type { OpenTelemetryClient, OpenTelemetrySpanContext } from './types';
import { getContextFromScope, getScopesFromContext } from './utils/contextData';
import { getContextFromScope } from './utils/contextData';
import { getSamplingDecision } from './utils/getSamplingDecision';
import { makeTraceState } from './utils/makeTraceState';

Expand Down Expand Up @@ -179,39 +179,11 @@ function ensureTimestampInMilliseconds(timestamp: number): number {

function getContext(scope: Scope | undefined, forceTransaction: boolean | undefined): Context {
const ctx = getContextForScope(scope);
// Note: If the context is the ROOT_CONTEXT, no scope is attached
// Thus we will not use the propagation context in this case, which is desired
const actualScope = getScopesFromContext(ctx)?.scope;
const parentSpan = trace.getSpan(ctx);

// In the case that we have no parent span, we need to "simulate" one to ensure the propagation context is correct
// In the case that we have no parent span, we start a new trace
// Note that if we continue a trace, we'll always have a remote parent span here anyhow
if (!parentSpan) {
const client = getClient();

if (actualScope && client) {
const propagationContext = actualScope.getPropagationContext();

// We store the DSC as OTEL trace state on the span context
const traceState = makeTraceState({
parentSpanId: propagationContext.parentSpanId,
// Not defined yet, we want to pick this up on-demand only
dsc: undefined,
sampled: propagationContext.sampled,
});

const spanOptions: SpanContext = {
traceId: propagationContext.traceId,
spanId: propagationContext.parentSpanId || propagationContext.spanId,
isRemote: true,
traceFlags: propagationContext.sampled ? TraceFlags.SAMPLED : TraceFlags.NONE,
traceState,
};

// Add remote parent span context,
return trace.setSpanContext(ctx, spanOptions);
}

// if we have no scope or client, we just return the context as-is
return ctx;
}

Expand Down
38 changes: 20 additions & 18 deletions packages/opentelemetry/test/trace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,7 @@ describe('trace', () => {
it('allows to pass parentSpan=null', () => {
startSpan({ name: 'GET users/[id' }, () => {
startSpan({ name: 'child', parentSpan: null }, span => {
// Due to the way we propagate the scope in OTEL,
// the parent_span_id is not actually undefined here, but comes from the propagation context
expect(spanToJSON(span).parent_span_id).toBe(getCurrentScope().getPropagationContext().spanId);
expect(spanToJSON(span).parent_span_id).toBe(undefined);
});
});
});
Expand Down Expand Up @@ -591,10 +589,7 @@ describe('trace', () => {
it('allows to pass parentSpan=null', () => {
startSpan({ name: 'outer' }, () => {
const span = startInactiveSpan({ name: 'test span', parentSpan: null });

// Due to the way we propagate the scope in OTEL,
// the parent_span_id is not actually undefined here, but comes from the propagation context
expect(spanToJSON(span).parent_span_id).toBe(getCurrentScope().getPropagationContext().spanId);
expect(spanToJSON(span).parent_span_id).toBe(undefined);
span.end();
});
});
Expand Down Expand Up @@ -881,9 +876,7 @@ describe('trace', () => {
it('allows to pass parentSpan=null', () => {
startSpan({ name: 'outer' }, () => {
startSpanManual({ name: 'GET users/[id]', parentSpan: null }, span => {
// Due to the way we propagate the scope in OTEL,
// the parent_span_id is not actually undefined here, but comes from the propagation context
expect(spanToJSON(span).parent_span_id).toBe(getCurrentScope().getPropagationContext().spanId);
expect(spanToJSON(span).parent_span_id).toBe(undefined);
span.end();
});
});
Expand Down Expand Up @@ -1016,36 +1009,45 @@ describe('trace', () => {
});

describe('propagation', () => {
it('picks up the trace context from the scope, if there is no parent', () => {
it('starts new trace, if there is no parent', () => {
withScope(scope => {
const propagationContext = scope.getPropagationContext();
const span = startInactiveSpan({ name: 'test span' });

expect(span).toBeDefined();
expect(spanToJSON(span).trace_id).toEqual(propagationContext.traceId);
expect(spanToJSON(span).parent_span_id).toEqual(propagationContext.spanId);
const traceId = spanToJSON(span).trace_id;
expect(traceId).toMatch(/[a-f0-9]{32}/);
expect(spanToJSON(span).parent_span_id).toBe(undefined);
expect(spanToJSON(span).trace_id).not.toEqual(propagationContext.traceId);

expect(getDynamicSamplingContextFromSpan(span)).toEqual({
...getDynamicSamplingContextFromClient(propagationContext.traceId, getClient()!),
trace_id: traceId,
environment: 'production',
public_key: 'username',
sample_rate: '1',
sampled: 'true',
transaction: 'test span',
});
});
});

it('picks up the trace context from the scope, including parentSpanId, if there is no parent', () => {
// Note: This _should_ never happen, when we have an incoming trace, we should always have a parent span
it('starts new trace, ignoring parentSpanId, if there is no parent', () => {
withScope(scope => {
const propagationContext = scope.getPropagationContext();
propagationContext.parentSpanId = '1121201211212012';
const span = startInactiveSpan({ name: 'test span' });

expect(span).toBeDefined();
expect(spanToJSON(span).trace_id).toEqual(propagationContext.traceId);
expect(spanToJSON(span).parent_span_id).toEqual('1121201211212012');
const traceId = spanToJSON(span).trace_id;
expect(traceId).toMatch(/[a-f0-9]{32}/);
expect(spanToJSON(span).parent_span_id).toBe(undefined);
expect(spanToJSON(span).trace_id).not.toEqual(propagationContext.traceId);

expect(getDynamicSamplingContextFromSpan(span)).toEqual({
...getDynamicSamplingContextFromClient(propagationContext.traceId, getClient()!),
environment: 'production',
public_key: 'username',
trace_id: traceId,
sample_rate: '1',
sampled: 'true',
transaction: 'test span',
Expand Down

0 comments on commit a4c84aa

Please sign in to comment.