diff --git a/packages/sveltekit/src/client/browserTracingIntegration.ts b/packages/sveltekit/src/client/browserTracingIntegration.ts index 3fb9b65bd1a7..fa1299f7ca77 100644 --- a/packages/sveltekit/src/client/browserTracingIntegration.ts +++ b/packages/sveltekit/src/client/browserTracingIntegration.ts @@ -1,5 +1,7 @@ import type { Integration } from '@sentry/core'; +import { setRouteProvider } from '@sentry/core'; import { browserTracingIntegration as originalBrowserTracingIntegration } from '@sentry/svelte'; +import { routeProvider } from './routeCache'; // The `sentrySvelteKit()` Vite plugin redirects this to the Svelte 4 or Svelte 5 variant per Kit // version; without the plugin it resolves via `exports` to the Svelte 4 variant, so builds don't break. import { instrumentSvelteKitTracing } from '@sentry/sveltekit/browser-tracing-variant'; @@ -20,6 +22,10 @@ export function browserTracingIntegration( return { ...integration, + setup: client => { + setRouteProvider(routeProvider, client); + integration.setup?.(client); + }, afterAllSetup: client => { integration.afterAllSetup(client); instrumentSvelteKitTracing(client, options); diff --git a/packages/sveltekit/src/client/routeCache.ts b/packages/sveltekit/src/client/routeCache.ts new file mode 100644 index 000000000000..ec61ee2741a2 --- /dev/null +++ b/packages/sveltekit/src/client/routeCache.ts @@ -0,0 +1,15 @@ +import { createCachedRouteProvider } from '@sentry/core'; + +// SvelteKit has no public route matcher, and `page.route.id` is not available synchronously, so the +// provider answers from route ids the instrumentation has already seen rather than by matching. +export const routeProvider = createCachedRouteProvider(); + +/** + * Records the parameterized route id SvelteKit reported for a path. + * + * Called from both the Kit 2 and Kit 3 instrumentation, since `page.route.id` is the only place the + * route id is available. + */ +export function recordRouteId(pathname: string | undefined, routeId: string | null | undefined): void { + routeProvider.record(pathname, routeId); +} diff --git a/packages/sveltekit/src/client/svelte4BrowserTracing.ts b/packages/sveltekit/src/client/svelte4BrowserTracing.ts index 818a8ffe2f61..5dbfd4de479e 100644 --- a/packages/sveltekit/src/client/svelte4BrowserTracing.ts +++ b/packages/sveltekit/src/client/svelte4BrowserTracing.ts @@ -17,6 +17,7 @@ import type { Navigation, Page } from '@sveltejs/kit'; // eslint-disable-next-line typescript/no-deprecated import { navigating, page } from '$app/stores'; import type { Readable } from 'svelte/store'; +import { recordRouteId } from './routeCache'; /** * SvelteKit 2 / Svelte 4 browser tracing (`$app/stores`). Selected at build time, so it's only @@ -62,6 +63,8 @@ function _instrumentPageload(client: Client, pageStore: Readable): void { const routeId = pageState.route?.id; + recordRouteId(pageState.url?.pathname, routeId); + if (routeId) { pageloadSpan.updateName(routeId); pageloadSpan.setAttributes({ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route', [URL_TEMPLATE]: routeId }); @@ -105,6 +108,8 @@ function _instrumentNavigations(client: Client, navigatingStore: Readable { + recordRouteId(WINDOW.location?.pathname, routeId); + if (routeId) { pageLoadSpan.updateName(routeId); pageLoadSpan.setAttributes({ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route', [URL_TEMPLATE]: routeId }); @@ -88,6 +91,8 @@ function _instrumentNavigations(client: Client): void { const parameterizedRouteOrigin = from?.route.id; const parameterizedRouteDestination = to?.route.id; + recordRouteId(to?.url.pathname, parameterizedRouteDestination); + routingSpan?.end(); const navigationInfo = {