Skip to content

Commit 9729ece

Browse files
committed
feat(core): Add OpenTelemetry-specific getTraceData version
1 parent 21830b1 commit 9729ece

File tree

5 files changed

+58
-3
lines changed

5 files changed

+58
-3
lines changed

packages/core/src/asyncContext/types.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Scope } from '@sentry/types';
2+
import { getTraceData } from '../utils/traceData';
23
import type {
34
startInactiveSpan,
45
startSpan,
@@ -64,4 +65,7 @@ export interface AsyncContextStrategy {
6465

6566
/** Suppress tracing in the given callback, ensuring no spans are generated inside of it. */
6667
suppressTracing?: typeof suppressTracing;
68+
69+
/** get trace data as serialized string values for propagation via `sentry-trace` and `baggage` */
70+
getTraceData?: typeof getTraceData;
6771
}

packages/core/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export type { OfflineStore, OfflineTransportOptions } from './transports/offline
55
export type { ServerRuntimeClientOptions } from './server-runtime-client';
66
export type { RequestDataIntegrationOptions } from './integrations/requestdata';
77
export type { IntegrationIndex } from './integration';
8+
export type { TraceData } from './utils/traceData';
89

910
export * from './tracing';
1011
export * from './semanticAttributes';

packages/core/src/utils/traceData.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import {
55
generateSentryTraceHeader,
66
logger,
77
} from '@sentry/utils';
8+
import { getAsyncContextStrategy } from '../asyncContext';
9+
import { getMainCarrier } from '../carrier';
810
import { getClient, getCurrentScope } from '../currentScopes';
911
import { getDynamicSamplingContextFromClient, getDynamicSamplingContextFromSpan } from '../tracing';
1012
import { getActiveSpan, getRootSpan, spanToTraceHeader } from './spanUtils';
1113

12-
type TraceData = {
14+
export type TraceData = {
1315
'sentry-trace'?: string;
1416
baggage?: string;
1517
};
@@ -30,6 +32,12 @@ type TraceData = {
3032
* or meta tag name.
3133
*/
3234
export function getTraceData(span?: Span, scope?: Scope, client?: Client): TraceData {
35+
const carrier = getMainCarrier();
36+
const acs = getAsyncContextStrategy(carrier);
37+
if (acs.getTraceData) {
38+
return acs.getTraceData(span, scope, client);
39+
}
40+
3341
const clientToUse = client || getClient();
3442
const scopeToUse = scope || getCurrentScope();
3543
const spanToUse = span || getActiveSpan();

packages/opentelemetry/src/asyncContextStrategy.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as api from '@opentelemetry/api';
22
import { getDefaultCurrentScope, getDefaultIsolationScope, setAsyncContextStrategy } from '@sentry/core';
3-
import type { withActiveSpan as defaultWithActiveSpan } from '@sentry/core';
3+
import type { getTraceData as defaultGetTraceData, withActiveSpan as defaultWithActiveSpan } from '@sentry/core';
44
import type { Scope } from '@sentry/types';
55

66
import {
@@ -12,6 +12,7 @@ import { startInactiveSpan, startSpan, startSpanManual, withActiveSpan } from '.
1212
import type { CurrentScopes } from './types';
1313
import { getScopesFromContext } from './utils/contextData';
1414
import { getActiveSpan } from './utils/getActiveSpan';
15+
import { getTraceData } from './utils/getTraceData';
1516
import { suppressTracing } from './utils/suppressTracing';
1617

1718
/**
@@ -102,9 +103,10 @@ export function setOpenTelemetryContextAsyncContextStrategy(): void {
102103
startSpanManual,
103104
startInactiveSpan,
104105
getActiveSpan,
106+
suppressTracing,
105107
// The types here don't fully align, because our own `Span` type is narrower
106108
// than the OTEL one - but this is OK for here, as we now we'll only have OTEL spans passed around
107109
withActiveSpan: withActiveSpan as typeof defaultWithActiveSpan,
108-
suppressTracing: suppressTracing,
110+
getTraceData: getTraceData as typeof defaultGetTraceData,
109111
});
110112
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import * as api from '@opentelemetry/api';
2+
import type { Span } from '@opentelemetry/api';
3+
import type { TraceData } from '@sentry/core';
4+
import { getCurrentScope } from '@sentry/core';
5+
import { getPropagationContextFromSpan } from '../propagator';
6+
import { generateSpanContextForPropagationContext } from './generateSpanContextForPropagationContext';
7+
8+
/**
9+
* Otel-specific implementation of `getTraceData`.
10+
* @see `@sentry/core` version of `getTraceData` for more information
11+
*/
12+
export function getTraceData(span?: Span): TraceData {
13+
const ctx = api.context.active();
14+
const spanToUse = span || api.trace.getSpan(ctx);
15+
16+
// This should never happen, given we always create an ambient non-recording span if there's no active span.
17+
if (!spanToUse) {
18+
return {};
19+
}
20+
const headersObject: Record<string, string> = {};
21+
22+
const propagationContext = spanToUse
23+
? getPropagationContextFromSpan(spanToUse)
24+
: getCurrentScope().getPropagationContext();
25+
26+
const spanContext = generateSpanContextForPropagationContext(propagationContext);
27+
28+
const context = api.trace.setSpanContext(ctx, spanContext);
29+
30+
api.propagation.inject(context, headersObject);
31+
32+
if (!headersObject['sentry-trace']) {
33+
return {};
34+
}
35+
36+
return {
37+
'sentry-trace': headersObject['sentry-trace'],
38+
baggage: headersObject['baggage'],
39+
};
40+
}

0 commit comments

Comments
 (0)