From 309a9e4a3f4f523c814f2e6453808888a82a7899 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 2 Sep 2026 16:01:33 +0200 Subject: [PATCH 1/2] test(e2e): Report which segment duplicates in the react-router-7 check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The double-instrumentation check has failed on develop since #23844 ported this app to span streaming, and its failure output says only that a bare `GET` segment showed up — not which instrumentation emitted it or which request it belongs to, which is exactly what is needed to tell a genuine duplicate apart from an unrouted second request. Collect `sentry.origin` and `url.path` alongside the name so the received value names the culprit, and assert the surviving segment comes from the instrumentation API rather than only checking its name. Co-Authored-By: Claude Opus 5 (1M context) --- .../performance/performance.server.test.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/performance.server.test.ts b/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/performance.server.test.ts index 2b83599e2560..797b978cf782 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/performance.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/performance.server.test.ts @@ -135,11 +135,18 @@ test.describe('server - instrumentation API performance', () => { 'Dev server emits extra http.server segments for module requests', ); - const httpServerSpanNames: string[] = []; + // A streamed server segment is named after the method alone until a route is matched, so a + // duplicate shows up as a bare `GET`. Collect the origin and path alongside the name — they are + // what says which instrumentation emitted the extra segment, and for which request. + const httpServerSegments: Array> = []; void waitForStreamedSpans(APP_NAME, spans => { for (const span of spans) { if (getSpanOp(span) === 'http.server' && span.is_segment) { - httpServerSpanNames.push(span.name); + httpServerSegments.push({ + name: span.name, + origin: span.attributes['sentry.origin']?.value, + urlPath: span.attributes['url.path']?.value, + }); } } return false; @@ -149,7 +156,13 @@ test.describe('server - instrumentation API performance', () => { // Give any (erroneous) duplicate span time to arrive before asserting. await page.waitForTimeout(3000); - expect(httpServerSpanNames).toEqual(['GET /performance']); + expect(httpServerSegments).toEqual([ + { + name: 'GET /performance', + origin: 'auto.http.react_router.instrumentation_api', + urlPath: expect.stringContaining('/performance'), + }, + ]); }); test('resolves a real http.route on routes without a loader/action', async ({ page }) => { From 5553242413e588c2e60453776f3d0bb54bd8c28d Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 2 Sep 2026 17:03:41 +0200 Subject: [PATCH 2/2] test(e2e): Skip the redirect in the react-router-7 double-instrumentation check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `/performance` is answered with a 301 to `/performance/`, so the navigation makes two requests and the redirect gets its own `http.server` segment. That segment should never be sent — `ignoreStatusCodes` covers 301 by default — but the option is applied in a `processEvent` hook that returns early for anything that is not a transaction, so span streaming emits it. The check has failed on develop since #23844 put this app on span streaming. Navigate straight to the final URL so the test stays about what it is named after. The underlying `ignoreStatusCodes` gap affects Node and Deno alike and is tracked separately. Co-Authored-By: Claude Opus 5 (1M context) --- .../tests/performance/performance.server.test.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/performance.server.test.ts b/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/performance.server.test.ts index 797b978cf782..e895b2e93f01 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/performance.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/performance.server.test.ts @@ -135,6 +135,12 @@ test.describe('server - instrumentation API performance', () => { 'Dev server emits extra http.server segments for module requests', ); + // Navigate to `/performance/` with the trailing slash: `/performance` is answered with a 301 to + // it, and that redirect is a second request with a second `http.server` segment. It should not + // be sent at all — `ignoreStatusCodes` covers 301 — but that option is only applied to + // transactions, so span streaming emits it. Going straight to the final URL keeps this test + // about double-instrumentation instead of failing on the redirect. + // // A streamed server segment is named after the method alone until a route is matched, so a // duplicate shows up as a bare `GET`. Collect the origin and path alongside the name — they are // what says which instrumentation emitted the extra segment, and for which request. @@ -152,7 +158,7 @@ test.describe('server - instrumentation API performance', () => { return false; }); - await page.goto(`/performance`); + await page.goto(`/performance/`); // Give any (erroneous) duplicate span time to arrive before asserting. await page.waitForTimeout(3000); @@ -160,7 +166,7 @@ test.describe('server - instrumentation API performance', () => { { name: 'GET /performance', origin: 'auto.http.react_router.instrumentation_api', - urlPath: expect.stringContaining('/performance'), + urlPath: '/performance/', }, ]); });