Skip to content

Commit 40f5201

Browse files
authored
fix(web-vitals): Adjust some web vitals to be relative to fetchStart and some other improvements (#3019)
* fix(web-vitals): Adjust some web vitals to be relative to fetchStart
1 parent c8e34e9 commit 40f5201

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

packages/tracing/src/browser/metrics.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,43 @@ export class MetricsInstrumentation {
134134

135135
// Measurements are only available for pageload transactions
136136
if (transaction.op === 'pageload') {
137+
// normalize applicable web vital values to be relative to transaction.startTimestamp
138+
139+
const timeOrigin = msToSec(performance.timeOrigin);
140+
141+
['fcp', 'fp', 'lcp', 'ttfb'].forEach(name => {
142+
if (!this._measurements[name] || timeOrigin >= transaction.startTimestamp) {
143+
return;
144+
}
145+
146+
// The web vitals, fcp, fp, lcp, and ttfb, all measure relative to timeOrigin.
147+
// Unfortunately, timeOrigin is not captured within the transaction span data, so these web vitals will need
148+
// to be adjusted to be relative to transaction.startTimestamp.
149+
150+
const oldValue = this._measurements[name].value;
151+
const measurementTimestamp = timeOrigin + msToSec(oldValue);
152+
// normalizedValue should be in milliseconds
153+
const normalizedValue = (measurementTimestamp - transaction.startTimestamp) * 1000;
154+
155+
const delta = normalizedValue - oldValue;
156+
logger.log(
157+
`[Measurements] Normalized ${name} from ${this._measurements[name].value} to ${normalizedValue} (${delta})`,
158+
);
159+
160+
this._measurements[name].value = normalizedValue;
161+
});
162+
163+
if (this._measurements['mark.fid'] && this._measurements['fid']) {
164+
// create span for FID
165+
166+
_startChild(transaction, {
167+
description: 'first input delay',
168+
endTimestamp: this._measurements['mark.fid'].value + msToSec(this._measurements['fid'].value),
169+
op: 'web.vitals',
170+
startTimestamp: this._measurements['mark.fid'].value,
171+
});
172+
}
173+
137174
transaction.setMeasurements(this._measurements);
138175
}
139176
}
@@ -253,6 +290,7 @@ function addNavigationSpans(transaction: Transaction, entry: Record<string, any>
253290
addPerformanceNavigationTiming(transaction, entry, 'loadEvent', timeOrigin);
254291
addPerformanceNavigationTiming(transaction, entry, 'connect', timeOrigin);
255292
addPerformanceNavigationTiming(transaction, entry, 'secureConnection', timeOrigin, 'connectEnd');
293+
addPerformanceNavigationTiming(transaction, entry, 'fetch', timeOrigin, 'domainLookupStart');
256294
addPerformanceNavigationTiming(transaction, entry, 'domainLookup', timeOrigin);
257295
addRequest(transaction, entry, timeOrigin);
258296
}

packages/tracing/src/browser/web-vitals/getTTFB.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { getGlobalObject } from '@sentry/utils';
18+
1719
import { initMetric } from './lib/initMetric';
1820
import { ReportHandler } from './types';
1921

22+
const global = getGlobalObject<Window>();
23+
2024
interface NavigationEntryShim {
2125
// From `PerformanceNavigationTimingEntry`.
2226
entryType: string;
@@ -80,7 +84,7 @@ const getNavigationEntryFromPerformanceTiming = (): PerformanceNavigationTiming
8084
// Note: browsers that do not support navigation entries will fall back to using performance.timing
8185
// (with the timestamps converted from epoch time to DOMHighResTimeStamp).
8286
// eslint-disable-next-line deprecation/deprecation
83-
const timing = performance.timing;
87+
const timing = global.performance.timing;
8488

8589
const navigationEntry: NavigationEntryShim = {
8690
entryType: 'navigation',
@@ -105,7 +109,7 @@ export const getTTFB = (onReport: ReportHandler): void => {
105109
try {
106110
// Use the NavigationTiming L2 entry if available.
107111
const navigationEntry =
108-
performance.getEntriesByType('navigation')[0] || getNavigationEntryFromPerformanceTiming();
112+
global.performance.getEntriesByType('navigation')[0] || getNavigationEntryFromPerformanceTiming();
109113

110114
metric.value = metric.delta = (navigationEntry as PerformanceNavigationTiming).responseStart;
111115

0 commit comments

Comments
 (0)