diff --git a/packages/core/src/asyncContext/types.ts b/packages/core/src/asyncContext/types.ts index bd69c8e63e78..a99f9eaae567 100644 --- a/packages/core/src/asyncContext/types.ts +++ b/packages/core/src/asyncContext/types.ts @@ -1,4 +1,5 @@ import type { Scope } from '@sentry/types'; +import { getTraceData } from '../utils/traceData'; import type { startInactiveSpan, startSpan, @@ -64,4 +65,7 @@ export interface AsyncContextStrategy { /** Suppress tracing in the given callback, ensuring no spans are generated inside of it. */ suppressTracing?: typeof suppressTracing; + + /** get trace data as serialized string values for propagation via `sentry-trace` and `baggage` */ + getTraceData?: typeof getTraceData; } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 73295f7df64c..79299f8092d6 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -5,6 +5,7 @@ export type { OfflineStore, OfflineTransportOptions } from './transports/offline export type { ServerRuntimeClientOptions } from './server-runtime-client'; export type { RequestDataIntegrationOptions } from './integrations/requestdata'; export type { IntegrationIndex } from './integration'; +export type { TraceData } from './utils/traceData'; export * from './tracing'; export * from './semanticAttributes'; diff --git a/packages/core/src/utils/traceData.ts b/packages/core/src/utils/traceData.ts index abc05f449365..854bdd41dd28 100644 --- a/packages/core/src/utils/traceData.ts +++ b/packages/core/src/utils/traceData.ts @@ -5,11 +5,13 @@ import { generateSentryTraceHeader, logger, } from '@sentry/utils'; +import { getAsyncContextStrategy } from '../asyncContext'; +import { getMainCarrier } from '../carrier'; import { getClient, getCurrentScope } from '../currentScopes'; import { getDynamicSamplingContextFromClient, getDynamicSamplingContextFromSpan } from '../tracing'; import { getActiveSpan, getRootSpan, spanToTraceHeader } from './spanUtils'; -type TraceData = { +export type TraceData = { 'sentry-trace'?: string; baggage?: string; }; @@ -30,6 +32,12 @@ type TraceData = { * or meta tag name. */ export function getTraceData(span?: Span, scope?: Scope, client?: Client): TraceData { + const carrier = getMainCarrier(); + const acs = getAsyncContextStrategy(carrier); + if (acs.getTraceData) { + return acs.getTraceData(span, scope, client); + } + const clientToUse = client || getClient(); const scopeToUse = scope || getCurrentScope(); const spanToUse = span || getActiveSpan(); diff --git a/packages/opentelemetry/src/asyncContextStrategy.ts b/packages/opentelemetry/src/asyncContextStrategy.ts index 69878d27b252..7d81a76d5d80 100644 --- a/packages/opentelemetry/src/asyncContextStrategy.ts +++ b/packages/opentelemetry/src/asyncContextStrategy.ts @@ -1,6 +1,6 @@ import * as api from '@opentelemetry/api'; import { getDefaultCurrentScope, getDefaultIsolationScope, setAsyncContextStrategy } from '@sentry/core'; -import type { withActiveSpan as defaultWithActiveSpan } from '@sentry/core'; +import type { getTraceData as defaultGetTraceData, withActiveSpan as defaultWithActiveSpan } from '@sentry/core'; import type { Scope } from '@sentry/types'; import { @@ -12,6 +12,7 @@ import { startInactiveSpan, startSpan, startSpanManual, withActiveSpan } from '. import type { CurrentScopes } from './types'; import { getScopesFromContext } from './utils/contextData'; import { getActiveSpan } from './utils/getActiveSpan'; +import { getTraceData } from './utils/getTraceData'; import { suppressTracing } from './utils/suppressTracing'; /** @@ -102,9 +103,10 @@ export function setOpenTelemetryContextAsyncContextStrategy(): void { startSpanManual, startInactiveSpan, getActiveSpan, + suppressTracing, // The types here don't fully align, because our own `Span` type is narrower // than the OTEL one - but this is OK for here, as we now we'll only have OTEL spans passed around withActiveSpan: withActiveSpan as typeof defaultWithActiveSpan, - suppressTracing: suppressTracing, + getTraceData: getTraceData as typeof defaultGetTraceData, }); }