Skip to content
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

fix(web-vitals): Adjust some web vitals to be relative to fetchStart and some other improvements #3019

Merged
merged 7 commits into from
Nov 3, 2020

Conversation

dashed
Copy link
Member

@dashed dashed commented Oct 30, 2020

Some Web Vitals that are based on timings, specifically FCP, FP, LCP, and TTFB are measured relative to timeOrigin (https://www.w3.org/TR/hr-time-2/#dfn-time-origin). Unfortunately, this conflicts with the generated span data sourced from the level 2 Navigation Timings as captured from the JS SDK (https://www.w3.org/TR/navigation-timing-2/).

As an example:

Screen Shot 2020-10-30 at 5 07 43 AM

One approach would be to measure relative to other timings such as fetchStart. See: GoogleChrome/web-vitals#19

Intuitively, it's more practical to adjust some web vitals to be relative to the starting point of the transaction.


This PR addresses the following:

  1. Create a span that measures from fetchStart to domainLookupStart. This adds more completeness to the processing model. By creating this span, this will usually adjust transaction.startTimestamp for some pageload transactions.

See: https://www.w3.org/TR/navigation-timing-2/#processing-model

Screen Shot 2020-10-30 at 4 46 53 AM

What it looks like:

Screen Shot 2020-10-30 at 5 03 40 AM

  1. Adjust web vitals, specifically FCP, FP, LCP, and TTFB, to be relative to transaction.startTimestamp. This makes an assumption that transaction.startTimestamp is the earliest known starting point.

What the adjustment looks like with debug: true:

Screen Shot 2020-10-30 at 5 20 25 AM

  1. Create FID span which gives visualization of when the user clicks on the page, up to the time that the click was processed by JS event loop handler.

Screen Shot 2020-10-30 at 5 03 20 AM

@dashed dashed requested review from a team October 30, 2020 09:27
@dashed dashed self-assigned this Oct 30, 2020
@github-actions
Copy link
Contributor

github-actions bot commented Oct 30, 2020

size-limit report

Path Size
@sentry/browser - CDN Bundle (gzipped) 19.68 KB (+0.01% 🔺)
@sentry/browser - Webpack 20.54 KB (0%)
@sentry/react - Webpack 20.54 KB (0%)
@sentry/browser + @sentry/tracing - CDN Bundle (gzipped) 26.83 KB (+0.63% 🔺)

_startChild(transaction, {
description: 'first input delay',
endTimestamp: this._measurements['mark.fid'].value + msToSec(this._measurements['fid'].value),
op: 'web vitals',
Copy link
Member

Choose a reason for hiding this comment

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

Should this be 'vitals' to match the more generic name we'll likely use in the future?

Copy link
Member Author

Choose a reason for hiding this comment

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

Right now we've not committed to using that term as a generic umbrella.

We've only used "web vitals" thus far.

Copy link
Member

Choose a reason for hiding this comment

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

Is the fact that the op is currently two words going to mean that when searching for it, you have to put it in quotes? (I would guess that the answer is yes.) If so, can we make this one word (even if it's webVitals or web.vitals or webvitals) so that users don't have to do that?

Copy link
Member Author

Choose a reason for hiding this comment

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

web.vitals works 👍

@lobsterkatie
Copy link
Member

After talking this over with @dashed , this makes good sense to me. By adding in a fetchStart span, we'll be starting the transaction at the earliest possible moment in all cases, meaning the only blocks we could ever potentially "miss" ("Prompt for Unload" and "Redirect" in the diagram above) are ones which either don't exist (redirect) or aren't relevant to our users (unload).

@dashed
Copy link
Member Author

dashed commented Nov 3, 2020

@Zylphrex feel free to push commits to this branch as you see fit.

@kamilogorek kamilogorek merged commit 40f5201 into master Nov 3, 2020
@kamilogorek kamilogorek deleted the normalize-web-vitals branch November 3, 2020 10:01
@eightHundreds
Copy link

eightHundreds commented Jul 29, 2021

Adjust web vitals, specifically FCP, FP, LCP, and TTFB, to be relative to transaction.startTimestamp. This makes an assumption that transaction.startTimestamp is the earliest known starting point.

@dashed

why relative to transaction.startTimestamp instead of fetchStart.
transaction.startTimestamp is performace.timeOrigin+performace.now().

@AbhiPrasad
Copy link
Member

AbhiPrasad commented Jul 29, 2021

@eightHundreds

The startTimestamp of a transaction gets adjusted when we add browser related spans. As such, making the web-vitals relative to the startTimestamp value should produce the most accurate value.

@Dante-dan
Copy link

we add browser related spans.

It is not found.

Actually, I am seeing significant differences between the data(LCP/FCP) I am getting from Sentry and what I am getting from Google Search Console. I don't know what to do in the above situation.

@AbhiPrasad
Copy link
Member

@Dante-dan found here now:

_addResourceSpans(transaction, entry, resourceName, startTime, duration, timeOrigin);

Actually, I am seeing significant differences between the data(LCP/FCP) I am getting from Sentry and what I am getting from Google Search Console. I don't know what to do in the above situation.

Under the hood we use Google's web vitals library to grab LCP/FCP data. This is what the web vitals team themselves recommend:

export const onLCP = (onReport: ReportCallback): void => {

It is strange there is a significant difference though. @Dante-dan could you provide some kind of reproduction and open an issue on the JS SDK repo? That will help us dig in further!

@Dante-dan
Copy link

Dante-dan commented Feb 15, 2023

Fine, I think I have found the problem.

  1. I tried scenarios where either performance.timeOrigin or performance.timing.navigationStart API do not exist, and in debug mode, the FCP values have minor discrepancies.
  2. I found the count of pageload and the count of LCP on Sentry, they're significant differences. Because the measurements are only available for pageload transactions. This means that only the earlier LCPs are reported with pageload, while the slower LCPs often occur after pageload, resulting in much smaller LCPs being collected than what Google reports.

CleanShot 2023-02-15 at 21 16 29@2x

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.

8 participants