Skip to content

Commit 5012125

Browse files
committed
fix(browser): Remove browserPerformanceTimeOrigin side effects
1 parent ab28544 commit 5012125

File tree

8 files changed

+29
-19
lines changed

8 files changed

+29
-19
lines changed

packages/browser-utils/src/metrics/browserMetrics.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ interface StartTrackingWebVitalsOptions {
7979
*/
8080
export function startTrackingWebVitals({ recordClsStandaloneSpans }: StartTrackingWebVitalsOptions): () => void {
8181
const performance = getBrowserPerformanceAPI();
82-
if (performance && browserPerformanceTimeOrigin) {
82+
if (performance && browserPerformanceTimeOrigin()) {
8383
// @ts-expect-error we want to make sure all of these are available, even if TS is sure they are
8484
if (performance.mark) {
8585
WINDOW.performance.mark('sentry-tracing-init');
@@ -109,7 +109,7 @@ export function startTrackingLongTasks(): void {
109109
return;
110110
}
111111
for (const entry of entries) {
112-
const startTime = msToSec((browserPerformanceTimeOrigin as number) + entry.startTime);
112+
const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);
113113
const duration = msToSec(entry.duration);
114114

115115
const span = startInactiveSpan({
@@ -143,7 +143,7 @@ export function startTrackingLongAnimationFrames(): void {
143143
continue;
144144
}
145145

146-
const startTime = msToSec((browserPerformanceTimeOrigin as number) + entry.startTime);
146+
const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);
147147
const duration = msToSec(entry.duration);
148148

149149
const attributes: SpanAttributes = {
@@ -189,7 +189,7 @@ export function startTrackingInteractions(): void {
189189
}
190190
for (const entry of entries) {
191191
if (entry.name === 'click') {
192-
const startTime = msToSec((browserPerformanceTimeOrigin as number) + entry.startTime);
192+
const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);
193193
const duration = msToSec(entry.duration);
194194

195195
const spanOptions: StartSpanOptions & Required<Pick<StartSpanOptions, 'attributes'>> = {
@@ -255,7 +255,7 @@ function _trackFID(): () => void {
255255
return;
256256
}
257257

258-
const timeOrigin = msToSec(browserPerformanceTimeOrigin as number);
258+
const timeOrigin = msToSec(browserPerformanceTimeOrigin() as number);
259259
const startTime = msToSec(entry.startTime);
260260
DEBUG_BUILD && logger.log('[Measurements] Adding FID');
261261
_measurements['fid'] = { value: metric.value, unit: 'millisecond' };
@@ -286,13 +286,14 @@ interface AddPerformanceEntriesOptions {
286286
/** Add performance related spans to a transaction */
287287
export function addPerformanceEntries(span: Span, options: AddPerformanceEntriesOptions): void {
288288
const performance = getBrowserPerformanceAPI();
289-
if (!performance || !WINDOW.performance.getEntries || !browserPerformanceTimeOrigin) {
289+
const origin = browserPerformanceTimeOrigin();
290+
if (!performance || !WINDOW.performance.getEntries || !origin) {
290291
// Gatekeeper if performance API not available
291292
return;
292293
}
293294

294295
DEBUG_BUILD && logger.log('[Tracing] Adding & adjusting spans using Performance API');
295-
const timeOrigin = msToSec(browserPerformanceTimeOrigin);
296+
const timeOrigin = msToSec(origin);
296297

297298
const performanceEntries = performance.getEntries();
298299

packages/browser-utils/src/metrics/cls.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export function trackClsAsStandaloneSpan(): void {
8484
function sendStandaloneClsSpan(clsValue: number, entry: LayoutShift | undefined, pageloadSpanId: string) {
8585
DEBUG_BUILD && logger.log(`Sending CLS span (${clsValue})`);
8686

87-
const startTime = msToSec((browserPerformanceTimeOrigin || 0) + (entry?.startTime || 0));
87+
const startTime = msToSec((browserPerformanceTimeOrigin() || 0) + (entry?.startTime || 0));
8888
const routeName = getCurrentScope().getScopeData().transactionName;
8989

9090
const name = entry ? htmlTreeAsString(entry.sources[0]?.node) : 'Layout shift';

packages/browser-utils/src/metrics/inp.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const INTERACTIONS_SPAN_MAP = new Map<number, Span>();
2626
*/
2727
export function startTrackingINP(): () => void {
2828
const performance = getBrowserPerformanceAPI();
29-
if (performance && browserPerformanceTimeOrigin) {
29+
if (performance && browserPerformanceTimeOrigin()) {
3030
const inpCallback = _trackINP();
3131

3232
return (): void => {
@@ -83,7 +83,7 @@ function _trackINP(): () => void {
8383
const interactionType = INP_ENTRY_MAP[entry.name];
8484

8585
/** Build the INP span, create an envelope from the span, and then send the envelope */
86-
const startTime = msToSec((browserPerformanceTimeOrigin as number) + entry.startTime);
86+
const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);
8787
const duration = msToSec(metric.value);
8888
const activeSpan = getActiveSpan();
8989
const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;

packages/browser/src/profiling/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,9 @@ export function convertJSSelfProfileToSampledFormat(input: JSSelfProfile): Profi
251251
// when that happens, we need to ensure we are correcting the profile timings so the two timelines stay in sync.
252252
// Since JS self profiling time origin is always initialized to performance.timeOrigin, we need to adjust for
253253
// the drift between the SDK selected value and our profile time origin.
254-
const origin =
255-
typeof performance.timeOrigin === 'number' ? performance.timeOrigin : browserPerformanceTimeOrigin || 0;
256-
const adjustForOriginChange = origin - (browserPerformanceTimeOrigin || origin);
254+
const perfOrigin = browserPerformanceTimeOrigin();
255+
const origin = typeof performance.timeOrigin === 'number' ? performance.timeOrigin : perfOrigin || 0;
256+
const adjustForOriginChange = origin - (perfOrigin || origin);
257257

258258
input.samples.forEach((jsSample, i) => {
259259
// If sample has no stack, add an empty sample

packages/browser/src/tracing/browserTracingIntegration.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,11 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
362362

363363
if (WINDOW.location) {
364364
if (instrumentPageLoad) {
365+
let origin = browserPerformanceTimeOrigin();
365366
startBrowserTracingPageLoadSpan(client, {
366367
name: WINDOW.location.pathname,
367368
// pageload should always start at timeOrigin (and needs to be in s, not ms)
368-
startTime: browserPerformanceTimeOrigin ? browserPerformanceTimeOrigin / 1000 : undefined,
369+
startTime: origin ? origin / 1000 : undefined,
369370
attributes: {
370371
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
371372
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.browser',

packages/browser/src/tracing/request.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ export function extractNetworkProtocol(nextHopProtocol: string): { name: string;
268268
}
269269

270270
function getAbsoluteTime(time: number = 0): number {
271-
return ((browserPerformanceTimeOrigin || performance.timeOrigin) + time) / 1000;
271+
return ((browserPerformanceTimeOrigin() || performance.timeOrigin) + time) / 1000;
272272
}
273273

274274
function resourceTimingEntryToSpanData(resourceTiming: PerformanceResourceTiming): [string, string | number][] {
@@ -278,7 +278,7 @@ function resourceTimingEntryToSpanData(resourceTiming: PerformanceResourceTiming
278278

279279
timingSpanData.push(['network.protocol.version', version], ['network.protocol.name', name]);
280280

281-
if (!browserPerformanceTimeOrigin) {
281+
if (!browserPerformanceTimeOrigin()) {
282282
return timingSpanData;
283283
}
284284
return [

packages/replay-internal/src/util/createPerformanceEntries.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ function createPerformanceEntry(entry: AllPerformanceEntry): ReplayPerformanceEn
8989
function getAbsoluteTime(time: number): number {
9090
// browserPerformanceTimeOrigin can be undefined if `performance` or
9191
// `performance.now` doesn't exist, but this is already checked by this integration
92-
return ((browserPerformanceTimeOrigin || WINDOW.performance.timeOrigin) + time) / 1000;
92+
return ((browserPerformanceTimeOrigin() || WINDOW.performance.timeOrigin) + time) / 1000;
9393
}
9494

9595
function createPaintEntry(entry: PerformancePaintTiming): ReplayPerformanceEntry<PaintData> {

packages/utils/src/time.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,16 @@ export const timestampInSeconds = createUnixTimestampInSecondsFunc();
7373
*/
7474
export let _browserPerformanceTimeOriginMode: string;
7575

76+
let cachedbrowserPerformanceTimeOrigin: { value: number | undefined } | undefined;
77+
7678
/**
7779
* The number of milliseconds since the UNIX epoch. This value is only usable in a browser, and only when the
7880
* performance API is available.
7981
*/
80-
export const browserPerformanceTimeOrigin = ((): number | undefined => {
82+
export function browserPerformanceTimeOrigin(): number | undefined {
83+
if (cachedbrowserPerformanceTimeOrigin) {
84+
return cachedbrowserPerformanceTimeOrigin.value;
85+
}
8186
// Unfortunately browsers may report an inaccurate time origin data, through either performance.timeOrigin or
8287
// performance.timing.navigationStart, which results in poor results in performance data. We only treat time origin
8388
// data as reliable if they are within a reasonable threshold of the current time.
@@ -123,5 +128,8 @@ export const browserPerformanceTimeOrigin = ((): number | undefined => {
123128

124129
// Either both timeOrigin and navigationStart are skewed or neither is available, fallback to Date.
125130
_browserPerformanceTimeOriginMode = 'dateNow';
131+
132+
cachedbrowserPerformanceTimeOrigin = { value: dateNow };
133+
126134
return dateNow;
127-
})();
135+
}

0 commit comments

Comments
 (0)