@sentry/browser-utils 10.70.0 → 11.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/htmlTreeAsString.js.map +1 -1
- package/build/cjs/index.js +30 -28
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/instrumentation/dom.js.map +1 -0
- package/build/cjs/instrumentation/history.js.map +1 -0
- package/build/cjs/instrumentation/location.js.map +1 -0
- package/build/cjs/{metrics/instrument.js → instrumentation/performanceObserver.js} +44 -32
- package/build/cjs/instrumentation/performanceObserver.js.map +1 -0
- package/build/cjs/instrumentation/xhr.js.map +1 -0
- package/build/cjs/{metrics → performance}/elementTiming.js +2 -2
- package/build/cjs/performance/elementTiming.js.map +1 -0
- package/build/cjs/{metrics/browserMetrics.js → performance/entries.js} +43 -262
- package/build/cjs/performance/entries.js.map +1 -0
- package/build/cjs/performance/resourceTiming.js.map +1 -0
- package/build/cjs/performance/userTiming.js +119 -0
- package/build/cjs/performance/userTiming.js.map +1 -0
- package/build/cjs/performance/utils.js +68 -0
- package/build/cjs/performance/utils.js.map +1 -0
- package/build/cjs/{metrics → web-vitals}/inp.js +4 -61
- package/build/cjs/web-vitals/inp.js.map +1 -0
- package/build/cjs/web-vitals/lcp.js +10 -0
- package/build/cjs/web-vitals/lcp.js.map +1 -0
- package/build/cjs/web-vitals/reportEvents.js +31 -0
- package/build/cjs/web-vitals/reportEvents.js.map +1 -0
- package/build/cjs/{metrics/webVitalSpans.js → web-vitals/spans.js} +36 -19
- package/build/cjs/web-vitals/spans.js.map +1 -0
- package/build/cjs/web-vitals/tracking.js +164 -0
- package/build/cjs/web-vitals/tracking.js.map +1 -0
- package/build/cjs/web-vitals/utils.js +99 -0
- package/build/cjs/web-vitals/utils.js.map +1 -0
- package/build/esm/htmlTreeAsString.js.map +1 -1
- package/build/esm/index.js +14 -12
- package/build/esm/index.js.map +1 -1
- package/build/esm/instrumentation/dom.js.map +1 -0
- package/build/esm/instrumentation/history.js.map +1 -0
- package/build/esm/instrumentation/location.js.map +1 -0
- package/build/esm/{metrics/instrument.js → instrumentation/performanceObserver.js} +42 -30
- package/build/esm/instrumentation/performanceObserver.js.map +1 -0
- package/build/esm/instrumentation/xhr.js.map +1 -0
- package/build/esm/package.json +1 -1
- package/build/esm/{metrics → performance}/elementTiming.js +1 -1
- package/build/esm/performance/elementTiming.js.map +1 -0
- package/build/esm/{metrics/browserMetrics.js → performance/entries.js} +36 -252
- package/build/esm/performance/entries.js.map +1 -0
- package/build/esm/performance/resourceTiming.js.map +1 -0
- package/build/esm/performance/userTiming.js +116 -0
- package/build/esm/performance/userTiming.js.map +1 -0
- package/build/esm/performance/utils.js +61 -0
- package/build/esm/performance/utils.js.map +1 -0
- package/build/esm/{metrics → web-vitals}/inp.js +3 -57
- package/build/esm/web-vitals/inp.js.map +1 -0
- package/build/esm/web-vitals/lcp.js +7 -0
- package/build/esm/web-vitals/lcp.js.map +1 -0
- package/build/esm/web-vitals/reportEvents.js +29 -0
- package/build/esm/web-vitals/reportEvents.js.map +1 -0
- package/build/esm/{metrics/webVitalSpans.js → web-vitals/spans.js} +32 -15
- package/build/esm/web-vitals/spans.js.map +1 -0
- package/build/esm/web-vitals/tracking.js +161 -0
- package/build/esm/web-vitals/tracking.js.map +1 -0
- package/build/esm/web-vitals/utils.js +91 -0
- package/build/esm/web-vitals/utils.js.map +1 -0
- package/build/types/index.d.ts +13 -11
- package/build/types/index.d.ts.map +1 -1
- package/build/types/instrumentation/dom.d.ts.map +1 -0
- package/build/types/instrumentation/history.d.ts.map +1 -0
- package/build/types/instrumentation/location.d.ts.map +1 -0
- package/build/types/{metrics/instrument.d.ts → instrumentation/performanceObserver.d.ts} +3 -3
- package/build/types/instrumentation/performanceObserver.d.ts.map +1 -0
- package/build/types/instrumentation/xhr.d.ts.map +1 -0
- package/build/types/performance/elementTiming.d.ts.map +1 -0
- package/build/types/performance/entries.d.ts +49 -0
- package/build/types/performance/entries.d.ts.map +1 -0
- package/build/types/performance/resourceTiming.d.ts.map +1 -0
- package/build/types/performance/userTiming.d.ts +37 -0
- package/build/types/performance/userTiming.d.ts.map +1 -0
- package/build/types/performance/utils.d.ts +33 -0
- package/build/types/performance/utils.d.ts.map +1 -0
- package/build/types/types.d.ts +1 -1
- package/build/types/{metrics → web-vitals}/inp.d.ts +0 -13
- package/build/types/web-vitals/inp.d.ts.map +1 -0
- package/build/types/web-vitals/lcp.d.ts +6 -0
- package/build/types/web-vitals/lcp.d.ts.map +1 -0
- package/build/types/web-vitals/reportEvents.d.ts +18 -0
- package/build/types/web-vitals/reportEvents.d.ts.map +1 -0
- package/build/types/{metrics/webVitalSpans.d.ts → web-vitals/spans.d.ts} +18 -12
- package/build/types/web-vitals/spans.d.ts.map +1 -0
- package/build/types/web-vitals/tracking.d.ts +46 -0
- package/build/types/web-vitals/tracking.d.ts.map +1 -0
- package/build/types/{metrics/web-vitals/lib/globalListeners.d.ts → web-vitals/utils.d.ts} +16 -1
- package/build/types/web-vitals/utils.d.ts.map +1 -0
- package/package.json +8 -16
- package/build/cjs/instrument/dom.js.map +0 -1
- package/build/cjs/instrument/history.js.map +0 -1
- package/build/cjs/instrument/location.js.map +0 -1
- package/build/cjs/instrument/xhr.js.map +0 -1
- package/build/cjs/metrics/browserMetrics.js.map +0 -1
- package/build/cjs/metrics/cls.js +0 -64
- package/build/cjs/metrics/cls.js.map +0 -1
- package/build/cjs/metrics/elementTiming.js.map +0 -1
- package/build/cjs/metrics/inp.js.map +0 -1
- package/build/cjs/metrics/instrument.js.map +0 -1
- package/build/cjs/metrics/lcp.js +0 -77
- package/build/cjs/metrics/lcp.js.map +0 -1
- package/build/cjs/metrics/resourceTiming.js.map +0 -1
- package/build/cjs/metrics/utils.js +0 -137
- package/build/cjs/metrics/utils.js.map +0 -1
- package/build/cjs/metrics/web-vitals/getCLS.js +0 -46
- package/build/cjs/metrics/web-vitals/getCLS.js.map +0 -1
- package/build/cjs/metrics/web-vitals/getINP.js +0 -60
- package/build/cjs/metrics/web-vitals/getINP.js.map +0 -1
- package/build/cjs/metrics/web-vitals/getLCP.js +0 -62
- package/build/cjs/metrics/web-vitals/getLCP.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/InteractionManager.js +0 -87
- package/build/cjs/metrics/web-vitals/lib/InteractionManager.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/LCPEntryManager.js +0 -11
- package/build/cjs/metrics/web-vitals/lib/LCPEntryManager.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/LayoutShiftManager.js +0 -27
- package/build/cjs/metrics/web-vitals/lib/LayoutShiftManager.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/bindReporter.js +0 -31
- package/build/cjs/metrics/web-vitals/lib/bindReporter.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/generateUniqueID.js +0 -8
- package/build/cjs/metrics/web-vitals/lib/generateUniqueID.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/getActivationStart.js +0 -11
- package/build/cjs/metrics/web-vitals/lib/getActivationStart.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/getNavigationEntry.js +0 -17
- package/build/cjs/metrics/web-vitals/lib/getNavigationEntry.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/getVisibilityWatcher.js +0 -48
- package/build/cjs/metrics/web-vitals/lib/getVisibilityWatcher.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/globalListeners.js +0 -18
- package/build/cjs/metrics/web-vitals/lib/globalListeners.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/initMetric.js +0 -34
- package/build/cjs/metrics/web-vitals/lib/initMetric.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/initUnique.js +0 -16
- package/build/cjs/metrics/web-vitals/lib/initUnique.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/observe.js +0 -20
- package/build/cjs/metrics/web-vitals/lib/observe.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/onHidden.js +0 -17
- package/build/cjs/metrics/web-vitals/lib/onHidden.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js +0 -32
- package/build/cjs/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/runOnce.js +0 -14
- package/build/cjs/metrics/web-vitals/lib/runOnce.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/whenActivated.js +0 -14
- package/build/cjs/metrics/web-vitals/lib/whenActivated.js.map +0 -1
- package/build/cjs/metrics/web-vitals/lib/whenIdleOrHidden.js +0 -24
- package/build/cjs/metrics/web-vitals/lib/whenIdleOrHidden.js.map +0 -1
- package/build/cjs/metrics/web-vitals/onFCP.js +0 -37
- package/build/cjs/metrics/web-vitals/onFCP.js.map +0 -1
- package/build/cjs/metrics/web-vitals/onTTFB.js +0 -35
- package/build/cjs/metrics/web-vitals/onTTFB.js.map +0 -1
- package/build/cjs/metrics/webVitalSpans.js.map +0 -1
- package/build/esm/instrument/dom.js.map +0 -1
- package/build/esm/instrument/history.js.map +0 -1
- package/build/esm/instrument/location.js.map +0 -1
- package/build/esm/instrument/xhr.js.map +0 -1
- package/build/esm/metrics/browserMetrics.js.map +0 -1
- package/build/esm/metrics/cls.js +0 -61
- package/build/esm/metrics/cls.js.map +0 -1
- package/build/esm/metrics/elementTiming.js.map +0 -1
- package/build/esm/metrics/inp.js.map +0 -1
- package/build/esm/metrics/instrument.js.map +0 -1
- package/build/esm/metrics/lcp.js +0 -72
- package/build/esm/metrics/lcp.js.map +0 -1
- package/build/esm/metrics/resourceTiming.js.map +0 -1
- package/build/esm/metrics/utils.js +0 -128
- package/build/esm/metrics/utils.js.map +0 -1
- package/build/esm/metrics/web-vitals/getCLS.js +0 -43
- package/build/esm/metrics/web-vitals/getCLS.js.map +0 -1
- package/build/esm/metrics/web-vitals/getINP.js +0 -57
- package/build/esm/metrics/web-vitals/getINP.js.map +0 -1
- package/build/esm/metrics/web-vitals/getLCP.js +0 -59
- package/build/esm/metrics/web-vitals/getLCP.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/InteractionManager.js +0 -85
- package/build/esm/metrics/web-vitals/lib/InteractionManager.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/LCPEntryManager.js +0 -9
- package/build/esm/metrics/web-vitals/lib/LCPEntryManager.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/LayoutShiftManager.js +0 -25
- package/build/esm/metrics/web-vitals/lib/LayoutShiftManager.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/bindReporter.js +0 -29
- package/build/esm/metrics/web-vitals/lib/bindReporter.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/generateUniqueID.js +0 -6
- package/build/esm/metrics/web-vitals/lib/generateUniqueID.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/getActivationStart.js +0 -9
- package/build/esm/metrics/web-vitals/lib/getActivationStart.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/getNavigationEntry.js +0 -15
- package/build/esm/metrics/web-vitals/lib/getNavigationEntry.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/getVisibilityWatcher.js +0 -46
- package/build/esm/metrics/web-vitals/lib/getVisibilityWatcher.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/globalListeners.js +0 -15
- package/build/esm/metrics/web-vitals/lib/globalListeners.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/initMetric.js +0 -32
- package/build/esm/metrics/web-vitals/lib/initMetric.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/initUnique.js +0 -14
- package/build/esm/metrics/web-vitals/lib/initUnique.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/observe.js +0 -18
- package/build/esm/metrics/web-vitals/lib/observe.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/onHidden.js +0 -15
- package/build/esm/metrics/web-vitals/lib/onHidden.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js +0 -29
- package/build/esm/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/runOnce.js +0 -12
- package/build/esm/metrics/web-vitals/lib/runOnce.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/whenActivated.js +0 -12
- package/build/esm/metrics/web-vitals/lib/whenActivated.js.map +0 -1
- package/build/esm/metrics/web-vitals/lib/whenIdleOrHidden.js +0 -22
- package/build/esm/metrics/web-vitals/lib/whenIdleOrHidden.js.map +0 -1
- package/build/esm/metrics/web-vitals/onFCP.js +0 -34
- package/build/esm/metrics/web-vitals/onFCP.js.map +0 -1
- package/build/esm/metrics/web-vitals/onTTFB.js +0 -32
- package/build/esm/metrics/web-vitals/onTTFB.js.map +0 -1
- package/build/esm/metrics/webVitalSpans.js.map +0 -1
- package/build/types/instrument/dom.d.ts.map +0 -1
- package/build/types/instrument/history.d.ts.map +0 -1
- package/build/types/instrument/location.d.ts.map +0 -1
- package/build/types/instrument/xhr.d.ts.map +0 -1
- package/build/types/metrics/browserMetrics.d.ts +0 -116
- package/build/types/metrics/browserMetrics.d.ts.map +0 -1
- package/build/types/metrics/cls.d.ts +0 -17
- package/build/types/metrics/cls.d.ts.map +0 -1
- package/build/types/metrics/elementTiming.d.ts.map +0 -1
- package/build/types/metrics/inp.d.ts.map +0 -1
- package/build/types/metrics/instrument.d.ts.map +0 -1
- package/build/types/metrics/lcp.d.ts +0 -22
- package/build/types/metrics/lcp.d.ts.map +0 -1
- package/build/types/metrics/resourceTiming.d.ts.map +0 -1
- package/build/types/metrics/utils.d.ts +0 -73
- package/build/types/metrics/utils.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/getCLS.d.ts +0 -26
- package/build/types/metrics/web-vitals/getCLS.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/getINP.d.ts +0 -34
- package/build/types/metrics/web-vitals/getINP.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/getLCP.d.ts +0 -16
- package/build/types/metrics/web-vitals/getLCP.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/InteractionManager.d.ts +0 -37
- package/build/types/metrics/web-vitals/lib/InteractionManager.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/LCPEntryManager.d.ts +0 -5
- package/build/types/metrics/web-vitals/lib/LCPEntryManager.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/LayoutShiftManager.d.ts +0 -7
- package/build/types/metrics/web-vitals/lib/LayoutShiftManager.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/bindReporter.d.ts +0 -7
- package/build/types/metrics/web-vitals/lib/bindReporter.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/generateUniqueID.d.ts +0 -7
- package/build/types/metrics/web-vitals/lib/generateUniqueID.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/getActivationStart.d.ts +0 -2
- package/build/types/metrics/web-vitals/lib/getActivationStart.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/getNavigationEntry.d.ts +0 -2
- package/build/types/metrics/web-vitals/lib/getNavigationEntry.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/getVisibilityWatcher.d.ts +0 -5
- package/build/types/metrics/web-vitals/lib/getVisibilityWatcher.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/globalListeners.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/initMetric.d.ts +0 -21
- package/build/types/metrics/web-vitals/lib/initMetric.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/initUnique.d.ts +0 -7
- package/build/types/metrics/web-vitals/lib/initUnique.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/observe.d.ts +0 -23
- package/build/types/metrics/web-vitals/lib/observe.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/onHidden.d.ts +0 -27
- package/build/types/metrics/web-vitals/lib/onHidden.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.d.ts +0 -15
- package/build/types/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/runOnce.d.ts +0 -2
- package/build/types/metrics/web-vitals/lib/runOnce.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/whenActivated.d.ts +0 -2
- package/build/types/metrics/web-vitals/lib/whenActivated.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/lib/whenIdleOrHidden.d.ts +0 -6
- package/build/types/metrics/web-vitals/lib/whenIdleOrHidden.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/onFCP.d.ts +0 -11
- package/build/types/metrics/web-vitals/onFCP.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/onTTFB.d.ts +0 -20
- package/build/types/metrics/web-vitals/onTTFB.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/types/base.d.ts +0 -103
- package/build/types/metrics/web-vitals/types/base.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/types/cls.d.ts +0 -58
- package/build/types/metrics/web-vitals/types/cls.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/types/fcp.d.ts +0 -47
- package/build/types/metrics/web-vitals/types/fcp.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/types/inp.d.ts +0 -150
- package/build/types/metrics/web-vitals/types/inp.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/types/lcp.d.ts +0 -74
- package/build/types/metrics/web-vitals/types/lcp.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/types/ttfb.d.ts +0 -60
- package/build/types/metrics/web-vitals/types/ttfb.d.ts.map +0 -1
- package/build/types/metrics/web-vitals/types.d.ts +0 -78
- package/build/types/metrics/web-vitals/types.d.ts.map +0 -1
- package/build/types/metrics/webVitalSpans.d.ts.map +0 -1
- package/build/types-ts3.8/debug-build.d.ts +0 -7
- package/build/types-ts3.8/getNativeImplementation.d.ts +0 -69
- package/build/types-ts3.8/htmlTreeAsString.d.ts +0 -11
- package/build/types-ts3.8/index.d.ts +0 -17
- package/build/types-ts3.8/instrument/dom.d.ts +0 -11
- package/build/types-ts3.8/instrument/history.d.ts +0 -15
- package/build/types-ts3.8/instrument/location.d.ts +0 -13
- package/build/types-ts3.8/instrument/xhr.d.ts +0 -14
- package/build/types-ts3.8/is.d.ts +0 -7
- package/build/types-ts3.8/metrics/browserMetrics.d.ts +0 -119
- package/build/types-ts3.8/metrics/cls.d.ts +0 -17
- package/build/types-ts3.8/metrics/elementTiming.d.ts +0 -21
- package/build/types-ts3.8/metrics/inp.d.ts +0 -35
- package/build/types-ts3.8/metrics/instrument.d.ts +0 -121
- package/build/types-ts3.8/metrics/lcp.d.ts +0 -22
- package/build/types-ts3.8/metrics/resourceTiming.d.ts +0 -13
- package/build/types-ts3.8/metrics/utils.d.ts +0 -73
- package/build/types-ts3.8/metrics/web-vitals/getCLS.d.ts +0 -26
- package/build/types-ts3.8/metrics/web-vitals/getINP.d.ts +0 -34
- package/build/types-ts3.8/metrics/web-vitals/getLCP.d.ts +0 -16
- package/build/types-ts3.8/metrics/web-vitals/lib/InteractionManager.d.ts +0 -37
- package/build/types-ts3.8/metrics/web-vitals/lib/LCPEntryManager.d.ts +0 -5
- package/build/types-ts3.8/metrics/web-vitals/lib/LayoutShiftManager.d.ts +0 -7
- package/build/types-ts3.8/metrics/web-vitals/lib/bindReporter.d.ts +0 -7
- package/build/types-ts3.8/metrics/web-vitals/lib/generateUniqueID.d.ts +0 -7
- package/build/types-ts3.8/metrics/web-vitals/lib/getActivationStart.d.ts +0 -2
- package/build/types-ts3.8/metrics/web-vitals/lib/getNavigationEntry.d.ts +0 -2
- package/build/types-ts3.8/metrics/web-vitals/lib/getVisibilityWatcher.d.ts +0 -5
- package/build/types-ts3.8/metrics/web-vitals/lib/globalListeners.d.ts +0 -11
- package/build/types-ts3.8/metrics/web-vitals/lib/initMetric.d.ts +0 -21
- package/build/types-ts3.8/metrics/web-vitals/lib/initUnique.d.ts +0 -7
- package/build/types-ts3.8/metrics/web-vitals/lib/observe.d.ts +0 -23
- package/build/types-ts3.8/metrics/web-vitals/lib/onHidden.d.ts +0 -27
- package/build/types-ts3.8/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.d.ts +0 -15
- package/build/types-ts3.8/metrics/web-vitals/lib/runOnce.d.ts +0 -2
- package/build/types-ts3.8/metrics/web-vitals/lib/whenActivated.d.ts +0 -2
- package/build/types-ts3.8/metrics/web-vitals/lib/whenIdleOrHidden.d.ts +0 -6
- package/build/types-ts3.8/metrics/web-vitals/onFCP.d.ts +0 -11
- package/build/types-ts3.8/metrics/web-vitals/onTTFB.d.ts +0 -20
- package/build/types-ts3.8/metrics/web-vitals/types/base.d.ts +0 -106
- package/build/types-ts3.8/metrics/web-vitals/types/cls.d.ts +0 -58
- package/build/types-ts3.8/metrics/web-vitals/types/fcp.d.ts +0 -47
- package/build/types-ts3.8/metrics/web-vitals/types/inp.d.ts +0 -150
- package/build/types-ts3.8/metrics/web-vitals/types/lcp.d.ts +0 -74
- package/build/types-ts3.8/metrics/web-vitals/types/ttfb.d.ts +0 -60
- package/build/types-ts3.8/metrics/web-vitals/types.d.ts +0 -78
- package/build/types-ts3.8/metrics/webVitalSpans.d.ts +0 -65
- package/build/types-ts3.8/networkUtils.d.ts +0 -28
- package/build/types-ts3.8/types.d.ts +0 -15
- /package/build/cjs/{instrument → instrumentation}/dom.js +0 -0
- /package/build/cjs/{instrument → instrumentation}/history.js +0 -0
- /package/build/cjs/{instrument → instrumentation}/location.js +0 -0
- /package/build/cjs/{instrument → instrumentation}/xhr.js +0 -0
- /package/build/cjs/{metrics → performance}/resourceTiming.js +0 -0
- /package/build/esm/{instrument → instrumentation}/dom.js +0 -0
- /package/build/esm/{instrument → instrumentation}/history.js +0 -0
- /package/build/esm/{instrument → instrumentation}/location.js +0 -0
- /package/build/esm/{instrument → instrumentation}/xhr.js +0 -0
- /package/build/esm/{metrics → performance}/resourceTiming.js +0 -0
- /package/build/types/{instrument → instrumentation}/dom.d.ts +0 -0
- /package/build/types/{instrument → instrumentation}/history.d.ts +0 -0
- /package/build/types/{instrument → instrumentation}/location.d.ts +0 -0
- /package/build/types/{instrument → instrumentation}/xhr.d.ts +0 -0
- /package/build/types/{metrics → performance}/elementTiming.d.ts +0 -0
- /package/build/types/{metrics → performance}/resourceTiming.d.ts +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { spanToStaticSpanJSON, withActiveSpan, startInactiveSpan } from '@sentry/core';
|
|
2
|
+
import { WINDOW } from '../types.js';
|
|
3
|
+
|
|
4
|
+
function isMeasurementValue(value) {
|
|
5
|
+
return typeof value === "number" && isFinite(value);
|
|
6
|
+
}
|
|
7
|
+
function startAndEndSpan(parentSpan, startTimeInSeconds, endTime, { ...ctx }) {
|
|
8
|
+
const parentStartTime = spanToStaticSpanJSON(parentSpan).start_timestamp;
|
|
9
|
+
if (parentStartTime && parentStartTime > startTimeInSeconds) {
|
|
10
|
+
if (typeof parentSpan.updateStartTime === "function") {
|
|
11
|
+
parentSpan.updateStartTime(startTimeInSeconds);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return withActiveSpan(parentSpan, () => {
|
|
15
|
+
const span = startInactiveSpan({
|
|
16
|
+
startTime: startTimeInSeconds,
|
|
17
|
+
...ctx
|
|
18
|
+
});
|
|
19
|
+
if (span) {
|
|
20
|
+
span.end(endTime);
|
|
21
|
+
}
|
|
22
|
+
return span;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function getBrowserPerformanceAPI() {
|
|
26
|
+
return WINDOW.addEventListener && WINDOW.performance;
|
|
27
|
+
}
|
|
28
|
+
function msToSec(time) {
|
|
29
|
+
return time / 1e3;
|
|
30
|
+
}
|
|
31
|
+
function extractNetworkProtocol(nextHopProtocol) {
|
|
32
|
+
let name = "unknown";
|
|
33
|
+
let version = "unknown";
|
|
34
|
+
let _name = "";
|
|
35
|
+
for (const char of nextHopProtocol) {
|
|
36
|
+
if (char === "/") {
|
|
37
|
+
[name, version] = nextHopProtocol.split("/");
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
if (!isNaN(Number(char))) {
|
|
41
|
+
name = _name === "h" ? "http" : _name;
|
|
42
|
+
version = nextHopProtocol.split(_name)[1];
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
_name += char;
|
|
46
|
+
}
|
|
47
|
+
if (_name === nextHopProtocol) {
|
|
48
|
+
name = _name;
|
|
49
|
+
}
|
|
50
|
+
return { name, version };
|
|
51
|
+
}
|
|
52
|
+
function supportsWebVital(entryType) {
|
|
53
|
+
try {
|
|
54
|
+
return PerformanceObserver.supportedEntryTypes.includes(entryType);
|
|
55
|
+
} catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { extractNetworkProtocol, getBrowserPerformanceAPI, isMeasurementValue, msToSec, startAndEndSpan, supportsWebVital };
|
|
61
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../src/performance/utils.ts"],"sourcesContent":["import type { SentrySpan, Span, SpanTimeInput, StartSpanOptions } from '@sentry/core';\nimport { spanToStaticSpanJSON, startInactiveSpan, withActiveSpan } from '@sentry/core';\nimport { WINDOW } from '../types';\n\n/**\n * Checks if a given value is a valid measurement value.\n */\nexport function isMeasurementValue(value: unknown): value is number {\n return typeof value === 'number' && isFinite(value);\n}\n\n/**\n * Helper function to start child on transactions. This function will make sure that the transaction will\n * use the start timestamp of the created child span if it is earlier than the transactions actual\n * start timestamp.\n */\nexport function startAndEndSpan(\n parentSpan: Span,\n startTimeInSeconds: number,\n endTime: SpanTimeInput,\n { ...ctx }: StartSpanOptions,\n): Span | undefined {\n const parentStartTime = spanToStaticSpanJSON(parentSpan).start_timestamp;\n if (parentStartTime && parentStartTime > startTimeInSeconds) {\n // We can only do this for SentrySpans...\n if (typeof (parentSpan as Partial<SentrySpan>).updateStartTime === 'function') {\n (parentSpan as SentrySpan).updateStartTime(startTimeInSeconds);\n }\n }\n\n // The return value only exists for tests\n return withActiveSpan(parentSpan, () => {\n const span = startInactiveSpan({\n startTime: startTimeInSeconds,\n ...ctx,\n });\n\n if (span) {\n span.end(endTime);\n }\n\n return span;\n });\n}\n\n/** Get the browser performance API. */\nexport function getBrowserPerformanceAPI(): Performance | undefined {\n // @ts-expect-error we want to make sure all of these are available, even if TS is sure they are\n return WINDOW.addEventListener && WINDOW.performance;\n}\n\n/**\n * Converts from milliseconds to seconds\n * @param time time in ms\n */\nexport function msToSec(time: number): number {\n return time / 1000;\n}\n\n/**\n * Converts ALPN protocol ids to name and version.\n *\n * (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids)\n * @param nextHopProtocol PerformanceResourceTiming.nextHopProtocol\n */\nexport function extractNetworkProtocol(nextHopProtocol: string): { name: string; version: string } {\n let name = 'unknown';\n let version = 'unknown';\n let _name = '';\n for (const char of nextHopProtocol) {\n // http/1.1 etc.\n if (char === '/') {\n [name, version] = nextHopProtocol.split('/') as [string, string];\n break;\n }\n // h2, h3 etc.\n if (!isNaN(Number(char))) {\n name = _name === 'h' ? 'http' : _name;\n version = nextHopProtocol.split(_name)[1] as string;\n break;\n }\n _name += char;\n }\n if (_name === nextHopProtocol) {\n // webrtc, ftp, etc.\n name = _name;\n }\n return { name, version };\n}\n\n/**\n * Generic support check for web vitals\n */\nexport function supportsWebVital(entryType: 'layout-shift' | 'largest-contentful-paint'): boolean {\n try {\n return PerformanceObserver.supportedEntryTypes.includes(entryType);\n } catch {\n return false;\n }\n}\n"],"names":[],"mappings":";;;AAOO,SAAS,mBAAmB,KAAA,EAAiC;AAClE,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,QAAA,CAAS,KAAK,CAAA;AACpD;AAOO,SAAS,gBACd,UAAA,EACA,kBAAA,EACA,SACA,EAAE,GAAG,KAAI,EACS;AAClB,EAAA,MAAM,eAAA,GAAkB,oBAAA,CAAqB,UAAU,CAAA,CAAE,eAAA;AACzD,EAAA,IAAI,eAAA,IAAmB,kBAAkB,kBAAA,EAAoB;AAE3D,IAAA,IAAI,OAAQ,UAAA,CAAmC,eAAA,KAAoB,UAAA,EAAY;AAC7E,MAAC,UAAA,CAA0B,gBAAgB,kBAAkB,CAAA;AAAA,IAC/D;AAAA,EACF;AAGA,EAAA,OAAO,cAAA,CAAe,YAAY,MAAM;AACtC,IAAA,MAAM,OAAO,iBAAA,CAAkB;AAAA,MAC7B,SAAA,EAAW,kBAAA;AAAA,MACX,GAAG;AAAA,KACJ,CAAA;AAED,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,IAAA,CAAK,IAAI,OAAO,CAAA;AAAA,IAClB;AAEA,IAAA,OAAO,IAAA;AAAA,EACT,CAAC,CAAA;AACH;AAGO,SAAS,wBAAA,GAAoD;AAElE,EAAA,OAAO,MAAA,CAAO,oBAAoB,MAAA,CAAO,WAAA;AAC3C;AAMO,SAAS,QAAQ,IAAA,EAAsB;AAC5C,EAAA,OAAO,IAAA,GAAO,GAAA;AAChB;AAQO,SAAS,uBAAuB,eAAA,EAA4D;AACjG,EAAA,IAAI,IAAA,GAAO,SAAA;AACX,EAAA,IAAI,OAAA,GAAU,SAAA;AACd,EAAA,IAAI,KAAA,GAAQ,EAAA;AACZ,EAAA,KAAA,MAAW,QAAQ,eAAA,EAAiB;AAElC,IAAA,IAAI,SAAS,GAAA,EAAK;AAChB,MAAA,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,eAAA,CAAgB,MAAM,GAAG,CAAA;AAC3C,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,KAAA,CAAM,MAAA,CAAO,IAAI,CAAC,CAAA,EAAG;AACxB,MAAA,IAAA,GAAO,KAAA,KAAU,MAAM,MAAA,GAAS,KAAA;AAChC,MAAA,OAAA,GAAU,eAAA,CAAgB,KAAA,CAAM,KAAK,CAAA,CAAE,CAAC,CAAA;AACxC,MAAA;AAAA,IACF;AACA,IAAA,KAAA,IAAS,IAAA;AAAA,EACX;AACA,EAAA,IAAI,UAAU,eAAA,EAAiB;AAE7B,IAAA,IAAA,GAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,EAAE,MAAM,OAAA,EAAQ;AACzB;AAKO,SAAS,iBAAiB,SAAA,EAAiE;AAChG,EAAA,IAAI;AACF,IAAA,OAAO,mBAAA,CAAoB,mBAAA,CAAoB,QAAA,CAAS,SAAS,CAAA;AAAA,EACnE,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;;;;"}
|
|
@@ -1,23 +1,12 @@
|
|
|
1
|
-
import { isBrowser,
|
|
1
|
+
import { isBrowser, getActiveSpan, getRootSpan } from '@sentry/core';
|
|
2
2
|
import { htmlTreeAsString } from '../htmlTreeAsString.js';
|
|
3
3
|
import { WINDOW } from '../types.js';
|
|
4
|
-
import { addPerformanceInstrumentationHandler,
|
|
5
|
-
import { getBrowserPerformanceAPI, msToSec, startStandaloneWebVitalSpan } from './utils.js';
|
|
4
|
+
import { addPerformanceInstrumentationHandler, isPerformanceEventTiming } from '../instrumentation/performanceObserver.js';
|
|
6
5
|
|
|
7
6
|
const LAST_INTERACTIONS = [];
|
|
8
7
|
const INTERACTIONS_SPAN_MAP = /* @__PURE__ */ new Map();
|
|
9
8
|
const ELEMENT_NAME_TIMESTAMP_MAP = /* @__PURE__ */ new Map();
|
|
10
9
|
const MAX_PLAUSIBLE_INP_DURATION = 60;
|
|
11
|
-
function startTrackingINP() {
|
|
12
|
-
const performance = getBrowserPerformanceAPI();
|
|
13
|
-
if (performance && browserPerformanceTimeOrigin()) {
|
|
14
|
-
const inpCallback = _trackINP();
|
|
15
|
-
return () => {
|
|
16
|
-
inpCallback();
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
return () => void 0;
|
|
20
|
-
}
|
|
21
10
|
const INP_ENTRY_MAP = {
|
|
22
11
|
click: "click",
|
|
23
12
|
pointerdown: "click",
|
|
@@ -46,49 +35,6 @@ const INP_ENTRY_MAP = {
|
|
|
46
35
|
keypress: "press",
|
|
47
36
|
input: "press"
|
|
48
37
|
};
|
|
49
|
-
function _trackINP() {
|
|
50
|
-
return addInpInstrumentationHandler(_onInp);
|
|
51
|
-
}
|
|
52
|
-
const _onInp = ({ metric }) => {
|
|
53
|
-
if (metric.value == void 0) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
const duration = msToSec(metric.value);
|
|
57
|
-
if (duration > MAX_PLAUSIBLE_INP_DURATION) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
const entry = metric.entries.find((entry2) => entry2.duration === metric.value && INP_ENTRY_MAP[entry2.name]);
|
|
61
|
-
if (!entry) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
const { interactionId } = entry;
|
|
65
|
-
const interactionType = INP_ENTRY_MAP[entry.name];
|
|
66
|
-
const startTime = msToSec(browserPerformanceTimeOrigin() + entry.startTime);
|
|
67
|
-
const activeSpan = getActiveSpan();
|
|
68
|
-
const rootSpan = activeSpan ? getRootSpan(activeSpan) : void 0;
|
|
69
|
-
const cachedInteractionContext = interactionId != null ? INTERACTIONS_SPAN_MAP.get(interactionId) : void 0;
|
|
70
|
-
const spanToUse = cachedInteractionContext?.span || rootSpan;
|
|
71
|
-
const routeName = spanToUse ? spanToJSON(spanToUse).description : getCurrentScope().getScopeData().transactionName;
|
|
72
|
-
const name = cachedInteractionContext?.elementName || htmlTreeAsString(entry.target);
|
|
73
|
-
const attributes = {
|
|
74
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.browser.inp",
|
|
75
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: `ui.interaction.${interactionType}`,
|
|
76
|
-
[SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: entry.duration
|
|
77
|
-
};
|
|
78
|
-
const span = startStandaloneWebVitalSpan({
|
|
79
|
-
name,
|
|
80
|
-
transaction: routeName,
|
|
81
|
-
attributes,
|
|
82
|
-
startTime
|
|
83
|
-
});
|
|
84
|
-
if (span) {
|
|
85
|
-
span.addEvent("inp", {
|
|
86
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_UNIT]: "millisecond",
|
|
87
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_VALUE]: metric.value
|
|
88
|
-
});
|
|
89
|
-
span.end(startTime + duration);
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
38
|
function getCachedInteractionContext(interactionId) {
|
|
93
39
|
return interactionId != null ? INTERACTIONS_SPAN_MAP.get(interactionId) : void 0;
|
|
94
40
|
}
|
|
@@ -158,5 +104,5 @@ function registerInpInteractionListener() {
|
|
|
158
104
|
addPerformanceInstrumentationHandler("first-input", handleEntries);
|
|
159
105
|
}
|
|
160
106
|
|
|
161
|
-
export { INP_ENTRY_MAP, MAX_PLAUSIBLE_INP_DURATION,
|
|
107
|
+
export { INP_ENTRY_MAP, MAX_PLAUSIBLE_INP_DURATION, getCachedInteractionContext, registerInpInteractionListener };
|
|
162
108
|
//# sourceMappingURL=inp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inp.js","sources":["../../../src/web-vitals/inp.ts"],"sourcesContent":["import type { Span } from '@sentry/core';\nimport { getActiveSpan, getRootSpan, isBrowser } from '@sentry/core';\nimport { htmlTreeAsString } from '../htmlTreeAsString';\nimport { WINDOW } from '../types';\nimport { addPerformanceInstrumentationHandler, isPerformanceEventTiming } from '../instrumentation/performanceObserver';\n\ninterface InteractionContext {\n span: Span | undefined;\n elementName: string;\n}\n\nconst LAST_INTERACTIONS: number[] = [];\nconst INTERACTIONS_SPAN_MAP = new Map<number, InteractionContext>();\n\n// Map to store element names by timestamp, since we get the DOM event before the PerformanceObserver entry\nconst ELEMENT_NAME_TIMESTAMP_MAP = new Map<number, string>();\n\n/**\n * 60 seconds is the maximum for a plausible INP value\n * (source: Me)\n */\nexport const MAX_PLAUSIBLE_INP_DURATION = 60;\n\nexport const INP_ENTRY_MAP: Record<string, 'click' | 'hover' | 'drag' | 'press'> = {\n click: 'click',\n pointerdown: 'click',\n pointerup: 'click',\n mousedown: 'click',\n mouseup: 'click',\n touchstart: 'click',\n touchend: 'click',\n mouseover: 'hover',\n mouseout: 'hover',\n mouseenter: 'hover',\n mouseleave: 'hover',\n pointerover: 'hover',\n pointerout: 'hover',\n pointerenter: 'hover',\n pointerleave: 'hover',\n dragstart: 'drag',\n dragend: 'drag',\n drag: 'drag',\n dragenter: 'drag',\n dragleave: 'drag',\n dragover: 'drag',\n drop: 'drag',\n keydown: 'press',\n keyup: 'press',\n keypress: 'press',\n input: 'press',\n};\n\n/**\n * Look up a cached interaction context (element name + root span) by interactionId.\n * Returns undefined if no context was cached for this interaction.\n */\nexport function getCachedInteractionContext(interactionId: number | undefined): InteractionContext | undefined {\n return interactionId != null ? INTERACTIONS_SPAN_MAP.get(interactionId) : undefined;\n}\n\n/**\n * Register a listener to cache route information for INP interactions.\n */\nexport function registerInpInteractionListener(): void {\n // Listen for all interaction events that could contribute to INP\n const interactionEvents = Object.keys(INP_ENTRY_MAP);\n if (isBrowser()) {\n interactionEvents.forEach(eventType => {\n WINDOW.addEventListener(eventType, captureElementFromEvent, { capture: true, passive: true });\n });\n }\n\n /**\n * Captures the element name from a DOM event and stores it in the ELEMENT_NAME_TIMESTAMP_MAP.\n */\n function captureElementFromEvent(event: Event): void {\n const target = event.target as HTMLElement | null;\n if (!target) {\n return;\n }\n\n const elementName = htmlTreeAsString(target);\n const timestamp = Math.round(event.timeStamp);\n\n // Store the element name by timestamp so we can match it with the PerformanceEntry\n ELEMENT_NAME_TIMESTAMP_MAP.set(timestamp, elementName);\n\n // Clean up old\n if (ELEMENT_NAME_TIMESTAMP_MAP.size > 50) {\n const firstKey = ELEMENT_NAME_TIMESTAMP_MAP.keys().next().value;\n if (firstKey !== undefined) {\n ELEMENT_NAME_TIMESTAMP_MAP.delete(firstKey);\n }\n }\n }\n\n /**\n * Tries to get the element name from the timestamp map.\n */\n function resolveElementNameFromEntry(entry: PerformanceEntry): string {\n const timestamp = Math.round(entry.startTime);\n let elementName = ELEMENT_NAME_TIMESTAMP_MAP.get(timestamp);\n\n // try nearby timestamps (±5ms)\n if (!elementName) {\n for (let offset = -5; offset <= 5; offset++) {\n const nearbyName = ELEMENT_NAME_TIMESTAMP_MAP.get(timestamp + offset);\n if (nearbyName) {\n elementName = nearbyName;\n break;\n }\n }\n }\n\n return elementName || '<unknown>';\n }\n\n const handleEntries = ({ entries }: { entries: PerformanceEntry[] }): void => {\n const activeSpan = getActiveSpan();\n const activeRootSpan = activeSpan && getRootSpan(activeSpan);\n\n entries.forEach(entry => {\n if (!isPerformanceEventTiming(entry)) {\n return;\n }\n\n const interactionId = entry.interactionId;\n if (interactionId == null) {\n return;\n }\n\n // If the interaction was already recorded before, nothing more to do\n if (INTERACTIONS_SPAN_MAP.has(interactionId)) {\n return;\n }\n\n const elementName = entry.target ? htmlTreeAsString(entry.target) : resolveElementNameFromEntry(entry);\n\n // We keep max. 10 interactions in the list, then remove the oldest one & clean up\n if (LAST_INTERACTIONS.length > 10) {\n const last = LAST_INTERACTIONS.shift() as number;\n INTERACTIONS_SPAN_MAP.delete(last);\n }\n\n // We add the interaction to the list of recorded interactions\n // and store both the span and element name for this interaction\n LAST_INTERACTIONS.push(interactionId);\n INTERACTIONS_SPAN_MAP.set(interactionId, {\n span: activeRootSpan,\n elementName,\n });\n });\n };\n\n addPerformanceInstrumentationHandler('event', handleEntries);\n addPerformanceInstrumentationHandler('first-input', handleEntries);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lcp.js","sources":["../../../src/web-vitals/lcp.ts"],"sourcesContent":["/**\n * 60 seconds is the maximum for a plausible LCP value.\n */\nexport const MAX_PLAUSIBLE_LCP_DURATION = 60_000;\n\nexport function isValidLcpMetric(lcpValue: number | undefined): lcpValue is number {\n return lcpValue != null && lcpValue > 0 && lcpValue <= MAX_PLAUSIBLE_LCP_DURATION;\n}\n"],"names":[],"mappings":"AAGO,MAAM,0BAAA,GAA6B;AAEnC,SAAS,iBAAiB,QAAA,EAAkD;AACjF,EAAA,OAAO,QAAA,IAAY,IAAA,IAAQ,QAAA,GAAW,CAAA,IAAK,QAAA,IAAY,0BAAA;AACzD;;;;"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { onHidden } from './utils.js';
|
|
2
|
+
|
|
3
|
+
function listenForWebVitalReportEvents(client, collectorCallback) {
|
|
4
|
+
let pageloadSpan;
|
|
5
|
+
let collected = false;
|
|
6
|
+
function _runCollectorCallbackOnce(event) {
|
|
7
|
+
if (!collected && pageloadSpan) {
|
|
8
|
+
collectorCallback(event, pageloadSpan.spanContext().spanId, pageloadSpan);
|
|
9
|
+
}
|
|
10
|
+
collected = true;
|
|
11
|
+
}
|
|
12
|
+
onHidden(() => {
|
|
13
|
+
_runCollectorCallbackOnce("pagehide");
|
|
14
|
+
});
|
|
15
|
+
const unsubscribeStartNavigation = client.on("beforeStartNavigationSpan", (_, options) => {
|
|
16
|
+
if (!options?.isRedirect) {
|
|
17
|
+
_runCollectorCallbackOnce("navigation");
|
|
18
|
+
unsubscribeStartNavigation();
|
|
19
|
+
unsubscribeAfterStartPageLoadSpan();
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const unsubscribeAfterStartPageLoadSpan = client.on("afterStartPageLoadSpan", (span) => {
|
|
23
|
+
pageloadSpan = span;
|
|
24
|
+
unsubscribeAfterStartPageLoadSpan();
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { listenForWebVitalReportEvents };
|
|
29
|
+
//# sourceMappingURL=reportEvents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reportEvents.js","sources":["../../../src/web-vitals/reportEvents.ts"],"sourcesContent":["import type { Client, Span } from '@sentry/core';\nimport { onHidden } from './utils';\n\nexport type WebVitalReportEvent = 'pagehide' | 'navigation';\n\n/**\n * Listens for events on which we want to collect a previously accumulated web vital value.\n * Currently, this includes:\n *\n * - pagehide (i.e. user minimizes browser window, hides tab, etc)\n * - soft navigation (we only care about the vital of the initially loaded route)\n *\n * As a \"side-effect\", this function will also collect the span id of the pageload span.\n *\n * @param collectorCallback the callback to be called when the first of these events is triggered. Parameters:\n * - event: the event that triggered the reporting of the web vital value.\n * - pageloadSpanId: the span id of the pageload span. This is used to link the web vital span to the pageload span.\n * - pageloadSpan: the pageload span instance. This is used for full access to the pageload span for span streaming.\n */\nexport function listenForWebVitalReportEvents(\n client: Client,\n collectorCallback: (event: WebVitalReportEvent, pageloadSpanId: string, pageloadSpan?: Span) => void,\n) {\n let pageloadSpan: Span | undefined;\n\n let collected = false;\n function _runCollectorCallbackOnce(event: WebVitalReportEvent) {\n if (!collected && pageloadSpan) {\n collectorCallback(event, pageloadSpan.spanContext().spanId, pageloadSpan);\n }\n collected = true;\n }\n\n onHidden(() => {\n _runCollectorCallbackOnce('pagehide');\n });\n\n const unsubscribeStartNavigation = client.on('beforeStartNavigationSpan', (_, options) => {\n // we only want to collect LCP if we actually navigate. Redirects should be ignored.\n if (!options?.isRedirect) {\n _runCollectorCallbackOnce('navigation');\n unsubscribeStartNavigation();\n unsubscribeAfterStartPageLoadSpan();\n }\n });\n\n const unsubscribeAfterStartPageLoadSpan = client.on('afterStartPageLoadSpan', span => {\n pageloadSpan = span;\n unsubscribeAfterStartPageLoadSpan();\n });\n}\n"],"names":[],"mappings":";;AAmBO,SAAS,6BAAA,CACd,QACA,iBAAA,EACA;AACA,EAAA,IAAI,YAAA;AAEJ,EAAA,IAAI,SAAA,GAAY,KAAA;AAChB,EAAA,SAAS,0BAA0B,KAAA,EAA4B;AAC7D,IAAA,IAAI,CAAC,aAAa,YAAA,EAAc;AAC9B,MAAA,iBAAA,CAAkB,KAAA,EAAO,YAAA,CAAa,WAAA,EAAY,CAAE,QAAQ,YAAY,CAAA;AAAA,IAC1E;AACA,IAAA,SAAA,GAAY,IAAA;AAAA,EACd;AAEA,EAAA,QAAA,CAAS,MAAM;AACb,IAAA,yBAAA,CAA0B,UAAU,CAAA;AAAA,EACtC,CAAC,CAAA;AAED,EAAA,MAAM,6BAA6B,MAAA,CAAO,EAAA,CAAG,2BAAA,EAA6B,CAAC,GAAG,OAAA,KAAY;AAExF,IAAA,IAAI,CAAC,SAAS,UAAA,EAAY;AACxB,MAAA,yBAAA,CAA0B,YAAY,CAAA;AACtC,MAAA,0BAAA,EAA2B;AAC3B,MAAA,iCAAA,EAAkC;AAAA,IACpC;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAM,iCAAA,GAAoC,MAAA,CAAO,EAAA,CAAG,wBAAA,EAA0B,CAAA,IAAA,KAAQ;AACpF,IAAA,YAAA,GAAe,IAAA;AACf,IAAA,iCAAA,EAAkC;AAAA,EACpC,CAAC,CAAA;AACH;;;;"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { browserPerformanceTimeOrigin, debug, timestampInSeconds, getCurrentScope,
|
|
1
|
+
import { browserPerformanceTimeOrigin, hasSpanStreamingEnabled, debug, timestampInSeconds, getCurrentScope, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP, startInactiveSpan, SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, getClient, getActiveSpan, getRootSpan } from '@sentry/core';
|
|
2
2
|
import { DEBUG_BUILD } from '../debug-build.js';
|
|
3
3
|
import { htmlTreeAsString } from '../htmlTreeAsString.js';
|
|
4
4
|
import { WINDOW } from '../types.js';
|
|
5
5
|
import { MAX_PLAUSIBLE_INP_DURATION, INP_ENTRY_MAP, getCachedInteractionContext } from './inp.js';
|
|
6
|
-
import { addClsInstrumentationHandler, addInpInstrumentationHandler, addLcpInstrumentationHandler } from '
|
|
6
|
+
import { addClsInstrumentationHandler, addInpInstrumentationHandler, addLcpInstrumentationHandler } from '../instrumentation/performanceObserver.js';
|
|
7
7
|
import { isValidLcpMetric } from './lcp.js';
|
|
8
|
-
import {
|
|
8
|
+
import { listenForWebVitalReportEvents } from './reportEvents.js';
|
|
9
|
+
import { supportsWebVital, getBrowserPerformanceAPI, msToSec } from '../performance/utils.js';
|
|
9
10
|
import { SENTRY_SEGMENT_NAME, SENTRY_TRANSACTION } from '@sentry/conventions/attributes';
|
|
10
11
|
|
|
11
12
|
function _emitWebVitalSpan(options) {
|
|
@@ -19,7 +20,8 @@ function _emitWebVitalSpan(options) {
|
|
|
19
20
|
parentSpan,
|
|
20
21
|
reportEvent,
|
|
21
22
|
startTime,
|
|
22
|
-
endTime
|
|
23
|
+
endTime,
|
|
24
|
+
standalone
|
|
23
25
|
} = options;
|
|
24
26
|
const routeName = getCurrentScope().getScopeData().transactionName;
|
|
25
27
|
const attributes = {
|
|
@@ -34,25 +36,38 @@ function _emitWebVitalSpan(options) {
|
|
|
34
36
|
"user_agent.original": WINDOW.navigator?.userAgent,
|
|
35
37
|
...passedAttributes
|
|
36
38
|
};
|
|
37
|
-
if (parentSpan &&
|
|
39
|
+
if (parentSpan && spanToJSON(parentSpan).attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] === "pageload") {
|
|
38
40
|
attributes["sentry.pageload.span_id"] = parentSpan.spanContext().spanId;
|
|
39
41
|
}
|
|
40
42
|
if (reportEvent) {
|
|
41
43
|
attributes[`browser.web_vital.${metricName}.report_event`] = reportEvent;
|
|
42
44
|
}
|
|
45
|
+
if (standalone) {
|
|
46
|
+
Object.assign(attributes, getReplayAttributes());
|
|
47
|
+
}
|
|
43
48
|
const span = startInactiveSpan({
|
|
44
49
|
name,
|
|
45
50
|
attributes,
|
|
46
51
|
startTime,
|
|
47
|
-
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
parentSpan
|
|
52
|
+
parentSpan,
|
|
53
|
+
// oxlint-disable-next-line typescript/no-deprecated -- intentional during the v1/v2 transition; see the TODO(standalone) above
|
|
54
|
+
experimental: standalone ? { standalone: true } : void 0
|
|
51
55
|
});
|
|
52
56
|
if (span) {
|
|
53
57
|
span.end(endTime ?? startTime);
|
|
54
58
|
}
|
|
55
59
|
}
|
|
60
|
+
function getReplayAttributes() {
|
|
61
|
+
const replay = getClient()?.getIntegrationByName("Replay");
|
|
62
|
+
const replayId = replay?.getReplayId(true);
|
|
63
|
+
if (!replayId) {
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
"sentry.replay_id": replayId,
|
|
68
|
+
"sentry._internal.replay_is_buffering": replay.getRecordingMode() === "buffer" ? true : void 0
|
|
69
|
+
};
|
|
70
|
+
}
|
|
56
71
|
function trackLcpAsSpan(client) {
|
|
57
72
|
let lcpValue = 0;
|
|
58
73
|
let lcpEntry;
|
|
@@ -142,11 +157,12 @@ function _sendClsSpan(clsValue, entry, pageloadSpan, reportEvent) {
|
|
|
142
157
|
startTime
|
|
143
158
|
});
|
|
144
159
|
}
|
|
145
|
-
function trackInpAsSpan() {
|
|
160
|
+
function trackInpAsSpan(client) {
|
|
146
161
|
const performance = getBrowserPerformanceAPI();
|
|
147
162
|
if (!performance || !browserPerformanceTimeOrigin()) {
|
|
148
163
|
return;
|
|
149
164
|
}
|
|
165
|
+
const standalone = !hasSpanStreamingEnabled(client);
|
|
150
166
|
const onInp = ({ metric }) => {
|
|
151
167
|
if (metric.value == null) {
|
|
152
168
|
return;
|
|
@@ -159,11 +175,11 @@ function trackInpAsSpan() {
|
|
|
159
175
|
if (!entry) {
|
|
160
176
|
return;
|
|
161
177
|
}
|
|
162
|
-
_sendInpSpan(metric.value, entry);
|
|
178
|
+
_sendInpSpan(metric.value, entry, standalone);
|
|
163
179
|
};
|
|
164
180
|
addInpInstrumentationHandler(onInp);
|
|
165
181
|
}
|
|
166
|
-
function _sendInpSpan(inpValue, entry) {
|
|
182
|
+
function _sendInpSpan(inpValue, entry, standalone = false) {
|
|
167
183
|
DEBUG_BUILD && debug.log(`Sending INP span (${inpValue})`);
|
|
168
184
|
const startTime = msToSec(browserPerformanceTimeOrigin() + entry.startTime);
|
|
169
185
|
const duration = msToSec(inpValue);
|
|
@@ -172,7 +188,7 @@ function _sendInpSpan(inpValue, entry) {
|
|
|
172
188
|
const activeSpan = getActiveSpan();
|
|
173
189
|
const rootSpan = activeSpan ? getRootSpan(activeSpan) : void 0;
|
|
174
190
|
const spanToUse = cachedContext?.span || rootSpan;
|
|
175
|
-
const routeName = spanToUse ?
|
|
191
|
+
const routeName = spanToUse ? spanToJSON(spanToUse).name : getCurrentScope().getScopeData().transactionName;
|
|
176
192
|
const name = cachedContext?.elementName || htmlTreeAsString(entry.target);
|
|
177
193
|
_emitWebVitalSpan({
|
|
178
194
|
name,
|
|
@@ -188,9 +204,10 @@ function _sendInpSpan(inpValue, entry) {
|
|
|
188
204
|
},
|
|
189
205
|
startTime,
|
|
190
206
|
endTime: startTime + duration,
|
|
191
|
-
parentSpan: spanToUse
|
|
207
|
+
parentSpan: spanToUse,
|
|
208
|
+
standalone
|
|
192
209
|
});
|
|
193
210
|
}
|
|
194
211
|
|
|
195
212
|
export { _emitWebVitalSpan, _sendClsSpan, _sendInpSpan, _sendLcpSpan, trackClsAsSpan, trackInpAsSpan, trackLcpAsSpan };
|
|
196
|
-
//# sourceMappingURL=
|
|
213
|
+
//# sourceMappingURL=spans.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spans.js","sources":["../../../src/web-vitals/spans.ts"],"sourcesContent":["import type { Client, Integration, Span, SpanAttributes } from '@sentry/core';\nimport {\n browserPerformanceTimeOrigin,\n debug,\n getActiveSpan,\n getClient,\n getCurrentScope,\n getRootSpan,\n hasSpanStreamingEnabled,\n SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n startInactiveSpan,\n timestampInSeconds,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { htmlTreeAsString } from '../htmlTreeAsString';\nimport { WINDOW } from '../types';\nimport { getCachedInteractionContext, INP_ENTRY_MAP, MAX_PLAUSIBLE_INP_DURATION } from './inp';\nimport type { InstrumentationHandlerCallback } from '../instrumentation/performanceObserver';\nimport {\n addClsInstrumentationHandler,\n addInpInstrumentationHandler,\n addLcpInstrumentationHandler,\n} from '../instrumentation/performanceObserver';\nimport { isValidLcpMetric } from './lcp';\nimport type { WebVitalReportEvent } from './reportEvents';\nimport { listenForWebVitalReportEvents } from './reportEvents';\nimport { getBrowserPerformanceAPI, msToSec, supportsWebVital } from '../performance/utils';\nimport type { PerformanceEventTiming } from '../instrumentation/performanceObserver';\nimport { SENTRY_SEGMENT_NAME, SENTRY_TRANSACTION } from '@sentry/conventions/attributes';\n\n// Locally-defined interfaces to avoid leaking bare global type references into the\n// generated .d.ts. The `declare global` augmentations in web-vitals/types.ts make these\n// available during this package's compilation but are NOT carried to consumers.\n// This mirrors the pattern used for PerformanceEventTiming in instrument.ts.\nexport interface LayoutShift extends PerformanceEntry {\n value: number;\n sources: Array<{ node: Node | null }>;\n hadRecentInput: boolean;\n}\n\nexport interface LargestContentfulPaint extends PerformanceEntry {\n readonly renderTime: DOMHighResTimeStamp;\n readonly loadTime: DOMHighResTimeStamp;\n readonly size: number;\n readonly id: string;\n readonly url: string;\n readonly element: Element | null;\n}\n\ninterface WebVitalSpanOptions {\n name: string;\n op: string;\n origin: string;\n metricName: 'lcp' | 'cls' | 'inp';\n value: number;\n attributes?: SpanAttributes;\n parentSpan?: Span;\n reportEvent?: WebVitalReportEvent;\n startTime: number;\n endTime?: number;\n /**\n * When `true`, the span is sent on its own as a v2 streamed span instead of being folded into a\n * transaction. Used for INP when span streaming is disabled (it reports late, so it can't ride\n * the pageload transaction).\n *\n * TODO(standalone): remove once the static (transaction) trace lifecycle is dropped and INP always streams.\n */\n standalone?: boolean;\n}\n\n/**\n * Emits a web vital span. When `standalone` is set it is sent on its own as a v2 streamed span;\n * otherwise it flows through the span streaming pipeline as a child of `parentSpan`.\n */\nexport function _emitWebVitalSpan(options: WebVitalSpanOptions): void {\n const {\n name,\n op,\n origin,\n metricName,\n value,\n attributes: passedAttributes,\n parentSpan,\n reportEvent,\n startTime,\n endTime,\n standalone,\n } = options;\n\n const routeName = getCurrentScope().getScopeData().transactionName;\n\n const attributes: SpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: op,\n [SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: 0,\n [`browser.web_vital.${metricName}.value`]: value,\n // oxlint-disable-next-line typescript-eslint/no-deprecated\n [SENTRY_TRANSACTION]: routeName,\n [SENTRY_SEGMENT_NAME]: routeName,\n // Web vital score calculation relies on the user agent\n 'user_agent.original': WINDOW.navigator?.userAgent,\n ...passedAttributes,\n };\n\n if (parentSpan && spanToJSON(parentSpan).attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'pageload') {\n // for LCP and CLS, we collect the pageload span id as an attribute\n attributes['sentry.pageload.span_id'] = parentSpan.spanContext().spanId;\n }\n\n if (reportEvent) {\n attributes[`browser.web_vital.${metricName}.report_event`] = reportEvent;\n }\n\n // A standalone span is sent as a plain v2 span without running the `processSpan` hooks (see\n // `captureStandaloneSpanWithStaticCallback`), so Replay can't attach the replay id itself. Set it\n // here, mirroring Replay's `processSpan`, so INP keeps its replay association like it did on v1.\n // TODO(standalone): remove once the static (transaction) trace lifecycle is dropped and INP always\n // streams, at which point Replay's `processSpan` runs and attaches the replay id.\n if (standalone) {\n Object.assign(attributes, getReplayAttributes());\n }\n\n const span = startInactiveSpan({\n name,\n attributes,\n startTime,\n parentSpan,\n // oxlint-disable-next-line typescript/no-deprecated -- intentional during the v1/v2 transition; see the TODO(standalone) above\n experimental: standalone ? { standalone: true } : undefined,\n });\n\n if (span) {\n span.end(endTime ?? startTime);\n }\n}\n\ninterface ReplayIntegration extends Integration {\n getReplayId: (onlyIfSampled?: boolean) => string | undefined;\n getRecordingMode: () => 'session' | 'buffer' | undefined;\n}\n\n// TODO(standalone): remove once the static (transaction) trace lifecycle is dropped; Replay's\n// `processSpan` then attaches the replay id to the streamed INP span instead.\nfunction getReplayAttributes(): SpanAttributes {\n const replay = getClient()?.getIntegrationByName<ReplayIntegration>('Replay');\n const replayId = replay?.getReplayId(true);\n if (!replayId) {\n return {};\n }\n\n return {\n 'sentry.replay_id': replayId,\n 'sentry._internal.replay_is_buffering': replay!.getRecordingMode() === 'buffer' ? true : undefined,\n };\n}\n\n/**\n * Tracks LCP as a streamed span.\n */\nexport function trackLcpAsSpan(client: Client): void {\n let lcpValue = 0;\n let lcpEntry: LargestContentfulPaint | undefined;\n\n if (!supportsWebVital('largest-contentful-paint')) {\n return;\n }\n\n const cleanupLcpHandler = addLcpInstrumentationHandler(({ metric }) => {\n const entry = metric.entries[metric.entries.length - 1] as LargestContentfulPaint | undefined;\n if (!entry || !isValidLcpMetric(metric.value)) {\n return;\n }\n lcpValue = metric.value;\n lcpEntry = entry;\n }, true);\n\n listenForWebVitalReportEvents(client, (reportEvent, _, pageloadSpan) => {\n _sendLcpSpan(lcpValue, lcpEntry, pageloadSpan, reportEvent);\n cleanupLcpHandler();\n });\n}\n\n/**\n * Exported only for testing.\n */\nexport function _sendLcpSpan(\n lcpValue: number,\n entry: LargestContentfulPaint | undefined,\n pageloadSpan?: Span,\n reportEvent?: WebVitalReportEvent,\n): void {\n if (!isValidLcpMetric(lcpValue)) {\n return;\n }\n\n DEBUG_BUILD && debug.log(`Sending LCP span (${lcpValue})`);\n\n const performanceTimeOrigin = browserPerformanceTimeOrigin() || 0;\n const timeOrigin = msToSec(performanceTimeOrigin);\n const endTime = msToSec(performanceTimeOrigin + (entry?.startTime || 0));\n const name = entry ? htmlTreeAsString(entry.element) : 'Largest contentful paint';\n\n const attributes: SpanAttributes = {};\n\n entry?.element && (attributes['browser.web_vital.lcp.element'] = htmlTreeAsString(entry.element));\n entry?.id && (attributes['browser.web_vital.lcp.id'] = entry.id);\n entry?.url && (attributes['browser.web_vital.lcp.url'] = entry.url);\n entry?.loadTime != null && (attributes['browser.web_vital.lcp.load_time'] = entry.loadTime);\n entry?.renderTime != null && (attributes['browser.web_vital.lcp.render_time'] = entry.renderTime);\n entry?.size != null && (attributes['browser.web_vital.lcp.size'] = entry.size);\n\n _emitWebVitalSpan({\n name,\n op: 'ui.webvital.lcp',\n origin: 'auto.http.browser.lcp',\n metricName: 'lcp',\n value: lcpValue,\n attributes,\n parentSpan: pageloadSpan,\n reportEvent,\n startTime: timeOrigin,\n endTime,\n });\n}\n\n/**\n * Tracks CLS as a streamed span.\n */\nexport function trackClsAsSpan(client: Client): void {\n let clsValue = 0;\n let clsEntry: LayoutShift | undefined;\n\n if (!supportsWebVital('layout-shift')) {\n return;\n }\n\n const cleanupClsHandler = addClsInstrumentationHandler(({ metric }) => {\n const entry = metric.entries[metric.entries.length - 1] as LayoutShift | undefined;\n if (!entry) {\n return;\n }\n clsValue = metric.value;\n clsEntry = entry;\n }, true);\n\n listenForWebVitalReportEvents(client, (reportEvent, _, pageloadSpan) => {\n _sendClsSpan(clsValue, clsEntry, pageloadSpan, reportEvent);\n cleanupClsHandler();\n });\n}\n\n/**\n * Exported only for testing.\n */\nexport function _sendClsSpan(\n clsValue: number,\n entry: LayoutShift | undefined,\n pageloadSpan?: Span,\n reportEvent?: WebVitalReportEvent,\n): void {\n DEBUG_BUILD && debug.log(`Sending CLS span (${clsValue})`);\n\n const startTime = entry ? msToSec((browserPerformanceTimeOrigin() || 0) + entry.startTime) : timestampInSeconds();\n const name = entry ? htmlTreeAsString(entry.sources[0]?.node) : 'Layout shift';\n\n const attributes: SpanAttributes = {};\n\n if (entry?.sources) {\n entry.sources.forEach((source, index) => {\n attributes[`browser.web_vital.cls.source.${index + 1}`] = htmlTreeAsString(source.node);\n });\n }\n\n _emitWebVitalSpan({\n name,\n op: 'ui.webvital.cls',\n origin: 'auto.http.browser.cls',\n metricName: 'cls',\n value: clsValue,\n attributes,\n parentSpan: pageloadSpan,\n reportEvent,\n startTime,\n });\n}\n\n/**\n * Tracks INP and emits it as a web vital span, as a child of the interaction's root span.\n * Requires `registerInpInteractionListener()` to be called separately for cached element names and\n * root spans per interaction.\n */\nexport function trackInpAsSpan(client: Client): void {\n const performance = getBrowserPerformanceAPI();\n if (!performance || !browserPerformanceTimeOrigin()) {\n return;\n }\n\n // INP reports late (on pagehide, after the pageload span has ended). With span streaming enabled\n // it rides the streaming pipeline. With streaming disabled it would be dropped as a late span, so\n // it is emitted as its own standalone v2 span instead (see `_emitWebVitalSpan`), overriding the\n // static trace lifecycle for INP only.\n // TODO(standalone): once the static trace lifecycle is dropped, INP always streams; drop this flag.\n const standalone = !hasSpanStreamingEnabled(client);\n\n const onInp: InstrumentationHandlerCallback = ({ metric }) => {\n if (metric.value == null) {\n return;\n }\n\n const duration = msToSec(metric.value);\n\n if (duration > MAX_PLAUSIBLE_INP_DURATION) {\n return;\n }\n\n const entry = metric.entries.find(e => e.duration === metric.value && INP_ENTRY_MAP[e.name]);\n\n if (!entry) {\n return;\n }\n\n _sendInpSpan(metric.value, entry, standalone);\n };\n\n addInpInstrumentationHandler(onInp);\n}\n\n/**\n * Exported only for testing.\n */\nexport function _sendInpSpan(inpValue: number, entry: PerformanceEventTiming, standalone = false): void {\n DEBUG_BUILD && debug.log(`Sending INP span (${inpValue})`);\n\n const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);\n const duration = msToSec(inpValue);\n const interactionType = INP_ENTRY_MAP[entry.name];\n\n const cachedContext = getCachedInteractionContext(entry.interactionId);\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n const spanToUse = cachedContext?.span || rootSpan;\n const routeName = spanToUse ? spanToJSON(spanToUse).name : getCurrentScope().getScopeData().transactionName;\n const name = cachedContext?.elementName || htmlTreeAsString(entry.target);\n\n _emitWebVitalSpan({\n name,\n op: `ui.interaction.${interactionType}`,\n origin: 'auto.http.browser.inp',\n metricName: 'inp',\n value: inpValue,\n attributes: {\n [SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: entry.duration,\n // oxlint-disable-next-line typescript-eslint/no-deprecated\n [SENTRY_TRANSACTION]: routeName,\n [SENTRY_SEGMENT_NAME]: routeName,\n },\n startTime,\n endTime: startTime + duration,\n parentSpan: spanToUse,\n standalone,\n });\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { browserPerformanceTimeOrigin, spanToJSON, setMeasurement, debug } from '@sentry/core';
|
|
2
|
+
import { SENTRY_OP } from '@sentry/conventions/attributes';
|
|
3
|
+
import { DEBUG_BUILD } from '../debug-build.js';
|
|
4
|
+
import { htmlTreeAsString } from '../htmlTreeAsString.js';
|
|
5
|
+
import { addLcpInstrumentationHandler, addClsInstrumentationHandler, addTtfbInstrumentationHandler, addPerformanceInstrumentationHandler } from '../instrumentation/performanceObserver.js';
|
|
6
|
+
import { getBrowserPerformanceAPI, msToSec } from '../performance/utils.js';
|
|
7
|
+
import { isValidLcpMetric } from './lcp.js';
|
|
8
|
+
import { getActivationStart, getNavigationEntry, getVisibilityWatcher } from './utils.js';
|
|
9
|
+
|
|
10
|
+
let _measurements = {};
|
|
11
|
+
let _lcpEntry;
|
|
12
|
+
let _clsEntry;
|
|
13
|
+
function startTrackingWebVitals({ trackCls, trackLcp }) {
|
|
14
|
+
const performance = getBrowserPerformanceAPI();
|
|
15
|
+
if (performance && browserPerformanceTimeOrigin()) {
|
|
16
|
+
const lcpCleanupCallback = trackLcp ? _trackLCP() : void 0;
|
|
17
|
+
const clsCleanupCallback = trackCls ? _trackCLS() : void 0;
|
|
18
|
+
const ttfbCleanupCallback = _trackTtfb();
|
|
19
|
+
const fpFcpCleanupCallback = _trackFpFcp();
|
|
20
|
+
return () => {
|
|
21
|
+
ttfbCleanupCallback();
|
|
22
|
+
fpFcpCleanupCallback();
|
|
23
|
+
lcpCleanupCallback?.();
|
|
24
|
+
clsCleanupCallback?.();
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return () => void 0;
|
|
28
|
+
}
|
|
29
|
+
function _trackCLS() {
|
|
30
|
+
return addClsInstrumentationHandler(({ metric }) => {
|
|
31
|
+
const entry = metric.entries[metric.entries.length - 1];
|
|
32
|
+
if (!entry) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
_measurements["cls"] = { value: metric.value, unit: "" };
|
|
36
|
+
_clsEntry = entry;
|
|
37
|
+
}, true);
|
|
38
|
+
}
|
|
39
|
+
function _trackLCP() {
|
|
40
|
+
return addLcpInstrumentationHandler(({ metric }) => {
|
|
41
|
+
const entry = metric.entries[metric.entries.length - 1];
|
|
42
|
+
if (!entry || !isValidLcpMetric(metric.value)) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
_measurements["lcp"] = { value: metric.value, unit: "millisecond" };
|
|
46
|
+
_lcpEntry = entry;
|
|
47
|
+
}, true);
|
|
48
|
+
}
|
|
49
|
+
function _trackTtfb() {
|
|
50
|
+
return addTtfbInstrumentationHandler(({ metric }) => {
|
|
51
|
+
const entry = metric.entries[metric.entries.length - 1];
|
|
52
|
+
if (!entry) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
_measurements["ttfb"] = { value: metric.value, unit: "millisecond" };
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function _trackFpFcp() {
|
|
59
|
+
return addPerformanceInstrumentationHandler("paint", ({ entries }) => {
|
|
60
|
+
const firstHidden = getVisibilityWatcher();
|
|
61
|
+
for (const entry of entries) {
|
|
62
|
+
const shouldRecord = entry.startTime < firstHidden.firstHiddenTime;
|
|
63
|
+
if (entry.name === "first-paint" && shouldRecord) {
|
|
64
|
+
_measurements["fp"] = { value: entry.startTime, unit: "millisecond" };
|
|
65
|
+
}
|
|
66
|
+
if (entry.name === "first-contentful-paint" && shouldRecord) {
|
|
67
|
+
_measurements["fcp"] = { value: entry.startTime, unit: "millisecond" };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function addWebVitalsToSpan(span, options) {
|
|
73
|
+
const origin = browserPerformanceTimeOrigin();
|
|
74
|
+
if (!getBrowserPerformanceAPI()?.getEntries || !origin) {
|
|
75
|
+
resetWebVitalState();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const { spanStreamingEnabled, recordClsOnPageloadSpan, recordLcpOnPageloadSpan } = options;
|
|
79
|
+
const timeOrigin = msToSec(origin);
|
|
80
|
+
if (spanToJSON(span).attributes[SENTRY_OP] === "pageload") {
|
|
81
|
+
_addTtfbRequestTimeToMeasurements(_measurements);
|
|
82
|
+
if (spanStreamingEnabled) {
|
|
83
|
+
const setAttr = (shortWebVitalName, value, customAttrName) => {
|
|
84
|
+
const attrKey = customAttrName ?? `browser.web_vital.${shortWebVitalName}.value`;
|
|
85
|
+
span.setAttribute(attrKey, value);
|
|
86
|
+
DEBUG_BUILD && debug.log("Setting web vital attribute", { [attrKey]: value }, "on pageload span");
|
|
87
|
+
};
|
|
88
|
+
["ttfb", "fp", "fcp"].forEach((measurementName) => {
|
|
89
|
+
if (_measurements[measurementName]) {
|
|
90
|
+
setAttr(measurementName, _measurements[measurementName].value);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
if (_measurements["ttfb.requestTime"]) {
|
|
94
|
+
setAttr("ttfb.requestTime", _measurements["ttfb.requestTime"].value, "browser.web_vital.ttfb.request_time");
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
if (!recordClsOnPageloadSpan) {
|
|
98
|
+
delete _measurements.cls;
|
|
99
|
+
}
|
|
100
|
+
if (!recordLcpOnPageloadSpan) {
|
|
101
|
+
delete _measurements.lcp;
|
|
102
|
+
}
|
|
103
|
+
Object.entries(_measurements).forEach(([measurementName, measurement]) => {
|
|
104
|
+
setMeasurement(measurementName, measurement.value, measurement.unit, span);
|
|
105
|
+
});
|
|
106
|
+
_setWebVitalAttributes(span, options);
|
|
107
|
+
}
|
|
108
|
+
span.setAttribute(spanStreamingEnabled ? "browser.performance.time_origin" : "performance.timeOrigin", timeOrigin);
|
|
109
|
+
span.setAttribute(
|
|
110
|
+
spanStreamingEnabled ? "browser.performance.navigation.activation_start" : "performance.activationStart",
|
|
111
|
+
getActivationStart()
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
resetWebVitalState();
|
|
115
|
+
}
|
|
116
|
+
function resetWebVitalState() {
|
|
117
|
+
_lcpEntry = void 0;
|
|
118
|
+
_clsEntry = void 0;
|
|
119
|
+
_measurements = {};
|
|
120
|
+
}
|
|
121
|
+
function _setWebVitalAttributes(span, options) {
|
|
122
|
+
if (_lcpEntry && options.recordLcpOnPageloadSpan) {
|
|
123
|
+
if (_lcpEntry.element) {
|
|
124
|
+
span.setAttribute("lcp.element", htmlTreeAsString(_lcpEntry.element));
|
|
125
|
+
}
|
|
126
|
+
if (_lcpEntry.id) {
|
|
127
|
+
span.setAttribute("lcp.id", _lcpEntry.id);
|
|
128
|
+
}
|
|
129
|
+
if (_lcpEntry.url) {
|
|
130
|
+
span.setAttribute("lcp.url", _lcpEntry.url.trim().slice(0, 200));
|
|
131
|
+
}
|
|
132
|
+
if (_lcpEntry.loadTime != null) {
|
|
133
|
+
span.setAttribute("lcp.loadTime", _lcpEntry.loadTime);
|
|
134
|
+
}
|
|
135
|
+
if (_lcpEntry.renderTime != null) {
|
|
136
|
+
span.setAttribute("lcp.renderTime", _lcpEntry.renderTime);
|
|
137
|
+
}
|
|
138
|
+
span.setAttribute("lcp.size", _lcpEntry.size);
|
|
139
|
+
}
|
|
140
|
+
if (_clsEntry?.sources && options.recordClsOnPageloadSpan) {
|
|
141
|
+
_clsEntry.sources.forEach(
|
|
142
|
+
(source, index) => span.setAttribute(`cls.source.${index + 1}`, htmlTreeAsString(source.node))
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function _addTtfbRequestTimeToMeasurements(_measurements2) {
|
|
147
|
+
const navEntry = getNavigationEntry(false);
|
|
148
|
+
if (!navEntry) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const { responseStart, requestStart } = navEntry;
|
|
152
|
+
if (requestStart <= responseStart) {
|
|
153
|
+
_measurements2["ttfb.requestTime"] = {
|
|
154
|
+
value: responseStart - requestStart,
|
|
155
|
+
unit: "millisecond"
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export { addWebVitalsToSpan, startTrackingWebVitals };
|
|
161
|
+
//# sourceMappingURL=tracking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracking.js","sources":["../../../src/web-vitals/tracking.ts"],"sourcesContent":["import type { Client, Measurements, Span } from '@sentry/core';\nimport { browserPerformanceTimeOrigin, debug, setMeasurement, spanToJSON } from '@sentry/core';\nimport { SENTRY_OP } from '@sentry/conventions/attributes';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { htmlTreeAsString } from '../htmlTreeAsString';\nimport {\n addClsInstrumentationHandler,\n addLcpInstrumentationHandler,\n addPerformanceInstrumentationHandler,\n addTtfbInstrumentationHandler,\n} from '../instrumentation/performanceObserver';\nimport { getBrowserPerformanceAPI, msToSec } from '../performance/utils';\nimport { isValidLcpMetric } from './lcp';\nimport { getActivationStart, getNavigationEntry, getVisibilityWatcher } from './utils';\n\nlet _measurements: Measurements = {};\nlet _lcpEntry: LargestContentfulPaint | undefined;\nlet _clsEntry: LayoutShift | undefined;\n\ninterface StartTrackingWebVitalsOptions {\n trackCls: boolean;\n trackLcp: boolean;\n client: Client;\n}\n\n/**\n * Start tracking web vitals.\n * The callback returned by this function can be used to stop tracking & ensure all measurements are final & captured.\n *\n * @returns A function that forces web vitals collection\n */\nexport function startTrackingWebVitals({ trackCls, trackLcp }: StartTrackingWebVitalsOptions): () => void {\n const performance = getBrowserPerformanceAPI();\n if (performance && browserPerformanceTimeOrigin()) {\n const lcpCleanupCallback = trackLcp ? _trackLCP() : undefined;\n const clsCleanupCallback = trackCls ? _trackCLS() : undefined;\n const ttfbCleanupCallback = _trackTtfb();\n const fpFcpCleanupCallback = _trackFpFcp();\n\n return (): void => {\n ttfbCleanupCallback();\n fpFcpCleanupCallback();\n lcpCleanupCallback?.();\n clsCleanupCallback?.();\n };\n }\n\n return () => undefined;\n}\n\nexport { registerInpInteractionListener } from './inp';\n\n/**\n * Starts tracking the Cumulative Layout Shift on the current page and collects the value and last entry\n * to the `_measurements` object which ultimately is applied to the pageload span's measurements.\n */\nfunction _trackCLS(): () => void {\n return addClsInstrumentationHandler(({ metric }) => {\n const entry = metric.entries[metric.entries.length - 1] as LayoutShift | undefined;\n if (!entry) {\n return;\n }\n _measurements['cls'] = { value: metric.value, unit: '' };\n _clsEntry = entry;\n }, true);\n}\n\n/** Starts tracking the Largest Contentful Paint on the current page. */\nfunction _trackLCP(): () => void {\n return addLcpInstrumentationHandler(({ metric }) => {\n const entry = metric.entries[metric.entries.length - 1];\n if (!entry || !isValidLcpMetric(metric.value)) {\n return;\n }\n\n _measurements['lcp'] = { value: metric.value, unit: 'millisecond' };\n _lcpEntry = entry as LargestContentfulPaint;\n }, true);\n}\n\nfunction _trackTtfb(): () => void {\n return addTtfbInstrumentationHandler(({ metric }) => {\n const entry = metric.entries[metric.entries.length - 1];\n if (!entry) {\n return;\n }\n\n _measurements['ttfb'] = { value: metric.value, unit: 'millisecond' };\n });\n}\n\n/** Starts tracking First Paint and First Contentful Paint on the current page. */\nfunction _trackFpFcp(): () => void {\n return addPerformanceInstrumentationHandler('paint', ({ entries }) => {\n const firstHidden = getVisibilityWatcher();\n for (const entry of entries) {\n // Only report if the page wasn't hidden prior to the web vital.\n const shouldRecord = entry.startTime < firstHidden.firstHiddenTime;\n if (entry.name === 'first-paint' && shouldRecord) {\n _measurements['fp'] = { value: entry.startTime, unit: 'millisecond' };\n }\n if (entry.name === 'first-contentful-paint' && shouldRecord) {\n _measurements['fcp'] = { value: entry.startTime, unit: 'millisecond' };\n }\n }\n });\n}\n\ninterface AddWebVitalsToSpanOptions {\n /**\n * Flag to determine if CLS should be recorded as a measurement on the pageload span or\n * sent as a standalone span instead.\n * Sending it as a standalone span will yield more accurate LCP values.\n *\n * Default: `false` for backwards compatibility.\n */\n recordClsOnPageloadSpan: boolean;\n\n /**\n * Flag to determine if LCP should be recorded as a measurement on the pageload span or\n * sent as a standalone span instead.\n * Sending it as a standalone span will yield more accurate LCP values.\n *\n * Default: `false` for backwards compatibility.\n */\n recordLcpOnPageloadSpan: boolean;\n\n /**\n * Whether span streaming is enabled.\n */\n spanStreamingEnabled?: boolean;\n}\n\n/**\n * Writes the collected web vitals (LCP, CLS, INP, TTFB, FP, FCP) onto the pageload span,\n * either as measurements/attributes (v1) or as web vital attributes (span streaming).\n *\n * This should be called when the pageload span ends, after the web vitals have been finalized.\n * It is a no-op for non-pageload spans, but always resets the collected web vital state so it\n * doesn't leak into a subsequent navigation.\n */\nexport function addWebVitalsToSpan(span: Span, options: AddWebVitalsToSpanOptions): void {\n const origin = browserPerformanceTimeOrigin();\n if (!getBrowserPerformanceAPI()?.getEntries || !origin) {\n // Gatekeeper if performance API not available\n resetWebVitalState();\n return;\n }\n\n const { spanStreamingEnabled, recordClsOnPageloadSpan, recordLcpOnPageloadSpan } = options;\n const timeOrigin = msToSec(origin);\n\n // Measurements are only available for pageload transactions\n if (spanToJSON(span).attributes[SENTRY_OP] === 'pageload') {\n _addTtfbRequestTimeToMeasurements(_measurements);\n\n if (spanStreamingEnabled) {\n const setAttr = (shortWebVitalName: string, value: number, customAttrName?: string) => {\n const attrKey = customAttrName ?? `browser.web_vital.${shortWebVitalName}.value`;\n span.setAttribute(attrKey, value);\n DEBUG_BUILD && debug.log('Setting web vital attribute', { [attrKey]: value }, 'on pageload span');\n };\n // for streamed pageload spans, we add the web vital measurements as attributes.\n // We omit LCP, CLS and INP because they're tracked separately as spans\n ['ttfb', 'fp', 'fcp'].forEach(measurementName => {\n if (_measurements[measurementName]) {\n setAttr(measurementName, _measurements[measurementName].value);\n }\n });\n if (_measurements['ttfb.requestTime']) {\n setAttr('ttfb.requestTime', _measurements['ttfb.requestTime'].value, 'browser.web_vital.ttfb.request_time');\n }\n } else {\n // If CLS is tracked as a span (span streaming), don't record CLS as a measurement\n if (!recordClsOnPageloadSpan) {\n delete _measurements.cls;\n }\n\n // If LCP is tracked as a span (span streaming), don't record LCP as a measurement\n if (!recordLcpOnPageloadSpan) {\n delete _measurements.lcp;\n }\n\n Object.entries(_measurements).forEach(([measurementName, measurement]) => {\n setMeasurement(measurementName, measurement.value, measurement.unit, span);\n });\n\n _setWebVitalAttributes(span, options);\n }\n\n // Set timeOrigin which denotes the timestamp which to base the LCP/FCP/FP/TTFB measurements on\n span.setAttribute(spanStreamingEnabled ? 'browser.performance.time_origin' : 'performance.timeOrigin', timeOrigin);\n\n // In prerendering scenarios, where a page might be prefetched and pre-rendered before the user clicks the link,\n // the navigation starts earlier than when the user clicks it. Web Vitals should always be based on the\n // user-perceived time, so they are not reported from the actual start of the navigation, but rather from the\n // time where the user actively started the navigation, for example by clicking a link.\n // This is user action is called \"activation\" and the time between navigation and activation is stored in\n // the `activationStart` attribute of the \"navigation\" PerformanceEntry.\n span.setAttribute(\n spanStreamingEnabled ? 'browser.performance.navigation.activation_start' : 'performance.activationStart',\n getActivationStart(),\n );\n }\n\n resetWebVitalState();\n}\n\nfunction resetWebVitalState(): void {\n _lcpEntry = undefined;\n _clsEntry = undefined;\n _measurements = {};\n}\n\n/** Add LCP / CLS data to span to allow debugging */\nfunction _setWebVitalAttributes(span: Span, options: AddWebVitalsToSpanOptions): void {\n // Only add LCP attributes if LCP is being recorded on the pageload span\n if (_lcpEntry && options.recordLcpOnPageloadSpan) {\n // Capture Properties of the LCP element that contributes to the LCP.\n\n if (_lcpEntry.element) {\n span.setAttribute('lcp.element', htmlTreeAsString(_lcpEntry.element));\n }\n\n if (_lcpEntry.id) {\n span.setAttribute('lcp.id', _lcpEntry.id);\n }\n\n if (_lcpEntry.url) {\n // Trim URL to the first 200 characters.\n span.setAttribute('lcp.url', _lcpEntry.url.trim().slice(0, 200));\n }\n\n if (_lcpEntry.loadTime != null) {\n // loadTime is the time of LCP that's related to receiving the LCP element response..\n span.setAttribute('lcp.loadTime', _lcpEntry.loadTime);\n }\n\n if (_lcpEntry.renderTime != null) {\n // renderTime is loadTime + rendering time\n // it's 0 if the LCP element is loaded from a 3rd party origin that doesn't send the\n // `Timing-Allow-Origin` header.\n span.setAttribute('lcp.renderTime', _lcpEntry.renderTime);\n }\n\n span.setAttribute('lcp.size', _lcpEntry.size);\n }\n\n // Only add CLS attributes if CLS is being recorded on the pageload span\n if (_clsEntry?.sources && options.recordClsOnPageloadSpan) {\n _clsEntry.sources.forEach((source, index) =>\n span.setAttribute(`cls.source.${index + 1}`, htmlTreeAsString(source.node)),\n );\n }\n}\n\n/**\n * Add ttfb request time information to measurements.\n *\n * ttfb information is added via the web vitals library.\n */\nfunction _addTtfbRequestTimeToMeasurements(_measurements: Measurements): void {\n const navEntry = getNavigationEntry(false);\n if (!navEntry) {\n return;\n }\n\n const { responseStart, requestStart } = navEntry;\n\n if (requestStart <= responseStart) {\n _measurements['ttfb.requestTime'] = {\n value: responseStart - requestStart,\n unit: 'millisecond',\n };\n }\n}\n"],"names":["_measurements"],"mappings":"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"}
|