-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(metrics): use web-vitals ttfb calculation
- Loading branch information
1 parent
a99f260
commit 2a8b25c
Showing
8 changed files
with
228 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
91
packages/tracing-internal/src/browser/web-vitals/onTTFB.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* Copyright 2020 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import { WINDOW } from '../types'; | ||
import { bindReporter } from './lib/bindReporter'; | ||
import { getActivationStart } from './lib/getActivationStart'; | ||
import { getNavigationEntry } from './lib/getNavigationEntry'; | ||
import { initMetric } from './lib/initMetric'; | ||
import type { ReportCallback, ReportOpts } from './types'; | ||
import type { TTFBMetric } from './types/ttfb'; | ||
|
||
/** | ||
* Runs in the next task after the page is done loading and/or prerendering. | ||
* @param callback | ||
*/ | ||
const whenReady = (callback: () => void): void => { | ||
if (!WINDOW.document) { | ||
return; | ||
} | ||
|
||
if (WINDOW.document.prerendering) { | ||
addEventListener('prerenderingchange', () => whenReady(callback), true); | ||
} else if (WINDOW.document.readyState !== 'complete') { | ||
addEventListener('load', () => whenReady(callback), true); | ||
} else { | ||
// Queue a task so the callback runs after `loadEventEnd`. | ||
setTimeout(callback, 0); | ||
} | ||
}; | ||
|
||
/** | ||
* Calculates the [TTFB](https://web.dev/time-to-first-byte/) value for the | ||
* current page and calls the `callback` function once the page has loaded, | ||
* along with the relevant `navigation` performance entry used to determine the | ||
* value. The reported value is a `DOMHighResTimeStamp`. | ||
* | ||
* Note, this function waits until after the page is loaded to call `callback` | ||
* in order to ensure all properties of the `navigation` entry are populated. | ||
* This is useful if you want to report on other metrics exposed by the | ||
* [Navigation Timing API](https://w3c.github.io/navigation-timing/). For | ||
* example, the TTFB metric starts from the page's [time | ||
* origin](https://www.w3.org/TR/hr-time-2/#sec-time-origin), which means it | ||
* includes time spent on DNS lookup, connection negotiation, network latency, | ||
* and server processing time. | ||
*/ | ||
export const onTTFB = (onReport: ReportCallback, opts?: ReportOpts): void => { | ||
// Set defaults | ||
// eslint-disable-next-line no-param-reassign | ||
opts = opts || {}; | ||
|
||
// https://web.dev/ttfb/#what-is-a-good-ttfb-score | ||
// const thresholds = [800, 1800]; | ||
|
||
const metric = initMetric('TTFB'); | ||
const report = bindReporter(onReport, metric, opts.reportAllChanges); | ||
|
||
whenReady(() => { | ||
const navEntry = getNavigationEntry() as TTFBMetric['entries'][number]; | ||
|
||
if (navEntry) { | ||
// The activationStart reference is used because TTFB should be | ||
// relative to page activation rather than navigation start if the | ||
// page was prerendered. But in cases where `activationStart` occurs | ||
// after the first byte is received, this time should be clamped at 0. | ||
metric.value = Math.max(navEntry.responseStart - getActivationStart(), 0); | ||
|
||
// In some cases the value reported is negative or is larger | ||
// than the current page time. Ignore these cases: | ||
// https://github.com/GoogleChrome/web-vitals/issues/137 | ||
// https://github.com/GoogleChrome/web-vitals/issues/162 | ||
if (metric.value < 0 || metric.value > performance.now()) return; | ||
|
||
metric.entries = [navEntry]; | ||
|
||
report(true); | ||
} | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
packages/tracing-internal/src/browser/web-vitals/types/ttfb.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
* Copyright 2022 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import type { Metric, ReportCallback } from './base'; | ||
import type { NavigationTimingPolyfillEntry } from './polyfills'; | ||
|
||
/** | ||
* A TTFB-specific version of the Metric object. | ||
*/ | ||
export interface TTFBMetric extends Metric { | ||
name: 'TTFB'; | ||
entries: PerformanceNavigationTiming[] | NavigationTimingPolyfillEntry[]; | ||
} | ||
|
||
/** | ||
* An object containing potentially-helpful debugging information that | ||
* can be sent along with the TTFB value for the current page visit in order | ||
* to help identify issues happening to real-users in the field. | ||
*/ | ||
export interface TTFBAttribution { | ||
/** | ||
* The total time from when the user initiates loading the page to when the | ||
* DNS lookup begins. This includes redirects, service worker startup, and | ||
* HTTP cache lookup times. | ||
*/ | ||
waitingTime: number; | ||
/** | ||
* The total time to resolve the DNS for the current request. | ||
*/ | ||
dnsTime: number; | ||
/** | ||
* The total time to create the connection to the requested domain. | ||
*/ | ||
connectionTime: number; | ||
/** | ||
* The time time from when the request was sent until the first byte of the | ||
* response was received. This includes network time as well as server | ||
* processing time. | ||
*/ | ||
requestTime: number; | ||
/** | ||
* The `PerformanceNavigationTiming` entry used to determine TTFB (or the | ||
* polyfill entry in browsers that don't support Navigation Timing). | ||
*/ | ||
navigationEntry?: PerformanceNavigationTiming | NavigationTimingPolyfillEntry; | ||
} | ||
|
||
/** | ||
* A TTFB-specific version of the Metric object with attribution. | ||
*/ | ||
export interface TTFBMetricWithAttribution extends TTFBMetric { | ||
attribution: TTFBAttribution; | ||
} | ||
|
||
/** | ||
* A TTFB-specific version of the ReportCallback function. | ||
*/ | ||
export interface TTFBReportCallback extends ReportCallback { | ||
(metric: TTFBMetric): void; | ||
} | ||
|
||
/** | ||
* A TTFB-specific version of the ReportCallback function with attribution. | ||
*/ | ||
export interface TTFBReportCallbackWithAttribution extends TTFBReportCallback { | ||
(metric: TTFBMetricWithAttribution): void; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters