From 829d885c3c277c10b6c754a0d760a4c7d9b20b8b Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Mon, 1 Sep 2025 12:28:10 +0200 Subject: [PATCH 1/2] fix(astro): Ensure span name from `beforeStartSpan` isn't overwritten --- .../astro-5/sentry.client.config.js | 14 +++- .../astro-5/src/pages/blog/[slug].astro | 12 ++++ .../astro-5/src/pages/index.astro | 1 + .../astro-5/tests/tracing.dynamic.test.ts | 14 ++++ .../src/client/browserTracingIntegration.ts | 72 ++++++++++++------- 5 files changed, 85 insertions(+), 28 deletions(-) create mode 100644 dev-packages/e2e-tests/test-applications/astro-5/src/pages/blog/[slug].astro diff --git a/dev-packages/e2e-tests/test-applications/astro-5/sentry.client.config.js b/dev-packages/e2e-tests/test-applications/astro-5/sentry.client.config.js index 7bb40f0c60d4..d934cb6937eb 100644 --- a/dev-packages/e2e-tests/test-applications/astro-5/sentry.client.config.js +++ b/dev-packages/e2e-tests/test-applications/astro-5/sentry.client.config.js @@ -5,5 +5,17 @@ Sentry.init({ environment: 'qa', tracesSampleRate: 1.0, tunnel: 'http://localhost:3031/', // proxy server - integrations: [Sentry.browserTracingIntegration()], + integrations: [ + Sentry.browserTracingIntegration({ + beforeStartSpan: opts => { + if (opts.name.startsWith('/blog/')) { + return { + ...opts, + name: window.location.pathname, + } + } + return opts; + } + }) + ], }); diff --git a/dev-packages/e2e-tests/test-applications/astro-5/src/pages/blog/[slug].astro b/dev-packages/e2e-tests/test-applications/astro-5/src/pages/blog/[slug].astro new file mode 100644 index 000000000000..72b221da4a70 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/astro-5/src/pages/blog/[slug].astro @@ -0,0 +1,12 @@ +--- +import Layout from '../../layouts/Layout.astro'; + +export const prerender = false; + +const { slug } = Astro.params; + +--- + + +

Blog post: {slug}

