Skip to content

feat(core): Add route provider API for parameterized route resolution - #23551

Open
logaretm wants to merge 7 commits into
developfrom
awad/route-provider-api
Open

logaretm wants to merge 7 commits into
developfrom
awad/route-provider-api

Conversation

@logaretm

@logaretm logaretm commented Aug 24, 2026 •

Copy link
Copy Markdown
Member

Adds the route provider API to core so framework SDKs can register how to resolve a URL to a parameterized route, and wires up bfcacheMetricsIntegration as the first consumer since that is where the fragmentation currently produces a raw URL on a metric dimension.

bfcacheMetrics keeps its pathname fallback, so nothing changes until a provider is registered.

closes #23556

@github-actions

github-actions Bot commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 29.24 kB - -
@sentry/browser - with treeshaking flags 27.5 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 27.4 kB - -
@sentry/browser (incl. Tracing) 51.16 kB +0.02% +9 B 🔺
@sentry/browser (incl. Tracing + Span Streaming) 51.18 kB +0.02% +8 B 🔺
@sentry/browser (incl. Tracing, Profiling) 54.19 kB +0.02% +9 B 🔺
@sentry/browser (incl. Tracing, Replay) 90.77 kB +0.01% +8 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 79.87 kB +0.02% +9 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 95.47 kB +0.01% +7 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 108.42 kB +0.01% +8 B 🔺
@sentry/browser (incl. Feedback) 46.76 kB - -
@sentry/browser (incl. sendFeedback) 34.3 kB - -
@sentry/browser (incl. FeedbackAsync) 39.41 kB - -
@sentry/browser (incl. Metrics) 30.25 kB - -
@sentry/browser (incl. Logs) 30.51 kB - -
@sentry/browser (incl. Metrics & Logs) 31.18 kB - -
@sentry/react 31 kB - -
@sentry/react (incl. Tracing) 53.46 kB +0.03% +11 B 🔺
@sentry/vue 36.74 kB - -
@sentry/vue (incl. Tracing) 53.71 kB +0.02% +10 B 🔺
@sentry/svelte 29.26 kB - -
CDN Bundle 30.93 kB - -
CDN Bundle (incl. Tracing) 51.7 kB +0.03% +12 B 🔺
CDN Bundle (incl. Logs, Metrics) 33.2 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 53.67 kB +0.03% +11 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) 73.92 kB - -
CDN Bundle (incl. Tracing, Replay) 89.29 kB +0.02% +9 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 91.25 kB +0.01% +9 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 95.46 kB +0.02% +11 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 97.43 kB +0.02% +12 B 🔺
CDN Bundle - uncompressed 91.4 kB - -
CDN Bundle (incl. Tracing) - uncompressed 153.81 kB +0.03% +41 B 🔺
CDN Bundle (incl. Logs, Metrics) - uncompressed 97.97 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 159.77 kB +0.03% +41 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 227.54 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 273.54 kB +0.02% +41 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 279.48 kB +0.02% +41 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 287.25 kB +0.02% +41 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 293.17 kB +0.02% +41 B 🔺
@sentry/nextjs (client) 55.78 kB +0.02% +11 B 🔺
@sentry/sveltekit (client) 51.6 kB +0.02% +9 B 🔺
@sentry/core/server 39.96 kB +0.03% +11 B 🔺
@sentry/core/browser 13.63 kB - -
@sentry/node 133.91 kB +0.02% +16 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 82.43 kB - -
@sentry/node - without tracing 90.47 kB +0.04% +28 B 🔺
@sentry/node - without channel injection 112.42 kB +0.02% +21 B 🔺
@sentry/aws-serverless 98.72 kB +0.02% +14 B 🔺
@sentry/cloudflare (withSentry) - minified 206.53 kB +0.03% +49 B 🔺
@sentry/cloudflare (withSentry) 513.8 kB +0.02% +70 B 🔺

View base workflow run

@logaretm
logaretm force-pushed the awad/route-provider-api branch 3 times, most recently from 905570f to 488ffe0 Compare August 24, 2026 20:57
@logaretm
logaretm requested review from Lms24 and msonnb August 31, 2026 14:17
@logaretm

Copy link
Copy Markdown
Member Author

I requested a draft review because I need opinions on this stack but may not be around to merge this till next week.

@Lms24 Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought a bit about the router provider and I like the idea of it! Initially, I was wondering if we could just get away with a url -> route map or cache. But the idea of having a "live" resolver for the framework SDKs that support resolving a url to a route is a good one! Bonus points that this is not something users have to configure but is (for now) baked into browserTracingIntegrations. We can see where exactly this makes more sense as we split up the integration into sub integrations.

