From dd7df87e030efe799515d956efb6bf98a10f02a4 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Mon, 18 May 2026 18:03:27 +0900 Subject: [PATCH 1/5] feat(opentelemetry): Add SentryTraceProvider --- packages/core/src/tracing/idleSpan.ts | 7 +- .../src/tracing/sentryNonRecordingSpan.ts | 9 +- packages/core/src/tracing/sentrySpan.ts | 15 +- packages/core/src/tracing/trace.ts | 54 ++- packages/core/src/types/span.ts | 8 +- packages/core/src/utils/spanUtils.ts | 19 +- .../core/test/lib/tracing/idleSpan.test.ts | 5 +- packages/opentelemetry/README.md | 33 ++ .../opentelemetry/src/asyncContextStrategy.ts | 99 ++++- packages/opentelemetry/src/custom/client.ts | 5 +- packages/opentelemetry/src/exports.ts | 2 + .../opentelemetry/src/sentryTraceProvider.ts | 379 ++++++++++++++++++ packages/opentelemetry/src/types.ts | 9 +- .../opentelemetry/src/utils/setupCheck.ts | 7 +- 14 files changed, 614 insertions(+), 37 deletions(-) create mode 100644 packages/opentelemetry/src/sentryTraceProvider.ts diff --git a/packages/core/src/tracing/idleSpan.ts b/packages/core/src/tracing/idleSpan.ts index 22ba70b81a65..f6f3bab6ecdd 100644 --- a/packages/core/src/tracing/idleSpan.ts +++ b/packages/core/src/tracing/idleSpan.ts @@ -6,6 +6,7 @@ import type { Span } from '../types/span'; import type { StartSpanOptions } from '../types/startSpanOptions'; import { debug } from '../utils/debug-logger'; import { hasSpansEnabled } from '../utils/hasSpansEnabled'; +import { dropUndefinedKeys } from '../utils/object'; import { shouldIgnoreSpan } from '../utils/should-ignore-span'; import { _setSpanForScope } from '../utils/spanOnScope'; import { @@ -124,11 +125,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti if (!client || !hasSpansEnabled()) { const span = new SentryNonRecordingSpan(); - const dsc = { - sample_rate: '0', - sampled: 'false', - ...getDynamicSamplingContextFromSpan(span), - } satisfies Partial; + const dsc = dropUndefinedKeys(getDynamicSamplingContextFromSpan(span)) satisfies Partial; freezeDscOnSpan(span, dsc); return span; diff --git a/packages/core/src/tracing/sentryNonRecordingSpan.ts b/packages/core/src/tracing/sentryNonRecordingSpan.ts index 4c4c1064eedb..e009d53a2ce1 100644 --- a/packages/core/src/tracing/sentryNonRecordingSpan.ts +++ b/packages/core/src/tracing/sentryNonRecordingSpan.ts @@ -9,7 +9,7 @@ import type { } from '../types/span'; import type { SpanStatus } from '../types/spanStatus'; import { generateSpanId, generateTraceId } from '../utils/propagationContext'; -import { TRACE_FLAG_NONE } from '../utils/spanUtils'; +import { TRACE_FLAG_NONE, TRACE_FLAG_SAMPLED } from '../utils/spanUtils'; interface SentryNonRecordingSpanArguments extends SentrySpanArguments { dropReason?: EventDropReason; @@ -21,6 +21,7 @@ interface SentryNonRecordingSpanArguments extends SentrySpanArguments { export class SentryNonRecordingSpan implements Span { private _traceId: string; private _spanId: string; + private _sampled: boolean | undefined; /** * Reason why this span was dropped, if applicable ('ignored' or 'sample_rate'). @@ -32,6 +33,7 @@ export class SentryNonRecordingSpan implements Span { public constructor(spanContext: SentryNonRecordingSpanArguments = {}) { this._traceId = spanContext.traceId || generateTraceId(); this._spanId = spanContext.spanId || generateSpanId(); + this._sampled = spanContext.sampled; this.dropReason = spanContext.dropReason; } @@ -40,7 +42,8 @@ export class SentryNonRecordingSpan implements Span { return { spanId: this._spanId, traceId: this._traceId, - traceFlags: TRACE_FLAG_NONE, + traceFlags: this._sampled ? TRACE_FLAG_SAMPLED : TRACE_FLAG_NONE, + sampled: this._sampled, }; } @@ -98,7 +101,7 @@ export class SentryNonRecordingSpan implements Span { * @hidden * @internal */ - public recordException(_exception: unknown, _time?: number | undefined): void { + public recordException(_exception: unknown, _time?: SpanTimeInput | undefined): void { // noop } } diff --git a/packages/core/src/tracing/sentrySpan.ts b/packages/core/src/tracing/sentrySpan.ts index 84c78e73356d..9271c5c855f8 100644 --- a/packages/core/src/tracing/sentrySpan.ts +++ b/packages/core/src/tracing/sentrySpan.ts @@ -143,8 +143,19 @@ export class SentrySpan implements Span { * @hidden * @internal */ - public recordException(_exception: unknown, _time?: number | undefined): void { - // noop + public recordException(exception: unknown, time?: SpanTimeInput | undefined): void { + const attributes: SpanAttributes = {}; + + if (typeof exception === 'string') { + attributes['exception.message'] = exception; + } else if (exception && typeof exception === 'object') { + const error = exception as { name?: string; message?: string; stack?: string }; + attributes['exception.type'] = error.name; + attributes['exception.message'] = error.message; + attributes['exception.stacktrace'] = error.stack; + } + + this.addEvent('exception', attributes, time); } /** @inheritdoc */ diff --git a/packages/core/src/tracing/trace.ts b/packages/core/src/tracing/trace.ts index 3134c58309b1..94234007f99c 100644 --- a/packages/core/src/tracing/trace.ts +++ b/packages/core/src/tracing/trace.ts @@ -22,10 +22,18 @@ import { hasSpansEnabled } from '../utils/hasSpansEnabled'; import { shouldIgnoreSpan } from '../utils/should-ignore-span'; import { hasSpanStreamingEnabled } from './spans/hasSpanStreamingEnabled'; import { parseSampleRate } from '../utils/parseSampleRate'; +import { dropUndefinedKeys } from '../utils/object'; import { generateTraceId } from '../utils/propagationContext'; import { safeMathRandom } from '../utils/randomSafeContext'; import { _getSpanForScope, _setSpanForScope } from '../utils/spanOnScope'; -import { addChildSpanToSpan, getRootSpan, spanIsSampled, spanTimeInputToSeconds, spanToJSON } from '../utils/spanUtils'; +import { + addChildSpanToSpan, + getRootSpan, + spanIsSampled, + spanTimeInputToSeconds, + spanToJSON, + spanToTraceSamplingDecision, +} from '../utils/spanUtils'; import { propagationContextFromHeaders, shouldContinueTrace } from '../utils/tracing'; import { freezeDscOnSpan, getDynamicSamplingContextFromSpan } from './dynamicSamplingContext'; import { logSpanStart } from './logSpans'; @@ -344,18 +352,45 @@ function createChildOrRootSpan({ forceTransaction?: boolean; scope: Scope; }): Span { + const isolationScope = getIsolationScope(); + if (!hasSpansEnabled()) { - const span = new SentryNonRecordingSpan(); + let propagationContext: { + traceId: string; + parentSpanId?: string | undefined; + sampled?: boolean | undefined; + dsc?: Partial | undefined; + }; + + if (parentSpan) { + const parentSpanContext = parentSpan.spanContext(); + + propagationContext = { + traceId: parentSpanContext.traceId, + parentSpanId: parentSpanContext.spanId, + sampled: spanToTraceSamplingDecision(parentSpan), + dsc: undefined, + }; + } else { + propagationContext = { + ...isolationScope.getPropagationContext(), + ...scope.getPropagationContext(), + }; + } + + const span = new SentryNonRecordingSpan({ + traceId: propagationContext.traceId, + parentSpanId: propagationContext.parentSpanId, + sampled: propagationContext.sampled, + }); // If this is a root span, we ensure to freeze a DSC // So we can have at least partial data here if (forceTransaction || !parentSpan) { - const dsc = { - sampled: 'false', - sample_rate: '0', + const dsc = dropUndefinedKeys({ + ...(propagationContext.dsc || getDynamicSamplingContextFromSpan(span)), transaction: spanArguments.name, - ...getDynamicSamplingContextFromSpan(span), - } satisfies Partial; + }) satisfies Partial; freezeDscOnSpan(span, dsc); } @@ -373,11 +408,10 @@ function createChildOrRootSpan({ return new SentryNonRecordingSpan({ dropReason: 'ignored', traceId: parentSpan?.spanContext().traceId ?? scope.getPropagationContext().traceId, + sampled: false, }); } - const isolationScope = getIsolationScope(); - let span: Span; if (parentSpan && !forceTransaction) { span = _startChildSpan(parentSpan, scope, spanArguments); @@ -529,7 +563,7 @@ function _startChildSpan(parentSpan: Span, scope: Scope, spanArguments: SentrySp traceId, sampled, }) - : new SentryNonRecordingSpan({ traceId }); + : new SentryNonRecordingSpan({ traceId, sampled }); addChildSpanToSpan(parentSpan, childSpan); diff --git a/packages/core/src/types/span.ts b/packages/core/src/types/span.ts index 26dbbf9d29a4..31b61cb5dcc4 100644 --- a/packages/core/src/types/span.ts +++ b/packages/core/src/types/span.ts @@ -173,6 +173,12 @@ export interface SpanContextData { /** In OpenTelemetry, this can be used to store trace state, which are basically key-value pairs. */ traceState?: TraceState | undefined; + + /** + * Sentry-specific sampling decision for this span context. + * `undefined` means no local sampling decision was made yet. + */ + sampled?: boolean | undefined; } /** @@ -319,5 +325,5 @@ export interface Span { /** * NOT USED IN SENTRY, only added for compliance with OTEL Span interface */ - recordException(exception: unknown, time?: number): void; + recordException(exception: unknown, time?: SpanTimeInput): void; } diff --git a/packages/core/src/utils/spanUtils.ts b/packages/core/src/utils/spanUtils.ts index 9f495ef7b30e..be24d888d65e 100644 --- a/packages/core/src/utils/spanUtils.ts +++ b/packages/core/src/utils/spanUtils.ts @@ -83,7 +83,7 @@ export function spanToTraceContext(span: Span): TraceContext { */ export function spanToTraceHeader(span: Span): string { const { traceId, spanId } = span.spanContext(); - const sampled = spanIsSampled(span); + const sampled = spanToTraceSamplingDecision(span); return generateSentryTraceHeader(traceId, spanId, sampled); } @@ -92,7 +92,7 @@ export function spanToTraceHeader(span: Span): string { */ export function spanToTraceparentHeader(span: Span): string { const { traceId, spanId } = span.spanContext(); - const sampled = spanIsSampled(span); + const sampled = spanToTraceSamplingDecision(span); return generateTraceparentHeader(traceId, spanId, sampled); } @@ -314,6 +314,21 @@ export function spanIsSampled(span: Span): boolean { return traceFlags === TRACE_FLAG_SAMPLED; } +/** + * Returns the sampling decision to propagate for trace headers. + * This intentionally differs from `spanIsSampled`: non-recording spans can + * represent either "sampled false" or "no decision yet" in TwP mode. + */ +export function spanToTraceSamplingDecision(span: Span): boolean | undefined { + const spanContext = span.spanContext(); + + if ('sampled' in spanContext) { + return spanContext.sampled; + } + + return spanIsSampled(span); +} + /** Get the status message to use for a JSON representation of a span. */ export function getStatusMessage(status: SpanStatus | undefined): string | undefined { if (!status || status.code === SPAN_STATUS_UNSET) { diff --git a/packages/core/test/lib/tracing/idleSpan.test.ts b/packages/core/test/lib/tracing/idleSpan.test.ts index 29aaa63c2bb0..ffa92939db26 100644 --- a/packages/core/test/lib/tracing/idleSpan.test.ts +++ b/packages/core/test/lib/tracing/idleSpan.test.ts @@ -62,12 +62,11 @@ describe('startIdleSpan', () => { const idleSpan = startIdleSpan({ name: 'foo' }); expect(idleSpan).toBeDefined(); expect(idleSpan).toBeInstanceOf(SentryNonRecordingSpan); - // DSC is still correctly set on the span + // DSC is still set on the span, but tracing-without-performance should + // preserve deferred sampling instead of freezing an explicit negative decision. expect(getDynamicSamplingContextFromSpan(idleSpan)).toEqual({ environment: 'production', public_key: '123', - sample_rate: '0', - sampled: 'false', trace_id: expect.stringMatching(/[a-f0-9]{32}/), }); diff --git a/packages/opentelemetry/README.md b/packages/opentelemetry/README.md index dd20135c268b..f64d3571fbc1 100644 --- a/packages/opentelemetry/README.md +++ b/packages/opentelemetry/README.md @@ -86,6 +86,39 @@ function setupSentry() { A full setup example can be found in [node-experimental](https://github.com/getsentry/sentry-javascript/blob/develop/packages/node-experimental). +## Experimental Sentry Trace Provider + +`SentryTraceProvider` is an experimental minimal OpenTelemetry tracer provider which creates native Sentry spans directly. +It is useful when code uses the global OpenTelemetry API and you do not need the full OpenTelemetry SDK span processor +and exporter pipeline. + +```js +import { trace } from '@opentelemetry/api'; +import { SentryTraceProvider } from '@sentry/opentelemetry'; + +trace.setGlobalTracerProvider(new SentryTraceProvider()); + +const span = trace.getTracer('example').startSpan('work'); +span.end(); +``` + +In `@sentry/node`, this provider can be enabled with the experimental option: + +```js +Sentry.init({ + dsn: 'xxx', + _experiments: { + useSentryTraceProvider: true, + }, +}); +``` + +This only captures spans from code that uses the global OpenTelemetry tracer provider. Spans created from a separate +custom provider instance still belong to that provider and should be sent to Sentry with `SentrySpanProcessor`. + +When this provider is enabled, additional OpenTelemetry span processors are ignored because Sentry spans are created +directly. OpenTelemetry logs and metrics are not handled by this provider. + ## Links - [Official SDK Docs](https://docs.sentry.io/quickstart/) diff --git a/packages/opentelemetry/src/asyncContextStrategy.ts b/packages/opentelemetry/src/asyncContextStrategy.ts index 7cb8dc0f54eb..95cd41310204 100644 --- a/packages/opentelemetry/src/asyncContextStrategy.ts +++ b/packages/opentelemetry/src/asyncContextStrategy.ts @@ -1,23 +1,38 @@ import * as api from '@opentelemetry/api'; -import type { Scope, withActiveSpan as defaultWithActiveSpan } from '@sentry/core'; -import { getDefaultCurrentScope, getDefaultIsolationScope, setAsyncContextStrategy } from '@sentry/core'; +import type { Scope, Span, withActiveSpan as defaultWithActiveSpan } from '@sentry/core'; +import { + _INTERNAL_safeMathRandom, + _INTERNAL_setSpanForScope, + baggageHeaderToDynamicSamplingContext, + getDefaultCurrentScope, + getDefaultIsolationScope, + setAsyncContextStrategy, +} from '@sentry/core'; import { SENTRY_FORK_ISOLATION_SCOPE_CONTEXT_KEY, SENTRY_FORK_SET_ISOLATION_SCOPE_CONTEXT_KEY, SENTRY_FORK_SET_SCOPE_CONTEXT_KEY, + SENTRY_TRACE_STATE_DSC, + SENTRY_TRACE_STATE_SAMPLE_RAND, } from './constants'; import { continueTrace, startInactiveSpan, startNewTrace, startSpan, startSpanManual, withActiveSpan } from './trace'; import type { CurrentScopes } from './types'; import { getContextFromScope, getScopesFromContext } from './utils/contextData'; +import { getSamplingDecision } from './utils/getSamplingDecision'; import { getActiveSpan } from './utils/getActiveSpan'; import { getTraceData } from './utils/getTraceData'; import { suppressTracing } from './utils/suppressTracing'; +import { isSentryTraceProviderSpan } from './sentryTraceProvider'; /** * Sets the async context strategy to use follow the OTEL context under the hood. * We handle forking a hub inside of our custom OTEL Context Manager (./otelContextManager.ts) */ -export function setOpenTelemetryContextAsyncContextStrategy(): void { +export function setOpenTelemetryContextAsyncContextStrategy( + options: { useOpenTelemetrySpanCreation?: boolean } = {}, +): void { + const { useOpenTelemetrySpanCreation = true } = options; + function getScopes(): CurrentScopes { const ctx = api.context.active(); const scopes = getScopesFromContext(ctx); @@ -83,20 +98,94 @@ export function setOpenTelemetryContextAsyncContextStrategy(): void { } function getCurrentScope(): Scope { - return getScopes().scope; + const scope = getScopes().scope; + if (!useOpenTelemetrySpanCreation) { + syncOpenTelemetrySpanWithScope(scope); + } + return scope; } function getIsolationScope(): Scope { return getScopes().isolationScope; } - setAsyncContextStrategy({ + function withActiveSpanContextOnly(span: Span | null, callback: (scope: Scope) => T): T { + const ctx = span + ? api.trace.setSpan(api.context.active(), span as api.Span) + : api.trace.deleteSpan(api.context.active()); + + return api.context.with(ctx, () => { + const scope = getCurrentScope(); + _INTERNAL_setSpanForScope(scope, span || undefined); + return callback(scope); + }); + } + + function syncOpenTelemetrySpanWithScope(scope: Scope): void { + const activeSpan = api.trace.getSpan(api.context.active()) as Span | undefined; + + if (!activeSpan) { + return; + } + + const scopeSpan = scope.getScopeData().span; + if (scopeSpan === activeSpan) { + return; + } + + const activeSpanContext = activeSpan.spanContext(); + if (activeSpanContext.isRemote) { + if (scopeSpan) { + return; + } + + // A remote OTel span context represents an incoming parent, not a local span + // we can finish and send. Store it as propagation context so the next core + // root span continues the trace and becomes the transaction segment. + const dsc = + baggageHeaderToDynamicSamplingContext(activeSpanContext.traceState?.get(SENTRY_TRACE_STATE_DSC)) ?? {}; + const sampleRandString = activeSpanContext.traceState?.get(SENTRY_TRACE_STATE_SAMPLE_RAND) ?? dsc?.sample_rand; + const sampleRand = typeof sampleRandString === 'string' ? Number(sampleRandString) : undefined; + + scope.setPropagationContext({ + traceId: activeSpanContext.traceId, + parentSpanId: activeSpanContext.spanId, + sampled: getSamplingDecision(activeSpanContext), + dsc, + sampleRand: + typeof sampleRand === 'number' && !Number.isNaN(sampleRand) ? sampleRand : _INTERNAL_safeMathRandom(), + }); + return; + } + + if (scopeSpan && !isSentryTraceProviderSpan(scopeSpan)) { + return; + } + + _INTERNAL_setSpanForScope(scope, activeSpan); + } + + const baseStrategy = { withScope, withSetScope, withSetIsolationScope, withIsolationScope, getCurrentScope, getIsolationScope, + }; + + if (!useOpenTelemetrySpanCreation) { + setAsyncContextStrategy({ + ...baseStrategy, + // Keep OTEL Context and Sentry Scope active-span state in sync, but let + // the core tracing implementation create and send spans. + withActiveSpan: withActiveSpanContextOnly as typeof defaultWithActiveSpan, + }); + return; + } + + setAsyncContextStrategy({ + ...baseStrategy, startSpan, startSpanManual, startInactiveSpan, diff --git a/packages/opentelemetry/src/custom/client.ts b/packages/opentelemetry/src/custom/client.ts index a1f0e4792048..ed97faae4f62 100644 --- a/packages/opentelemetry/src/custom/client.ts +++ b/packages/opentelemetry/src/custom/client.ts @@ -1,9 +1,8 @@ import type { Tracer } from '@opentelemetry/api'; import { trace } from '@opentelemetry/api'; -import type { BasicTracerProvider } from '@opentelemetry/sdk-trace-base'; import type { Client } from '@sentry/core'; import { SDK_VERSION } from '@sentry/core'; -import type { OpenTelemetryClient as OpenTelemetryClientInterface } from '../types'; +import type { OpenTelemetryClient as OpenTelemetryClientInterface, OpenTelemetryTraceProvider } from '../types'; // Typescript complains if we do not use `...args: any[]` for the mixin, with: // A mixin class must have a constructor with a single rest parameter of type 'any[]'.ts(2545) @@ -23,7 +22,7 @@ export function wrapClientClass< >(ClientClass: ClassConstructor): WrappedClassConstructor { // @ts-expect-error We just assume that this is non-abstract, if you pass in an abstract class this would make it non-abstract class OpenTelemetryClient extends ClientClass implements OpenTelemetryClientInterface { - public traceProvider: BasicTracerProvider | undefined; + public traceProvider: OpenTelemetryTraceProvider | undefined; private _tracer: Tracer | undefined; public constructor(...args: any[]) { diff --git a/packages/opentelemetry/src/exports.ts b/packages/opentelemetry/src/exports.ts index bdda20fd94ce..3baa495fd446 100644 --- a/packages/opentelemetry/src/exports.ts +++ b/packages/opentelemetry/src/exports.ts @@ -45,6 +45,8 @@ export { wrapContextManagerClass } from './contextManager'; export { SentryPropagator, shouldPropagateTraceForUrl } from './propagator'; export { SentrySpanProcessor } from './spanProcessor'; export { SentrySampler, wrapSamplingDecision } from './sampler'; +export { _INTERNAL_getSpanForRecordedException, applyOtelSpanData, SentryTraceProvider } from './sentryTraceProvider'; +export type { OpenTelemetryTraceProvider } from './types'; export { openTelemetrySetupCheck } from './utils/setupCheck'; diff --git a/packages/opentelemetry/src/sentryTraceProvider.ts b/packages/opentelemetry/src/sentryTraceProvider.ts new file mode 100644 index 000000000000..88c9a4fd3cf2 --- /dev/null +++ b/packages/opentelemetry/src/sentryTraceProvider.ts @@ -0,0 +1,379 @@ +/* eslint-disable max-lines */ +import type { + Context, + Span as OpenTelemetrySpan, + SpanOptions, + Tracer, + TracerOptions, + TracerProvider, +} from '@opentelemetry/api'; +import { context, SpanKind, trace } from '@opentelemetry/api'; +import { isTracingSuppressed } from '@opentelemetry/core'; +import { + _INTERNAL_safeMathRandom, + _INTERNAL_setSpanForScope, + addNonEnumerableProperty, + getCurrentScope, + getDynamicSamplingContextFromSpan, + SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME, + SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, + SentryNonRecordingSpan, + getSpanStatusFromHttpCode, + spanToJSON, + SPAN_STATUS_ERROR, + SPAN_STATUS_OK, + startInactiveSpan, + startNewTrace, + withScope, +} from '@sentry/core'; +import type { Span, SpanAttributes, SpanLink, SpanStatus, SpanTimeInput } from '@sentry/core'; +import { inferSpanData } from './utils/parseSpanDescription'; +import { getSamplingDecision } from './utils/getSamplingDecision'; +import { setIsSetup } from './utils/setupCheck'; + +type SentrySpanWithOtelKind = Span & { kind?: SpanKind }; +type SentrySpanWithOtelSourceInference = Span & { _sentryOtelInferSource?: boolean }; +type SentryTraceProviderSpan = Span & { _sentryTraceProviderSpan?: true }; + +const recordedExceptionSpans = new WeakMap(); + +export function isSentryTraceProviderSpan(span: Span | undefined): boolean { + return (span as SentryTraceProviderSpan | undefined)?._sentryTraceProviderSpan === true; +} + +export function _INTERNAL_getSpanForRecordedException(exception: unknown): Span | undefined { + if (exception === null || (typeof exception !== 'object' && typeof exception !== 'function')) { + return undefined; + } + + return recordedExceptionSpans.get(exception); +} + +function markSentryTraceProviderSpan(span: Span): Span { + addNonEnumerableProperty(span as SentryTraceProviderSpan, '_sentryTraceProviderSpan', true); + const originalRecordException = span.recordException.bind(span); + addNonEnumerableProperty(span, 'recordException', function (this: Span, exception: unknown, time?: SpanTimeInput) { + if (exception !== null && (typeof exception === 'object' || typeof exception === 'function')) { + // Preserve the closest span that recorded this exception. Frameworks like Nest + // may capture after OTel context has unwound to a parent request span. + if (!recordedExceptionSpans.has(exception)) { + recordedExceptionSpans.set(exception, span); + } + } + + return originalRecordException(exception, time); + }); + return span; +} + +const HTTP_RESPONSE_STATUS_CODE_ATTRIBUTE = 'http.response.status_code'; +const LEGACY_HTTP_RESPONSE_STATUS_CODE_ATTRIBUTE = 'http.status_code'; +const RPC_GRPC_STATUS_CODE_ATTRIBUTE = 'rpc.grpc.status_code'; + +const VALID_SPAN_STATUS_MESSAGES = new Set([ + 'ok', + 'deadline_exceeded', + 'unauthenticated', + 'permission_denied', + 'not_found', + 'resource_exhausted', + 'invalid_argument', + 'unimplemented', + 'unavailable', + 'internal_error', + 'unknown_error', + 'cancelled', + 'already_exists', + 'failed_precondition', + 'aborted', + 'out_of_range', + 'data_loss', +]); + +const GRPC_STATUS_CODE_MAP: Record = { + '1': 'cancelled', + '2': 'unknown_error', + '3': 'invalid_argument', + '4': 'deadline_exceeded', + '5': 'not_found', + '6': 'already_exists', + '7': 'permission_denied', + '8': 'resource_exhausted', + '9': 'failed_precondition', + '10': 'aborted', + '11': 'out_of_range', + '12': 'unimplemented', + '13': 'internal_error', + '14': 'unavailable', + '15': 'data_loss', + '16': 'unauthenticated', +}; + +/** + * A minimal OpenTelemetry TracerProvider which creates native Sentry spans. + */ +export class SentryTraceProvider implements TracerProvider { + public readonly resource?: { attributes: SpanAttributes }; + + private readonly _tracers = new Map(); + + public constructor(options: { resource?: { attributes: SpanAttributes } } = {}) { + this.resource = options.resource; + setIsSetup('SentryTraceProvider'); + } + + /** @inheritdoc */ + public getTracer(name: string, version?: string, options?: TracerOptions): Tracer { + const key = JSON.stringify([name, version, options]); + const cachedTracer = this._tracers.get(key); + if (cachedTracer) { + return cachedTracer; + } + + const tracer = new SentryTracer(); + this._tracers.set(key, tracer); + return tracer; + } + + /** Compatibility with SDK tracer providers. */ + public forceFlush(): Promise { + return Promise.resolve(); + } + + /** Compatibility with SDK tracer providers. */ + public shutdown(): Promise { + return Promise.resolve(); + } +} + +class SentryTracer implements Tracer { + /** @inheritdoc */ + public startSpan(name: string, options: SpanOptions = {}, ctx?: Context): OpenTelemetrySpan { + const parentContext = ctx || context.active(); + const parentSpan = options.root ? undefined : trace.getSpan(parentContext); + + if (isTracingSuppressed(parentContext)) { + return this._createNonRecordingSpan(parentSpan); + } + + return context.with(parentContext, () => { + const span = this._startSentrySpan(name, options, parentSpan, ctx !== undefined); + markSentryTraceProviderSpan(span); + applyOtelSpanKind(span, options.kind); + if (options.attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] === undefined) { + addNonEnumerableProperty(span as SentrySpanWithOtelSourceInference, '_sentryOtelInferSource', true); + } + applyOtelSpanData(span); + return span as OpenTelemetrySpan; + }); + } + + /** @inheritdoc */ + public startActiveSpan unknown>(name: string, fn: F): ReturnType; + public startActiveSpan unknown>( + name: string, + options: SpanOptions, + fn: F, + ): ReturnType; + public startActiveSpan unknown>( + name: string, + options: SpanOptions, + ctx: Context, + fn: F, + ): ReturnType; + public startActiveSpan unknown>( + name: string, + optionsOrFn: SpanOptions | F, + contextOrFn?: Context | F, + fn?: F, + ): ReturnType { + const options = typeof optionsOrFn === 'function' ? {} : optionsOrFn; + const ctx = typeof contextOrFn === 'function' || contextOrFn === undefined ? context.active() : contextOrFn; + const callback = ( + typeof optionsOrFn === 'function' ? optionsOrFn : typeof contextOrFn === 'function' ? contextOrFn : fn + ) as F; + + const span = this.startSpan(name, options, ctx); + const ctxWithSpan = trace.setSpan(ctx, span); + + return context.with(ctxWithSpan, () => { + _INTERNAL_setSpanForScope(getCurrentScope(), span as unknown as Span); + return callback(span) as ReturnType; + }); + } + + private _startSentrySpan( + name: string, + options: SpanOptions, + parentSpan: OpenTelemetrySpan | undefined, + hasExplicitContext: boolean, + ): Span { + const sentryOptions = { + name, + attributes: options.attributes as SpanAttributes | undefined, + links: options.links as SpanLink[] | undefined, + startTime: options.startTime, + }; + + if (options.root) { + return startNewTrace(() => startInactiveSpan({ ...sentryOptions, parentSpan: null })); + } + + if (parentSpan?.spanContext().isRemote) { + return this._startRootSpanWithRemoteParent(sentryOptions, parentSpan); + } + + if (parentSpan) { + return startInactiveSpan({ ...sentryOptions, parentSpan: parentSpan as unknown as Span }); + } + + return startInactiveSpan({ + ...sentryOptions, + parentSpan: hasExplicitContext ? null : undefined, + }); + } + + private _startRootSpanWithRemoteParent( + options: Parameters[0], + parentSpan: OpenTelemetrySpan, + ): Span { + const { spanId, traceId } = parentSpan.spanContext(); + const dsc = getDynamicSamplingContextFromSpan(parentSpan as unknown as Span); + const sampleRand = typeof dsc.sample_rand === 'string' ? Number(dsc.sample_rand) : undefined; + + return withScope(scope => { + scope.setPropagationContext({ + traceId, + parentSpanId: spanId, + sampled: getSamplingDecision(parentSpan.spanContext()), + dsc, + sampleRand: + typeof sampleRand === 'number' && !Number.isNaN(sampleRand) ? sampleRand : _INTERNAL_safeMathRandom(), + }); + _INTERNAL_setSpanForScope(scope, undefined); + + return startInactiveSpan({ ...options, parentSpan: null }); + }); + } + + private _createNonRecordingSpan(parentSpan: OpenTelemetrySpan | undefined): OpenTelemetrySpan { + const span = new SentryNonRecordingSpan({ + traceId: parentSpan?.spanContext().traceId, + }); + markSentryTraceProviderSpan(span); + + return span as OpenTelemetrySpan; + } +} + +/** Apply OTel semantic inference to a Sentry span. */ +export function applyOtelSpanData(span: Span, options: { finalizeStatus?: boolean } = {}): void { + const spanJSON = spanToJSON(span); + const attributes = spanJSON.data; + const kind = (span as SentrySpanWithOtelKind).kind ?? SpanKind.INTERNAL; + const mayInferSource = (span as SentrySpanWithOtelSourceInference)._sentryOtelInferSource === true; + const hasCustomSpanName = attributes[SEMANTIC_ATTRIBUTE_SENTRY_CUSTOM_SPAN_NAME] !== undefined; + const attributesForInference = + mayInferSource && !hasCustomSpanName && attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] === 'custom' + ? { ...attributes, [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: undefined } + : attributes; + const inferred = inferSpanData(spanJSON.description || '', attributesForInference, kind); + + if (kind !== SpanKind.INTERNAL && attributes['otel.kind'] === undefined) { + span.setAttribute('otel.kind', SpanKind[kind]); + } + + if (inferred.op && attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] === undefined) { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, inferred.op); + } + + const shouldApplyInferredSource = + inferred.source !== undefined && + inferred.source !== 'custom' && + (spanJSON.parent_span_id === undefined || kind === SpanKind.SERVER); + + if ( + shouldApplyInferredSource && + (attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] === undefined || (mayInferSource && !hasCustomSpanName)) + ) { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, inferred.source); + } + + if (inferred.data) { + Object.entries(inferred.data).forEach(([key, value]) => { + if (value !== undefined && attributes[key] === undefined) { + span.setAttribute(key, value); + } + }); + } + + if ( + mayInferSource && + !hasCustomSpanName && + attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] === 'custom' && + (inferred.source === undefined || inferred.source === 'custom') + ) { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, undefined); + } + + if (options.finalizeStatus) { + applyOtelCompatibilityAttributes(span, attributes); + applyOtelSpanStatus(span, attributes, spanJSON.status); + } + + if ( + inferred.description !== spanJSON.description && + (attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] !== 'custom' || (mayInferSource && !hasCustomSpanName)) + ) { + addNonEnumerableProperty(span as Span & { _name?: string }, '_name', inferred.description); + } +} + +function applyOtelSpanKind(span: Span, kind: SpanKind | undefined): void { + addNonEnumerableProperty(span as SentrySpanWithOtelKind, 'kind', kind ?? SpanKind.INTERNAL); +} + +function applyOtelSpanStatus(span: Span, attributes: SpanAttributes, status: string | undefined): void { + if (status === undefined) { + const inferredStatus = inferOtelSpanStatusFromAttributes(attributes); + span.setStatus(inferredStatus || { code: SPAN_STATUS_OK }); + return; + } + + if (!VALID_SPAN_STATUS_MESSAGES.has(status)) { + span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' }); + } +} + +function applyOtelCompatibilityAttributes(span: Span, attributes: SpanAttributes): void { + const legacyHttpStatusCode = attributes[LEGACY_HTTP_RESPONSE_STATUS_CODE_ATTRIBUTE]; + + if (attributes[HTTP_RESPONSE_STATUS_CODE_ATTRIBUTE] === undefined && legacyHttpStatusCode !== undefined) { + span.setAttribute(HTTP_RESPONSE_STATUS_CODE_ATTRIBUTE, legacyHttpStatusCode); + attributes[HTTP_RESPONSE_STATUS_CODE_ATTRIBUTE] = legacyHttpStatusCode; + } +} + +function inferOtelSpanStatusFromAttributes(attributes: SpanAttributes): SpanStatus | undefined { + const httpCodeAttribute = + attributes[HTTP_RESPONSE_STATUS_CODE_ATTRIBUTE] ?? attributes[LEGACY_HTTP_RESPONSE_STATUS_CODE_ATTRIBUTE]; + const grpcCodeAttribute = attributes[RPC_GRPC_STATUS_CODE_ATTRIBUTE]; + + const numberHttpCode = + typeof httpCodeAttribute === 'number' + ? httpCodeAttribute + : typeof httpCodeAttribute === 'string' + ? parseInt(httpCodeAttribute, 10) + : undefined; + + if (typeof numberHttpCode === 'number') { + return getSpanStatusFromHttpCode(numberHttpCode); + } + + if (typeof grpcCodeAttribute === 'string') { + return { code: SPAN_STATUS_ERROR, message: GRPC_STATUS_CODE_MAP[grpcCodeAttribute] || 'unknown_error' }; + } + + return undefined; +} diff --git a/packages/opentelemetry/src/types.ts b/packages/opentelemetry/src/types.ts index 807e9b1d857f..4563f7b8c72f 100644 --- a/packages/opentelemetry/src/types.ts +++ b/packages/opentelemetry/src/types.ts @@ -1,10 +1,15 @@ -import type { Span as WriteableSpan, SpanKind, Tracer } from '@opentelemetry/api'; +import type { Span as WriteableSpan, SpanKind, Tracer, TracerProvider } from '@opentelemetry/api'; import type { BasicTracerProvider, ReadableSpan } from '@opentelemetry/sdk-trace-base'; import type { Scope, Span, StartSpanOptions } from '@sentry/core'; +export interface OpenTelemetryTraceProvider extends TracerProvider { + forceFlush(): Promise; + shutdown(): Promise; +} + export interface OpenTelemetryClient { tracer: Tracer; - traceProvider: BasicTracerProvider | undefined; + traceProvider: BasicTracerProvider | OpenTelemetryTraceProvider | undefined; } export interface OpenTelemetrySpanContext extends StartSpanOptions { diff --git a/packages/opentelemetry/src/utils/setupCheck.ts b/packages/opentelemetry/src/utils/setupCheck.ts index 66bc7b445f83..0cc8d9d310f7 100644 --- a/packages/opentelemetry/src/utils/setupCheck.ts +++ b/packages/opentelemetry/src/utils/setupCheck.ts @@ -1,4 +1,9 @@ -type OpenTelemetryElement = 'SentrySpanProcessor' | 'SentryContextManager' | 'SentryPropagator' | 'SentrySampler'; +type OpenTelemetryElement = + | 'SentrySpanProcessor' + | 'SentryContextManager' + | 'SentryPropagator' + | 'SentrySampler' + | 'SentryTraceProvider'; const setupElements = new Set(); From e05e0c7c226e04af4c4eb2171cd0e0f8f4b3b6c7 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Mon, 18 May 2026 18:08:30 +0900 Subject: [PATCH 2/5] Add useSentryTraceProvider flag --- packages/core/src/types/options.ts | 8 +++ packages/node-core/src/sdk/client.ts | 9 ++- packages/node-core/src/sdk/index.ts | 6 +- packages/node/src/sdk/initOtel.ts | 86 +++++++++++++++++++++++++++- 4 files changed, 102 insertions(+), 7 deletions(-) diff --git a/packages/core/src/types/options.ts b/packages/core/src/types/options.ts index e6d5714adff0..6107d99f024b 100644 --- a/packages/core/src/types/options.ts +++ b/packages/core/src/types/options.ts @@ -462,6 +462,14 @@ export interface ClientOptions { - public traceProvider: BasicTracerProvider | undefined; + public traceProvider: OpenTelemetryTraceProvider | undefined; public asyncLocalStorageLookup: AsyncLocalStorageLookup | undefined; private _tracer: Tracer | undefined; diff --git a/packages/node-core/src/sdk/index.ts b/packages/node-core/src/sdk/index.ts index 52271ee62363..e4906c5b732e 100644 --- a/packages/node-core/src/sdk/index.ts +++ b/packages/node-core/src/sdk/index.ts @@ -168,7 +168,9 @@ export function validateOpenTelemetrySetup(): void { const required: ReturnType = ['SentryContextManager', 'SentryPropagator']; - if (hasSpansEnabled()) { + const hasSentryTraceProvider = setup.includes('SentryTraceProvider'); + + if (hasSpansEnabled() && !hasSentryTraceProvider) { required.push('SentrySpanProcessor'); } @@ -180,7 +182,7 @@ export function validateOpenTelemetrySetup(): void { } } - if (!setup.includes('SentrySampler')) { + if (!hasSentryTraceProvider && !setup.includes('SentrySampler')) { debug.warn( 'You have to set up the SentrySampler. Without this, the OpenTelemetry & Sentry integration may still work, but sample rates set for the Sentry SDK will not be respected. If you use a custom sampler, make sure to use `wrapSamplingDecision`.', ); diff --git a/packages/node/src/sdk/initOtel.ts b/packages/node/src/sdk/initOtel.ts index 2554b98c76f7..9a0e3e05bbe3 100644 --- a/packages/node/src/sdk/initOtel.ts +++ b/packages/node/src/sdk/initOtel.ts @@ -1,7 +1,7 @@ import { context, propagation, trace } from '@opentelemetry/api'; import type { SpanProcessor } from '@opentelemetry/sdk-trace-base'; import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base'; -import { debug as coreDebug } from '@sentry/core'; +import { debug as coreDebug, spanToTraceContext } from '@sentry/core'; import { initializeEsmLoader, type NodeClient, @@ -9,11 +9,16 @@ import { setupOpenTelemetryLogger, } from '@sentry/node-core'; import { + _INTERNAL_getSpanForRecordedException, + applyOtelSpanData, type AsyncLocalStorageLookup, getSentryResource, + type OpenTelemetryTraceProvider, SentryPropagator, SentrySampler, SentrySpanProcessor, + SentryTraceProvider, + setOpenTelemetryContextAsyncContextStrategy, } from '@sentry/opentelemetry'; import { DEBUG_BUILD } from '../debug-build'; import { getOpenTelemetryInstrumentationToPreload } from '../integrations/tracing'; @@ -86,7 +91,12 @@ function getPreloadMethods(integrationNames?: string[]): ((() => void) & { id: s export function setupOtel( client: NodeClient, options: AdditionalOpenTelemetryOptions = {}, -): [BasicTracerProvider, AsyncLocalStorageLookup] { +): [OpenTelemetryTraceProvider | undefined, AsyncLocalStorageLookup | undefined] { + if (client.getOptions()._experiments?.useSentryTraceProvider) { + setOpenTelemetryContextAsyncContextStrategy({ useOpenTelemetrySpanCreation: false }); + return setupSentryTraceProvider(client, options); + } + // Create and configure NodeTracerProvider const provider = new BasicTracerProvider({ sampler: new SentrySampler(client), @@ -110,6 +120,78 @@ export function setupOtel( return [provider, ctxManager.getAsyncLocalStorageLookup()]; } +function setupSentryTraceProvider( + client: NodeClient, + options: AdditionalOpenTelemetryOptions = {}, +): [SentryTraceProvider | undefined, AsyncLocalStorageLookup | undefined] { + if (options.spanProcessors?.length) { + DEBUG_BUILD && + coreDebug.warn( + 'Ignoring `openTelemetrySpanProcessors` because `_experiments.useSentryTraceProvider` is enabled.', + ); + } + + const provider = new SentryTraceProvider({ resource: getSentryResource('node') }); + + if (!trace.setGlobalTracerProvider(provider)) { + DEBUG_BUILD && + coreDebug.warn( + 'Could not register SentryTraceProvider because another OpenTelemetry tracer provider is already registered.', + ); + return [undefined, undefined]; + } + + propagation.setGlobalPropagator(new SentryPropagator()); + + const ctxManager = new SentryContextManager(); + context.setGlobalContextManager(ctxManager); + + client.on('spanEnd', span => { + applyOtelSpanData(span, { finalizeStatus: true }); + }); + + client.addEventProcessor((event, hint) => { + // Some frameworks capture exceptions after the OTel context has already + // unwound. If a provider-created span recorded this exact exception first, + // keep the error event linked to that span instead of the ambient parent. + const span = _INTERNAL_getSpanForRecordedException(hint.originalException); + if (!span) { + return event; + } + + event.contexts = { + ...event.contexts, + trace: spanToTraceContext(span), + }; + + return event; + }); + + client.on('preprocessEvent', event => { + if (event.type !== 'transaction' || client.getOptions().traceLifecycle === 'stream') { + return; + } + + event.contexts = { + ...event.contexts, + ...(typeof event.contexts?.trace?.data?.['http.response.status_code'] === 'number' + ? { + response: { + status_code: event.contexts.trace.data['http.response.status_code'], + ...event.contexts.response, + }, + } + : undefined), + otel: { + resource: provider.resource?.attributes, + ...event.contexts?.otel, + }, + }; + }); + + return [provider, ctxManager.getAsyncLocalStorageLookup()]; +} + /** Just exported for tests. */ export function _clampSpanProcessorTimeout(maxSpanWaitDuration: number | undefined): number | undefined { if (maxSpanWaitDuration == null) { From f872de0baa25765084c40b228440d78fd49586e6 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Mon, 18 May 2026 18:11:17 +0900 Subject: [PATCH 3/5] Fix HTTP propagation with SentryTraceProvider --- .../src/integrations/http/httpServerSpansIntegration.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/node-core/src/integrations/http/httpServerSpansIntegration.ts b/packages/node-core/src/integrations/http/httpServerSpansIntegration.ts index 314f733a7dae..9028f8d68d69 100644 --- a/packages/node-core/src/integrations/http/httpServerSpansIntegration.ts +++ b/packages/node-core/src/integrations/http/httpServerSpansIntegration.ts @@ -2,7 +2,7 @@ import { errorMonitor } from 'node:events'; import type { IncomingHttpHeaders } from 'node:http'; import { context, SpanKind, trace } from '@opentelemetry/api'; import type { RPCMetadata } from '@opentelemetry/core'; -import { getRPCMetadata, isTracingSuppressed, RPCType, setRPCMetadata } from '@opentelemetry/core'; +import { isTracingSuppressed, RPCType, setRPCMetadata } from '@opentelemetry/core'; import { ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_HTTP_ROUTE, @@ -199,7 +199,7 @@ const _httpServerSpansIntegration = ((options: HttpServerSpansIntegrationOptions isEnded = true; - const newAttributes = getIncomingRequestAttributesOnResponse(request, response); + const newAttributes = getIncomingRequestAttributesOnResponse(request, response, rpcMetadata); span.setAttributes(newAttributes); span.setStatus(status); span.end(); @@ -371,6 +371,7 @@ function isCompressed(headers: IncomingHttpHeaders): boolean { function getIncomingRequestAttributesOnResponse( request: HttpIncomingMessage, response: HttpServerResponse, + rpcMetadata?: RPCMetadata, ): SpanAttributes { // take socket from the request, // since it may be detached from the response object in keep-alive mode @@ -384,7 +385,6 @@ function getIncomingRequestAttributesOnResponse( 'http.status_text': statusMessage?.toUpperCase(), }; - const rpcMetadata = getRPCMetadata(context.active()); if (socket) { const { localAddress, localPort, remoteAddress, remotePort } = socket; // eslint-disable-next-line deprecation/deprecation From 15c2fe5694e628fd6e08d7fc50788e9b5a186223 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Mon, 18 May 2026 18:15:11 +0900 Subject: [PATCH 4/5] Add SentryTraceProvider test coverage --- .../tracing/sentryNonRecordingSpan.test.ts | 12 + packages/core/test/lib/tracing/trace.test.ts | 12 +- .../core/test/lib/utils/traceData.test.ts | 32 +++ packages/node/test/sdk/init.test.ts | 29 +++ .../test/sentryTraceProvider.test.ts | 225 ++++++++++++++++++ .../test/utils/setupCheck.test.ts | 8 + 6 files changed, 312 insertions(+), 6 deletions(-) create mode 100644 packages/opentelemetry/test/sentryTraceProvider.test.ts diff --git a/packages/core/test/lib/tracing/sentryNonRecordingSpan.test.ts b/packages/core/test/lib/tracing/sentryNonRecordingSpan.test.ts index 1aeec1893908..93617f706f5f 100644 --- a/packages/core/test/lib/tracing/sentryNonRecordingSpan.test.ts +++ b/packages/core/test/lib/tracing/sentryNonRecordingSpan.test.ts @@ -12,6 +12,7 @@ describe('SentryNonRecordingSpan', () => { spanId: expect.any(String), traceId: expect.any(String), traceFlags: TRACE_FLAG_NONE, + sampled: undefined, }); expect(spanIsSampled(span)).toBe(false); @@ -39,4 +40,15 @@ describe('SentryNonRecordingSpan', () => { start_timestamp: 0, }); }); + + it('can carry an explicit negative sampling decision', () => { + const span: Span = new SentryNonRecordingSpan({ sampled: false }); + + expect(span.spanContext()).toEqual({ + spanId: expect.any(String), + traceId: expect.any(String), + traceFlags: TRACE_FLAG_NONE, + sampled: false, + }); + }); }); diff --git a/packages/core/test/lib/tracing/trace.test.ts b/packages/core/test/lib/tracing/trace.test.ts index 0d0e652e64aa..4d3258eb338a 100644 --- a/packages/core/test/lib/tracing/trace.test.ts +++ b/packages/core/test/lib/tracing/trace.test.ts @@ -230,16 +230,20 @@ describe('startSpan', () => { setCurrentClient(client); client.init(); + getCurrentScope().setPropagationContext({ + traceId: '12345678901234567890123456789012', + sampleRand: 0.42, + }); + const span = startSpan({ name: 'GET users/[id]' }, span => { return span; }); expect(span).toBeDefined(); expect(span).toBeInstanceOf(SentryNonRecordingSpan); + expect(span.spanContext().traceId).toBe('12345678901234567890123456789012'); expect(getDynamicSamplingContextFromSpan(span)).toEqual({ environment: 'production', - sample_rate: '0', - sampled: 'false', trace_id: expect.stringMatching(/[a-f0-9]{32}/), transaction: 'GET users/[id]', }); @@ -882,8 +886,6 @@ describe('startSpanManual', () => { expect(span).toBeInstanceOf(SentryNonRecordingSpan); expect(getDynamicSamplingContextFromSpan(span)).toEqual({ environment: 'production', - sample_rate: '0', - sampled: 'false', trace_id: expect.stringMatching(/[a-f0-9]{32}/), transaction: 'GET users/[id]', }); @@ -1394,8 +1396,6 @@ describe('startInactiveSpan', () => { expect(span).toBeInstanceOf(SentryNonRecordingSpan); expect(getDynamicSamplingContextFromSpan(span)).toEqual({ environment: 'production', - sample_rate: '0', - sampled: 'false', trace_id: expect.stringMatching(/[a-f0-9]{32}/), transaction: 'GET users/[id]', }); diff --git a/packages/core/test/lib/utils/traceData.test.ts b/packages/core/test/lib/utils/traceData.test.ts index b2101502cb43..678eec31d2de 100644 --- a/packages/core/test/lib/utils/traceData.test.ts +++ b/packages/core/test/lib/utils/traceData.test.ts @@ -11,6 +11,7 @@ import { SentrySpan, setAsyncContextStrategy, setCurrentClient, + startSpan, withActiveSpan, } from '../../../src/'; import { getAsyncContextStrategy } from '../../../src/asyncContext'; @@ -142,6 +143,37 @@ describe('getTraceData', () => { }); }); + it('does not add a sampled flag for an active TwP placeholder span', () => { + setupClient({ tracesSampleRate: undefined }); + + getCurrentScope().setPropagationContext({ + traceId: '12345678901234567890123456789012', + sampleRand: 0.42, + }); + + startSpan({ name: 'twp-root' }, () => { + const data = getTraceData(); + + expect(data).toEqual({ + 'sentry-trace': expect.stringMatching(/^12345678901234567890123456789012-[a-f0-9]{16}$/), + baggage: + 'sentry-environment=production,sentry-public_key=123,sentry-trace_id=12345678901234567890123456789012,sentry-transaction=twp-root', + }); + expect(data['sentry-trace']?.split('-')).toHaveLength(2); + }); + }); + + it('keeps an explicit negative sampling decision for an active unsampled span', () => { + setupClient({ tracesSampleRate: 0 }); + + startSpan({ name: 'unsampled-root' }, () => { + const data = getTraceData(); + + expect(data['sentry-trace']).toMatch(/^[a-f0-9]{32}-[a-f0-9]{16}-0$/); + expect(data.baggage).toContain('sentry-sampled=false'); + }); + }); + it('allows to pass a span directly', () => { setupClient(); diff --git a/packages/node/test/sdk/init.test.ts b/packages/node/test/sdk/init.test.ts index 26fe2d9933e6..0fe346b09f88 100644 --- a/packages/node/test/sdk/init.test.ts +++ b/packages/node/test/sdk/init.test.ts @@ -194,6 +194,35 @@ describe('init()', () => { expect(client?.traceProvider).not.toBeDefined(); }); + + it('uses the minimal Sentry trace provider when the experiment is enabled', () => { + init({ dsn: PUBLIC_DSN, _experiments: { useSentryTraceProvider: true } }); + + const client = getClient(); + + expect(client?.traceProvider).toBeInstanceOf(SentryOpentelemetry.SentryTraceProvider); + }); + + it('warns and ignores additional span processors when the minimal Sentry trace provider is enabled', () => { + const warnSpy = vi.spyOn(debug, 'warn').mockImplementation(() => {}); + + init({ + dsn: PUBLIC_DSN, + _experiments: { useSentryTraceProvider: true }, + openTelemetrySpanProcessors: [ + { + forceFlush: () => Promise.resolve(), + onStart: () => undefined, + onEnd: () => undefined, + shutdown: () => Promise.resolve(), + }, + ], + }); + + expect(warnSpy).toHaveBeenCalledWith( + 'Ignoring `openTelemetrySpanProcessors` because `_experiments.useSentryTraceProvider` is enabled.', + ); + }); }); it('returns initialized client', () => { diff --git a/packages/opentelemetry/test/sentryTraceProvider.test.ts b/packages/opentelemetry/test/sentryTraceProvider.test.ts new file mode 100644 index 000000000000..ffb409ef0558 --- /dev/null +++ b/packages/opentelemetry/test/sentryTraceProvider.test.ts @@ -0,0 +1,225 @@ +import { context, SpanKind, trace, TraceFlags } from '@opentelemetry/api'; +import { + continueTrace, + getActiveSpan, + getDynamicSamplingContextFromSpan, + getRootSpan, + spanToJSON, + SPAN_STATUS_ERROR, + startSpanManual, + type Span, +} from '@sentry/core'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; +import { SentryAsyncLocalStorageContextManager } from '../src/asyncLocalStorageContextManager'; +import { setOpenTelemetryContextAsyncContextStrategy } from '../src/asyncContextStrategy'; +import { + _INTERNAL_getSpanForRecordedException, + applyOtelSpanData, + SentryTraceProvider, +} from '../src/sentryTraceProvider'; +import { cleanupOtel } from './helpers/mockSdkInit'; +import { init as initTestClient } from './helpers/TestClient'; + +describe('SentryTraceProvider', () => { + beforeEach(() => { + (global as { __SENTRY__?: unknown }).__SENTRY__ = {}; + setOpenTelemetryContextAsyncContextStrategy({ useOpenTelemetrySpanCreation: false }); + initTestClient({ tracesSampleRate: 1 }); + context.setGlobalContextManager(new SentryAsyncLocalStorageContextManager()); + trace.setGlobalTracerProvider(new SentryTraceProvider()); + }); + + afterEach(async () => { + await cleanupOtel(); + }); + + it('creates Sentry spans from the global OpenTelemetry tracer', () => { + const span = trace.getTracer('test').startSpan('SELECT users', { + attributes: { + 'db.system.name': 'postgresql', + 'db.statement': 'SELECT * FROM users', + }, + }); + + expect(spanToJSON(span as Span)).toEqual({ + data: { + 'sentry.origin': 'manual', + 'sentry.op': 'db', + 'sentry.sample_rate': 1, + 'sentry.source': 'task', + 'db.system.name': 'postgresql', + 'db.statement': 'SELECT * FROM users', + }, + description: 'SELECT * FROM users', + op: 'db', + origin: 'manual', + parent_span_id: undefined, + span_id: span.spanContext().spanId, + start_timestamp: expect.any(Number), + status: undefined, + timestamp: undefined, + trace_id: span.spanContext().traceId, + profile_id: undefined, + exclusive_time: undefined, + measurements: undefined, + is_segment: undefined, + segment_id: undefined, + links: undefined, + }); + }); + + it('parents inactive spans to the active OpenTelemetry span', () => { + trace.getTracer('test').startActiveSpan('parent', parent => { + const child = trace.getTracer('test').startSpan('child'); + + expect(spanToJSON(child as Span).parent_span_id).toBe(parent.spanContext().spanId); + }); + }); + + it('sets active OpenTelemetry spans on the Sentry scope', () => { + trace.getTracer('test').startActiveSpan('parent', parent => { + expect(getActiveSpan()).toBe(parent); + }); + }); + + it('syncs manual OpenTelemetry context switches onto the Sentry scope', () => { + const tracer = trace.getTracer('test'); + + tracer.startActiveSpan('parent', parent => { + const child = tracer.startSpan('child'); + const childContext = trace.setSpan(context.active(), child); + + context.with(childContext, () => { + expect(getActiveSpan()).toBe(child); + }); + + expect(getActiveSpan()).toBe(parent); + + child.end(); + parent.end(); + }); + }); + + it('does not replace active core spans with provider-created OpenTelemetry spans', () => { + const tracer = trace.getTracer('test'); + + tracer.startActiveSpan('otel-parent', otelParent => { + startSpanManual({ name: 'sentry-parent' }, sentryParent => { + const otelChild = tracer.startSpan('otel-child'); + const otelChildContext = trace.setSpan(context.active(), otelChild); + + context.with(otelChildContext, () => { + expect(getActiveSpan()).toBe(sentryParent); + }); + + otelChild.end(); + sentryParent.end(); + }); + + otelParent.end(); + }); + }); + + it('parents core spans to the active OpenTelemetry span in context-only mode', () => { + trace.getTracer('test').startActiveSpan('parent', parent => { + startSpanManual({ name: 'child' }, child => { + expect(spanToJSON(child).parent_span_id).toBe(parent.spanContext().spanId); + child.end(); + }); + }); + }); + + it('continues remote OpenTelemetry contexts as root core spans in context-only mode', () => { + const traceId = '12312012123120121231201212312012'; + const parentSpanId = '1121201211212012'; + const remoteContext = trace.setSpanContext(context.active(), { + traceId, + spanId: parentSpanId, + isRemote: true, + traceFlags: TraceFlags.SAMPLED, + }); + + context.with(remoteContext, () => { + continueTrace({ sentryTrace: `${traceId}-${parentSpanId}-1`, baggage: undefined }, () => { + startSpanManual({ name: 'server' }, span => { + expect(getRootSpan(span)).toBe(span); + expect(spanToJSON(span)).toMatchObject({ + trace_id: traceId, + parent_span_id: parentSpanId, + }); + expect(getDynamicSamplingContextFromSpan(span)).toEqual({}); + span.end(); + }); + }); + }); + }); + + it('continues remote OpenTelemetry span contexts as root Sentry spans', () => { + const remoteContext = trace.setSpanContext(context.active(), { + traceId: '12312012123120121231201212312012', + spanId: '1121201211212012', + isRemote: true, + traceFlags: TraceFlags.SAMPLED, + }); + + const span = trace.getTracer('test').startSpan('server', { kind: SpanKind.SERVER }, remoteContext); + const json = spanToJSON(span as Span); + + expect(json.trace_id).toBe('12312012123120121231201212312012'); + expect(json.parent_span_id).toBe('1121201211212012'); + expect(json.data?.['otel.kind']).toBe('SERVER'); + }); + + it('remembers the closest provider-created span that recorded an exception', () => { + const error = new Error('test error'); + + trace.getTracer('test').startActiveSpan('outer', outer => { + let innerSpan: unknown; + + trace.getTracer('test').startActiveSpan('inner', inner => { + innerSpan = inner; + inner.recordException(error); + inner.end(); + }); + + outer.recordException(error); + + expect(_INTERNAL_getSpanForRecordedException(error)).toBe(innerSpan); + outer.end(); + }); + }); + + it('finalizes span statuses like the OpenTelemetry exporter', () => { + const okSpan = trace.getTracer('test').startSpan('ok'); + applyOtelSpanData(okSpan as Span, { finalizeStatus: true }); + expect(spanToJSON(okSpan as Span).status).toBe('ok'); + + const httpErrorSpan = trace.getTracer('test').startSpan('http-error'); + httpErrorSpan.setAttribute('http.response.status_code', 500); + applyOtelSpanData(httpErrorSpan as Span, { finalizeStatus: true }); + expect(spanToJSON(httpErrorSpan as Span).status).toBe('internal_error'); + + const legacyHttpErrorSpan = trace.getTracer('test').startSpan('legacy-http-error'); + legacyHttpErrorSpan.setAttribute('http.status_code', 500); + applyOtelSpanData(legacyHttpErrorSpan as Span, { finalizeStatus: true }); + expect(spanToJSON(legacyHttpErrorSpan as Span).status).toBe('internal_error'); + expect(spanToJSON(legacyHttpErrorSpan as Span).data).toMatchObject({ + 'http.response.status_code': 500, + 'http.status_code': 500, + }); + + const customErrorSpan = trace.getTracer('test').startSpan('custom-error'); + customErrorSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'This is a custom error' }); + applyOtelSpanData(customErrorSpan as Span, { finalizeStatus: true }); + expect(spanToJSON(customErrorSpan as Span).status).toBe('internal_error'); + }); + + it('does not keep default custom source on provider-created spans', () => { + const span = trace.getTracer('test').startSpan('custom-source'); + span.setAttribute('sentry.source', 'custom'); + + applyOtelSpanData(span as Span, { finalizeStatus: true }); + + expect(spanToJSON(span as Span).data?.['sentry.source']).toBeUndefined(); + }); +}); diff --git a/packages/opentelemetry/test/utils/setupCheck.test.ts b/packages/opentelemetry/test/utils/setupCheck.test.ts index 526945108ba7..ca3073197249 100644 --- a/packages/opentelemetry/test/utils/setupCheck.test.ts +++ b/packages/opentelemetry/test/utils/setupCheck.test.ts @@ -2,6 +2,7 @@ import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { SentrySampler } from '../../src/sampler'; import { SentrySpanProcessor } from '../../src/spanProcessor'; +import { SentryTraceProvider } from '../../src/sentryTraceProvider'; import { openTelemetrySetupCheck } from '../../src/utils/setupCheck'; import { setupOtel } from '../helpers/initOtel'; import { cleanupOtel } from '../helpers/mockSdkInit'; @@ -41,4 +42,11 @@ describe('openTelemetrySetupCheck', () => { const setup = openTelemetrySetupCheck(); expect(setup).toEqual(['SentrySampler', 'SentrySpanProcessor']); }); + + it('returns SentryTraceProvider setup', () => { + new SentryTraceProvider(); + + const setup = openTelemetrySetupCheck(); + expect(setup).toEqual(['SentryTraceProvider']); + }); }); From a44215e16d040a005341506850acf2dffbc77b49 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Mon, 18 May 2026 19:44:36 +0900 Subject: [PATCH 5/5] Add e2e tests --- .../test-applications/astro-4/package.json | 9 +++ .../astro-4/sentry.server.config.js | 7 ++ .../test-applications/astro-5/package.json | 9 +++ .../astro-5/sentry.server.config.js | 7 ++ .../test-applications/astro-6/package.json | 13 +++- .../astro-6/sentry.server.config.js | 7 ++ .../aws-serverless/package.json | 9 +++ .../TracingCjs/sentry-trace-provider-auto.mjs | 14 ++++ .../TracingEsm/sentry-trace-provider-auto.mjs | 14 ++++ .../aws-serverless/src/stack.ts | 6 +- .../instrument.mjs | 7 ++ .../package.json | 9 +++ .../create-remix-app-express/instrument.mjs | 7 ++ .../create-remix-app-express/package.json | 9 +++ .../app/entry.server.tsx | 7 ++ .../instrument.server.cjs | 7 ++ .../create-remix-app-v2-non-vite/package.json | 9 +++ .../create-remix-app-v2/instrument.server.cjs | 7 ++ .../create-remix-app-v2/package.json | 9 +++ .../elysia-node/package.json | 13 +++- .../test-applications/elysia-node/src/app.ts | 7 ++ .../test-applications/hono-4/package.json | 15 +++- .../hono-4/src/instrument.node.ts | 7 ++ .../test-applications/nestjs-11/package.json | 9 +++ .../nestjs-11/src/instrument.ts | 7 ++ .../test-applications/nestjs-8/package.json | 9 +++ .../nestjs-8/src/instrument.ts | 7 ++ .../nestjs-basic-with-graphql/package.json | 9 +++ .../src/instrument.ts | 7 ++ .../nestjs-basic/package.json | 9 +++ .../nestjs-basic/src/instrument.ts | 7 ++ .../nestjs-bullmq/package.json | 9 +++ .../nestjs-bullmq/src/instrument.ts | 7 ++ .../nestjs-distributed-tracing/package.json | 9 +++ .../src/instrument.ts | 7 ++ .../nestjs-fastify/package.json | 9 +++ .../nestjs-fastify/src/instrument.ts | 7 ++ .../nestjs-graphql/package.json | 9 +++ .../nestjs-graphql/src/instrument.ts | 7 ++ .../nestjs-microservices/package.json | 9 +++ .../nestjs-microservices/src/instrument.ts | 7 ++ .../nestjs-websockets/package.json | 9 +++ .../nestjs-websockets/src/instrument.ts | 7 ++ .../package.json | 9 +++ .../src/instrument.ts | 7 ++ .../nestjs-with-submodules/package.json | 9 +++ .../nestjs-with-submodules/src/instrument.ts | 7 ++ .../nextjs-13/instrumentation.ts | 7 ++ .../test-applications/nextjs-13/package.json | 7 ++ .../nextjs-14/instrumentation.ts | 7 ++ .../test-applications/nextjs-14/package.json | 7 ++ .../nextjs-15-basepath/package.json | 9 +++ .../sentry.server.config.ts | 7 ++ .../nextjs-15-intl/package.json | 9 +++ .../nextjs-15-intl/sentry.server.config.ts | 7 ++ .../nextjs-15-t3/package.json | 9 +++ .../nextjs-15-t3/sentry.server.config.ts | 7 ++ .../test-applications/nextjs-15/package.json | 7 ++ .../nextjs-15/sentry.server.config.ts | 7 ++ .../nextjs-16-cacheComponents/package.json | 9 ++- .../sentry.server.config.ts | 7 ++ .../nextjs-16-streaming/package.json | 9 +++ .../sentry.server.config.ts | 7 ++ .../nextjs-16-trailing-slash/package.json | 5 ++ .../sentry.server.config.ts | 7 ++ .../nextjs-16-tunnel/package.json | 5 ++ .../nextjs-16-tunnel/sentry.server.config.ts | 7 ++ .../nextjs-16-userfeedback/package.json | 9 +++ .../sentry.server.config.ts | 7 ++ .../test-applications/nextjs-16/package.json | 5 ++ .../nextjs-16/sentry.server.config.ts | 7 ++ .../nextjs-app-dir/instrumentation.ts | 7 ++ .../nextjs-app-dir/package.json | 5 ++ .../nextjs-orpc/package.json | 9 ++- .../nextjs-orpc/sentry.server.config.ts | 7 ++ .../nextjs-pages-dir/instrumentation.ts | 7 ++ .../nextjs-pages-dir/package.json | 5 ++ .../test-applications/nitro-3/instrument.mjs | 7 ++ .../test-applications/nitro-3/package.json | 9 +++ .../node-connect/package.json | 9 +++ .../test-applications/node-connect/src/app.ts | 7 ++ .../node-connect/tests/transactions.test.ts | 78 +++++++++++-------- .../node-express-cjs-preload/package.json | 9 +++ .../node-express-cjs-preload/src/app.js | 7 ++ .../node-express-esm-loader/package.json | 9 +++ .../src/instrument.mjs | 7 ++ .../node-express-esm-preload/package.json | 9 +++ .../node-express-esm-preload/src/app.mjs | 7 ++ .../package.json | 9 +++ .../src/app.ts | 7 ++ .../node-express-mcp-v2/instrument.mjs | 7 ++ .../node-express-mcp-v2/package.json | 9 ++- .../node-express-send-to-sentry/package.json | 9 ++- .../node-express-send-to-sentry/src/app.ts | 7 ++ .../node-express-streaming/package.json | 9 +++ .../node-express-streaming/src/app.ts | 7 ++ .../node-express-v5/package.json | 9 +++ .../node-express-v5/src/app.ts | 7 ++ .../node-express/package.json | 9 +++ .../test-applications/node-express/src/app.ts | 7 ++ .../node-fastify-3/package.json | 9 +++ .../src/app-handle-error-override.ts | 7 ++ .../node-fastify-3/src/app.ts | 7 ++ .../node-fastify-4/package.json | 9 +++ .../src/app-handle-error-override.ts | 7 ++ .../node-fastify-4/src/app.ts | 7 ++ .../node-fastify-5/package.json | 9 +++ .../src/app-handle-error-override.ts | 7 ++ .../node-fastify-5/src/app.ts | 7 ++ .../node-firebase/firestore-app/src/init.ts | 7 ++ .../node-firebase/functions/src/init.ts | 7 ++ .../node-firebase/package.json | 9 +++ .../test-applications/node-hapi/package.json | 9 +++ .../test-applications/node-hapi/src/app.js | 7 ++ .../test-applications/node-koa/index.js | 7 ++ .../test-applications/node-koa/package.json | 9 +++ .../node-profiling-cjs/index.ts | 7 ++ .../node-profiling-cjs/package.json | 9 +++ .../node-profiling-esm/index.ts | 7 ++ .../node-profiling-esm/package.json | 9 +++ .../nuxt-3-dynamic-import/package.json | 9 +++ .../sentry.server.config.ts | 7 ++ .../test-applications/nuxt-3-min/package.json | 9 +++ .../nuxt-3-min/sentry.server.config.ts | 7 ++ .../nuxt-3-top-level-import/package.json | 9 +++ .../sentry.server.config.ts | 7 ++ .../test-applications/nuxt-3/package.json | 11 ++- .../nuxt-3/sentry.server.config.ts | 7 ++ .../test-applications/nuxt-4/package.json | 11 ++- .../nuxt-4/sentry.server.config.ts | 7 ++ .../test-applications/nuxt-5/package.json | 13 +++- .../nuxt-5/sentry.server.config.ts | 7 ++ .../instrument.mjs | 7 ++ .../package.json | 9 +++ .../instrument.mjs | 7 ++ .../package.json | 9 ++- .../instrument.mjs | 7 ++ .../package.json | 11 +++ .../routes/performance/with-middleware.tsx | 3 +- .../react-router-7-framework/instrument.mjs | 7 ++ .../react-router-7-framework/package.json | 5 ++ .../performance/middleware.server.test.ts | 17 ++-- .../remix-server-timing/instrument.server.cjs | 7 ++ .../remix-server-timing/package.json | 9 +++ .../solidstart-dynamic-import/package.json | 9 +++ .../src/instrument.server.ts | 7 ++ .../solidstart-spa/package.json | 9 +++ .../solidstart-spa/src/instrument.server.ts | 7 ++ .../solidstart-top-level-import/package.json | 9 +++ .../src/instrument.server.ts | 7 ++ .../test-applications/solidstart/package.json | 9 +++ .../solidstart/src/instrument.server.ts | 7 ++ .../supabase-nextjs/package.json | 9 +++ .../supabase-nextjs/sentry.server.config.ts | 7 ++ .../sveltekit-2-kit-tracing/package.json | 9 +++ .../src/instrumentation.server.ts | 7 ++ .../sveltekit-2-svelte-5/package.json | 9 +++ .../sveltekit-2-svelte-5/src/hooks.server.ts | 7 ++ .../sveltekit-2.5.0-twp/package.json | 9 +++ .../sveltekit-2.5.0-twp/src/hooks.server.ts | 7 ++ .../sveltekit-2/package.json | 11 ++- .../sveltekit-2/src/hooks.server.ts | 7 ++ .../tanstackstart-react/instrument.server.mjs | 7 ++ .../tanstackstart-react/package.json | 5 ++ .../tsx-express/instrument.mjs | 7 ++ .../tsx-express/package.json | 9 +++ 166 files changed, 1342 insertions(+), 58 deletions(-) create mode 100644 dev-packages/e2e-tests/test-applications/aws-serverless/src/lambda-functions-npm/TracingCjs/sentry-trace-provider-auto.mjs create mode 100644 dev-packages/e2e-tests/test-applications/aws-serverless/src/lambda-functions-npm/TracingEsm/sentry-trace-provider-auto.mjs diff --git a/dev-packages/e2e-tests/test-applications/astro-4/package.json b/dev-packages/e2e-tests/test-applications/astro-4/package.json index 0afd444f6d3d..e5a3b963dc10 100644 --- a/dev-packages/e2e-tests/test-applications/astro-4/package.json +++ b/dev-packages/e2e-tests/test-applications/astro-4/package.json @@ -26,5 +26,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "astro-4 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/astro-4/sentry.server.config.js b/dev-packages/e2e-tests/test-applications/astro-4/sentry.server.config.js index 0662d678dc7c..2599cb4541e0 100644 --- a/dev-packages/e2e-tests/test-applications/astro-4/sentry.server.config.js +++ b/dev-packages/e2e-tests/test-applications/astro-4/sentry.server.config.js @@ -4,6 +4,13 @@ Sentry.init({ dsn: import.meta.env.PUBLIC_E2E_TEST_DSN, environment: 'qa', tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), spotlight: true, tunnel: 'http://localhost:3031/', // proxy server }); diff --git a/dev-packages/e2e-tests/test-applications/astro-5/package.json b/dev-packages/e2e-tests/test-applications/astro-5/package.json index 268ce9ed82ca..718c0edf4882 100644 --- a/dev-packages/e2e-tests/test-applications/astro-5/package.json +++ b/dev-packages/e2e-tests/test-applications/astro-5/package.json @@ -26,5 +26,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "astro-5 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/astro-5/sentry.server.config.js b/dev-packages/e2e-tests/test-applications/astro-5/sentry.server.config.js index 2b79ec0ed337..e429642768ed 100644 --- a/dev-packages/e2e-tests/test-applications/astro-5/sentry.server.config.js +++ b/dev-packages/e2e-tests/test-applications/astro-5/sentry.server.config.js @@ -4,5 +4,12 @@ Sentry.init({ dsn: import.meta.env.PUBLIC_E2E_TEST_DSN, environment: 'qa', tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server }); diff --git a/dev-packages/e2e-tests/test-applications/astro-6/package.json b/dev-packages/e2e-tests/test-applications/astro-6/package.json index 71a3182f4b7c..edf62e53bc50 100644 --- a/dev-packages/e2e-tests/test-applications/astro-6/package.json +++ b/dev-packages/e2e-tests/test-applications/astro-6/package.json @@ -9,7 +9,9 @@ "astro": "astro", "start": "node ./dist/server/entry.mjs", "test:build": "pnpm install && pnpm build", - "test:assert": "TEST_ENV=production playwright test" + "test:build:sentry-trace-provider": "E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "test:assert": "TEST_ENV=production playwright test", + "test:assert:sentry-trace-provider": "E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert" }, "dependencies": { "@astrojs/node": "^10.0.0", @@ -21,5 +23,14 @@ "volta": { "node": "22.22.0", "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "pnpm test:build:sentry-trace-provider", + "assert-command": "pnpm test:assert:sentry-trace-provider", + "label": "astro-6 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/astro-6/sentry.server.config.js b/dev-packages/e2e-tests/test-applications/astro-6/sentry.server.config.js index bc90470cef38..91af273dc4b7 100644 --- a/dev-packages/e2e-tests/test-applications/astro-6/sentry.server.config.js +++ b/dev-packages/e2e-tests/test-applications/astro-6/sentry.server.config.js @@ -4,6 +4,13 @@ Sentry.init({ dsn: import.meta.env.PUBLIC_E2E_TEST_DSN, environment: 'qa', tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server debug: true, }); diff --git a/dev-packages/e2e-tests/test-applications/aws-serverless/package.json b/dev-packages/e2e-tests/test-applications/aws-serverless/package.json index f74e7a670c50..1f214e20f4f9 100644 --- a/dev-packages/e2e-tests/test-applications/aws-serverless/package.json +++ b/dev-packages/e2e-tests/test-applications/aws-serverless/package.json @@ -21,5 +21,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "aws-serverless (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/aws-serverless/src/lambda-functions-npm/TracingCjs/sentry-trace-provider-auto.mjs b/dev-packages/e2e-tests/test-applications/aws-serverless/src/lambda-functions-npm/TracingCjs/sentry-trace-provider-auto.mjs new file mode 100644 index 000000000000..7aa885da2405 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/aws-serverless/src/lambda-functions-npm/TracingCjs/sentry-trace-provider-auto.mjs @@ -0,0 +1,14 @@ +import * as Sentry from '@sentry/aws-serverless'; + +const optionsWithTracingEnabled = process.env.SENTRY_TRACES_SAMPLE_RATE + ? { + tracesSampleRate: parseFloat(process.env.SENTRY_TRACES_SAMPLE_RATE), + } + : {}; + +Sentry.init({ + integrations: Sentry.getDefaultIntegrations(optionsWithTracingEnabled), + _experiments: { + useSentryTraceProvider: true, + }, +}); diff --git a/dev-packages/e2e-tests/test-applications/aws-serverless/src/lambda-functions-npm/TracingEsm/sentry-trace-provider-auto.mjs b/dev-packages/e2e-tests/test-applications/aws-serverless/src/lambda-functions-npm/TracingEsm/sentry-trace-provider-auto.mjs new file mode 100644 index 000000000000..7aa885da2405 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/aws-serverless/src/lambda-functions-npm/TracingEsm/sentry-trace-provider-auto.mjs @@ -0,0 +1,14 @@ +import * as Sentry from '@sentry/aws-serverless'; + +const optionsWithTracingEnabled = process.env.SENTRY_TRACES_SAMPLE_RATE + ? { + tracesSampleRate: parseFloat(process.env.SENTRY_TRACES_SAMPLE_RATE), + } + : {}; + +Sentry.init({ + integrations: Sentry.getDefaultIntegrations(optionsWithTracingEnabled), + _experiments: { + useSentryTraceProvider: true, + }, +}); diff --git a/dev-packages/e2e-tests/test-applications/aws-serverless/src/stack.ts b/dev-packages/e2e-tests/test-applications/aws-serverless/src/stack.ts index 63ab8a533e70..06bead99cb5b 100644 --- a/dev-packages/e2e-tests/test-applications/aws-serverless/src/stack.ts +++ b/dev-packages/e2e-tests/test-applications/aws-serverless/src/stack.ts @@ -9,6 +9,10 @@ import { execFileSync } from 'node:child_process'; const LAMBDA_FUNCTIONS_DIR = './src/lambda-functions-npm'; const LAMBDA_FUNCTION_TIMEOUT = 10; +const LAMBDA_AUTO_INIT_IMPORT = + process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? './sentry-trace-provider-auto.mjs' + : '@sentry/aws-serverless/awslambda-auto'; export const SAM_PORT = 3001; /** Match SAM / Docker to this machine so Apple Silicon does not mix arm64 images with an x86_64 template default. */ @@ -104,7 +108,7 @@ export class LocalLambdaStack extends Stack { SENTRY_DSN: dsn, SENTRY_TRACES_SAMPLE_RATE: 1.0, SENTRY_DEBUG: true, - NODE_OPTIONS: `--import=@sentry/aws-serverless/awslambda-auto`, + NODE_OPTIONS: `--import=${LAMBDA_AUTO_INIT_IMPORT}`, }, }, }, diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/instrument.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/instrument.mjs index b52053445456..290544241a70 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/instrument.mjs +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/instrument.mjs @@ -3,6 +3,13 @@ import * as process from 'process'; Sentry.init({ tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production! + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), environment: 'qa', // dynamic sampling bias to keep transactions dsn: process.env.E2E_TEST_DSN, tunnel: 'http://localhost:3031/', // proxy server diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/package.json b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/package.json index a413c5c31ba0..4ba9fa8cb99e 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/package.json +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/package.json @@ -48,5 +48,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "create-remix-app-express-vite-dev (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express/instrument.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-express/instrument.mjs index 0cbfe8ec4e5b..db001c8304ee 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express/instrument.mjs +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express/instrument.mjs @@ -3,6 +3,13 @@ import process from 'process'; Sentry.init({ tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production! + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), environment: 'qa', // dynamic sampling bias to keep transactions dsn: process.env.E2E_TEST_DSN, tunnel: 'http://localhost:3031/', // proxy server diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express/package.json b/dev-packages/e2e-tests/test-applications/create-remix-app-express/package.json index 2dc4f42dd34d..584521625cbe 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express/package.json +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express/package.json @@ -52,5 +52,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "create-remix-app-express (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-non-vite/app/entry.server.tsx b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-non-vite/app/entry.server.tsx index 41974897eeae..d3ec2c5e489d 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-non-vite/app/entry.server.tsx +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-non-vite/app/entry.server.tsx @@ -23,6 +23,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: 'http://localhost:3031/', // proxy server tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production! + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); const handleErrorImpl = () => { diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-non-vite/instrument.server.cjs b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-non-vite/instrument.server.cjs index 557ab8d18f17..7efece8057fb 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-non-vite/instrument.server.cjs +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-non-vite/instrument.server.cjs @@ -2,6 +2,13 @@ const Sentry = require('@sentry/remix'); Sentry.init({ tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production! + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), environment: 'qa', // dynamic sampling bias to keep transactions dsn: process.env.E2E_TEST_DSN, tunnel: 'http://localhost:3032/', // proxy server diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-non-vite/package.json b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-non-vite/package.json index 38a7e231ddf1..d2ad0a78b1ff 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2-non-vite/package.json +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-v2-non-vite/package.json @@ -35,5 +35,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "create-remix-app-v2-non-vite (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/instrument.server.cjs b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/instrument.server.cjs index 6d211cac4592..023cd91bd8cd 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/instrument.server.cjs +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/instrument.server.cjs @@ -2,6 +2,13 @@ const Sentry = require('@sentry/remix'); Sentry.init({ tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production! + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), environment: 'qa', // dynamic sampling bias to keep transactions dsn: process.env.E2E_TEST_DSN, tunnel: 'http://localhost:3031/', // proxy server diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/package.json b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/package.json index fd57d2920d5a..8d5734eac613 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/package.json +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/package.json @@ -38,5 +38,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "create-remix-app-v2 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/package.json b/dev-packages/e2e-tests/test-applications/elysia-node/package.json index fcd2a4e8f71b..84e363973b3a 100644 --- a/dev-packages/e2e-tests/test-applications/elysia-node/package.json +++ b/dev-packages/e2e-tests/test-applications/elysia-node/package.json @@ -8,7 +8,9 @@ "test": "playwright test", "clean": "npx rimraf node_modules pnpm-lock.yaml", "test:build": "pnpm install", - "test:assert": "pnpm test" + "test:build:sentry-trace-provider": "E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "test:assert": "pnpm test", + "test:assert:sentry-trace-provider": "E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert" }, "dependencies": { "@sentry/elysia": "file:../../packed/sentry-elysia-packed.tgz", @@ -22,5 +24,14 @@ "volta": { "extends": "../../package.json", "node": "24.11.0" + }, + "sentryTest": { + "variants": [ + { + "build-command": "pnpm test:build:sentry-trace-provider", + "assert-command": "pnpm test:assert:sentry-trace-provider", + "label": "elysia-node (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts b/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts index 375ca9a29c6d..365ced0c99ac 100644 --- a/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/elysia-node/src/app.ts @@ -8,6 +8,13 @@ Sentry.init({ tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, tracePropagationTargets: ['http://localhost:3030', '/external-allowed'], + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); const app = Sentry.withElysia(new Elysia({ adapter: node() })); diff --git a/dev-packages/e2e-tests/test-applications/hono-4/package.json b/dev-packages/e2e-tests/test-applications/hono-4/package.json index 2cec8fc563bb..2e91f861c35e 100644 --- a/dev-packages/e2e-tests/test-applications/hono-4/package.json +++ b/dev-packages/e2e-tests/test-applications/hono-4/package.json @@ -9,7 +9,11 @@ "dev:bun": "bun src/entry.bun.ts", "build": "wrangler deploy --dry-run", "test:build": "pnpm install && pnpm build", - "test:assert": "TEST_ENV=production playwright test" + "test:build:sentry-trace-provider": "E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "test:assert": "TEST_ENV=production playwright test", + "test:assert:node": "RUNTIME=node pnpm test:assert", + "test:assert:bun": "RUNTIME=bun pnpm test:assert", + "test:assert:sentry-trace-provider": "RUNTIME=node E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert" }, "dependencies": { "@sentry/bun": "latest || *", @@ -34,12 +38,17 @@ "sentryTest": { "variants": [ { - "assert-command": "RUNTIME=node pnpm test:assert", + "assert-command": "pnpm test:assert:node", "label": "hono-4 (node)" }, { - "assert-command": "RUNTIME=bun pnpm test:assert", + "assert-command": "pnpm test:assert:bun", "label": "hono-4 (bun)" + }, + { + "build-command": "pnpm test:build:sentry-trace-provider", + "assert-command": "pnpm test:assert:sentry-trace-provider", + "label": "hono-4 (node, sentry-trace-provider)" } ] } diff --git a/dev-packages/e2e-tests/test-applications/hono-4/src/instrument.node.ts b/dev-packages/e2e-tests/test-applications/hono-4/src/instrument.node.ts index 82f2a3864125..aa70d0a1ace9 100644 --- a/dev-packages/e2e-tests/test-applications/hono-4/src/instrument.node.ts +++ b/dev-packages/e2e-tests/test-applications/hono-4/src/instrument.node.ts @@ -4,5 +4,12 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, environment: 'qa', tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', }); diff --git a/dev-packages/e2e-tests/test-applications/nestjs-11/package.json b/dev-packages/e2e-tests/test-applications/nestjs-11/package.json index 2a230d9d5a68..3562a5beca55 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-11/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-11/package.json @@ -49,5 +49,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nestjs-11 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nestjs-11/src/instrument.ts b/dev-packages/e2e-tests/test-applications/nestjs-11/src/instrument.ts index 4f16ebb36d11..439b222f1229 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-11/src/instrument.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-11/src/instrument.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), transportOptions: { // We expect the app to send a lot of events in a short time bufferSize: 1000, diff --git a/dev-packages/e2e-tests/test-applications/nestjs-8/package.json b/dev-packages/e2e-tests/test-applications/nestjs-8/package.json index 3bd765774d2e..c38e541d37e5 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-8/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-8/package.json @@ -43,5 +43,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nestjs-8 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nestjs-8/src/instrument.ts b/dev-packages/e2e-tests/test-applications/nestjs-8/src/instrument.ts index 4f16ebb36d11..439b222f1229 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-8/src/instrument.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-8/src/instrument.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), transportOptions: { // We expect the app to send a lot of events in a short time bufferSize: 1000, diff --git a/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/package.json b/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/package.json index e429f8cbb328..263ac0775513 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/package.json @@ -45,5 +45,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nestjs-basic-with-graphql (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/src/instrument.ts b/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/src/instrument.ts index f1f4de865435..b7ca310219a8 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/src/instrument.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-basic-with-graphql/src/instrument.ts @@ -5,4 +5,11 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); diff --git a/dev-packages/e2e-tests/test-applications/nestjs-basic/package.json b/dev-packages/e2e-tests/test-applications/nestjs-basic/package.json index ebf0244bc276..078d9bf3b5f8 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-basic/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-basic/package.json @@ -44,5 +44,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nestjs-basic (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nestjs-basic/src/instrument.ts b/dev-packages/e2e-tests/test-applications/nestjs-basic/src/instrument.ts index 4f16ebb36d11..439b222f1229 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-basic/src/instrument.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-basic/src/instrument.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), transportOptions: { // We expect the app to send a lot of events in a short time bufferSize: 1000, diff --git a/dev-packages/e2e-tests/test-applications/nestjs-bullmq/package.json b/dev-packages/e2e-tests/test-applications/nestjs-bullmq/package.json index c4cfcd118f53..7a5351a1e945 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-bullmq/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-bullmq/package.json @@ -32,5 +32,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nestjs-bullmq (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nestjs-bullmq/src/instrument.ts b/dev-packages/e2e-tests/test-applications/nestjs-bullmq/src/instrument.ts index 4f16ebb36d11..439b222f1229 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-bullmq/src/instrument.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-bullmq/src/instrument.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), transportOptions: { // We expect the app to send a lot of events in a short time bufferSize: 1000, diff --git a/dev-packages/e2e-tests/test-applications/nestjs-distributed-tracing/package.json b/dev-packages/e2e-tests/test-applications/nestjs-distributed-tracing/package.json index c8fe82cff563..acb9281e1123 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-distributed-tracing/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-distributed-tracing/package.json @@ -42,5 +42,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nestjs-distributed-tracing (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nestjs-distributed-tracing/src/instrument.ts b/dev-packages/e2e-tests/test-applications/nestjs-distributed-tracing/src/instrument.ts index 1cf7b8ee1f76..34864c22d67f 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-distributed-tracing/src/instrument.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-distributed-tracing/src/instrument.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tracePropagationTargets: ['http://localhost:3030', '/external-allowed'], transportOptions: { // We expect the app to send a lot of events in a short time diff --git a/dev-packages/e2e-tests/test-applications/nestjs-fastify/package.json b/dev-packages/e2e-tests/test-applications/nestjs-fastify/package.json index 720cfe158eae..e644c81d64a9 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-fastify/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-fastify/package.json @@ -43,5 +43,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nestjs-fastify (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nestjs-fastify/src/instrument.ts b/dev-packages/e2e-tests/test-applications/nestjs-fastify/src/instrument.ts index 4f16ebb36d11..439b222f1229 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-fastify/src/instrument.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-fastify/src/instrument.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), transportOptions: { // We expect the app to send a lot of events in a short time bufferSize: 1000, diff --git a/dev-packages/e2e-tests/test-applications/nestjs-graphql/package.json b/dev-packages/e2e-tests/test-applications/nestjs-graphql/package.json index 05a38d691807..130d18ba33ce 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-graphql/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-graphql/package.json @@ -45,5 +45,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nestjs-graphql (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nestjs-graphql/src/instrument.ts b/dev-packages/e2e-tests/test-applications/nestjs-graphql/src/instrument.ts index f1f4de865435..b7ca310219a8 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-graphql/src/instrument.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-graphql/src/instrument.ts @@ -5,4 +5,11 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); diff --git a/dev-packages/e2e-tests/test-applications/nestjs-microservices/package.json b/dev-packages/e2e-tests/test-applications/nestjs-microservices/package.json index 4bfc4eee7710..3f0d8619ec21 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-microservices/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-microservices/package.json @@ -35,5 +35,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nestjs-microservices (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nestjs-microservices/src/instrument.ts b/dev-packages/e2e-tests/test-applications/nestjs-microservices/src/instrument.ts index e0a1cead1153..42a1c592640e 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-microservices/src/instrument.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-microservices/src/instrument.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), transportOptions: { bufferSize: 1000, }, diff --git a/dev-packages/e2e-tests/test-applications/nestjs-websockets/package.json b/dev-packages/e2e-tests/test-applications/nestjs-websockets/package.json index c859d4e49791..2860e378eacf 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-websockets/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-websockets/package.json @@ -30,5 +30,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nestjs-websockets (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nestjs-websockets/src/instrument.ts b/dev-packages/e2e-tests/test-applications/nestjs-websockets/src/instrument.ts index e0a1cead1153..42a1c592640e 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-websockets/src/instrument.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-websockets/src/instrument.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), transportOptions: { bufferSize: 1000, }, diff --git a/dev-packages/e2e-tests/test-applications/nestjs-with-submodules-decorator/package.json b/dev-packages/e2e-tests/test-applications/nestjs-with-submodules-decorator/package.json index 35ce0bc009e1..9b6a84f72ce3 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-with-submodules-decorator/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-with-submodules-decorator/package.json @@ -41,5 +41,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nestjs-with-submodules-decorator (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nestjs-with-submodules-decorator/src/instrument.ts b/dev-packages/e2e-tests/test-applications/nestjs-with-submodules-decorator/src/instrument.ts index 4f16ebb36d11..439b222f1229 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-with-submodules-decorator/src/instrument.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-with-submodules-decorator/src/instrument.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), transportOptions: { // We expect the app to send a lot of events in a short time bufferSize: 1000, diff --git a/dev-packages/e2e-tests/test-applications/nestjs-with-submodules/package.json b/dev-packages/e2e-tests/test-applications/nestjs-with-submodules/package.json index e9da4c97ae26..9351fffd671a 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-with-submodules/package.json +++ b/dev-packages/e2e-tests/test-applications/nestjs-with-submodules/package.json @@ -41,5 +41,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nestjs-with-submodules (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nestjs-with-submodules/src/instrument.ts b/dev-packages/e2e-tests/test-applications/nestjs-with-submodules/src/instrument.ts index 4f16ebb36d11..439b222f1229 100644 --- a/dev-packages/e2e-tests/test-applications/nestjs-with-submodules/src/instrument.ts +++ b/dev-packages/e2e-tests/test-applications/nestjs-with-submodules/src/instrument.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), transportOptions: { // We expect the app to send a lot of events in a short time bufferSize: 1000, diff --git a/dev-packages/e2e-tests/test-applications/nextjs-13/instrumentation.ts b/dev-packages/e2e-tests/test-applications/nextjs-13/instrumentation.ts index 180685d41b4a..c1f448b0a48a 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-13/instrumentation.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-13/instrumentation.ts @@ -7,6 +7,13 @@ export function register() { dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.NEXT_RUNTIME === 'nodejs' && process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), sendDefaultPii: true, transportOptions: { // We are doing a lot of events at once in this test app diff --git a/dev-packages/e2e-tests/test-applications/nextjs-13/package.json b/dev-packages/e2e-tests/test-applications/nextjs-13/package.json index f6137db6843c..82c9562d515c 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-13/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-13/package.json @@ -34,6 +34,13 @@ "build-command": "pnpm test:build-latest", "label": "nextjs-13 (latest)" } + ], + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-13 (sentry-trace-provider)" + } ] } } diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/instrumentation.ts b/dev-packages/e2e-tests/test-applications/nextjs-14/instrumentation.ts index 2dd920dfcc73..29b907f5c562 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-14/instrumentation.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-14/instrumentation.ts @@ -7,6 +7,13 @@ export function register() { dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, + ...(process.env.NEXT_RUNTIME === 'nodejs' && process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), sendDefaultPii: true, transportOptions: { // We are doing a lot of events at once in this test diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/package.json b/dev-packages/e2e-tests/test-applications/nextjs-14/package.json index 09a928eddfa0..bf64ca2ce398 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-14/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-14/package.json @@ -40,6 +40,13 @@ "build-command": "pnpm test:build-latest", "label": "nextjs-14 (latest)" } + ], + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-14 (sentry-trace-provider)" + } ] } } diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15-basepath/package.json b/dev-packages/e2e-tests/test-applications/nextjs-15-basepath/package.json index ce63c62aeefa..2c42348c803b 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15-basepath/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-15-basepath/package.json @@ -26,5 +26,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-15-basepath (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15-basepath/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-15-basepath/sentry.server.config.ts index 067d2ead0b8b..b7f15ef32945 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15-basepath/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-15-basepath/sentry.server.config.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), sendDefaultPii: true, transportOptions: { // We are doing a lot of events at once in this test diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15-intl/package.json b/dev-packages/e2e-tests/test-applications/nextjs-15-intl/package.json index d935f67fa39e..6bbf0dd6c927 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15-intl/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-15-intl/package.json @@ -27,5 +27,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-15-intl (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15-intl/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-15-intl/sentry.server.config.ts index 760b8b581a29..40be7c74bda7 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15-intl/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-15-intl/sentry.server.config.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN, tunnel: `http://localhost:3031/`, tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), sendDefaultPii: true, transportOptions: { bufferSize: 1000, diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15-t3/package.json b/dev-packages/e2e-tests/test-applications/nextjs-15-t3/package.json index 24fde175baea..2cfd893adcae 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15-t3/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-15-t3/package.json @@ -46,5 +46,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-15-t3 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15-t3/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-15-t3/sentry.server.config.ts index ad780407a5b7..5d5953afc52c 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15-t3/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-15-t3/sentry.server.config.ts @@ -5,4 +5,11 @@ Sentry.init({ dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/package.json b/dev-packages/e2e-tests/test-applications/nextjs-15/package.json index 25fc16f8702e..2cca87cd3542 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-15/package.json @@ -44,6 +44,13 @@ "assert-command": "pnpm test:prod-turbo && pnpm test:dev-turbo", "label": "nextjs-15 (turbo)" } + ], + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-15 (sentry-trace-provider)" + } ] } } diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-15/sentry.server.config.ts index e5306a66e579..8259b2755c02 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-15/sentry.server.config.ts @@ -6,6 +6,13 @@ Sentry.init({ tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, sendDefaultPii: true, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), transportOptions: { // We are doing a lot of events at once in this test bufferSize: 1000, diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/package.json b/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/package.json index 22beb292ca79..2035cfc1f4e6 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/package.json @@ -46,6 +46,13 @@ "extends": "../../package.json" }, "sentryTest": { - "//": "TODO: Add variants for webpack once supported" + "//": "TODO: Add variants for webpack once supported", + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-16-cacheComponents (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/sentry.server.config.ts index 08d5d580b314..d99e122d2e41 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/sentry.server.config.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), sendDefaultPii: true, // debug: true, integrations: [Sentry.vercelAIIntegration()], diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-streaming/package.json b/dev-packages/e2e-tests/test-applications/nextjs-16-streaming/package.json index 4fbc3bf64c27..79fd792e7a2b 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16-streaming/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-16-streaming/package.json @@ -37,5 +37,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-16-streaming (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-streaming/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-16-streaming/sentry.server.config.ts index d44e4da73818..b71872ae112b 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16-streaming/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-16-streaming/sentry.server.config.ts @@ -6,6 +6,13 @@ Sentry.init({ dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), sendDefaultPii: true, traceLifecycle: 'stream', integrations: [ diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-trailing-slash/package.json b/dev-packages/e2e-tests/test-applications/nextjs-16-trailing-slash/package.json index 98896eae5d1b..8d6e6c885928 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16-trailing-slash/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-16-trailing-slash/package.json @@ -37,6 +37,11 @@ { "build-command": "pnpm test:build-latest", "label": "nextjs-16-trailing-slash (latest, turbopack)" + }, + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-16-trailing-slash (sentry-trace-provider)" } ] } diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-trailing-slash/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-16-trailing-slash/sentry.server.config.ts index 85bd765c9c44..3f1ce6e53e7a 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16-trailing-slash/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-16-trailing-slash/sentry.server.config.ts @@ -5,5 +5,12 @@ Sentry.init({ dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), sendDefaultPii: true, }); diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-tunnel/package.json b/dev-packages/e2e-tests/test-applications/nextjs-16-tunnel/package.json index 7dfa8f923f6e..ca21224df739 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16-tunnel/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-16-tunnel/package.json @@ -57,6 +57,11 @@ "build-command": "pnpm test:build", "label": "nextjs-16-tunnel (turbopack)", "assert-command": "pnpm test:assert" + }, + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-16-tunnel (sentry-trace-provider)" } ] } diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-tunnel/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-16-tunnel/sentry.server.config.ts index 8ba3a3bf2faa..8ba93d326dc9 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16-tunnel/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-16-tunnel/sentry.server.config.ts @@ -6,6 +6,13 @@ Sentry.init({ dsn: 'https://public@o12345.ingest.us.sentry.io/67890', // No tunnel option - using tunnelRoute from withSentryConfig tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), sendDefaultPii: true, // debug: true, }); diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-userfeedback/package.json b/dev-packages/e2e-tests/test-applications/nextjs-16-userfeedback/package.json index b30636cd3576..e58498572ded 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16-userfeedback/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-16-userfeedback/package.json @@ -28,5 +28,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-16-userfeedback (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-userfeedback/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-16-userfeedback/sentry.server.config.ts index 1f1c7f5b0bcb..d80553929970 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16-userfeedback/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-16-userfeedback/sentry.server.config.ts @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), sendDefaultPii: true, transportOptions: { bufferSize: 1000, diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16/package.json b/dev-packages/e2e-tests/test-applications/nextjs-16/package.json index beda2252d915..b99f9e7a8d02 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-16/package.json @@ -62,6 +62,11 @@ { "build-command": "pnpm test:build-latest", "label": "nextjs-16 (latest, turbopack)" + }, + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-16 (sentry-trace-provider)" } ], "optionalVariants": [ diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-16/sentry.server.config.ts index 8428c75580ba..88a153fa7ecd 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-16/sentry.server.config.ts @@ -7,6 +7,13 @@ Sentry.init({ tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, sendDefaultPii: true, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), // debug: true, integrations: [Sentry.vercelAIIntegration(), Sentry.nodeRuntimeMetricsIntegration({ collectionIntervalMs: 1_000 })], streamGenAiSpans: true, diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/instrumentation.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/instrumentation.ts index a95bb9ee95ee..8c03c7883beb 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/instrumentation.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/instrumentation.ts @@ -8,6 +8,13 @@ export function register() { tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, sendDefaultPii: true, + ...(process.env.NEXT_RUNTIME === 'nodejs' && process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), transportOptions: { // We are doing a lot of events at once in this test bufferSize: 1000, diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json index cb7927e9b0d8..7f1be88ebe99 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json @@ -41,6 +41,11 @@ { "build-command": "pnpm test:build-15", "label": "nextjs-app-dir (next@15)" + }, + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-app-dir (sentry-trace-provider)" } ] } diff --git a/dev-packages/e2e-tests/test-applications/nextjs-orpc/package.json b/dev-packages/e2e-tests/test-applications/nextjs-orpc/package.json index 21f835e2ecd4..de89d8aa8c42 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-orpc/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-orpc/package.json @@ -43,6 +43,13 @@ "extends": "../../package.json" }, "sentryTest": { - "optional": true + "optional": true, + "optionalVariants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-orpc (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nextjs-orpc/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-orpc/sentry.server.config.ts index ad780407a5b7..5d5953afc52c 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-orpc/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-orpc/sentry.server.config.ts @@ -5,4 +5,11 @@ Sentry.init({ dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); diff --git a/dev-packages/e2e-tests/test-applications/nextjs-pages-dir/instrumentation.ts b/dev-packages/e2e-tests/test-applications/nextjs-pages-dir/instrumentation.ts index a95bb9ee95ee..8c03c7883beb 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-pages-dir/instrumentation.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-pages-dir/instrumentation.ts @@ -8,6 +8,13 @@ export function register() { tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, sendDefaultPii: true, + ...(process.env.NEXT_RUNTIME === 'nodejs' && process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), transportOptions: { // We are doing a lot of events at once in this test bufferSize: 1000, diff --git a/dev-packages/e2e-tests/test-applications/nextjs-pages-dir/package.json b/dev-packages/e2e-tests/test-applications/nextjs-pages-dir/package.json index f677e02dd954..d8cfe9d59e16 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-pages-dir/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-pages-dir/package.json @@ -42,6 +42,11 @@ { "build-command": "pnpm test:build-15", "label": "nextjs-pages-dir (next@15)" + }, + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nextjs-pages-dir (sentry-trace-provider)" } ], "optionalVariants": [] diff --git a/dev-packages/e2e-tests/test-applications/nitro-3/instrument.mjs b/dev-packages/e2e-tests/test-applications/nitro-3/instrument.mjs index 53b80d309a5b..cc5fa7028c51 100644 --- a/dev-packages/e2e-tests/test-applications/nitro-3/instrument.mjs +++ b/dev-packages/e2e-tests/test-applications/nitro-3/instrument.mjs @@ -5,4 +5,11 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); diff --git a/dev-packages/e2e-tests/test-applications/nitro-3/package.json b/dev-packages/e2e-tests/test-applications/nitro-3/package.json index 85713dccc138..58c8b9f5b14e 100644 --- a/dev-packages/e2e-tests/test-applications/nitro-3/package.json +++ b/dev-packages/e2e-tests/test-applications/nitro-3/package.json @@ -25,5 +25,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nitro-3 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-connect/package.json b/dev-packages/e2e-tests/test-applications/node-connect/package.json index 729cfbe6c095..8e4d515b6765 100644 --- a/dev-packages/e2e-tests/test-applications/node-connect/package.json +++ b/dev-packages/e2e-tests/test-applications/node-connect/package.json @@ -24,5 +24,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-connect (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-connect/src/app.ts b/dev-packages/e2e-tests/test-applications/node-connect/src/app.ts index 375554845d6f..a3026c71a244 100644 --- a/dev-packages/e2e-tests/test-applications/node-connect/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-connect/src/app.ts @@ -6,6 +6,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, integrations: [], tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server tracePropagationTargets: ['http://localhost:3030', '/external-allowed'], }); diff --git a/dev-packages/e2e-tests/test-applications/node-connect/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/node-connect/tests/transactions.test.ts index 9b06ad052f58..9dca6119b360 100644 --- a/dev-packages/e2e-tests/test-applications/node-connect/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-connect/tests/transactions.test.ts @@ -1,6 +1,8 @@ import { expect, test } from '@playwright/test'; import { waitForTransaction } from '@sentry-internal/test-utils'; +const useSentryTraceProvider = process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1'; + test('Sends an API route transaction', async ({ baseURL }) => { const pageloadTransactionEventPromise = waitForTransaction('node-connect', transactionEvent => { return ( @@ -54,41 +56,51 @@ test('Sends an API route transaction', async ({ baseURL }) => { origin: 'auto.http.otel.http', }); + const manualSpanExpectation = { + data: { + 'sentry.origin': 'manual', + }, + description: 'test-span', + parent_span_id: expect.stringMatching(/[a-f0-9]{16}/), + span_id: expect.stringMatching(/[a-f0-9]{16}/), + start_timestamp: expect.any(Number), + status: 'ok', + timestamp: expect.any(Number), + trace_id: expect.stringMatching(/[a-f0-9]{32}/), + origin: 'manual', + }; + + const connectSpanExpectation = { + data: { + 'sentry.origin': 'auto.http.otel.connect', + 'sentry.op': 'request_handler.connect', + 'http.route': '/test-transaction', + 'connect.type': 'request_handler', + 'connect.name': '/test-transaction', + }, + op: 'request_handler.connect', + description: '/test-transaction', + parent_span_id: expect.stringMatching(/[a-f0-9]{16}/), + span_id: expect.stringMatching(/[a-f0-9]{16}/), + start_timestamp: expect.any(Number), + status: 'ok', + timestamp: expect.any(Number), + trace_id: expect.stringMatching(/[a-f0-9]{32}/), + origin: 'auto.http.otel.connect', + }; + expect(transactionEvent).toEqual( expect.objectContaining({ - spans: [ - { - data: { - 'sentry.origin': 'manual', - }, - description: 'test-span', - parent_span_id: expect.stringMatching(/[a-f0-9]{16}/), - span_id: expect.stringMatching(/[a-f0-9]{16}/), - start_timestamp: expect.any(Number), - status: 'ok', - timestamp: expect.any(Number), - trace_id: expect.stringMatching(/[a-f0-9]{32}/), - origin: 'manual', - }, - { - data: { - 'sentry.origin': 'auto.http.otel.connect', - 'sentry.op': 'request_handler.connect', - 'http.route': '/test-transaction', - 'connect.type': 'request_handler', - 'connect.name': '/test-transaction', - }, - op: 'request_handler.connect', - description: '/test-transaction', - parent_span_id: expect.stringMatching(/[a-f0-9]{16}/), - span_id: expect.stringMatching(/[a-f0-9]{16}/), - start_timestamp: expect.any(Number), - status: 'ok', - timestamp: expect.any(Number), - trace_id: expect.stringMatching(/[a-f0-9]{32}/), - origin: 'auto.http.otel.connect', - }, - ], + spans: useSentryTraceProvider + ? [ + // TODO: Investigate whether transaction span array ordering is expected to stay + // compatible with the legacy OTel exporter path. SentryTraceProvider serializes + // native child spans in start/tree order, so the Connect handler span appears + // before the manual span created inside it. + connectSpanExpectation, + manualSpanExpectation, + ] + : [manualSpanExpectation, connectSpanExpectation], transaction: 'GET /test-transaction', type: 'transaction', transaction_info: { diff --git a/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/package.json b/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/package.json index 125372c4501a..696dddbaeed0 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/package.json @@ -19,5 +19,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-express-cjs-preload (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/src/app.js b/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/src/app.js index b41d99ab6440..3f6278256b00 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/src/app.js +++ b/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/src/app.js @@ -42,6 +42,13 @@ async function run() { dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); app.listen(port, () => { diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/package.json b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/package.json index a2d2c720e92a..5fb064435314 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/package.json @@ -19,5 +19,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-express-esm-loader (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/src/instrument.mjs b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/src/instrument.mjs index 544c773e5e7c..f6afd668b278 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/src/instrument.mjs +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/src/instrument.mjs @@ -5,4 +5,11 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-preload/package.json b/dev-packages/e2e-tests/test-applications/node-express-esm-preload/package.json index 4a602b6bd304..6397a953d3c6 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-preload/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-preload/package.json @@ -19,5 +19,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-express-esm-preload (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-preload/src/app.mjs b/dev-packages/e2e-tests/test-applications/node-express-esm-preload/src/app.mjs index cc680866ab1a..69e4f57d5783 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-preload/src/app.mjs +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-preload/src/app.mjs @@ -57,6 +57,13 @@ async function run() { dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); app.listen(port, () => { diff --git a/dev-packages/e2e-tests/test-applications/node-express-incorrect-instrumentation/package.json b/dev-packages/e2e-tests/test-applications/node-express-incorrect-instrumentation/package.json index 84afe281c642..0f98c5dadf89 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-incorrect-instrumentation/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-incorrect-instrumentation/package.json @@ -26,5 +26,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-express-incorrect-instrumentation (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-express-incorrect-instrumentation/src/app.ts b/dev-packages/e2e-tests/test-applications/node-express-incorrect-instrumentation/src/app.ts index 2ab5d1ace5a0..41c28299f819 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-incorrect-instrumentation/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-express-incorrect-instrumentation/src/app.ts @@ -18,6 +18,13 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); app.get('/test-exception/:id', function (req, _res) { diff --git a/dev-packages/e2e-tests/test-applications/node-express-mcp-v2/instrument.mjs b/dev-packages/e2e-tests/test-applications/node-express-mcp-v2/instrument.mjs index f3dd95215d03..39e5b0f5bdaf 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-mcp-v2/instrument.mjs +++ b/dev-packages/e2e-tests/test-applications/node-express-mcp-v2/instrument.mjs @@ -6,4 +6,11 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); diff --git a/dev-packages/e2e-tests/test-applications/node-express-mcp-v2/package.json b/dev-packages/e2e-tests/test-applications/node-express-mcp-v2/package.json index 4460adbd034c..52cada285930 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-mcp-v2/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-mcp-v2/package.json @@ -32,6 +32,13 @@ "extends": "../../package.json" }, "sentryTest": { - "optional": true + "optional": true, + "optionalVariants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-express-mcp-v2 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/package.json b/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/package.json index e5ec85096dce..b0f57c15c571 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/package.json @@ -24,6 +24,13 @@ "extends": "../../package.json" }, "sentryTest": { - "optional": true + "optional": true, + "optionalVariants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-express-send-to-sentry (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/src/app.ts b/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/src/app.ts index ca5d61f742d9..fa39a66779f7 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/src/app.ts @@ -7,6 +7,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, includeLocalVariables: true, tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), beforeSendTransaction(event) { lastTransactionId = event.event_id; return event; diff --git a/dev-packages/e2e-tests/test-applications/node-express-streaming/package.json b/dev-packages/e2e-tests/test-applications/node-express-streaming/package.json index 77124040ff6f..44783dee360e 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-streaming/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-streaming/package.json @@ -31,5 +31,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-express-streaming (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-express-streaming/src/app.ts b/dev-packages/e2e-tests/test-applications/node-express-streaming/src/app.ts index 5a0d1afa4141..49cfb19d9a19 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-streaming/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-express-streaming/src/app.ts @@ -7,6 +7,13 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), enableLogs: true, traceLifecycle: 'stream', integrations: [ diff --git a/dev-packages/e2e-tests/test-applications/node-express-v5/package.json b/dev-packages/e2e-tests/test-applications/node-express-v5/package.json index cf33b86e8669..0a7a415876ce 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-v5/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-v5/package.json @@ -31,5 +31,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-express-v5 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-express-v5/src/app.ts b/dev-packages/e2e-tests/test-applications/node-express-v5/src/app.ts index 9a7f6f07d8bc..ef59f1449d5b 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-v5/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-express-v5/src/app.ts @@ -14,6 +14,13 @@ Sentry.init({ tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, enableLogs: true, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), integrations: [Sentry.nodeRuntimeMetricsIntegration({ collectionIntervalMs: 1_000 })], }); diff --git a/dev-packages/e2e-tests/test-applications/node-express/package.json b/dev-packages/e2e-tests/test-applications/node-express/package.json index 4d2ad1833a58..78580049f846 100644 --- a/dev-packages/e2e-tests/test-applications/node-express/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express/package.json @@ -31,5 +31,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-express (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-express/src/app.ts b/dev-packages/e2e-tests/test-applications/node-express/src/app.ts index dc755f95d062..f429777e6767 100644 --- a/dev-packages/e2e-tests/test-applications/node-express/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-express/src/app.ts @@ -14,6 +14,13 @@ Sentry.init({ tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, enableLogs: true, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), integrations: [ Sentry.nativeNodeFetchIntegration({ headersToSpanAttributes: { diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-3/package.json b/dev-packages/e2e-tests/test-applications/node-fastify-3/package.json index 3fa36adbbbd5..c6e944333a65 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-3/package.json +++ b/dev-packages/e2e-tests/test-applications/node-fastify-3/package.json @@ -25,5 +25,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-fastify-3 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-3/src/app-handle-error-override.ts b/dev-packages/e2e-tests/test-applications/node-fastify-3/src/app-handle-error-override.ts index 378ef99fa309..3f7b06aafe11 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-3/src/app-handle-error-override.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify-3/src/app-handle-error-override.ts @@ -25,6 +25,13 @@ Sentry.init({ }), ], tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server tracePropagationTargets: ['http://localhost:3030', '/external-allowed'], }); diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-3/src/app.ts b/dev-packages/e2e-tests/test-applications/node-fastify-3/src/app.ts index 5b4a2f0d16ac..ad057a278584 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-3/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify-3/src/app.ts @@ -31,6 +31,13 @@ Sentry.init({ }), ], tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server tracePropagationTargets: ['http://localhost:3030', '/external-allowed'], }); diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-4/package.json b/dev-packages/e2e-tests/test-applications/node-fastify-4/package.json index 086ec85fac7a..c43933b8baae 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-4/package.json +++ b/dev-packages/e2e-tests/test-applications/node-fastify-4/package.json @@ -25,5 +25,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-fastify-4 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-4/src/app-handle-error-override.ts b/dev-packages/e2e-tests/test-applications/node-fastify-4/src/app-handle-error-override.ts index 72270efc05de..0287292a710b 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-4/src/app-handle-error-override.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify-4/src/app-handle-error-override.ts @@ -25,6 +25,13 @@ Sentry.init({ }), ], tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server tracePropagationTargets: ['http://localhost:3030', '/external-allowed'], }); diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-4/src/app.ts b/dev-packages/e2e-tests/test-applications/node-fastify-4/src/app.ts index 1c428c0486f9..47a98e1a9964 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-4/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify-4/src/app.ts @@ -30,6 +30,13 @@ Sentry.init({ }), ], tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server tracePropagationTargets: ['http://localhost:3030', '/external-allowed'], }); diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-5/package.json b/dev-packages/e2e-tests/test-applications/node-fastify-5/package.json index dc0fa7770c70..92163b2552ef 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-5/package.json +++ b/dev-packages/e2e-tests/test-applications/node-fastify-5/package.json @@ -25,5 +25,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-fastify-5 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app-handle-error-override.ts b/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app-handle-error-override.ts index 91f0353816bb..39921c6b6ecc 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app-handle-error-override.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app-handle-error-override.ts @@ -25,6 +25,13 @@ Sentry.init({ }), ], tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server tracePropagationTargets: ['http://localhost:3030', '/external-allowed'], }); diff --git a/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app.ts b/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app.ts index 610a42f6fc00..71a5c0cd8038 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify-5/src/app.ts @@ -35,6 +35,13 @@ Sentry.init({ }), ], tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server tracePropagationTargets: ['http://localhost:3030', '/external-allowed'], }); diff --git a/dev-packages/e2e-tests/test-applications/node-firebase/firestore-app/src/init.ts b/dev-packages/e2e-tests/test-applications/node-firebase/firestore-app/src/init.ts index c3b4a642375a..13c387c15520 100644 --- a/dev-packages/e2e-tests/test-applications/node-firebase/firestore-app/src/init.ts +++ b/dev-packages/e2e-tests/test-applications/node-firebase/firestore-app/src/init.ts @@ -4,6 +4,13 @@ Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', release: '1.0', tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), integrations: [Sentry.firebaseIntegration()], defaultIntegrations: false, tunnel: `http://localhost:3031/`, // proxy server diff --git a/dev-packages/e2e-tests/test-applications/node-firebase/functions/src/init.ts b/dev-packages/e2e-tests/test-applications/node-firebase/functions/src/init.ts index c3b4a642375a..13c387c15520 100644 --- a/dev-packages/e2e-tests/test-applications/node-firebase/functions/src/init.ts +++ b/dev-packages/e2e-tests/test-applications/node-firebase/functions/src/init.ts @@ -4,6 +4,13 @@ Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', release: '1.0', tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), integrations: [Sentry.firebaseIntegration()], defaultIntegrations: false, tunnel: `http://localhost:3031/`, // proxy server diff --git a/dev-packages/e2e-tests/test-applications/node-firebase/package.json b/dev-packages/e2e-tests/test-applications/node-firebase/package.json index a1d4965e9745..0243e906cb6e 100644 --- a/dev-packages/e2e-tests/test-applications/node-firebase/package.json +++ b/dev-packages/e2e-tests/test-applications/node-firebase/package.json @@ -26,5 +26,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-firebase (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-hapi/package.json b/dev-packages/e2e-tests/test-applications/node-hapi/package.json index ae87544644bf..e5675084d44a 100644 --- a/dev-packages/e2e-tests/test-applications/node-hapi/package.json +++ b/dev-packages/e2e-tests/test-applications/node-hapi/package.json @@ -21,5 +21,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-hapi (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-hapi/src/app.js b/dev-packages/e2e-tests/test-applications/node-hapi/src/app.js index 8b68e8412aba..663c0086609f 100644 --- a/dev-packages/e2e-tests/test-applications/node-hapi/src/app.js +++ b/dev-packages/e2e-tests/test-applications/node-hapi/src/app.js @@ -7,6 +7,13 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); const Hapi = require('@hapi/hapi'); diff --git a/dev-packages/e2e-tests/test-applications/node-koa/index.js b/dev-packages/e2e-tests/test-applications/node-koa/index.js index 9e800a4fcc99..35b705c2a075 100644 --- a/dev-packages/e2e-tests/test-applications/node-koa/index.js +++ b/dev-packages/e2e-tests/test-applications/node-koa/index.js @@ -7,6 +7,13 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tracePropagationTargets: ['http://localhost:3030', 'external-allowed'], }); diff --git a/dev-packages/e2e-tests/test-applications/node-koa/package.json b/dev-packages/e2e-tests/test-applications/node-koa/package.json index f4ef47cd0940..7c22dfe4df57 100644 --- a/dev-packages/e2e-tests/test-applications/node-koa/package.json +++ b/dev-packages/e2e-tests/test-applications/node-koa/package.json @@ -23,5 +23,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-koa (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-profiling-cjs/index.ts b/dev-packages/e2e-tests/test-applications/node-profiling-cjs/index.ts index e956a1d9de33..85da32bd4e9d 100644 --- a/dev-packages/e2e-tests/test-applications/node-profiling-cjs/index.ts +++ b/dev-packages/e2e-tests/test-applications/node-profiling-cjs/index.ts @@ -7,6 +7,13 @@ Sentry.init({ dsn: 'https://7fa19397baaf433f919fbe02228d5470@o1137848.ingest.sentry.io/6625302', integrations: [nodeProfilingIntegration()], tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), profilesSampleRate: 1.0, }); diff --git a/dev-packages/e2e-tests/test-applications/node-profiling-cjs/package.json b/dev-packages/e2e-tests/test-applications/node-profiling-cjs/package.json index b136ea49dd4c..cc3c3a4e246d 100644 --- a/dev-packages/e2e-tests/test-applications/node-profiling-cjs/package.json +++ b/dev-packages/e2e-tests/test-applications/node-profiling-cjs/package.json @@ -19,5 +19,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-profiling-cjs (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/node-profiling-esm/index.ts b/dev-packages/e2e-tests/test-applications/node-profiling-esm/index.ts index e956a1d9de33..85da32bd4e9d 100644 --- a/dev-packages/e2e-tests/test-applications/node-profiling-esm/index.ts +++ b/dev-packages/e2e-tests/test-applications/node-profiling-esm/index.ts @@ -7,6 +7,13 @@ Sentry.init({ dsn: 'https://7fa19397baaf433f919fbe02228d5470@o1137848.ingest.sentry.io/6625302', integrations: [nodeProfilingIntegration()], tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), profilesSampleRate: 1.0, }); diff --git a/dev-packages/e2e-tests/test-applications/node-profiling-esm/package.json b/dev-packages/e2e-tests/test-applications/node-profiling-esm/package.json index c7e5c39b9807..cec0c2a9d176 100644 --- a/dev-packages/e2e-tests/test-applications/node-profiling-esm/package.json +++ b/dev-packages/e2e-tests/test-applications/node-profiling-esm/package.json @@ -19,5 +19,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "node-profiling-esm (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3-dynamic-import/package.json b/dev-packages/e2e-tests/test-applications/nuxt-3-dynamic-import/package.json index a61e1da1bdcd..a472a47537f9 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3-dynamic-import/package.json +++ b/dev-packages/e2e-tests/test-applications/nuxt-3-dynamic-import/package.json @@ -23,5 +23,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nuxt-3-dynamic-import (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3-dynamic-import/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nuxt-3-dynamic-import/sentry.server.config.ts index 729b2296c683..eb662e854b22 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3-dynamic-import/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-3-dynamic-import/sentry.server.config.ts @@ -4,5 +4,12 @@ Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', environment: 'qa', // dynamic sampling bias to keep transactions tracesSampleRate: 1.0, // Capture 100% of the transactions + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server }); diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3-min/package.json b/dev-packages/e2e-tests/test-applications/nuxt-3-min/package.json index 73b0c59e8a24..cfdefe2ad209 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3-min/package.json +++ b/dev-packages/e2e-tests/test-applications/nuxt-3-min/package.json @@ -33,5 +33,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nuxt-3-min (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3-min/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nuxt-3-min/sentry.server.config.ts index 729b2296c683..eb662e854b22 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3-min/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-3-min/sentry.server.config.ts @@ -4,5 +4,12 @@ Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', environment: 'qa', // dynamic sampling bias to keep transactions tracesSampleRate: 1.0, // Capture 100% of the transactions + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server }); diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3-top-level-import/package.json b/dev-packages/e2e-tests/test-applications/nuxt-3-top-level-import/package.json index 21acb5644735..770b7dbb125b 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3-top-level-import/package.json +++ b/dev-packages/e2e-tests/test-applications/nuxt-3-top-level-import/package.json @@ -24,5 +24,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "nuxt-3-top-level-import (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3-top-level-import/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nuxt-3-top-level-import/sentry.server.config.ts index f08dea23ae03..33cd7fc4928d 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3-top-level-import/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-3-top-level-import/sentry.server.config.ts @@ -4,6 +4,13 @@ Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', environment: 'qa', // dynamic sampling bias to keep transactions tracesSampleRate: 1.0, // Capture 100% of the transactions + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server debug: !!process.env.DEBUG, }); diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3/package.json b/dev-packages/e2e-tests/test-applications/nuxt-3/package.json index b7481e044b3e..dd2d3f7a98b9 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3/package.json +++ b/dev-packages/e2e-tests/test-applications/nuxt-3/package.json @@ -12,8 +12,10 @@ "clean": "npx nuxi cleanup", "test": "playwright test", "test:build": "pnpm install && pnpm build", + "test:build:sentry-trace-provider": "E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", "test:build-canary": "pnpm add nuxt@npm:nuxt-nightly@3x && pnpm add nitropack@npm:nitropack-nightly@latest && pnpm install --force && pnpm build", - "test:assert": "pnpm test" + "test:assert": "pnpm test", + "test:assert:sentry-trace-provider": "E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert" }, "dependencies": { "@sentry/nuxt": "file:../../packed/sentry-nuxt-packed.tgz", @@ -30,6 +32,13 @@ "build-command": "pnpm test:build-canary", "label": "nuxt-3 (canary)" } + ], + "variants": [ + { + "build-command": "pnpm test:build:sentry-trace-provider", + "assert-command": "pnpm test:assert:sentry-trace-provider", + "label": "nuxt-3 (sentry-trace-provider)" + } ] }, "volta": { diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nuxt-3/sentry.server.config.ts index e04331934f99..a3ee4c3a9ced 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-3/sentry.server.config.ts @@ -4,6 +4,13 @@ Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', environment: 'qa', // dynamic sampling bias to keep transactions tracesSampleRate: 1.0, // Capture 100% of the transactions + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server enableNitroErrorHandler: false, // Error handler is defined in server/plugins/customNitroErrorHandler.ts }); diff --git a/dev-packages/e2e-tests/test-applications/nuxt-4/package.json b/dev-packages/e2e-tests/test-applications/nuxt-4/package.json index 02477111483d..cb6d446911b2 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-4/package.json +++ b/dev-packages/e2e-tests/test-applications/nuxt-4/package.json @@ -14,8 +14,10 @@ "test:prod": "TEST_ENV=production playwright test", "test:dev": "bash ./nuxt-start-dev-server.bash && TEST_ENV=development playwright test environment", "test:build": "pnpm install && pnpm build", + "test:build:sentry-trace-provider": "E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", "test:build-canary": "pnpm add nuxt@npm:nuxt-nightly@latest && pnpm add nitropack@npm:nitropack-nightly@latest && pnpm install --force && pnpm build", - "test:assert": "pnpm test:prod && pnpm test:dev" + "test:assert": "pnpm test:prod && pnpm test:dev", + "test:assert:sentry-trace-provider": "E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert" }, "dependencies": { "@pinia/nuxt": "^0.5.5", @@ -36,6 +38,13 @@ "build-command": "pnpm test:build-canary", "label": "nuxt-4 (canary)" } + ], + "variants": [ + { + "build-command": "pnpm test:build:sentry-trace-provider", + "assert-command": "pnpm test:assert:sentry-trace-provider", + "label": "nuxt-4 (sentry-trace-provider)" + } ] } } diff --git a/dev-packages/e2e-tests/test-applications/nuxt-4/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nuxt-4/sentry.server.config.ts index 26519911072b..228f0dcccbd1 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-4/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-4/sentry.server.config.ts @@ -3,5 +3,12 @@ import * as Sentry from '@sentry/nuxt'; Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', tracesSampleRate: 1.0, // Capture 100% of the transactions + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server }); diff --git a/dev-packages/e2e-tests/test-applications/nuxt-5/package.json b/dev-packages/e2e-tests/test-applications/nuxt-5/package.json index bff128f66ed9..2428915bf3f6 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-5/package.json +++ b/dev-packages/e2e-tests/test-applications/nuxt-5/package.json @@ -14,8 +14,10 @@ "test:prod": "TEST_ENV=production playwright test", "test:dev": "bash ./nuxt-start-dev-server.bash && TEST_ENV=development playwright test environment", "test:build": "pnpm install && pnpm build", + "test:build:sentry-trace-provider": "E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", "test:build-canary": "pnpm add nuxt@npm:nuxt-nightly@latest && pnpm add nitro@npm:nitro-nightly@latest && pnpm install --force && pnpm build", - "test:assert": "pnpm test:prod && pnpm test:dev" + "test:assert": "pnpm test:prod && pnpm test:dev", + "test:assert:sentry-trace-provider": "E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert" }, "//": [ "Currently, we need to install the latest version of Nitro and the Nuxt nightlies as those contain Nuxt v5", @@ -32,7 +34,14 @@ "@sentry-internal/test-utils": "link:../../../test-utils" }, "sentryTest": { - "optional": true + "optional": true, + "optionalVariants": [ + { + "build-command": "pnpm test:build:sentry-trace-provider", + "assert-command": "pnpm test:assert:sentry-trace-provider", + "label": "nuxt-5 (sentry-trace-provider)" + } + ] }, "volta": { "extends": "../../package.json", diff --git a/dev-packages/e2e-tests/test-applications/nuxt-5/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/nuxt-5/sentry.server.config.ts index 26519911072b..228f0dcccbd1 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-5/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-5/sentry.server.config.ts @@ -3,5 +3,12 @@ import * as Sentry from '@sentry/nuxt'; Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', tracesSampleRate: 1.0, // Capture 100% of the transactions + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server }); diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework-custom/instrument.mjs b/dev-packages/e2e-tests/test-applications/react-router-7-framework-custom/instrument.mjs index c16240141b6d..48a130bd25d6 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework-custom/instrument.mjs +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework-custom/instrument.mjs @@ -4,5 +4,12 @@ Sentry.init({ dsn: 'https://username@domain/123', environment: 'qa', // dynamic sampling bias to keep transactions tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: `http://localhost:3031/`, // proxy server }); diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework-custom/package.json b/dev-packages/e2e-tests/test-applications/react-router-7-framework-custom/package.json index 20fdccf46f4c..4c76a7bc3eb6 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework-custom/package.json +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework-custom/package.json @@ -54,5 +54,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "react-router-7-framework-custom (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/instrument.mjs b/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/instrument.mjs index bb1dad2e5da9..22e362a9b1bd 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/instrument.mjs +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/instrument.mjs @@ -6,5 +6,12 @@ Sentry.init({ dsn: 'https://username@domain/123', environment: 'qa', // dynamic sampling bias to keep transactions tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: `http://localhost:3031/`, // proxy server }); diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/package.json b/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/package.json index b7e2fd8de655..0b4852abbd0c 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/package.json +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/package.json @@ -56,6 +56,13 @@ "extends": "../../package.json" }, "sentryTest": { - "optional": true + "optional": true, + "optionalVariants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "react-router-7-framework-instrumentation (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework-node-20-18/instrument.mjs b/dev-packages/e2e-tests/test-applications/react-router-7-framework-node-20-18/instrument.mjs index 48e4b7b61ff3..aef6f9cb866e 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework-node-20-18/instrument.mjs +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework-node-20-18/instrument.mjs @@ -4,5 +4,12 @@ Sentry.init({ dsn: 'https://username@domain/123', environment: 'qa', // dynamic sampling bias to keep transactions tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: `http://localhost:3031/`, // proxy server, }); diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework-node-20-18/package.json b/dev-packages/e2e-tests/test-applications/react-router-7-framework-node-20-18/package.json index 65f4a96b0165..91b44e1e4aac 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework-node-20-18/package.json +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework-node-20-18/package.json @@ -30,7 +30,9 @@ "typecheck": "react-router typegen && tsc", "clean": "npx rimraf node_modules pnpm-lock.yaml", "test:build": "pnpm install && pnpm build", + "test:build:sentry-trace-provider": "E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", "test:assert": "pnpm test:ts && pnpm test:playwright", + "test:assert:sentry-trace-provider": "E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", "test:ts": "pnpm typecheck", "test:playwright": "playwright test" }, @@ -60,5 +62,14 @@ "overrides": { "p-map": "^4.0.0" } + }, + "sentryTest": { + "variants": [ + { + "build-command": "pnpm test:build:sentry-trace-provider", + "assert-command": "pnpm test:assert:sentry-trace-provider", + "label": "react-router-7-framework-node-20-18 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework/app/routes/performance/with-middleware.tsx b/dev-packages/e2e-tests/test-applications/react-router-7-framework/app/routes/performance/with-middleware.tsx index c86f78e17164..e0cd8c004cf5 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework/app/routes/performance/with-middleware.tsx +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework/app/routes/performance/with-middleware.tsx @@ -12,7 +12,8 @@ async function getUser() { } const authMiddleware: Route.MiddlewareFunction = async ({ request, context }, next) => { - Sentry.startSpan({ name: 'authMiddleware', op: 'middleware.auth' }, async () => { + // React Router middleware must keep the async `next()` chain alive until it completes. + await Sentry.startSpan({ name: 'authMiddleware', op: 'middleware.auth' }, async () => { const user: User = await getUser(); context.set(userContext, user); await next(); diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework/instrument.mjs b/dev-packages/e2e-tests/test-applications/react-router-7-framework/instrument.mjs index c16240141b6d..48a130bd25d6 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework/instrument.mjs +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework/instrument.mjs @@ -4,5 +4,12 @@ Sentry.init({ dsn: 'https://username@domain/123', environment: 'qa', // dynamic sampling bias to keep transactions tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: `http://localhost:3031/`, // proxy server }); diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework/package.json b/dev-packages/e2e-tests/test-applications/react-router-7-framework/package.json index fde0e1699d6a..539d0ae3e980 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework/package.json +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework/package.json @@ -61,6 +61,11 @@ { "build-command": "pnpm test:build-latest", "label": "react-router-7-framework (latest)" + }, + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "react-router-7-framework (sentry-trace-provider)" } ] } diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework/tests/performance/middleware.server.test.ts b/dev-packages/e2e-tests/test-applications/react-router-7-framework/tests/performance/middleware.server.test.ts index dbce05350ad9..971541eb7536 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework/tests/performance/middleware.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework/tests/performance/middleware.server.test.ts @@ -12,27 +12,28 @@ test.describe('server - middleware', () => { return transactionEvent.transaction === '/performance/with-middleware'; }); - const customMiddlewareTxPromise = waitForTransaction(APP_NAME, async transactionEvent => { - return transactionEvent.transaction === 'authMiddleware'; - }); - await page.goto(`/performance/with-middleware`); const serverTx = await serverTxPromise; const pageloadTx = await pageloadTxPromise; - const customMiddlewareTx = await customMiddlewareTxPromise; const traceIds = { server: serverTx?.contexts?.trace?.trace_id, pageload: pageloadTx?.contexts?.trace?.trace_id, - customMiddleware: customMiddlewareTx?.contexts?.trace?.trace_id, }; expect(pageloadTx).toBeDefined(); - expect(customMiddlewareTx).toBeDefined(); + + // The app awaits Sentry.startSpan around the middleware `next()` call, so the manual + // middleware span belongs to the request transaction instead of becoming a root transaction. + const customMiddlewareSpans = + serverTx.spans?.filter(span => { + return span.description === 'authMiddleware' && span.op === 'middleware.auth'; + }) ?? []; + + expect(customMiddlewareSpans).toHaveLength(1); // Assert that all transactions belong to the same trace expect(traceIds.server).toBe(traceIds.pageload); - expect(traceIds.server).toBe(traceIds.customMiddleware); }); }); diff --git a/dev-packages/e2e-tests/test-applications/remix-server-timing/instrument.server.cjs b/dev-packages/e2e-tests/test-applications/remix-server-timing/instrument.server.cjs index 6d211cac4592..023cd91bd8cd 100644 --- a/dev-packages/e2e-tests/test-applications/remix-server-timing/instrument.server.cjs +++ b/dev-packages/e2e-tests/test-applications/remix-server-timing/instrument.server.cjs @@ -2,6 +2,13 @@ const Sentry = require('@sentry/remix'); Sentry.init({ tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production! + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), environment: 'qa', // dynamic sampling bias to keep transactions dsn: process.env.E2E_TEST_DSN, tunnel: 'http://localhost:3031/', // proxy server diff --git a/dev-packages/e2e-tests/test-applications/remix-server-timing/package.json b/dev-packages/e2e-tests/test-applications/remix-server-timing/package.json index fd57d2920d5a..d0f4b3f96fe5 100644 --- a/dev-packages/e2e-tests/test-applications/remix-server-timing/package.json +++ b/dev-packages/e2e-tests/test-applications/remix-server-timing/package.json @@ -38,5 +38,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "remix-server-timing (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/solidstart-dynamic-import/package.json b/dev-packages/e2e-tests/test-applications/solidstart-dynamic-import/package.json index 747162d0bd75..77379c98288d 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-dynamic-import/package.json +++ b/dev-packages/e2e-tests/test-applications/solidstart-dynamic-import/package.json @@ -34,5 +34,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "solidstart-dynamic-import (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/solidstart-dynamic-import/src/instrument.server.ts b/dev-packages/e2e-tests/test-applications/solidstart-dynamic-import/src/instrument.server.ts index 3dd5d8933b7b..16897c2903d0 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-dynamic-import/src/instrument.server.ts +++ b/dev-packages/e2e-tests/test-applications/solidstart-dynamic-import/src/instrument.server.ts @@ -4,6 +4,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, environment: 'qa', // dynamic sampling bias to keep transactions tracesSampleRate: 1.0, // Capture 100% of the transactions + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server debug: !!process.env.DEBUG, }); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-spa/package.json b/dev-packages/e2e-tests/test-applications/solidstart-spa/package.json index a9d1d6b91da3..cf2f7db4f0f9 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-spa/package.json +++ b/dev-packages/e2e-tests/test-applications/solidstart-spa/package.json @@ -34,5 +34,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "solidstart-spa (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/solidstart-spa/src/instrument.server.ts b/dev-packages/e2e-tests/test-applications/solidstart-spa/src/instrument.server.ts index 3dd5d8933b7b..16897c2903d0 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-spa/src/instrument.server.ts +++ b/dev-packages/e2e-tests/test-applications/solidstart-spa/src/instrument.server.ts @@ -4,6 +4,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, environment: 'qa', // dynamic sampling bias to keep transactions tracesSampleRate: 1.0, // Capture 100% of the transactions + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server debug: !!process.env.DEBUG, }); diff --git a/dev-packages/e2e-tests/test-applications/solidstart-top-level-import/package.json b/dev-packages/e2e-tests/test-applications/solidstart-top-level-import/package.json index c97a130c92b1..fb4a82cddac2 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-top-level-import/package.json +++ b/dev-packages/e2e-tests/test-applications/solidstart-top-level-import/package.json @@ -34,5 +34,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "solidstart-top-level-import (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/solidstart-top-level-import/src/instrument.server.ts b/dev-packages/e2e-tests/test-applications/solidstart-top-level-import/src/instrument.server.ts index 3dd5d8933b7b..16897c2903d0 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart-top-level-import/src/instrument.server.ts +++ b/dev-packages/e2e-tests/test-applications/solidstart-top-level-import/src/instrument.server.ts @@ -4,6 +4,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, environment: 'qa', // dynamic sampling bias to keep transactions tracesSampleRate: 1.0, // Capture 100% of the transactions + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server debug: !!process.env.DEBUG, }); diff --git a/dev-packages/e2e-tests/test-applications/solidstart/package.json b/dev-packages/e2e-tests/test-applications/solidstart/package.json index 7e382b6dc54b..f7e00d311aad 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart/package.json +++ b/dev-packages/e2e-tests/test-applications/solidstart/package.json @@ -34,5 +34,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "solidstart (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/solidstart/src/instrument.server.ts b/dev-packages/e2e-tests/test-applications/solidstart/src/instrument.server.ts index 3dd5d8933b7b..16897c2903d0 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart/src/instrument.server.ts +++ b/dev-packages/e2e-tests/test-applications/solidstart/src/instrument.server.ts @@ -4,6 +4,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, environment: 'qa', // dynamic sampling bias to keep transactions tracesSampleRate: 1.0, // Capture 100% of the transactions + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), tunnel: 'http://localhost:3031/', // proxy server debug: !!process.env.DEBUG, }); diff --git a/dev-packages/e2e-tests/test-applications/supabase-nextjs/package.json b/dev-packages/e2e-tests/test-applications/supabase-nextjs/package.json index c5c86c0d31ae..a572a2780c16 100644 --- a/dev-packages/e2e-tests/test-applications/supabase-nextjs/package.json +++ b/dev-packages/e2e-tests/test-applications/supabase-nextjs/package.json @@ -36,5 +36,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "supabase-nextjs (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/supabase-nextjs/sentry.server.config.ts b/dev-packages/e2e-tests/test-applications/supabase-nextjs/sentry.server.config.ts index a9966e3a71a5..8f32eca94d31 100644 --- a/dev-packages/e2e-tests/test-applications/supabase-nextjs/sentry.server.config.ts +++ b/dev-packages/e2e-tests/test-applications/supabase-nextjs/sentry.server.config.ts @@ -8,6 +8,13 @@ Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', environment: 'qa', // dynamic sampling bias to keep transactions tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), sendDefaultPii: true, tunnel: 'http://localhost:3031/', // proxy server transportOptions: { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-kit-tracing/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-2-kit-tracing/package.json index 12f39178da15..61bb0f73ec40 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-kit-tracing/package.json +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-kit-tracing/package.json @@ -33,5 +33,14 @@ "type": "module", "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "sveltekit-2-kit-tracing (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-kit-tracing/src/instrumentation.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-kit-tracing/src/instrumentation.server.ts index 136b51a44dee..8c3ea06e3a5f 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-kit-tracing/src/instrumentation.server.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-kit-tracing/src/instrumentation.server.ts @@ -7,5 +7,12 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), spotlight: import.meta.env.DEV, }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/package.json index 50fd974e98b9..b3986dc72a02 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/package.json +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/package.json @@ -33,5 +33,14 @@ "type": "module", "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "sveltekit-2-svelte-5 (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.server.ts index 99bf4a17aa96..ab30c4682fd7 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.server.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.server.ts @@ -8,6 +8,13 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), spotlight: import.meta.env.DEV, }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/package.json index 23f059eaee43..a83c53ee5f82 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/package.json +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/package.json @@ -32,5 +32,14 @@ "type": "module", "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "sveltekit-2.5.0-twp (sentry-trace-provider)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/hooks.server.ts index e60e51b25968..4292c5b676b0 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/hooks.server.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/hooks.server.ts @@ -5,6 +5,13 @@ Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); // not logging anything to console to avoid noise in the test output diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json index 75b1967d802f..538a51fbabc9 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json @@ -32,5 +32,14 @@ "volta": { "extends": "../../package.json" }, - "type": "module" + "type": "module", + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "sveltekit-2 (sentry-trace-provider)" + } + ] + } } diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.server.ts index 92909c53a24c..719a12efc391 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.server.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.server.ts @@ -7,6 +7,13 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), }); // not logging anything to console to avoid noise in the test output diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs b/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs index 8bc20de7578b..a607a0046c5b 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/instrument.server.mjs @@ -5,6 +5,13 @@ Sentry.init({ dsn: process.env.E2E_TEST_DSN, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), transportOptions: { // We expect the app to send a lot of events in a short time bufferSize: 1000, diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json index 0525acfad587..910d2586b994 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/package.json @@ -66,6 +66,11 @@ "label": "tanstackstart-react (tunnel-object)", "build-command": "pnpm test:build:tunnel-object", "assert-command": "pnpm test:assert:tunnel-object" + }, + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "tanstackstart-react (sentry-trace-provider)" } ] } diff --git a/dev-packages/e2e-tests/test-applications/tsx-express/instrument.mjs b/dev-packages/e2e-tests/test-applications/tsx-express/instrument.mjs index ddc96c7c17fc..809ca41f133b 100644 --- a/dev-packages/e2e-tests/test-applications/tsx-express/instrument.mjs +++ b/dev-packages/e2e-tests/test-applications/tsx-express/instrument.mjs @@ -6,5 +6,12 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, + ...(process.env.E2E_USE_SENTRY_TRACE_PROVIDER === '1' + ? { + _experiments: { + useSentryTraceProvider: true, + }, + } + : {}), enableLogs: true, }); diff --git a/dev-packages/e2e-tests/test-applications/tsx-express/package.json b/dev-packages/e2e-tests/test-applications/tsx-express/package.json index 7794d2c7ac52..d12206ae9ceb 100644 --- a/dev-packages/e2e-tests/test-applications/tsx-express/package.json +++ b/dev-packages/e2e-tests/test-applications/tsx-express/package.json @@ -31,5 +31,14 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "variants": [ + { + "build-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:build", + "assert-command": "env E2E_USE_SENTRY_TRACE_PROVIDER=1 pnpm test:assert", + "label": "tsx-express (sentry-trace-provider)" + } + ] } }