From 215561c60e71efa404672f699e2a1b1fae04bb17 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Mon, 24 Aug 2026 16:09:59 -0400 Subject: [PATCH] feat(angular): Register a route provider backed by resolved routes The parameterized route only exists on Angular's `ResolveEnd` event, resolved from the router state snapshot, so there is no matcher to call. `TraceService` already derives it to rename the span, so it records it on the way through. --- packages/angular/src/tracing.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/angular/src/tracing.ts b/packages/angular/src/tracing.ts index c45c3d7f4185..de631c36e679 100644 --- a/packages/angular/src/tracing.ts +++ b/packages/angular/src/tracing.ts @@ -25,8 +25,10 @@ import { CODE_FUNCTION_NAME, SENTRY_OP, URL_FULL, URL_PATH, URL_TEMPLATE } from import { FUNCTION } from '@sentry/conventions/op'; import type { Integration, Span } from '@sentry/core'; import { + createCachedRouteProvider, debug, parseStringToURLObject, + setRouteProvider, stripUrlQueryAndFragment, timestampInSeconds, filterCollectedUrl, @@ -40,6 +42,11 @@ import { runOutsideAngular } from './zone'; let instrumentationInitialized: boolean; +// The parameterized route only exists on Angular's `ResolveEnd` event, resolved from the router +// state snapshot, so there is no matcher the integration could call. `TraceService` records each +// route as it resolves and the provider answers from that. +const ROUTE_PROVIDER = createCachedRouteProvider(); + /** * A custom browser tracing integration for Angular. * @@ -54,10 +61,18 @@ export function browserTracingIntegration( instrumentationInitialized = true; } - return originalBrowserTracingIntegration({ + const integration = originalBrowserTracingIntegration({ ...options, instrumentNavigation: false, }); + + return { + ...integration, + setup(client) { + setRouteProvider(ROUTE_PROVIDER, client); + integration.setup?.(client); + }, + }; } /** @@ -171,6 +186,7 @@ export class TraceService implements OnDestroy { ); if (route) { + ROUTE_PROVIDER.record(stripUrlQueryAndFragment(event.urlAfterRedirects), route); getCurrentScope().setTransactionName(route); }