Repository navigation
fix(replay): Place CLS and INP web vitals at the right time #24990
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -220,7 +220,10 @@ export function getCumulativeLayoutShift(metric: Metric): ReplayPerformanceEntry | |
| } | ||
| } | ||
|
|
||
| return getWebVital(metric, 'cumulative-layout-shift', nodes, layoutShifts); | ||
| // The CLS value is a score, not a time, so we place the event at the last layout shift. A CLS of 0 has no layout | ||
| // shift, so it goes at the time origin. | ||
| const lastEntry = metric.entries[metric.entries.length - 1]; | ||
| return getWebVital(metric, 'cumulative-layout-shift', nodes, layoutShifts, lastEntry?.startTime ?? 0); | ||
|
cursor[bot] marked this conversation as resolved.
|
||
| } | ||
|
|
||
| /** | ||
|
|
@@ -230,7 +233,8 @@ export function getInteractionToNextPaint(metric: Metric): ReplayPerformanceEntr | |
| // oxlint-disable-next-line typescript/no-unnecessary-type-assertion -- rule false positive: the cast exposes the entry's `target` field; tsc errors without it | ||
| const lastEntry = metric.entries[metric.entries.length - 1] as (PerformanceEntry & { target?: Node }) | undefined; | ||
| const node = lastEntry?.target ? [lastEntry.target] : undefined; | ||
| return getWebVital(metric, 'interaction-to-next-paint', node); | ||
| // The INP value is a duration, not a time, so we place the event at the interaction. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Soft navigation metrics without entries are incorrectly timestamped at page load because the Suggested FixUpdate the timestamp calculation in Prompt for AI AgentAlso affects:
Did we get this right? 👍 / 👎 to inform future reviews. |
||
| return getWebVital(metric, 'interaction-to-next-paint', node, undefined, lastEntry?.startTime ?? 0); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -241,11 +245,12 @@ function getWebVital( | |
| name: string, | ||
| nodes: Node[] | undefined, | ||
| attributions?: WebVitalData['attributions'], | ||
| time = metric.value, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. q: Can't we set this inside this function? It seem we set INP and CLS both the "last entry", but they are both setting it to const time = metric.entries[metric.entries.length - 1] ?? metric.valueIt is a different logic than the current implemented, but asking since LCP doesn't make use of the "last entry". If LCP shouldn't make use of it, maybe we should document when this should be overwritten
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. m: +1, LCP's last entry For bfcache there are no entries, so we could fall back to the navigation start: const lastEntry = metric.entries[metric.entries.length - 1];
const time = lastEntry?.startTime ?? (metric.navigationStartTime ?? 0) + metric.value;This also would put a CLS of 0 on its soft nav which is correct. |
||
| ): ReplayPerformanceEntry<WebVitalData> { | ||
| const value = metric.value; | ||
| const rating = metric.rating; | ||
|
|
||
| const end = getAbsoluteTime(value); | ||
| const end = getAbsoluteTime(time); | ||
|
|
||
| return { | ||
| type: 'web-vital', | ||
|
|
||
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.
l: a soft nav with a CLS of 0 lands at page load here.
metric.navigationStartTime ?? 0would put it on its navigation, like_sendClsSpandoes.