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..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 @@ -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..b776fa25c494 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/astro-5/src/pages/blog/[slug].astro @@ -0,0 +1,11 @@ +--- +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..5ffdb3fd8860 100644 --- a/packages/astro/src/client/browserTracingIntegration.ts +++ b/packages/astro/src/client/browserTracingIntegration.ts @@ -1,6 +1,15 @@ -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 +27,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', + }; +}