feat(browser): Report web vitals for soft navigations - #23425
Draft
logaretm wants to merge 7 commits into
Draft
Conversation
Report LCP, CLS and INP for soft navigations, using upstream web-vitals'
`reportSoftNavs` option and the browser's Soft Navigations API.
Soft navigation vitals are correlated back to the SDK's navigation spans
through the `interactionId` of the interaction that triggered the
navigation, which both the `soft-navigation` entry and the interaction's
own Event Timing entry carry.
Opt-in via `webVitalsIntegration({ reportSoftNavs: true })` or
`browserTracingIntegration({ _experiments: { enableSoftNavWebVitals: true } })`.
Contributor
size-limit report 📦
|
Drop `reportAllChanges` when soft navigations are on, so every value a handler receives is already final for its navigation and can be sent as a span directly. Replaces the accumulate/flush state machine, and leaves the default path untouched.
The Soft Navigations API is stable in Chromium 151+, web-vitals ships `reportSoftNavs` as an ordinary option, and span streaming is already the default, so there is nothing experimental left to gate on. `enableSoftNavWebVitals` becomes a plain `browserTracingIntegration` option, mirroring how `enableInp` forwards to `webVitalsIntegration`.
Web vital spans read the route name from the current scope, which has already moved on by the time a late vital is reported: a soft navigation's CLS and INP only finalize at the next navigation, so `sentry.segment.name` was systematically the following route. Prefer the name of the span the vital is parented to, which is what `_sendInpSpan` already computed for itself. Also fixes the page load LCP and CLS, which were labelled with the first navigated-to route.
INP took its parent from the interaction cache, which records whichever root span was active when the interaction's entry was observed. For a click that drives a navigation that is the destination navigation span, so the page load's INP was reported against the first navigation. With soft navigations the metric carries the navigation it belongs to, so INP now flows through the same path as LCP and CLS. The cache is still used for the element name, and still parents INP when soft navigations are off.
web-vitals decides what an INP is; we map its emissions to telemetry rather than filtering them. It reports a soft navigation's INP with no entries when every interaction stayed below the Event Timing threshold, and we were dropping those, so a fast navigation reported no INP at all. Without an entry there is no element or interaction type to describe, so the span falls back to a bare `ui.interaction` op and a generic name, the same way CLS falls back to a "Layout shift" span. It is placed at the start of the navigation it belongs to.
web-vitals synthesizes an INP value with no entries when a soft navigation's interactions all stayed below the Event Timing threshold, so that fast navigations are not excluded from INP reporting (GoogleChrome/web-vitals#724). Emitting those under a bare `ui.interaction` op would hide them from any aggregation matching `ui.interaction.*`, reintroducing exactly the bias upstream added the synthetic value to remove. Without an entry there is no interaction type to derive, so the op falls back to `click`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reports LCP, CLS and INP for soft navigations, opt-in via
webVitalsIntegration({ reportSoftNavs: true }). Correlates them to navigation spans via the triggeringinteractionId, sincenavigationIdisn't available at history-change time. Requires span streaming.Verified in Chrome 151, which surfaced two pre-existing attribution bugs, fixed here. One changes the default path: vital spans read the route name from the current scope, so a page load's LCP and CLS were labelled with the next route.
One deliberate inaccuracy worth review. web-vitals synthesizes an INP with no entries so fast soft navs still report (GoogleChrome/web-vitals#724). That leaves no interaction type, and a bare op would hide those spans from aggregation. So it falls back to
click.closes #17857