From 04a0befe7140fd345678f1da5ce33246975cff77 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 b0456e144c37..2b7eba1a47d4 100644 --- a/packages/angular/src/tracing.ts +++ b/packages/angular/src/tracing.ts @@ -31,11 +31,13 @@ import { import { FUNCTION, ROUTER } from '@sentry/conventions/op'; import type { Integration, Span } from '@sentry/core'; import { + createCachedRouteProvider, debug, hasSpanStreamingEnabled, NAVIGATION_SPAN_NAME_FALLBACK, parseStringToURLObject, ROUTER_SPAN_NAME_FALLBACK, + setRouteProvider, stripUrlQueryAndFragment, timestampInSeconds, filterCollectedUrl, @@ -49,6 +51,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. * @@ -63,10 +70,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); + }, + }; } /** @@ -182,6 +197,7 @@ export class TraceService implements OnDestroy { ); if (route) { + ROUTE_PROVIDER.record(stripUrlQueryAndFragment(event.urlAfterRedirects), route); getCurrentScope().setTransactionName(route); }