diff --git a/packages/tracing/src/browser/metrics.ts b/packages/tracing/src/browser/metrics.ts index 849503e6e068..27ad7cc1c6c6 100644 --- a/packages/tracing/src/browser/metrics.ts +++ b/packages/tracing/src/browser/metrics.ts @@ -136,7 +136,7 @@ export class MetricsInstrumentation { if (transaction.op === 'pageload') { // normalize applicable web vital values to be relative to transaction.startTimestamp - const timeOrigin = msToSec(performance.timeOrigin); + const timeOrigin = msToSec(browserPerformanceTimeOrigin); ['fcp', 'fp', 'lcp', 'ttfb'].forEach(name => { if (!this._measurements[name] || timeOrigin >= transaction.startTimestamp) { @@ -150,12 +150,10 @@ export class MetricsInstrumentation { const oldValue = this._measurements[name].value; const measurementTimestamp = timeOrigin + msToSec(oldValue); // normalizedValue should be in milliseconds - const normalizedValue = (measurementTimestamp - transaction.startTimestamp) * 1000; + const normalizedValue = Math.abs((measurementTimestamp - transaction.startTimestamp) * 1000); const delta = normalizedValue - oldValue; - logger.log( - `[Measurements] Normalized ${name} from ${this._measurements[name].value} to ${normalizedValue} (${delta})`, - ); + logger.log(`[Measurements] Normalized ${name} from ${oldValue} to ${normalizedValue} (${delta})`); this._measurements[name].value = normalizedValue; }); diff --git a/packages/tracing/src/browser/web-vitals/getTTFB.ts b/packages/tracing/src/browser/web-vitals/getTTFB.ts index 18f2aa0df45f..63fda201caf5 100644 --- a/packages/tracing/src/browser/web-vitals/getTTFB.ts +++ b/packages/tracing/src/browser/web-vitals/getTTFB.ts @@ -17,58 +17,10 @@ import { getGlobalObject } from '@sentry/utils'; import { initMetric } from './lib/initMetric'; -import { ReportHandler } from './types'; +import { NavigationTimingPolyfillEntry, ReportHandler } from './types'; const global = getGlobalObject(); -interface NavigationEntryShim { - // From `PerformanceNavigationTimingEntry`. - entryType: string; - startTime: number; - - // From `performance.timing`. - connectEnd?: number; - connectStart?: number; - domComplete?: number; - domContentLoadedEventEnd?: number; - domContentLoadedEventStart?: number; - domInteractive?: number; - domainLookupEnd?: number; - domainLookupStart?: number; - fetchStart?: number; - loadEventEnd?: number; - loadEventStart?: number; - redirectEnd?: number; - redirectStart?: number; - requestStart?: number; - responseEnd?: number; - responseStart?: number; - secureConnectionStart?: number; - unloadEventEnd?: number; - unloadEventStart?: number; -} - -type PerformanceTimingKeys = - | 'connectEnd' - | 'connectStart' - | 'domComplete' - | 'domContentLoadedEventEnd' - | 'domContentLoadedEventStart' - | 'domInteractive' - | 'domainLookupEnd' - | 'domainLookupStart' - | 'fetchStart' - | 'loadEventEnd' - | 'loadEventStart' - | 'redirectEnd' - | 'redirectStart' - | 'requestStart' - | 'responseEnd' - | 'responseStart' - | 'secureConnectionStart' - | 'unloadEventEnd' - | 'unloadEventStart'; - const afterLoad = (callback: () => void): void => { if (document.readyState === 'complete') { // Queue a task so the callback runs after `loadEventEnd`. @@ -79,27 +31,22 @@ const afterLoad = (callback: () => void): void => { } }; -const getNavigationEntryFromPerformanceTiming = (): PerformanceNavigationTiming => { +const getNavigationEntryFromPerformanceTiming = (): NavigationTimingPolyfillEntry => { // Really annoying that TypeScript errors when using `PerformanceTiming`. - // Note: browsers that do not support navigation entries will fall back to using performance.timing - // (with the timestamps converted from epoch time to DOMHighResTimeStamp). // eslint-disable-next-line deprecation/deprecation const timing = global.performance.timing; - const navigationEntry: NavigationEntryShim = { + const navigationEntry: { [key: string]: number | string } = { entryType: 'navigation', startTime: 0, }; for (const key in timing) { if (key !== 'navigationStart' && key !== 'toJSON') { - navigationEntry[key as PerformanceTimingKeys] = Math.max( - timing[key as PerformanceTimingKeys] - timing.navigationStart, - 0, - ); + navigationEntry[key] = Math.max((timing[key as keyof PerformanceTiming] as number) - timing.navigationStart, 0); } } - return navigationEntry as PerformanceNavigationTiming; + return navigationEntry as NavigationTimingPolyfillEntry; }; export const getTTFB = (onReport: ReportHandler): void => { @@ -114,7 +61,6 @@ export const getTTFB = (onReport: ReportHandler): void => { metric.value = metric.delta = (navigationEntry as PerformanceNavigationTiming).responseStart; metric.entries = [navigationEntry]; - metric.isFinal = true; onReport(metric); } catch (error) { diff --git a/packages/tracing/src/browser/web-vitals/types.ts b/packages/tracing/src/browser/web-vitals/types.ts index cd80b29f89a5..72d846e1eb2b 100644 --- a/packages/tracing/src/browser/web-vitals/types.ts +++ b/packages/tracing/src/browser/web-vitals/types.ts @@ -82,3 +82,14 @@ interface NetworkInformation extends EventTarget { export interface NavigatorDeviceMemory { readonly deviceMemory?: number; } + +export type NavigationTimingPolyfillEntry = Omit< + PerformanceNavigationTiming, + | 'initiatorType' + | 'nextHopProtocol' + | 'redirectCount' + | 'transferSize' + | 'encodedBodySize' + | 'decodedBodySize' + | 'toJSON' +>;