-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
fix(vue): Make pageload span handling more reliable #16799
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
base: develop
Are you sure you want to change the base?
Conversation
size-limit report 📦
|
We used to rely on a somewhat complex heuristic to determine if a router change is a pageload or not. This somehow did not work anymore here: #16783 in nuxt-3-min. Likely some vue router difference... However, I think this can be simplified anyhow, by just checking if we have an active pageload span. That seems to work reliably enough.
cc59c02
to
43a5fa0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Page Load Detection Fails on Subsequent Loads
The new pageload detection logic incorrectly handles page loads. The hasHandledFirstPageLoad
flag, once set, prevents getActivePageLoadSpan()
from being called, causing all subsequent legitimate page loads (e.g., hard refreshes) to be incorrectly treated as navigation events. Additionally, if no active pageload span exists during the initial route resolution, the first page load may also be incorrectly classified as a navigation. This results in incorrect transaction types ('navigation' instead of 'pageload') and missed updates for pageload spans. Furthermore, if the hasHandledFirstPageLoad
flag is never set (e.g., if pageload instrumentation is disabled or no initial pageload span exists), getActivePageLoadSpan()
is inefficiently called on every subsequent navigation.
packages/vue/src/router.ts#L58-L106
sentry-javascript/packages/vue/src/router.ts
Lines 58 to 106 in 43a5fa0
// We avoid trying to re-fetch the page load span when we know we already handled it the first time | |
const activePageLoadSpan = !hasHandledFirstPageLoad ? getActivePageLoadSpan() : undefined; | |
const attributes: SpanAttributes = {}; | |
for (const key of Object.keys(to.params)) { | |
attributes[`params.${key}`] = to.params[key]; | |
} | |
for (const key of Object.keys(to.query)) { | |
const value = to.query[key]; | |
if (value) { | |
attributes[`query.${key}`] = value; | |
} | |
} | |
// Determine a name for the routing transaction and where that name came from | |
let spanName: string = to.path; | |
let transactionSource: TransactionSource = 'url'; | |
if (to.name && options.routeLabel !== 'path') { | |
spanName = to.name.toString(); | |
transactionSource = 'custom'; | |
} else if (to.matched.length > 0) { | |
const lastIndex = to.matched.length - 1; | |
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | |
spanName = to.matched[lastIndex]!.path; | |
transactionSource = 'route'; | |
} | |
getCurrentScope().setTransactionName(spanName); | |
// Update the existing page load span with parametrized route information | |
if (options.instrumentPageLoad && activePageLoadSpan) { | |
const existingAttributes = spanToJSON(activePageLoadSpan).data; | |
if (existingAttributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] !== 'custom') { | |
activePageLoadSpan.updateName(spanName); | |
activePageLoadSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, transactionSource); | |
} | |
// Set router attributes on the existing pageload transaction | |
// This will override the origin, and add params & query attributes | |
activePageLoadSpan.setAttributes({ | |
...attributes, | |
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.vue', | |
}); | |
hasHandledFirstPageLoad = true; | |
} | |
if (options.instrumentNavigation && !activePageLoadSpan) { |
Bug: Page Load Flag Fails, Navigation Spans Mismanaged
The hasHandledFirstPageLoad
flag is not reliably set to true
after the initial page load, causing getActivePageLoadSpan()
to be called on every subsequent navigation and defeating optimization. This occurs because the flag is only updated if options.instrumentPageLoad
is true and an active pageload span exists. Consequently, the !activePageLoadSpan
check can also incorrectly prevent navigation spans from being created when options.instrumentNavigation
is true but options.instrumentPageLoad
is false, as an active pageload span might still be present.
packages/vue/src/router.ts#L88-L106
sentry-javascript/packages/vue/src/router.ts
Lines 88 to 106 in 43a5fa0
// Update the existing page load span with parametrized route information | |
if (options.instrumentPageLoad && activePageLoadSpan) { | |
const existingAttributes = spanToJSON(activePageLoadSpan).data; | |
if (existingAttributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] !== 'custom') { | |
activePageLoadSpan.updateName(spanName); | |
activePageLoadSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, transactionSource); | |
} | |
// Set router attributes on the existing pageload transaction | |
// This will override the origin, and add params & query attributes | |
activePageLoadSpan.setAttributes({ | |
...attributes, | |
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.vue', | |
}); | |
hasHandledFirstPageLoad = true; | |
} | |
if (options.instrumentNavigation && !activePageLoadSpan) { |
Was this report helpful? Give feedback by reacting with 👍 or 👎
We used to rely on a somewhat complex heuristic to determine if a router change is a pageload or not. This somehow did not work anymore here: #16783 in nuxt-3-min. Likely some vue router difference... However, I think this can be simplified anyhow, by just checking if we have an active pageload span. That seems to work reliably enough.