Skip to content

Commit 830362c

Browse files
committed
feat(apm): Update Span timing from absolute ref
Use performance.timeOrigin as the absolute reference to update Span start and end timestamps.
1 parent 0bc7a4d commit 830362c

File tree

1 file changed

+36
-21
lines changed

1 file changed

+36
-21
lines changed

packages/apm/src/integrations/tracing.ts

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,18 @@ interface Activity {
9595
const global = getGlobalObject<Window>();
9696
const defaultTracingOrigins = ['localhost', /^\//];
9797

98+
if (global.performance) {
99+
// Polyfill for performance.timeOrigin.
100+
//
101+
// While performance.timing.navigationStart is deprecated in favor of performance.timeOrigin, performance.timeOrigin
102+
// is not as widely supported. Namely, performance.timeOrigin is undefined in Safari as of writing.
103+
// tslint:disable-next-line:strict-type-predicates
104+
if (performance.timeOrigin === undefined) {
105+
// tslint:disable-next-line:deprecation
106+
performance.timeOrigin = performance.timing.navigationStart;
107+
}
108+
}
109+
98110
/**
99111
* Tracing Integration
100112
*/
@@ -382,15 +394,11 @@ export class Tracing implements Integration {
382394
// Gatekeeper if performance API not available
383395
return;
384396
}
397+
385398
logger.log('[Tracing] Adding & adjusting spans using Performance API');
386-
let navigationOffset = 0;
387-
if (
388-
transactionSpan.op === 'navigation' &&
389-
transactionSpan.data &&
390-
typeof transactionSpan.data.offset === 'number'
391-
) {
392-
navigationOffset = transactionSpan.data.offset;
393-
}
399+
400+
const timeOrigin = Tracing._msToSec(performance.timeOrigin);
401+
394402
// tslint:disable-next-line: completed-docs
395403
function addSpan(span: SpanClass): void {
396404
if (transactionSpan.spanRecorder) {
@@ -404,8 +412,8 @@ export class Tracing implements Integration {
404412
description: event,
405413
op: 'browser',
406414
});
407-
span.startTimestamp = parent.startTimestamp + Tracing._msToSec(entry[`${event}Start`]);
408-
span.timestamp = parent.startTimestamp + Tracing._msToSec(entry[`${event}End`]);
415+
span.startTimestamp = timeOrigin + Tracing._msToSec(entry[`${event}Start`]);
416+
span.timestamp = timeOrigin + Tracing._msToSec(entry[`${event}End`]);
409417
addSpan(span);
410418
}
411419

@@ -415,15 +423,15 @@ export class Tracing implements Integration {
415423
description: 'request',
416424
op: 'browser',
417425
});
418-
request.startTimestamp = parent.startTimestamp + Tracing._msToSec(entry.requestStart);
419-
request.timestamp = parent.startTimestamp + Tracing._msToSec(entry.responseEnd);
426+
request.startTimestamp = timeOrigin + Tracing._msToSec(entry.requestStart);
427+
request.timestamp = timeOrigin + Tracing._msToSec(entry.responseEnd);
420428
addSpan(request);
421429
const response = parent.child({
422430
description: 'response',
423431
op: 'browser',
424432
});
425-
response.startTimestamp = parent.startTimestamp + Tracing._msToSec(entry.responseStart);
426-
response.timestamp = parent.startTimestamp + Tracing._msToSec(entry.responseEnd);
433+
response.startTimestamp = timeOrigin + Tracing._msToSec(entry.responseStart);
434+
response.timestamp = timeOrigin + Tracing._msToSec(entry.responseEnd);
427435
addSpan(response);
428436
}
429437

@@ -469,7 +477,7 @@ export class Tracing implements Integration {
469477
description: `${entry.entryType} ${entry.name}`,
470478
op: 'mark',
471479
});
472-
mark.startTimestamp = transactionSpan.startTimestamp + startTime - navigationOffset;
480+
mark.startTimestamp = timeOrigin + startTime;
473481
mark.timestamp = mark.startTimestamp + duration;
474482
if (tracingInitMarkStartTime === undefined && entry.name === 'sentry-tracing-init') {
475483
tracingInitMarkStartTime = mark.startTimestamp;
@@ -483,7 +491,7 @@ export class Tracing implements Integration {
483491
if (transactionSpan.spanRecorder) {
484492
transactionSpan.spanRecorder.finishedSpans.map((finishedSpan: SpanClass) => {
485493
if (finishedSpan.description && finishedSpan.description.indexOf(resourceName) !== -1) {
486-
finishedSpan.startTimestamp = transactionSpan.startTimestamp + startTime - navigationOffset;
494+
finishedSpan.startTimestamp = timeOrigin + startTime;
487495
finishedSpan.timestamp = finishedSpan.startTimestamp + duration;
488496
}
489497
});
@@ -493,7 +501,7 @@ export class Tracing implements Integration {
493501
description: `${entry.initiatorType} ${resourceName}`,
494502
op: `resource`,
495503
});
496-
resource.startTimestamp = transactionSpan.startTimestamp + startTime - navigationOffset;
504+
resource.startTimestamp = timeOrigin + startTime;
497505
resource.timestamp = resource.startTimestamp + duration;
498506
// We remember the entry script end time to calculate the difference to the first init mark
499507
if (entryScriptStartEndTime === undefined && (entryScriptSrc || '').includes(resourceName)) {
@@ -651,10 +659,17 @@ export class Tracing implements Integration {
651659
});
652660
}
653661
span.finish();
654-
// If there is an offset in data, we need to shift timestamps towards it
655-
if (span.data && typeof span.data.offset === 'number' && typeof span.timestamp === 'number') {
656-
span.startTimestamp += span.data.offset;
657-
span.timestamp += span.data.offset;
662+
// If there is an offset in data, update timestamps accordingly
663+
if (
664+
global.performance &&
665+
span.data &&
666+
typeof span.data.offset === 'number' &&
667+
typeof span.timestamp === 'number'
668+
) {
669+
const timeOrigin = Tracing._msToSec(performance.timeOrigin);
670+
const duration = span.timestamp - span.startTimestamp;
671+
span.startTimestamp = timeOrigin + span.data.offset;
672+
span.timestamp = timeOrigin + duration;
658673
}
659674
}
660675
// tslint:disable-next-line: no-dynamic-delete

0 commit comments

Comments
 (0)