Skip to content

fix(browser): Fix INP span creation & transaction tagging #12372

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 7, 2024

Conversation

mydea
Copy link
Member

@mydea mydea commented Jun 5, 2024

Instead of #12358, this is a simpler change which ensures we pick the transaction from the scope instead.

I also added tests for the various different scenarios, to ensure we see how they behave:

  1. INP is emitted during pageload (span is active)
  2. INP is emitted after pageload

a. Pageload is parametrized (route)
b. Pageload is unparametrized (URL)

When the pageload is unparametrized (default browser SDK), the transaction is not added to the DSC envelope header (which is correct and also what we do in other places). it is always added to the span attributes now, though. If no span is active, it will use transactionName from the last active pageload/navigation span.

There may be edge cases where this is not 100% correct (e.g. if the INP span is only emitted once the pageload is done but another navigation already started) but IMHO these are more edge cases and this change is probably fine for now..?

(While at it, I also added an origin to the INP spans)

Copy link
Contributor

github-actions bot commented Jun 5, 2024

size-limit report 📦

Path Size
@sentry/browser 22 KB (0%)
@sentry/browser (incl. Tracing) 33.19 KB (+0.42% 🔺)
@sentry/browser (incl. Tracing, Replay) 68.81 KB (+0.22% 🔺)
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 62.09 KB (+0.24% 🔺)
@sentry/browser (incl. Tracing, Replay with Canvas) 72.86 KB (+0.21% 🔺)
@sentry/browser (incl. Tracing, Replay, Feedback) 85 KB (+0.2% 🔺)
@sentry/browser (incl. Tracing, Replay, Feedback, metrics) 86.83 KB (+0.19% 🔺)
@sentry/browser (incl. metrics) 26.19 KB (0%)
@sentry/browser (incl. Feedback) 38.17 KB (0%)
@sentry/browser (incl. sendFeedback) 26.59 KB (0%)
@sentry/browser (incl. FeedbackAsync) 31.15 KB (0%)
@sentry/react 24.77 KB (0%)
@sentry/react (incl. Tracing) 36.24 KB (+0.42% 🔺)
@sentry/vue 26.01 KB (0%)
@sentry/vue (incl. Tracing) 35.03 KB (+0.44% 🔺)
@sentry/svelte 22.14 KB (0%)
CDN Bundle 23.36 KB (0%)
CDN Bundle (incl. Tracing) 34.87 KB (+0.4% 🔺)
CDN Bundle (incl. Tracing, Replay) 68.84 KB (+0.23% 🔺)
CDN Bundle (incl. Tracing, Replay, Feedback) 73.99 KB (+0.21% 🔺)
CDN Bundle - uncompressed 68.63 KB (0%)
CDN Bundle (incl. Tracing) - uncompressed 103.22 KB (+0.38% 🔺)
CDN Bundle (incl. Tracing, Replay) - uncompressed 213.14 KB (+0.19% 🔺)
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 225.61 KB (+0.18% 🔺)
@sentry/nextjs (client) 35.59 KB (+0.39% 🔺)
@sentry/sveltekit (client) 33.83 KB (+0.42% 🔺)
@sentry/node 129.8 KB (0%)
@sentry/node - without tracing 92.55 KB (0%)
@sentry/aws-serverless 117.61 KB (0%)

@@ -83,7 +84,9 @@ function _trackINP(): () => void {
const activeSpan = getActiveSpan();
const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;

const routeName = rootSpan ? spanToJSON(rootSpan).description : undefined;
// If there is no active span, we fall back to look at the transactionName on the scope
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, this may produce a lot of garbage data when the user does custom instrumentation. Normally I would say this is fine but "garbage data" in this case would be polluting the INP dashboard in Sentry massively with random crap and people have no way of figuring out why.

Could we just store the last active route on some global and read it here? That way we will never not receive route/url names - never ending up with crap in the INP dashboard.

Copy link
Member Author

Choose a reason for hiding this comment

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

but this is exactly the semantics of the transactionName on the scope, isn't it? we use this literally to set this as "transaction" on the INP span :D makes sense to me to use the same thing we set as transaction on e.g. errors here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah I am sorry. That is correct. Mentally I was still in the old world where we had transactions on the scope 😄 All good then!

@edwardgou-sentry
Copy link
Contributor

edwardgou-sentry commented Jun 5, 2024

Hey @mydea one thing to keep in mind is that when INP is reported, it is not always on the last pageload/navigation.
e.g.

  • User pageloads /a
  • User interacts on /a with causes 2000ms delay
  • User navigates to /b
  • User interacts on /b many times, each with 10ms delay (this step probably isn't even needed)
  • User sends page to background, which triggers inp with a value of 2000ms

The proper route for this interaction should be /a, but I think the code will pick up /b here. I think this is going to be a pretty common scenario and not just an edge case (this behaviour is common on the Sentry ui as well).

Another smaller/side point we should consider, INP is the p98 of all interactions, so we need a mechanism to know the route of the p98, not just the p100:
https://github.com/getsentry/sentry-javascript/blob/develop/packages/browser-utils/src/metrics/web-vitals/getINP.ts#L107

mydea added a commit that referenced this pull request Jun 6, 2024
This is a PR adjusting
#12372 to keep
transaction name for INP even if the route has changed in the meanwhile.

Now, we keep a map of the last 10 interactionId <> route names, which we
use instead (if possible).
@mydea
Copy link
Member Author

mydea commented Jun 6, 2024

Addressed concerns in #12378, which while not 100% should handle most cases. We can ship it like this for now and possibly revisit this later if we find this does not work perfectly in certain scecnarios.

mydea added 3 commits June 7, 2024 09:13
Instead of #12358, this is a simpler change which ensures we pick the transaction from the scope instead.

I also added tests for the various different scenarios, to ensure we see how they behave:

1. INP is emitted _during_ pageload (span is active)
2. INP is emitted _after_ pageload
a. Pageload is parametrized (route)
b. Pageload is unparametrized (URL)
This is a PR adjusting
#12372 to keep
transaction name for INP even if the route has changed in the meanwhile.

Now, we keep a map of the last 10 interactionId <> route names, which we
use instead (if possible).
@mydea mydea force-pushed the fn/web-vitals-inp branch from 489b950 to 615340a Compare June 7, 2024 07:16
@mydea mydea merged commit d6ec881 into develop Jun 7, 2024
111 checks passed
@mydea mydea deleted the fn/web-vitals-inp branch June 7, 2024 07:39
billyvg pushed a commit that referenced this pull request Jun 10, 2024
Instead of #12358,
this is a simpler change which ensures we pick the transaction from the
scope instead.

I also added tests for the various different scenarios, to ensure we see
how they behave:

1. INP is emitted _during_ pageload (span is active)
2. INP is emitted _after_ pageload

a. Pageload is parametrized (route)
b. Pageload is unparametrized (URL)

When the pageload is unparametrized (default browser SDK), the
transaction is not added to the DSC envelope header (which is correct
and also what we do in other places). it is _always_ added to the span
attributes now, though. If no span is active, it will use
transactionName from the last active pageload/navigation span.

There may be edge cases where this is not 100% correct (e.g. if the INP
span is only emitted once the pageload is done but another navigation
already started) but IMHO these are more edge cases and this change is
probably fine for now..?

(While at it, I also added an origin to the INP spans)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants