Skip to content

Commit 107e2b0

Browse files
authored
ref(core): Remove dependence between performance.timeOrigin and performance.timing.navigationStart (#18710)
The `performance.timeOrigin` HighResTimestamp [replaced `performance.timing.navigationStart`](https://www.w3.org/TR/navigation-timing-2/#dom-performancetiming-navigationstart) a while ago. With this patch we can simplify our timeOrigin determination logic by fully decoupling both values. Previously, we'd only take `timeOrigin` if `navigationStart` was "more reliable" (less delta to `Date.now()`). Since `timeOrigin` has sub-millisecond precision, this leads to cases where we'd incorrectly take the older, less precise `navigationStart` entry, simply because `timeOrigin` had a couple of decimal places.
1 parent a68ac90 commit 107e2b0

File tree

2 files changed

+17
-45
lines changed

2 files changed

+17
-45
lines changed

packages/core/src/utils/time.ts

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,14 @@ let cachedTimeOrigin: number | null | undefined = null;
7878

7979
/**
8080
* Gets the time origin and the mode used to determine it.
81+
*
82+
* Unfortunately browsers may report an inaccurate time origin data, through either performance.timeOrigin or
83+
* performance.timing.navigationStart, which results in poor results in performance data. We only treat time origin
84+
* data as reliable if they are within a reasonable threshold of the current time.
85+
*
8186
* TODO: move to `@sentry/browser-utils` package.
8287
*/
8388
function getBrowserTimeOrigin(): number | undefined {
84-
// Unfortunately browsers may report an inaccurate time origin data, through either performance.timeOrigin or
85-
// performance.timing.navigationStart, which results in poor results in performance data. We only treat time origin
86-
// data as reliable if they are within a reasonable threshold of the current time.
8789
const { performance } = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;
8890
if (!performance?.now) {
8991
return undefined;
@@ -94,11 +96,13 @@ function getBrowserTimeOrigin(): number | undefined {
9496
const performanceNow = performance.now();
9597
const dateNow = Date.now();
9698

97-
// if timeOrigin isn't available set delta to threshold so it isn't used
98-
const timeOriginDelta = performance.timeOrigin
99-
? Math.abs(performance.timeOrigin + performanceNow - dateNow)
100-
: threshold;
101-
const timeOriginIsReliable = timeOriginDelta < threshold;
99+
const timeOrigin = performance.timeOrigin;
100+
if (typeof timeOrigin === 'number') {
101+
const timeOriginDelta = Math.abs(timeOrigin + performanceNow - dateNow);
102+
if (timeOriginDelta < threshold) {
103+
return timeOrigin;
104+
}
105+
}
102106

103107
// TODO: Remove all code related to `performance.timing.navigationStart` once we drop support for Safari 14.
104108
// `performance.timeSince` is available in Safari 15.
@@ -111,18 +115,11 @@ function getBrowserTimeOrigin(): number | undefined {
111115
// Date API.
112116
// eslint-disable-next-line deprecation/deprecation
113117
const navigationStart = performance.timing?.navigationStart;
114-
const hasNavigationStart = typeof navigationStart === 'number';
115-
// if navigationStart isn't available set delta to threshold so it isn't used
116-
const navigationStartDelta = hasNavigationStart ? Math.abs(navigationStart + performanceNow - dateNow) : threshold;
117-
const navigationStartIsReliable = navigationStartDelta < threshold;
118-
119-
// TODO: Since timeOrigin explicitly replaces navigationStart, we should probably remove the navigationStartIsReliable check.
120-
if (timeOriginIsReliable && timeOriginDelta <= navigationStartDelta) {
121-
return performance.timeOrigin;
122-
}
123-
124-
if (navigationStartIsReliable) {
125-
return navigationStart;
118+
if (typeof navigationStart === 'number') {
119+
const navigationStartDelta = Math.abs(navigationStart + performanceNow - dateNow);
120+
if (navigationStartDelta < threshold) {
121+
return navigationStart;
122+
}
126123
}
127124

128125
// Either both timeOrigin and navigationStart are skewed or neither is available, fallback to subtracting

packages/core/test/lib/utils/time.test.ts

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -99,31 +99,6 @@ describe('browserPerformanceTimeOrigin', () => {
9999
vi.unstubAllGlobals();
100100
});
101101

102-
it('returns `performance.timing.navigationStart` if `performance.timeOrigin` is less reliable', async () => {
103-
const currentTimeMs = 1767778040874;
104-
105-
const navigationStartMs = currentTimeMs - 2_000;
106-
107-
const timeSincePageloadMs = 1_234.789;
108-
109-
vi.useFakeTimers();
110-
vi.setSystemTime(new Date(currentTimeMs));
111-
112-
vi.stubGlobal('performance', {
113-
timeOrigin: navigationStartMs - 1,
114-
timing: {
115-
navigationStart: navigationStartMs,
116-
},
117-
now: () => timeSincePageloadMs,
118-
});
119-
120-
const timeOrigin = await getFreshPerformanceTimeOrigin();
121-
expect(timeOrigin).toBe(navigationStartMs);
122-
123-
vi.useRealTimers();
124-
vi.unstubAllGlobals();
125-
});
126-
127102
describe('caching', () => {
128103
it('caches `undefined` result', async () => {
129104
vi.stubGlobal('performance', undefined);

0 commit comments

Comments
 (0)