diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/instrument.client.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/instrument.client.ts index b3b083c3c644..ac3e62c26447 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/instrument.client.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/instrument.client.ts @@ -1,7 +1,6 @@ import * as Sentry from '@sentry/browser'; Sentry.init({ - traceLifecycle: 'static', environment: 'qa', dsn: 'https://public@dsn.ingest.sentry.io/1337', tracesSampleRate: 1.0, diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/server.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/server.ts index 154f291d0462..b35026939d88 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/server.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/src/server.ts @@ -4,7 +4,6 @@ import handler from '@tanstack/react-start/server-entry'; export default Sentry.withSentry( (env: Env) => ({ - traceLifecycle: 'static', dsn: env.E2E_TEST_DSN, tunnel: 'http://localhost:3031/', tracesSampleRate: 1.0, diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/errors.test.ts index f03a611e9592..c53a938f98aa 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; +import { getSpanOp, waitForError, waitForStreamedSpan } from '@sentry-internal/test-utils'; test('Sends client-side error to Sentry', async ({ page }) => { const errorEventPromise = waitForError('tanstackstart-react-cloudflare', errorEvent => { @@ -107,16 +107,16 @@ test('Does not send SSR loader error to Sentry', async ({ baseURL, page }) => { if (!event.type && event.exception?.values?.[0]?.value === 'Sentry SSR Test Error') { errorEventOccurred = true; } - return event?.transaction === 'GET /ssr-error'; + return false; }); - const transactionEventPromise = waitForTransaction('tanstackstart-react-cloudflare', transactionEvent => { - return transactionEvent?.transaction === 'GET /ssr-error'; + const serverSpanPromise = waitForStreamedSpan('tanstackstart-react-cloudflare', span => { + return span.is_segment && getSpanOp(span) === 'http.server' && span.attributes['url.path']?.value === '/ssr-error'; }); await page.goto('/ssr-error'); - await transactionEventPromise; + await serverSpanPromise; await (await fetch(`${baseURL}/api/flush`)).text(); diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/trace-propagation.test.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/trace-propagation.test.ts index f96ea3ce5f71..8fecc24b93e1 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/trace-propagation.test.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/trace-propagation.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/test-utils'; +import { collectStreamedSpans, getSpanOp } from '@sentry-internal/test-utils'; test.describe('Trace propagation', () => { test('should inject metatags in ssr pageload', async ({ page }) => { @@ -18,19 +18,30 @@ test.describe('Trace propagation', () => { }); test('should have trace connection between server and client', async ({ page }) => { - const serverTxPromise = waitForTransaction('tanstackstart-react-cloudflare', transactionEvent => { - return transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /'; - }); - - const clientTxPromise = waitForTransaction('tanstackstart-react-cloudflare', transactionEvent => { - return transactionEvent?.contexts?.trace?.op === 'pageload' && transactionEvent?.transaction === '/'; + const spansPromise = collectStreamedSpans('tanstackstart-react-cloudflare', spans => { + return ( + spans.some( + span => span.is_segment && getSpanOp(span) === 'http.server' && span.attributes['url.path']?.value === '/', + ) && + spans.some( + span => + span.is_segment && + getSpanOp(span) === 'pageload' && + (span.name === '/' || span.attributes['url.path']?.value === '/'), + ) + ); }); await page.goto('/'); - const serverTx = await serverTxPromise; - const clientTx = await clientTxPromise; + const spans = await spansPromise; + const serverSpan = spans.find( + span => span.is_segment && getSpanOp(span) === 'http.server' && span.attributes['url.path']?.value === '/', + ); + const clientSpan = spans.find(span => span.is_segment && getSpanOp(span) === 'pageload'); - expect(clientTx.contexts?.trace?.trace_id).toBe(serverTx.contexts?.trace?.trace_id); + expect(serverSpan).toBeDefined(); + expect(clientSpan).toBeDefined(); + expect(clientSpan?.trace_id).toBe(serverSpan?.trace_id); }); }); diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/transaction.test.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/transaction.test.ts index 8bdb0dbc9d7b..d6365da67be8 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/transaction.test.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-cloudflare/tests/transaction.test.ts @@ -1,13 +1,19 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/test-utils'; - -test('Sends a server function transaction with span from wrapFetchWithSentry', async ({ page }) => { - const transactionEventPromise = waitForTransaction('tanstackstart-react-cloudflare', transactionEvent => { - return ( - transactionEvent?.contexts?.trace?.op === 'http.server' && - !!transactionEvent?.transaction?.startsWith('GET /_serverFn') - ); - }); +import { collectStreamedSpans, getSpanOp, waitForStreamedSpan } from '@sentry-internal/test-utils'; + +function isServerFnSegment(span: Parameters[0]): boolean { + return ( + !!span.is_segment && + getSpanOp(span) === 'http.server' && + String(span.attributes['url.path']?.value ?? '').startsWith('/_serverFn') + ); +} + +test('Sends a server function span with wrapFetchWithSentry', async ({ page }) => { + const spansPromise = collectStreamedSpans( + 'tanstackstart-react-cloudflare', + spans => spans.some(isServerFnSegment) && spans.some(span => span.name === 'GET /_serverFn/testLog'), + ); await page.goto('/test-serverFn'); @@ -15,36 +21,37 @@ test('Sends a server function transaction with span from wrapFetchWithSentry', a await page.locator('#server-fn-btn').click(); - const transactionEvent = await transactionEventPromise; + const spans = await spansPromise; - expect(transactionEvent.contexts?.trace).toMatchObject({ - op: 'http.server', - origin: 'auto.http.cloudflare', + const serverSegment = spans.find(isServerFnSegment); + expect(serverSegment?.attributes).toMatchObject({ + 'sentry.op': { type: 'string', value: 'http.server' }, + 'sentry.origin': { type: 'string', value: 'auto.http.cloudflare' }, }); - expect(transactionEvent?.spans).toHaveLength(1); - expect(transactionEvent?.spans).toEqual([ - expect.objectContaining({ - description: 'GET /_serverFn/testLog', - op: 'function', - origin: 'auto.function.tanstackstart.server', - data: { - 'sentry.op': 'function', - 'sentry.origin': 'auto.function.tanstackstart.server', - 'tanstackstart.function.id': expect.any(String), - 'tanstackstart.function.filename': 'src/routes/test-serverFn.tsx', - }, - }), - ]); + expect(spans).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + name: 'GET /_serverFn/testLog', + attributes: expect.objectContaining({ + 'sentry.op': { type: 'string', value: 'function' }, + 'sentry.origin': { type: 'string', value: 'auto.function.tanstackstart.server' }, + 'tanstackstart.function.id': { type: 'string', value: expect.any(String) }, + 'tanstackstart.function.filename': { type: 'string', value: 'src/routes/test-serverFn.tsx' }, + }), + }), + ]), + ); }); -test('Sends a server function transaction for a nested server function with manual span', async ({ page }) => { - const transactionEventPromise = waitForTransaction('tanstackstart-react-cloudflare', transactionEvent => { - return ( - transactionEvent?.contexts?.trace?.op === 'http.server' && - !!transactionEvent?.transaction?.startsWith('GET /_serverFn') - ); - }); +test('Sends a server function span for a nested server function with manual span', async ({ page }) => { + const spansPromise = collectStreamedSpans( + 'tanstackstart-react-cloudflare', + spans => + spans.some(isServerFnSegment) && + spans.some(span => span.name === 'GET /_serverFn/testNestedLog') && + spans.some(span => span.name === 'testNestedLog'), + ); await page.goto('/test-serverFn'); @@ -52,48 +59,47 @@ test('Sends a server function transaction for a nested server function with manu await page.locator('#server-fn-nested-btn').click(); - const transactionEvent = await transactionEventPromise; + const spans = await spansPromise; - expect(transactionEvent.contexts?.trace).toMatchObject({ - op: 'http.server', - origin: 'auto.http.cloudflare', + const serverSegment = spans.find(isServerFnSegment); + expect(serverSegment?.attributes).toMatchObject({ + 'sentry.op': { type: 'string', value: 'http.server' }, + 'sentry.origin': { type: 'string', value: 'auto.http.cloudflare' }, }); - expect(transactionEvent?.spans).toHaveLength(2); - expect(transactionEvent?.spans).toEqual( + expect(spans).toEqual( expect.arrayContaining([ expect.objectContaining({ - description: 'GET /_serverFn/testNestedLog', - op: 'function', - origin: 'auto.function.tanstackstart.server', - data: { - 'sentry.op': 'function', - 'sentry.origin': 'auto.function.tanstackstart.server', - 'tanstackstart.function.id': expect.any(String), - 'tanstackstart.function.filename': 'src/routes/test-serverFn.tsx', - }, + name: 'GET /_serverFn/testNestedLog', + attributes: expect.objectContaining({ + 'sentry.op': { type: 'string', value: 'function' }, + 'sentry.origin': { type: 'string', value: 'auto.function.tanstackstart.server' }, + 'tanstackstart.function.id': { type: 'string', value: expect.any(String) }, + 'tanstackstart.function.filename': { type: 'string', value: 'src/routes/test-serverFn.tsx' }, + }), }), expect.objectContaining({ - description: 'testNestedLog', - origin: 'manual', + name: 'testNestedLog', + attributes: expect.objectContaining({ + 'sentry.origin': { type: 'string', value: 'manual' }, + }), }), ]), ); }); -test('Sends server-side transaction for page request', async ({ baseURL }) => { - const transactionEventPromise = waitForTransaction('tanstackstart-react-cloudflare', transactionEvent => { - return transactionEvent?.contexts?.trace?.op === 'http.server' && transactionEvent?.transaction === 'GET /'; +test('Sends server-side span for page request', async ({ baseURL }) => { + const serverSpanPromise = waitForStreamedSpan('tanstackstart-react-cloudflare', span => { + return span.is_segment && getSpanOp(span) === 'http.server' && span.attributes['url.path']?.value === '/'; }); await fetch(`${baseURL}/`); - const transactionEvent = await transactionEventPromise; + const serverSpan = await serverSpanPromise; - expect(transactionEvent.transaction).toBe('GET /'); - expect(transactionEvent.contexts?.trace).toMatchObject({ - op: 'http.server', - origin: 'auto.http.cloudflare', - status: 'ok', + expect(serverSpan.attributes).toMatchObject({ + 'sentry.op': { type: 'string', value: 'http.server' }, + 'sentry.origin': { type: 'string', value: 'auto.http.cloudflare' }, }); + expect(serverSpan.status).toBe('ok'); });