+
diff --git a/dev-packages/e2e-tests/test-applications/astro-5/src/pages/index.astro b/dev-packages/e2e-tests/test-applications/astro-5/src/pages/index.astro index e598994f0b8e..7032437764f8 100644 --- a/dev-packages/e2e-tests/test-applications/astro-5/src/pages/index.astro +++ b/dev-packages/e2e-tests/test-applications/astro-5/src/pages/index.astro @@ -17,6 +17,7 @@ import Layout from '../layouts/Layout.astro'; Static Page Server Island Test Parametrized Routes + Route Parametrization override diff --git a/dev-packages/e2e-tests/test-applications/astro-5/tests/tracing.dynamic.test.ts b/dev-packages/e2e-tests/test-applications/astro-5/tests/tracing.dynamic.test.ts index b7dda807c65c..9151c13907af 100644 --- a/dev-packages/e2e-tests/test-applications/astro-5/tests/tracing.dynamic.test.ts +++ b/dev-packages/e2e-tests/test-applications/astro-5/tests/tracing.dynamic.test.ts @@ -369,4 +369,18 @@ test.describe('parametrized vs static paths', () => { request: { url: expect.stringContaining('/user-page/settings') }, }); }); + + test('allows for span name override via beforeStartSpan', async ({ page }) => { + const clientPageloadTxnPromise = waitForTransaction('astro-5', txnEvent => { + return txnEvent?.transaction?.startsWith('/blog/') ?? false; + }); + + await page.goto('/blog/my-post'); + + const clientPageloadTxn = await clientPageloadTxnPromise; + expect(clientPageloadTxn).toMatchObject({ + transaction: '/blog/my-post', + transaction_info: { source: 'custom' }, + }); + }); }); diff --git a/packages/astro/src/client/browserTracingIntegration.ts b/packages/astro/src/client/browserTracingIntegration.ts index 7f8576671635..9e36a5e252f7 100644 --- a/packages/astro/src/client/browserTracingIntegration.ts +++ b/packages/astro/src/client/browserTracingIntegration.ts @@ -1,6 +1,6 @@ -import { browserTracingIntegration as originalBrowserTracingIntegration, WINDOW } from '@sentry/browser'; +import { browserTracingIntegration as originalBrowserTracingIntegration, startBrowserTracingPageLoadSpan, WINDOW } from '@sentry/browser'; import type { Integration, TransactionSource } from '@sentry/core'; -import { debug, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core'; +import { browserPerformanceTimeOrigin, debug, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core'; import { DEBUG_BUILD } from '../debug-build'; /** @@ -18,35 +18,53 @@ function getMetaContent(metaName: string): string | undefined { export function browserTracingIntegration( options: Parameters[0] = {}, ): Integration { - const integration = originalBrowserTracingIntegration(options); + const integration = originalBrowserTracingIntegration({...options, instrumentPageLoad: false}); return { ...integration, - setup(client) { - // Original integration setup call - integration.setup?.(client); - - client.on('afterStartPageLoadSpan', pageLoadSpan => { - const routeNameFromMetaTags = getMetaContent('sentry-route-name'); - - if (routeNameFromMetaTags) { - let decodedRouteName; - try { - decodedRouteName = decodeURIComponent(routeNameFromMetaTags); - } catch { - // We ignore errors here, e.g. if the value cannot be URL decoded. - return; - } - - DEBUG_BUILD && debug.log(`[Tracing] Using route name from Sentry HTML meta-tag: ${decodedRouteName}`); - - pageLoadSpan.updateName(decodedRouteName); - pageLoadSpan.setAttributes({ - [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route' as TransactionSource, - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.astro', + afterAllSetup(client) { + // Original integration afterAllSetup call + integration.afterAllSetup?.(client); + + if (WINDOW.location) { + if (options.instrumentPageLoad != false) { + const origin = browserPerformanceTimeOrigin(); + + const { name, source } = getPageloadSpanName(); + + startBrowserTracingPageLoadSpan(client, { + name, + // pageload should always start at timeOrigin (and needs to be in s, not ms) + startTime: origin ? origin / 1000 : undefined, + attributes: { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source, + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.astro', + }, }); } - }); - }, + } + } + }; +} + +function getPageloadSpanName(): {name: string, source: TransactionSource} { + try { + const routeNameFromMetaTags = getMetaContent('sentry-route-name'); + if (routeNameFromMetaTags) { + const decodedRouteName = decodeURIComponent(routeNameFromMetaTags); + + DEBUG_BUILD && debug.log(`[Tracing] Using route name from Sentry HTML meta-tag: ${decodedRouteName}`); + + return { + name: decodedRouteName, + source: 'route', + }; + } + } catch { + // fail silently if decoding or reading the meta tag fails + } + return { + name: WINDOW.location.pathname, + source: 'url', }; } From 8fffb16290884e7acb7bfd23c733555556eaa4ef Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Mon, 1 Sep 2025 12:42:10 +0200 Subject: [PATCH 2/2] formatting --- .../astro-5/sentry.client.config.js | 6 +++--- .../astro-5/src/pages/blog/[slug].astro | 1 - .../src/client/browserTracingIntegration.ts | 19 ++++++++++++++----- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/astro-5/sentry.client.config.js b/dev-packages/e2e-tests/test-applications/astro-5/sentry.client.config.js index d934cb6937eb..865bb18ce84c 100644 --- a/dev-packages/e2e-tests/test-applications/astro-5/sentry.client.config.js +++ b/dev-packages/e2e-tests/test-applications/astro-5/sentry.client.config.js @@ -12,10 +12,10 @@ Sentry.init({ return { ...opts, name: window.location.pathname, - } + }; } return opts; - } - }) + }, + }), ], }); diff --git a/dev-packages/e2e-tests/test-applications/astro-5/src/pages/blog/[slug].astro b/dev-packages/e2e-tests/test-applications/astro-5/src/pages/blog/[slug].astro index 72b221da4a70..b776fa25c494 100644 --- a/dev-packages/e2e-tests/test-applications/astro-5/src/pages/blog/[slug].astro +++ b/dev-packages/e2e-tests/test-applications/astro-5/src/pages/blog/[slug].astro @@ -4,7 +4,6 @@ import Layout from '../../layouts/Layout.astro'; export const prerender = false; const { slug } = Astro.params; - --- diff --git a/packages/astro/src/client/browserTracingIntegration.ts b/packages/astro/src/client/browserTracingIntegration.ts index 9e36a5e252f7..5ffdb3fd8860 100644 --- a/packages/astro/src/client/browserTracingIntegration.ts +++ b/packages/astro/src/client/browserTracingIntegration.ts @@ -1,6 +1,15 @@ -import { browserTracingIntegration as originalBrowserTracingIntegration, startBrowserTracingPageLoadSpan, WINDOW } from '@sentry/browser'; +import { + browserTracingIntegration as originalBrowserTracingIntegration, + startBrowserTracingPageLoadSpan, + WINDOW, +} from '@sentry/browser'; import type { Integration, TransactionSource } from '@sentry/core'; -import { browserPerformanceTimeOrigin, debug, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core'; +import { + browserPerformanceTimeOrigin, + debug, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, +} from '@sentry/core'; import { DEBUG_BUILD } from '../debug-build'; /** @@ -18,7 +27,7 @@ function getMetaContent(metaName: string): string | undefined { export function browserTracingIntegration( options: Parameters[0] = {}, ): Integration { - const integration = originalBrowserTracingIntegration({...options, instrumentPageLoad: false}); + const integration = originalBrowserTracingIntegration({ ...options, instrumentPageLoad: false }); return { ...integration, @@ -43,11 +52,11 @@ export function browserTracingIntegration( }); } } - } + }, }; } -function getPageloadSpanName(): {name: string, source: TransactionSource} { +function getPageloadSpanName(): { name: string; source: TransactionSource } { try { const routeNameFromMetaTags = getMetaContent('sentry-route-name'); if (routeNameFromMetaTags) {