From 013f716ac7877c487bd0eaec8d19a5db18d5ca0f Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Mon, 7 Sep 2026 15:22:49 +0200 Subject: [PATCH] test(cloudflare): Add shared streamed-span helpers to the integration test runner Adds `spanUtils.ts` next to `runner.ts`, and two span collection methods on the runner. The suites ported to span streaming then do not each write their own envelope handling. `spanUtils.ts` reads a single envelope: `getSpanContainer` and `getSpansFromEnvelope`. It re-exports `getSpanOp` from `@sentry-internal/test-utils`, which this package already depends on. That avoids a third copy of the function in the repo. The runner reads across envelopes: `collectStreamedSpans` and `collectStreamedSpansUntilSegment`. The names follow `dev-packages/test-utils/src/event-proxy-server.ts`, so a streamed span assertion reads the same in this package and in the E2E apps. A trace does not arrive in one envelope when several isolates send spans. The collecting helpers therefore group the spans by trace, and resolve on the first trace that satisfies the predicate. Span waiters observe the envelope stream and never consume it. `.expect(...)` stays usable for error envelopes at the same time. Span waiters also receive the runner rejection, so a worker that fails to boot gives the real error instead of a Vitest timeout. `collectStreamedSpansUntilSegment` is for asserting on the segment span alone. Each envelope is its own request to the mock server, so the segment can be received before the envelope carrying its children even though it ends last. A suite that asserts on the children waits for those children instead, by name or by count. A runner now tears down its own workers from `onTestFinished`, and that teardown kills only its own workers rather than running the shared cleanup. Both halves are needed. A suite that asserts on streamed spans never calls `completed()`, so its runner never settles and its `wrangler dev` would otherwise stay alive until the Vitest process exits. A full run left 32 of them behind. Running the shared cleanup instead would kill the worker the next test had already started. The process-exit cleanup still covers every worker. Renames `public-api/startSpan-streamed` to `public-api/startSpan`, and `tracing/ignoreSpans-streamed` to `tracing/ignoreSpans`. Ports both suites onto the helpers, which proves the shape before the bulk of the port. Span streaming is the default, so a `-streamed` suffix no longer marks a difference, and the explicit `traceLifecycle: 'stream'` those four suites carried says nothing either. It goes with the suffix. Co-Authored-By: Claude Opus 5 (1M context) --- .../cloudflare-integration-tests/runner.ts | 154 ++++++++- .../cloudflare-integration-tests/spanUtils.ts | 18 ++ .../public-api/startSpan-streamed/test.ts | 298 ------------------ .../index.ts | 1 - .../suites/public-api/startSpan/test.ts | 291 +++++++++++++++++ .../wrangler.jsonc | 0 .../continued-trace-child/index.ts | 1 - .../continued-trace-child/test.ts | 17 +- .../continued-trace-child/wrangler.jsonc | 0 .../continued-trace-http-client/index.ts | 1 - .../continued-trace-http-client/test.ts | 15 +- .../wrangler.jsonc | 0 .../continued-trace-segment/index.ts | 1 - .../continued-trace-segment/test.ts | 0 .../continued-trace-segment/wrangler.jsonc | 0 15 files changed, 464 insertions(+), 333 deletions(-) create mode 100644 dev-packages/cloudflare-integration-tests/spanUtils.ts delete mode 100644 dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/test.ts rename dev-packages/cloudflare-integration-tests/suites/public-api/{startSpan-streamed => startSpan}/index.ts (96%) create mode 100644 dev-packages/cloudflare-integration-tests/suites/public-api/startSpan/test.ts rename dev-packages/cloudflare-integration-tests/suites/public-api/{startSpan-streamed => startSpan}/wrangler.jsonc (100%) rename dev-packages/cloudflare-integration-tests/suites/tracing/{ignoreSpans-streamed => ignoreSpans}/continued-trace-child/index.ts (94%) rename dev-packages/cloudflare-integration-tests/suites/tracing/{ignoreSpans-streamed => ignoreSpans}/continued-trace-child/test.ts (66%) rename dev-packages/cloudflare-integration-tests/suites/tracing/{ignoreSpans-streamed => ignoreSpans}/continued-trace-child/wrangler.jsonc (100%) rename dev-packages/cloudflare-integration-tests/suites/tracing/{ignoreSpans-streamed => ignoreSpans}/continued-trace-http-client/index.ts (94%) rename dev-packages/cloudflare-integration-tests/suites/tracing/{ignoreSpans-streamed => ignoreSpans}/continued-trace-http-client/test.ts (70%) rename dev-packages/cloudflare-integration-tests/suites/tracing/{ignoreSpans-streamed => ignoreSpans}/continued-trace-http-client/wrangler.jsonc (100%) rename dev-packages/cloudflare-integration-tests/suites/tracing/{ignoreSpans-streamed => ignoreSpans}/continued-trace-segment/index.ts (93%) rename dev-packages/cloudflare-integration-tests/suites/tracing/{ignoreSpans-streamed => ignoreSpans}/continued-trace-segment/test.ts (100%) rename dev-packages/cloudflare-integration-tests/suites/tracing/{ignoreSpans-streamed => ignoreSpans}/continued-trace-segment/wrangler.jsonc (100%) diff --git a/dev-packages/cloudflare-integration-tests/runner.ts b/dev-packages/cloudflare-integration-tests/runner.ts index 19873330d82e..76e83f15abc7 100644 --- a/dev-packages/cloudflare-integration-tests/runner.ts +++ b/dev-packages/cloudflare-integration-tests/runner.ts @@ -1,11 +1,12 @@ -import type { Envelope, EnvelopeItemType } from '@sentry/core'; +import type { Envelope, EnvelopeItemType, SerializedStreamedSpan } from '@sentry/core'; import { normalize } from '@sentry/core'; import { createBasicSentryServer } from '@sentry-internal/test-utils'; import { spawn, spawnSync } from 'child_process'; import { existsSync, readdirSync, readFileSync } from 'fs'; import { join } from 'path'; import { inspect } from 'util'; -import { expect } from 'vitest'; +import { expect, onTestFinished } from 'vitest'; +import { getSpansFromEnvelope } from './spanUtils'; const CLEANUP_STEPS = new Set<() => void>(); @@ -139,6 +140,9 @@ function deferredPromise( type Expected = Envelope | ((envelope: Envelope) => void); +/** Either the name of the segment span, or a predicate over it. */ +type SegmentMatcher = string | ((segmentSpan: SerializedStreamedSpan) => boolean); + type StartResult = { completed(): Promise; makeRequest( @@ -152,6 +156,25 @@ type StartResult = { expected: Expected | Expected[], options?: { headers?: Record; data?: BodyInit; expectError?: boolean }, ): Promise; + /** + * Accumulates spans across envelopes, grouped by trace, and resolves with the spans of the first + * trace that satisfies `isDone`. + * + * A trace reaches the mock server in more than one envelope: the span buffer flushes on a timer, so + * a segment that is still open when its children flush arrives separately, and a Durable Object or a + * service binding sends its own spans from its own isolate. Anything asserting on a whole trace has + * to accumulate rather than read a single envelope. + */ + collectStreamedSpans(isDone: (spansOfTrace: SerializedStreamedSpan[]) => boolean): Promise; + /** + * Accumulates the spans of a trace until its segment span has arrived. + * + * Only use this to assert on the segment span itself. The segment span ends last, but each + * envelope is its own request to the mock server, so the segment can still be *received* before + * the envelope carrying its children. A suite that asserts on the children has to wait for those + * children by name or by count through `collectStreamedSpans`. + */ + collectStreamedSpansUntilSegment(segment: SegmentMatcher): Promise; }; /** Creates a test runner */ @@ -211,17 +234,55 @@ export function createRunner(...paths: string[]) { return this; }, start: function (signal?: AbortSignal): StartResult { - const { resolve, reject, promise: isComplete } = deferredPromise(cleanupChildProcesses); + let child: ReturnType | undefined; + let childSubWorker: ReturnType | undefined; + + // Tears down this runner only. `cleanupChildProcesses` tears down every registered runner, so + // running it here would kill a worker another test has already started: a runner whose + // `isComplete` settles after its own test (a suite that asserts on streamed spans never calls + // `completed()`, so the abort signal settles it) would take the next test's worker with it. + // The mock server has to close here as well, otherwise one server per scenario stays listening + // for the whole run. + function cleanupThisRunner(): void { + child?.kill(); + childSubWorker?.kill(); + closeMockServer?.(); + closeMockServer = undefined; + } + + // A suite that asserts on streamed spans never calls `completed()`, so `isComplete` never + // settles and its worker would stay alive until the vitest process exits. With one such suite + // per file, a full run ends up with dozens of `wrangler dev` processes competing for the + // machine, and the later suites time out. Tie the teardown to the test instead. + onTestFinished(cleanupThisRunner); + + let closeMockServer: (() => void) | undefined; + + const { resolve, reject, promise: isComplete } = deferredPromise(cleanupThisRunner); + + const spanWaiters: { + onSpans: (spans: SerializedStreamedSpan[]) => boolean; + resolve: () => void; + reject: (e: unknown) => void; + }[] = []; + let failure: unknown; // `reject` is called from background event handlers (child process `error`/`exit`, mock server // callbacks) that fire at arbitrary times relative to the test's `await` points. If `reject` runs // while nothing is awaiting `isComplete` yet (e.g. a child transiently exits while the test is // parked in `makeRequest`), the rejection has no handler attached and surfaces as an unhandled // promise rejection — which Vitest reports as a spurious "Unhandled error" that fails the whole - // suite. Attaching a no-op catch keeps the promise "handled"; the real rejection is still delivered + // suite. Attaching a catch keeps the promise "handled"; the real rejection is still delivered // to callers via `completed()`, so genuine failures still fail the test. - isComplete.catch(() => { - // handled in `completed()` + // + // A test that only asserts on streamed spans never calls `completed()`, so the same rejection is + // handed to the span waiters as well. Without it, a worker that fails to boot would surface as a + // Vitest timeout instead of the actual error. + isComplete.catch(e => { + failure = e; + for (const waiter of spanWaiters.splice(0)) { + waiter.reject(e); + } }); const expectedEnvelopeCount = expectedEnvelopes.length; @@ -237,8 +298,6 @@ export function createRunner(...paths: string[]) { workerPortPromise.catch(() => { // handled in `makeRequest` }); - let child: ReturnType | undefined; - let childSubWorker: ReturnType | undefined; /** Called after each expect callback to check if we're complete */ function expectCallbackCalled(): void { @@ -254,6 +313,44 @@ export function createRunner(...paths: string[]) { }); } + /** Resolves once `onSpans` returns true for the spans of an arriving span envelope. */ + function waitForSpans(onSpans: (spans: SerializedStreamedSpan[]) => boolean): Promise { + return new Promise((resolveWaiter, rejectWaiter) => { + if (failure) { + rejectWaiter(failure); + return; + } + spanWaiters.push({ onSpans, resolve: resolveWaiter, reject: rejectWaiter }); + }); + } + + /** + * Span waiters observe the envelope stream, they never consume from it: a suite can assert on + * streamed spans and on error envelopes at the same time. + */ + function notifySpanWaiters(envelope: Envelope): void { + const spans = getSpansFromEnvelope(envelope); + if (!spans.length) { + return; + } + + for (const waiter of spanWaiters.slice()) { + let done: boolean; + try { + done = waiter.onSpans(spans); + } catch (e) { + spanWaiters.splice(spanWaiters.indexOf(waiter), 1); + waiter.reject(e); + continue; + } + + if (done) { + spanWaiters.splice(spanWaiters.indexOf(waiter), 1); + waiter.resolve(); + } + } + } + function assertEnvelopeMatches(expected: Expected, envelope: Envelope): void { if (typeof expected === 'function') { expected(envelope); @@ -265,6 +362,8 @@ export function createRunner(...paths: string[]) { function newEnvelope(envelope: Envelope): void { if (process.env.DEBUG) log('newEnvelope', inspect(envelope, false, null, true)); + notifySpanWaiters(envelope); + const envelopeItemType = envelope[1][0][0].type; if (ignored.has(envelopeItemType)) { @@ -332,6 +431,7 @@ export function createRunner(...paths: string[]) { createBasicSentryServer(newEnvelope) .then(async ([mockServerPort, mockServerClose]) => { if (mockServerClose) { + closeMockServer = mockServerClose; CLEANUP_STEPS.add(() => { mockServerClose(); }); @@ -501,6 +601,44 @@ export function createRunner(...paths: string[]) { await Promise.all(envelopePromises); return result; }, + collectStreamedSpans: async function ( + isDone: (spansOfTrace: SerializedStreamedSpan[]) => boolean, + ): Promise { + const spansByTrace = new Map(); + let matched: SerializedStreamedSpan[] = []; + + await waitForSpans(spans => { + for (const span of spans) { + const spansOfTrace = spansByTrace.get(span.trace_id); + if (spansOfTrace) { + spansOfTrace.push(span); + } else { + spansByTrace.set(span.trace_id, [span]); + } + } + + // Every trace is a candidate, so a trace that never satisfies `isDone` cannot hold up the + // one that does. Insertion order means the earliest-arriving trace wins a tie. + for (const spansOfTrace of spansByTrace.values()) { + if (isDone(spansOfTrace)) { + matched = spansOfTrace; + return true; + } + } + + return false; + }); + + return matched; + }, + collectStreamedSpansUntilSegment: function (segment: SegmentMatcher): Promise { + const matchesSegment = + typeof segment === 'string' ? (span: SerializedStreamedSpan) => span.name === segment : segment; + + return this.collectStreamedSpans(spansOfTrace => + spansOfTrace.some(span => span.is_segment && matchesSegment(span)), + ); + }, }; }, }; diff --git a/dev-packages/cloudflare-integration-tests/spanUtils.ts b/dev-packages/cloudflare-integration-tests/spanUtils.ts new file mode 100644 index 000000000000..f0a79b2c6e4b --- /dev/null +++ b/dev-packages/cloudflare-integration-tests/spanUtils.ts @@ -0,0 +1,18 @@ +import type { Envelope, SerializedStreamedSpan, SerializedStreamedSpanContainer } from '@sentry/core'; + +export { getSpanOp } from '@sentry-internal/test-utils'; + +/** + * The span v2 container of an envelope, or `undefined` when the envelope carries no span item. + */ +export function getSpanContainer(envelope: Envelope): SerializedStreamedSpanContainer | undefined { + const spanItem = envelope[1].find(item => item[0].type === 'span'); + return spanItem?.[1] as SerializedStreamedSpanContainer | undefined; +} + +/** + * The spans of an envelope, or an empty array when the envelope carries no span item. + */ +export function getSpansFromEnvelope(envelope: Envelope): SerializedStreamedSpan[] { + return getSpanContainer(envelope)?.items ?? []; +} diff --git a/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/test.ts b/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/test.ts deleted file mode 100644 index 8c6b18c3931d..000000000000 --- a/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/test.ts +++ /dev/null @@ -1,298 +0,0 @@ -import type { Envelope, SerializedStreamedSpanContainer } from '@sentry/core'; -import { - SDK_VERSION, - SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT, - SEMANTIC_ATTRIBUTE_SENTRY_OP, - SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, - SEMANTIC_ATTRIBUTE_SENTRY_RELEASE, - SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, - SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS, -} from '@sentry/core'; -import { - SENTRY_SEGMENT_NAME_SOURCE, - SENTRY_SDK_NAME, - SENTRY_SDK_VERSION, - SENTRY_SEGMENT_ID, - SENTRY_SEGMENT_NAME, - SENTRY_TRACE_LIFECYCLE, -} from '@sentry/conventions/attributes'; -import { expect, it } from 'vitest'; -import { createRunner } from '../../../runner'; - -const CLOUDFLARE_SDK = 'sentry.javascript.cloudflare'; - -function getSpanContainer(envelope: Envelope): SerializedStreamedSpanContainer { - const spanItem = envelope[1].find(item => item[0].type === 'span'); - expect(spanItem).toBeDefined(); - return spanItem![1] as SerializedStreamedSpanContainer; -} - -it('sends a streamed span envelope with correct envelope header', async ({ signal }) => { - const runner = createRunner(__dirname) - .expect(envelope => { - expect(getSpanContainer(envelope).items.length).toBeGreaterThan(0); - - expect(envelope[0]).toEqual( - expect.objectContaining({ - sent_at: expect.any(String), - sdk: { - name: CLOUDFLARE_SDK, - version: SDK_VERSION, - }, - trace: expect.objectContaining({ - public_key: 'public', - sample_rate: '1', - sampled: 'true', - trace_id: expect.stringMatching(/^[\da-f]{32}$/), - }), - }), - ); - }) - .start(signal); - - await runner.makeRequest('get', '/'); - await runner.completed(); -}); - -it('sends a streamed span envelope with correct spans for a manually started span with children', async ({ - signal, -}) => { - const runner = createRunner(__dirname) - .expect(envelope => { - const container = getSpanContainer(envelope); - const spans = container.items; - - // Cloudflare `withSentry` wraps fetch in an http.server span (segment) around the scenario. - expect(spans.length).toBe(5); - - const segmentSpan = spans.find(s => !!s.is_segment); - expect(segmentSpan).toBeDefined(); - - const segmentSpanId = segmentSpan!.span_id; - const traceId = segmentSpan!.trace_id; - const segmentName = segmentSpan!.name; - - const parentTestSpan = spans.find(s => s.name === 'test-span'); - expect(parentTestSpan).toBeDefined(); - expect(parentTestSpan!.parent_span_id).toBe(segmentSpanId); - - const childSpan = spans.find(s => s.name === 'test-child-span'); - expect(childSpan).toBeDefined(); - expect(childSpan).toEqual({ - attributes: { - [SENTRY_TRACE_LIFECYCLE]: { type: 'string', value: 'stream' }, - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: { - type: 'string', - value: 'test-child', - }, - [SENTRY_SDK_NAME]: { type: 'string', value: CLOUDFLARE_SDK }, - [SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, - [SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, - [SENTRY_SEGMENT_NAME]: { type: 'string', value: segmentName }, - [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' }, - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'manual' }, - [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { type: 'string', value: 'production' }, - }, - name: 'test-child-span', - is_segment: false, - parent_span_id: parentTestSpan!.span_id, - trace_id: traceId, - span_id: expect.stringMatching(/^[\da-f]{16}$/), - start_timestamp: expect.any(Number), - end_timestamp: expect.any(Number), - status: 'ok', - }); - - const inactiveSpan = spans.find(s => s.name === 'test-inactive-span'); - expect(inactiveSpan).toBeDefined(); - expect(inactiveSpan).toEqual({ - attributes: { - [SENTRY_TRACE_LIFECYCLE]: { type: 'string', value: 'stream' }, - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'manual' }, - [SENTRY_SDK_NAME]: { type: 'string', value: CLOUDFLARE_SDK }, - [SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, - [SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, - [SENTRY_SEGMENT_NAME]: { type: 'string', value: segmentName }, - [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' }, - [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { type: 'string', value: 'production' }, - }, - links: [ - { - attributes: { - 'sentry.link.type': { - type: 'string', - value: 'some_relation', - }, - }, - sampled: true, - span_id: parentTestSpan!.span_id, - trace_id: traceId, - }, - ], - name: 'test-inactive-span', - is_segment: false, - parent_span_id: parentTestSpan!.span_id, - trace_id: traceId, - span_id: expect.stringMatching(/^[\da-f]{16}$/), - start_timestamp: expect.any(Number), - end_timestamp: expect.any(Number), - status: 'ok', - }); - - const manualSpan = spans.find(s => s.name === 'test-manual-span'); - expect(manualSpan).toBeDefined(); - expect(manualSpan).toEqual({ - attributes: { - [SENTRY_TRACE_LIFECYCLE]: { type: 'string', value: 'stream' }, - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'manual' }, - [SENTRY_SDK_NAME]: { type: 'string', value: CLOUDFLARE_SDK }, - [SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, - [SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, - [SENTRY_SEGMENT_NAME]: { type: 'string', value: segmentName }, - [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' }, - [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { type: 'string', value: 'production' }, - }, - name: 'test-manual-span', - is_segment: false, - parent_span_id: parentTestSpan!.span_id, - trace_id: traceId, - span_id: expect.stringMatching(/^[\da-f]{16}$/), - start_timestamp: expect.any(Number), - end_timestamp: expect.any(Number), - status: 'ok', - }); - - expect(parentTestSpan).toEqual({ - attributes: { - [SENTRY_TRACE_LIFECYCLE]: { type: 'string', value: 'stream' }, - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: { type: 'string', value: 'test' }, - [SENTRY_SDK_NAME]: { type: 'string', value: CLOUDFLARE_SDK }, - [SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, - [SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, - [SENTRY_SEGMENT_NAME]: { type: 'string', value: segmentName }, - [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' }, - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'manual' }, - [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { type: 'string', value: 'production' }, - }, - name: 'test-span', - is_segment: false, - parent_span_id: segmentSpanId, - trace_id: traceId, - span_id: parentTestSpan!.span_id, - start_timestamp: expect.any(Number), - end_timestamp: expect.any(Number), - status: 'ok', - }); - - expect(segmentSpan).toEqual({ - attributes: { - [SENTRY_TRACE_LIFECYCLE]: { type: 'string', value: 'stream' }, - [SENTRY_SDK_NAME]: { type: 'string', value: CLOUDFLARE_SDK }, - [SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, - [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { - type: 'array', - value: expect.arrayContaining(['SpanStreaming']), - }, - [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' }, - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'auto.http.cloudflare' }, - [SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, - [SENTRY_SEGMENT_NAME]: { type: 'string', value: segmentName }, - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: { type: 'string', value: 'http.server' }, - [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: { type: 'integer', value: 1 }, - [SENTRY_SEGMENT_NAME_SOURCE]: { type: 'string', value: 'route' }, - [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { type: 'string', value: 'production' }, - 'server.address': { - type: 'string', - value: 'localhost', - }, - 'url.full': { - type: 'string', - value: expect.stringMatching(/^http:\/\/localhost:.+$/), - }, - 'url.path': { - type: 'string', - value: '/', - }, - 'url.port': { - type: 'string', - value: expect.stringMatching(/^\d{4,5}$/), - }, - 'url.scheme': { - type: 'string', - value: 'http:', - }, - 'user_agent.original': { - type: 'string', - value: 'node', - }, - 'http.request.header.accept': { - type: 'string', - value: '*/*', - }, - 'http.request.header.accept_encoding': { - type: 'string', - value: 'br, gzip', - }, - 'http.request.header.accept_language': { - type: 'string', - value: '*', - }, - 'http.request.header.cf_connecting_ip': { - type: 'string', - value: '127.0.0.1', - }, - 'user.ip_address': { - type: 'string', - value: '127.0.0.1', - }, - 'http.request.header.host': { - type: 'string', - value: expect.stringMatching(/^localhost:.+$/), - }, - 'http.request.header.sec_fetch_mode': { - type: 'string', - value: 'cors', - }, - 'http.request.header.user_agent': { - type: 'string', - value: 'node', - }, - 'http.request.method': { - type: 'string', - value: 'GET', - }, - 'http.response.status_code': { - type: 'integer', - value: 200, - }, - 'cloud.provider': { - type: 'string', - value: 'cloudflare', - }, - 'culture.timezone': { - type: 'string', - value: expect.any(String), - }, - 'network.protocol.name': { - type: 'string', - value: 'http', - }, - 'network.protocol.version': { - type: 'string', - value: '1.1', - }, - }, - is_segment: true, - trace_id: traceId, - span_id: segmentSpanId, - start_timestamp: expect.any(Number), - end_timestamp: expect.any(Number), - status: 'ok', - name: 'GET /', - }); - }) - .start(signal); - - await runner.makeRequest('get', '/'); - await runner.completed(); -}); diff --git a/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/index.ts b/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan/index.ts similarity index 96% rename from dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/index.ts rename to dev-packages/cloudflare-integration-tests/suites/public-api/startSpan/index.ts index 76039b6892ee..328cc01c19de 100644 --- a/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/index.ts +++ b/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan/index.ts @@ -8,7 +8,6 @@ export default Sentry.withSentry( (env: Env) => ({ dsn: env.SENTRY_DSN, tracesSampleRate: 1.0, - traceLifecycle: 'stream', release: '1.0.0', }), { diff --git a/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan/test.ts b/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan/test.ts new file mode 100644 index 000000000000..2685a1574340 --- /dev/null +++ b/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan/test.ts @@ -0,0 +1,291 @@ +import { + SDK_VERSION, + SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT, + SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SEMANTIC_ATTRIBUTE_SENTRY_RELEASE, + SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, + SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS, +} from '@sentry/core'; +import { + SENTRY_SEGMENT_NAME_SOURCE, + SENTRY_SDK_NAME, + SENTRY_SDK_VERSION, + SENTRY_SEGMENT_ID, + SENTRY_SEGMENT_NAME, + SENTRY_TRACE_LIFECYCLE, +} from '@sentry/conventions/attributes'; +import { expect, it } from 'vitest'; +import { createRunner } from '../../../runner'; +import { getSpansFromEnvelope } from '../../../spanUtils'; + +const CLOUDFLARE_SDK = 'sentry.javascript.cloudflare'; + +it('sends a streamed span envelope with correct envelope header', async ({ signal }) => { + const runner = createRunner(__dirname) + .expect(envelope => { + expect(getSpansFromEnvelope(envelope).length).toBeGreaterThan(0); + + expect(envelope[0]).toEqual( + expect.objectContaining({ + sent_at: expect.any(String), + sdk: { + name: CLOUDFLARE_SDK, + version: SDK_VERSION, + }, + trace: expect.objectContaining({ + public_key: 'public', + sample_rate: '1', + sampled: 'true', + trace_id: expect.stringMatching(/^[\da-f]{32}$/), + }), + }), + ); + }) + .start(signal); + + await runner.makeRequest('get', '/'); + await runner.completed(); +}); + +it('sends a streamed span envelope with correct spans for a manually started span with children', async ({ + signal, +}) => { + const runner = createRunner(__dirname).start(signal); + // Cloudflare `withSentry` wraps fetch in an http.server span (segment) around the scenario, so + // the trace holds five spans. Waiting for all of them rather than for the segment alone: the + // segment ends last but each envelope is its own request, so it can arrive before its children. + const spansPromise = runner.collectStreamedSpans(spansOfTrace => spansOfTrace.length === 5); + + await runner.makeRequest('get', '/'); + + const spans = await spansPromise; + + expect(spans.length).toBe(5); + + const segmentSpan = spans.find(s => !!s.is_segment); + expect(segmentSpan).toBeDefined(); + + const segmentSpanId = segmentSpan!.span_id; + const traceId = segmentSpan!.trace_id; + const segmentName = segmentSpan!.name; + + const parentTestSpan = spans.find(s => s.name === 'test-span'); + expect(parentTestSpan).toBeDefined(); + expect(parentTestSpan!.parent_span_id).toBe(segmentSpanId); + + const childSpan = spans.find(s => s.name === 'test-child-span'); + expect(childSpan).toBeDefined(); + expect(childSpan).toEqual({ + attributes: { + [SENTRY_TRACE_LIFECYCLE]: { type: 'string', value: 'stream' }, + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: { + type: 'string', + value: 'test-child', + }, + [SENTRY_SDK_NAME]: { type: 'string', value: CLOUDFLARE_SDK }, + [SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, + [SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, + [SENTRY_SEGMENT_NAME]: { type: 'string', value: segmentName }, + [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' }, + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'manual' }, + [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { type: 'string', value: 'production' }, + }, + name: 'test-child-span', + is_segment: false, + parent_span_id: parentTestSpan!.span_id, + trace_id: traceId, + span_id: expect.stringMatching(/^[\da-f]{16}$/), + start_timestamp: expect.any(Number), + end_timestamp: expect.any(Number), + status: 'ok', + }); + + const inactiveSpan = spans.find(s => s.name === 'test-inactive-span'); + expect(inactiveSpan).toBeDefined(); + expect(inactiveSpan).toEqual({ + attributes: { + [SENTRY_TRACE_LIFECYCLE]: { type: 'string', value: 'stream' }, + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'manual' }, + [SENTRY_SDK_NAME]: { type: 'string', value: CLOUDFLARE_SDK }, + [SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, + [SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, + [SENTRY_SEGMENT_NAME]: { type: 'string', value: segmentName }, + [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' }, + [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { type: 'string', value: 'production' }, + }, + links: [ + { + attributes: { + 'sentry.link.type': { + type: 'string', + value: 'some_relation', + }, + }, + sampled: true, + span_id: parentTestSpan!.span_id, + trace_id: traceId, + }, + ], + name: 'test-inactive-span', + is_segment: false, + parent_span_id: parentTestSpan!.span_id, + trace_id: traceId, + span_id: expect.stringMatching(/^[\da-f]{16}$/), + start_timestamp: expect.any(Number), + end_timestamp: expect.any(Number), + status: 'ok', + }); + + const manualSpan = spans.find(s => s.name === 'test-manual-span'); + expect(manualSpan).toBeDefined(); + expect(manualSpan).toEqual({ + attributes: { + [SENTRY_TRACE_LIFECYCLE]: { type: 'string', value: 'stream' }, + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'manual' }, + [SENTRY_SDK_NAME]: { type: 'string', value: CLOUDFLARE_SDK }, + [SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, + [SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, + [SENTRY_SEGMENT_NAME]: { type: 'string', value: segmentName }, + [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' }, + [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { type: 'string', value: 'production' }, + }, + name: 'test-manual-span', + is_segment: false, + parent_span_id: parentTestSpan!.span_id, + trace_id: traceId, + span_id: expect.stringMatching(/^[\da-f]{16}$/), + start_timestamp: expect.any(Number), + end_timestamp: expect.any(Number), + status: 'ok', + }); + + expect(parentTestSpan).toEqual({ + attributes: { + [SENTRY_TRACE_LIFECYCLE]: { type: 'string', value: 'stream' }, + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: { type: 'string', value: 'test' }, + [SENTRY_SDK_NAME]: { type: 'string', value: CLOUDFLARE_SDK }, + [SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, + [SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, + [SENTRY_SEGMENT_NAME]: { type: 'string', value: segmentName }, + [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' }, + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'manual' }, + [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { type: 'string', value: 'production' }, + }, + name: 'test-span', + is_segment: false, + parent_span_id: segmentSpanId, + trace_id: traceId, + span_id: parentTestSpan!.span_id, + start_timestamp: expect.any(Number), + end_timestamp: expect.any(Number), + status: 'ok', + }); + + expect(segmentSpan).toEqual({ + attributes: { + [SENTRY_TRACE_LIFECYCLE]: { type: 'string', value: 'stream' }, + [SENTRY_SDK_NAME]: { type: 'string', value: CLOUDFLARE_SDK }, + [SENTRY_SDK_VERSION]: { type: 'string', value: SDK_VERSION }, + [SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS]: { + type: 'array', + value: expect.arrayContaining(['SpanStreaming']), + }, + [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { type: 'string', value: '1.0.0' }, + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { type: 'string', value: 'auto.http.cloudflare' }, + [SENTRY_SEGMENT_ID]: { type: 'string', value: segmentSpanId }, + [SENTRY_SEGMENT_NAME]: { type: 'string', value: segmentName }, + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: { type: 'string', value: 'http.server' }, + [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: { type: 'integer', value: 1 }, + [SENTRY_SEGMENT_NAME_SOURCE]: { type: 'string', value: 'route' }, + [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { type: 'string', value: 'production' }, + 'server.address': { + type: 'string', + value: 'localhost', + }, + 'url.full': { + type: 'string', + value: expect.stringMatching(/^http:\/\/localhost:.+$/), + }, + 'url.path': { + type: 'string', + value: '/', + }, + 'url.port': { + type: 'string', + value: expect.stringMatching(/^\d{4,5}$/), + }, + 'url.scheme': { + type: 'string', + value: 'http:', + }, + 'user_agent.original': { + type: 'string', + value: 'node', + }, + 'http.request.header.accept': { + type: 'string', + value: '*/*', + }, + 'http.request.header.accept_encoding': { + type: 'string', + value: 'br, gzip', + }, + 'http.request.header.accept_language': { + type: 'string', + value: '*', + }, + 'http.request.header.cf_connecting_ip': { + type: 'string', + value: '127.0.0.1', + }, + 'user.ip_address': { + type: 'string', + value: '127.0.0.1', + }, + 'http.request.header.host': { + type: 'string', + value: expect.stringMatching(/^localhost:.+$/), + }, + 'http.request.header.sec_fetch_mode': { + type: 'string', + value: 'cors', + }, + 'http.request.header.user_agent': { + type: 'string', + value: 'node', + }, + 'http.request.method': { + type: 'string', + value: 'GET', + }, + 'http.response.status_code': { + type: 'integer', + value: 200, + }, + 'cloud.provider': { + type: 'string', + value: 'cloudflare', + }, + 'culture.timezone': { + type: 'string', + value: expect.any(String), + }, + 'network.protocol.name': { + type: 'string', + value: 'http', + }, + 'network.protocol.version': { + type: 'string', + value: '1.1', + }, + }, + is_segment: true, + trace_id: traceId, + span_id: segmentSpanId, + start_timestamp: expect.any(Number), + end_timestamp: expect.any(Number), + status: 'ok', + name: 'GET /', + }); +}); diff --git a/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/wrangler.jsonc b/dev-packages/cloudflare-integration-tests/suites/public-api/startSpan/wrangler.jsonc similarity index 100% rename from dev-packages/cloudflare-integration-tests/suites/public-api/startSpan-streamed/wrangler.jsonc rename to dev-packages/cloudflare-integration-tests/suites/public-api/startSpan/wrangler.jsonc diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-child/index.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-child/index.ts similarity index 94% rename from dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-child/index.ts rename to dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-child/index.ts index 89b990b60865..69d880d9b5da 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-child/index.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-child/index.ts @@ -9,7 +9,6 @@ export default Sentry.withSentry( (env: Env) => ({ dsn: env.SENTRY_DSN, tracesSampleRate: 0, - traceLifecycle: 'stream', ignoreSpans: ['ignored-child'], tracePropagationTargets: [env.SERVER_URL], }), diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-child/test.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-child/test.ts similarity index 66% rename from dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-child/test.ts rename to dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-child/test.ts index d9f587a14ccb..76394ced63a2 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-child/test.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-child/test.ts @@ -1,8 +1,7 @@ -import type { Envelope, SerializedStreamedSpanContainer } from '@sentry/core'; -import { SENTRY_OP } from '@sentry/conventions/attributes'; import { createTestServer } from '@sentry-internal/test-utils'; import { expect, it } from 'vitest'; import { createRunner } from '../../../../runner'; +import { getSpanOp, getSpansFromEnvelope } from '../../../../spanUtils'; it('preserves a positive sampling decision across an ignored child span', async ({ signal }) => { const [serverUrl, closeTestServer] = await createTestServer() @@ -17,14 +16,14 @@ it('preserves a positive sampling decision across an ignored child span', async const runner = createRunner(__dirname) .withServerUrl(serverUrl) .expect(envelope => { - const container = getSpanContainer(envelope); - const serverSpan = container.items.find(item => item.attributes[SENTRY_OP]?.value === 'http.server'); - const fetchSpan = container.items.find(item => item.attributes[SENTRY_OP]?.value === 'http.client'); + const spans = getSpansFromEnvelope(envelope); + const serverSpan = spans.find(span => getSpanOp(span) === 'http.server'); + const fetchSpan = spans.find(span => getSpanOp(span) === 'http.client'); expect(serverSpan?.is_segment).toBe(true); expect(serverSpan?.trace_id).toBe('12345678901234567890123456789012'); expect(fetchSpan?.parent_span_id).toBe(serverSpan?.span_id); - expect(container.items.some(item => item.name === 'ignored-child')).toBe(false); + expect(spans.some(span => span.name === 'ignored-child')).toBe(false); }) .start(signal); @@ -43,9 +42,3 @@ it('preserves a positive sampling decision across an ignored child span', async closeTestServer(); } }); - -function getSpanContainer(envelope: Envelope): SerializedStreamedSpanContainer { - const spanItem = envelope[1].find(item => item[0].type === 'span'); - expect(spanItem).toBeDefined(); - return spanItem![1] as SerializedStreamedSpanContainer; -} diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-child/wrangler.jsonc b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-child/wrangler.jsonc similarity index 100% rename from dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-child/wrangler.jsonc rename to dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-child/wrangler.jsonc diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-http-client/index.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-http-client/index.ts similarity index 94% rename from dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-http-client/index.ts rename to dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-http-client/index.ts index eee940bc8f3a..21e062199a80 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-http-client/index.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-http-client/index.ts @@ -9,7 +9,6 @@ export default Sentry.withSentry( (env: Env) => ({ dsn: env.SENTRY_DSN, tracesSampleRate: 0, - traceLifecycle: 'stream', ignoreSpans: [{ attributes: { 'sentry.op': 'http.client' } }], tracePropagationTargets: [env.SERVER_URL], }), diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-http-client/test.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-http-client/test.ts similarity index 70% rename from dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-http-client/test.ts rename to dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-http-client/test.ts index d7dc66316b88..0c390f63d877 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-http-client/test.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-http-client/test.ts @@ -1,8 +1,7 @@ -import type { Envelope, SerializedStreamedSpanContainer } from '@sentry/core'; -import { SENTRY_OP } from '@sentry/conventions/attributes'; import { createTestServer } from '@sentry-internal/test-utils'; import { expect, it } from 'vitest'; import { createRunner } from '../../../../runner'; +import { getSpanOp, getSpansFromEnvelope } from '../../../../spanUtils'; it('preserves a positive sampling decision when the outgoing fetch span is ignored', async ({ signal }) => { let outgoingSentryTrace: string | string[] | undefined; @@ -19,13 +18,13 @@ it('preserves a positive sampling decision when the outgoing fetch span is ignor const runner = createRunner(__dirname) .withServerUrl(serverUrl) .expect(envelope => { - const container = getSpanContainer(envelope); - const serverSpan = container.items.find(item => item.attributes[SENTRY_OP]?.value === 'http.server'); + const spans = getSpansFromEnvelope(envelope); + const serverSpan = spans.find(span => getSpanOp(span) === 'http.server'); expect(serverSpan?.is_segment).toBe(true); expect(serverSpan?.trace_id).toBe('12345678901234567890123456789012'); expect(outgoingSentryTrace).toBe(`12345678901234567890123456789012-${serverSpan?.span_id}-1`); - expect(container.items.some(item => item.attributes[SENTRY_OP]?.value === 'http.client')).toBe(false); + expect(spans.some(span => getSpanOp(span) === 'http.client')).toBe(false); }) .start(signal); @@ -44,9 +43,3 @@ it('preserves a positive sampling decision when the outgoing fetch span is ignor closeTestServer(); } }); - -function getSpanContainer(envelope: Envelope): SerializedStreamedSpanContainer { - const spanItem = envelope[1].find(item => item[0].type === 'span'); - expect(spanItem).toBeDefined(); - return spanItem![1] as SerializedStreamedSpanContainer; -} diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-http-client/wrangler.jsonc b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-http-client/wrangler.jsonc similarity index 100% rename from dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-http-client/wrangler.jsonc rename to dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-http-client/wrangler.jsonc diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-segment/index.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-segment/index.ts similarity index 93% rename from dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-segment/index.ts rename to dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-segment/index.ts index 457c8dce5ed6..08b098578610 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-segment/index.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-segment/index.ts @@ -9,7 +9,6 @@ export default Sentry.withSentry( (env: Env) => ({ dsn: env.SENTRY_DSN, tracesSampleRate: 0, - traceLifecycle: 'stream', ignoreSpans: [{ op: 'http.server' }], tracePropagationTargets: [env.SERVER_URL], }), diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-segment/test.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-segment/test.ts similarity index 100% rename from dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-segment/test.ts rename to dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-segment/test.ts diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-segment/wrangler.jsonc b/dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-segment/wrangler.jsonc similarity index 100% rename from dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans-streamed/continued-trace-segment/wrangler.jsonc rename to dev-packages/cloudflare-integration-tests/suites/tracing/ignoreSpans/continued-trace-segment/wrangler.jsonc