I suggest running this by the framework WG since it will primarily concern framework SDKs. I looked into a couple of the stacked framework PRs and the changes look fairly minimal which is nice!

Just had some minor nits for now

Comment thread packages/core/src/routing.ts Outdated
* Normalizes to a real `URL` so providers never have to parse, and relative locations (which memory
* routers hand around) resolve against the document.
*/
function toURLObject(url: string): URL | undefined {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

l: I think we already have a helper like this in core 🤔

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, the narrower shape still fits this functionality

Comment thread packages/browser-utils/src/routing.ts
@logaretm
logaretm force-pushed the awad/route-provider-api branch from 488ffe0 to 3754c50 Compare August 31, 2026 16:39
@logaretm

Copy link
Copy Markdown
Member Author

We can see where exactly this makes more sense as we split up the integration into sub integrations.

That was one of my goals, breaking up the dependency between route parameterization and tracing because parameterization could be needed in logs/metrics/errors or whatever.

This brings me to the next point, so it feels like we need a breaking change to break up this dependency in those frameworks, for example the Vue SDK accepts the router in browserTracingIntegration options, meaning we have no access to the router passively otherwise. Tanstack is in the same boat, seems like the other SDKs are fine tho.

The base API is fine, but I will need to do some more work on the stack in downstream SDKs.

I suggest running this by the framework WG since it will primarily concern framework SDKs. I looked into a couple of the stacked framework PRs and the changes look fairly minimal which is nice!

Will post in the channel!

@logaretm

logaretm commented Aug 31, 2026 •

Copy link
Copy Markdown
Member Author

This was a 9 PR stack. It's now only a few, I wanted to record the reasoning.

Every provider ended up registered inside a tracing integration, which is the coupling the work was meant to break. The deletions I expected only unlock once browserTracingIntegration names spans from the provider, and currently half the framework SDKs have a few blockers:

  • Route sometimes is only available through browserTracingIntegration like Vue and Tanstack.
  • Some routing instrumentation implementation is cache based rather than matcher based, which limits the functionality here.
  • Some SDKs have to do lifecycle adjustments, rather than starting a span on history change, they need their own hooks to listen for.

So these 2 PRs do the smallest useful thing, parameterization that doesn't need tracing and that only fits in Next.js and Remix because these are only ones that have decoupled implementations (by virtue of the routes being accessible globally), Astro may also fit as well.

I think what I have here is a good base that we can either merge today and improve later, or expand on the base API to address these concerns.

logaretm added a commit that referenced this pull request Sep 10, 2026
… name

No router event fires on a bfcache restore, so the span falls back to the raw
pathname. In a plain browser app that matches every other navigation, but in a
framework app it is the only navigation span not named from a parameterized
route. #23551 gives us `resolveCurrentRoute()` to fix it.
Framework SDKs can register a provider that resolves a URL to a low-cardinality
route name, so integrations stop each reaching for the route their own way.

Wires up `bfcacheIntegration` as the first consumer: its segment name ends up as
a metric dimension, where an unparameterized URL is unbounded cardinality.
@logaretm
logaretm force-pushed the awad/route-provider-api branch 2 times, most recently from 4f0b460 to 589ff5c Compare September 24, 2026 18:14
@logaretm

Copy link
Copy Markdown
Member Author

bugbot run

Providers only read the pathname, search and hash, so they get those instead of a
full `URL`, and core keeps a single URL parser.
…-utils`

It is browser-only, and `browser-utils` is where web vitals will consume it.
`@sentry/browser` re-exports it as the public API.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread packages/browser-utils/src/routing.ts
Comment thread packages/browser-utils/src/routing.ts
Comment thread packages/browser/src/exports.ts Outdated
It evicted the oldest entry whenever the map was full, even if the key was
already in it, and left an updated key in its old position instead of making it
the most recently used.
Its only consumer, `bfcacheMetricsIntegration`, is npm-only as well.
@logaretm

Copy link
Copy Markdown
Member Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit d758fc0. Configure here.

@logaretm
logaretm marked this pull request as ready for review September 24, 2026 19:49
@logaretm
logaretm requested a review from a team as a code owner September 24, 2026 19:49
@logaretm
logaretm requested review from Lms24 and removed request for a team September 24, 2026 19:49
@logaretm
logaretm requested review from a team, chargome, nicohrubec and s1gr1d and removed request for a team September 24, 2026 19:50
Framework SDKs know their provider at `init`, so passing it as an option has it
in place before any integration sets up, without relying on an integration of
its own. `setRouteProvider` still replaces it at runtime.
@github-actions

Copy link
Copy Markdown
Contributor

👋 @msonnb — Please review this PR when you get a chance!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Route parameterization is fragmented across browser integrations

2 participants