Skip to content

fix(browser): Ensure pageload & navigation spans have correct data #16279

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

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from

Conversation

mydea
Copy link
Member

@mydea mydea commented May 13, 2025

This PR fixes two things about our idle spans emitted from browserTracingIntegration:

  1. The navigation name was sometimes incorrect. This is because we look at window.location.pathname at the time when the popstate event is emitted - but at this point, this may not be updated yet. So a navigation transaction would possibly have the pathname of the previous page as transaction name.
  2. The request data is also possibly incorrect - this is set by HttpContext integration at event processing time. However, at this time the window.location data is also usually already of the following navigation, so the pageload would often have wrong request data associated to it. Now, we store this on the current scope at span creation time to ensure it is actually correct.

@mydea mydea self-assigned this May 13, 2025
Copy link
Contributor

github-actions bot commented May 13, 2025

size-limit report 📦

Path Size % Change Change
@sentry/browser 23.98 kB +0.1% +22 B 🔺
@sentry/browser - with treeshaking flags 23.64 kB +0.09% +19 B 🔺
@sentry/browser (incl. Tracing) 38.3 kB +0.24% +89 B 🔺
@sentry/browser (incl. Tracing, Replay) 76.42 kB +0.13% +94 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 69.45 kB +0.16% +107 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 81.19 kB +0.13% +98 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 93.28 kB +0.11% +98 B 🔺
@sentry/browser (incl. Feedback) 40.78 kB +0.05% +19 B 🔺
@sentry/browser (incl. sendFeedback) 28.72 kB +0.07% +19 B 🔺
@sentry/browser (incl. FeedbackAsync) 33.6 kB +0.09% +27 B 🔺
@sentry/react 25.79 kB +0.09% +23 B 🔺
@sentry/react (incl. Tracing) 40.31 kB +0.26% +102 B 🔺
@sentry/vue 28.38 kB +0.15% +41 B 🔺
@sentry/vue (incl. Tracing) 40.12 kB +0.29% +116 B 🔺
@sentry/svelte 24.02 kB +0.12% +27 B 🔺
CDN Bundle 25.19 kB +0.08% +18 B 🔺
CDN Bundle (incl. Tracing) 38.32 kB +0.24% +89 B 🔺
CDN Bundle (incl. Tracing, Replay) 74.19 kB +0.11% +75 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 79.6 kB +0.08% +61 B 🔺
CDN Bundle - uncompressed 73.55 kB +0.16% +112 B 🔺
CDN Bundle (incl. Tracing) - uncompressed 113.58 kB +0.39% +435 B 🔺
CDN Bundle (incl. Tracing, Replay) - uncompressed 227.54 kB +0.2% +435 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 240.37 kB +0.19% +435 B 🔺
@sentry/nextjs (client) 41.95 kB +0.21% +87 B 🔺
@sentry/sveltekit (client) 38.79 kB +0.3% +116 B 🔺
@sentry/node 158 kB - -
@sentry/node - without tracing 97.9 kB - -
@sentry/aws-serverless 123.24 kB - -

View base workflow run

Base automatically changed from fn/idleSpanCancelled to develop May 14, 2025 07:04
@mydea mydea force-pushed the fn/browser-span-data branch 2 times, most recently from 285cf52 to aa79811 Compare May 14, 2025 07:39
@mydea mydea force-pushed the fn/browser-span-data branch from aa79811 to 8102ffc Compare May 14, 2025 07:39
@mydea mydea requested review from s1gr1d and Lms24 May 14, 2025 07:39
@mydea mydea marked this pull request as ready for review May 14, 2025 07:40
Comment on lines 358 to 372

scope.setSDKProcessingMetadata({
normalizedRequest: undefined,
});
},
});

setActiveIdleSpan(client, idleSpan);

// We store the normalized request data on the scope, so we get the request data at time of span creation
// otherwise, the URL etc. may already be of the following navigation, and we'd report the wrong URL
getCurrentScope().setSDKProcessingMetadata({
normalizedRequest: getHttpRequestData(),
});

Copy link
Member

Choose a reason for hiding this comment

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

m/q: maybe I'm missing some timing information but isn't there a good chance that setting the normalizedRequest to undefined in 360 applies to the same scope where we previously set it (370)?

Copy link
Member Author

Choose a reason for hiding this comment

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

argh, actually that does not work I just noticed, it fixed one test but broke another one - as this resets the request before we even process the transaction 😬 need to do this in a different way... basically the problem was apparent in some e2e tests. I think it becomes problematic in certain cases, e.g. nextjs pages router, where routing instrumentation triggers navigation spans before the url is updated 🤔

@@ -459,16 +469,18 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
return;
}

if (from !== to) {
startingUrl = undefined;
startingUrl = undefined;
Copy link
Member

Choose a reason for hiding this comment

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

m/q: why did we remove the from !== to check?

Copy link
Member Author

Choose a reason for hiding this comment

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

sorry, forgot to mention this - we actually have the same check in the history handler code, where we do not even trigger the handler in this case!

Copy link
Member

Choose a reason for hiding this comment

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

nice, good catch!

Comment on lines 474 to 475
// We wait a tick here to ensure that WINDOW.location.pathname is updated
setTimeout(() => {
Copy link
Member

@Lms24 Lms24 May 14, 2025

Choose a reason for hiding this comment

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

m: I'm a bit worried about delaying the span start for a tick. I guess this comes down to the router or user implementation but what if users synchronously push a new state and e.g. make a fetch call directly afterwards? Would we still catch the span?
i think alternatively, we could still start the span directly but call updateSpanName once more in the setTimeout closure.
Not ideal in terms of DSC consistency but I'd rather have the span than miss it. WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

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

hmm, valid. one thing that would work as expected is if we just would use the to attribute from the history API, this is available already. I was afraid to do that because 🤷 if that is consistent with what we want/need there...?

@mydea
Copy link
Member Author

mydea commented May 14, 2025

OK, so I updated this based on feedback, to a more reliable heuristic I think:

  1. Removed the setTimeout stuff. Instead, we now use to from the history instrumentation, which is correct even if the navigation is still pending.
  2. However, to do this I had to fix the history instrumentation to ensure we always get a full URL - this was inconsistent before, where it could be a full URL or a path, depending on what is triggered. oops.
  3. I updated it to only keep the normalizedRequest for the default browserTracingIntegration - other implementations of startNavigationSpan will not set this, keeping the old behavior. This is because some frameworks (e.g. nextjs pages router) may trigger this before the URL is available. We can look at this later still, if needed.

@mydea mydea force-pushed the fn/browser-span-data branch from 4472bc8 to cee11ea Compare May 14, 2025 10:33
@mydea mydea requested a review from a team as a code owner May 14, 2025 11:15
Copy link
Member

@Lms24 Lms24 left a comment

Choose a reason for hiding this comment

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

Thanks for addressing my feedback!

@@ -459,16 +469,18 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
return;
}

if (from !== to) {
startingUrl = undefined;
startingUrl = undefined;
Copy link
Member

Choose a reason for hiding this comment

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

nice, good catch!

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.

2 participants