@sentry/browser-utils 11.0.0-alpha.0 → 11.0.0-alpha.2
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/component-name.js +28 -0
- package/build/cjs/component-name.js.map +1 -0
- package/build/cjs/getLocationHref.js +14 -0
- package/build/cjs/getLocationHref.js.map +1 -0
- package/build/cjs/index.js +36 -28
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/instrumentation/dom.js.map +1 -0
- package/build/cjs/{instrument → instrumentation}/history.js +5 -1
- 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/isBotUserAgent.js +15 -0
- package/build/cjs/isBotUserAgent.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} +45 -220
- package/build/cjs/performance/entries.js.map +1 -0
- package/build/cjs/performance/interactions.js +123 -0
- package/build/cjs/performance/interactions.js.map +1 -0
- package/build/cjs/performance/resourceTiming.js.map +1 -0
- package/build/cjs/{metrics → performance}/userTiming.js +4 -3
- package/build/cjs/performance/userTiming.js.map +1 -0
- package/build/cjs/{metrics → performance}/utils.js +4 -30
- package/build/cjs/performance/utils.js.map +1 -0
- package/build/cjs/types.js.map +1 -1
- package/build/cjs/{metrics → web-vitals}/inp.js +4 -4
- package/build/cjs/web-vitals/inp.js.map +1 -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} +30 -21
- 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/component-name.js +26 -0
- package/build/esm/component-name.js.map +1 -0
- package/build/esm/getLocationHref.js +12 -0
- package/build/esm/getLocationHref.js.map +1 -0
- package/build/esm/index.js +18 -13
- package/build/esm/index.js.map +1 -1
- package/build/esm/instrumentation/dom.js.map +1 -0
- package/build/esm/{instrument → instrumentation}/history.js +5 -2
- 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/isBotUserAgent.js +13 -0
- package/build/esm/isBotUserAgent.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} +41 -213
- package/build/esm/performance/entries.js.map +1 -0
- package/build/esm/performance/interactions.js +121 -0
- package/build/esm/performance/interactions.js.map +1 -0
- package/build/esm/performance/resourceTiming.js.map +1 -0
- package/build/esm/{metrics → performance}/userTiming.js +4 -3
- package/build/esm/performance/userTiming.js.map +1 -0
- package/build/esm/{metrics → performance}/utils.js +3 -28
- package/build/esm/performance/utils.js.map +1 -0
- package/build/esm/types.js.map +1 -1
- package/build/esm/{metrics → web-vitals}/inp.js +1 -1
- package/build/esm/web-vitals/inp.js.map +1 -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} +25 -16
- 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/component-name.d.ts +9 -0
- package/build/types/component-name.d.ts.map +1 -0
- package/build/types/getLocationHref.d.ts +5 -0
- package/build/types/getLocationHref.d.ts.map +1 -0
- package/build/types/index.d.ts +18 -13
- package/build/types/index.d.ts.map +1 -1
- package/build/types/{instrument → instrumentation}/dom.d.ts +1 -1
- package/build/types/instrumentation/dom.d.ts.map +1 -0
- package/build/types/{instrument → instrumentation}/history.d.ts +8 -1
- 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/{instrument → instrumentation}/xhr.d.ts +1 -1
- package/build/types/instrumentation/xhr.d.ts.map +1 -0
- package/build/types/isBotUserAgent.d.ts +5 -0
- package/build/types/isBotUserAgent.d.ts.map +1 -0
- package/build/types/performance/elementTiming.d.ts.map +1 -0
- package/build/types/{metrics/browserMetrics.d.ts → performance/entries.d.ts} +4 -51
- package/build/types/performance/entries.d.ts.map +1 -0
- package/build/types/performance/interactions.d.ts +48 -0
- package/build/types/performance/interactions.d.ts.map +1 -0
- package/build/types/performance/resourceTiming.d.ts.map +1 -0
- package/build/types/performance/userTiming.d.ts.map +1 -0
- package/build/types/{metrics → performance}/utils.d.ts +1 -17
- package/build/types/performance/utils.d.ts.map +1 -0
- package/build/types/types.d.ts +38 -1
- package/build/types/types.d.ts.map +1 -1
- package/build/types/{metrics → web-vitals}/inp.d.ts +2 -1
- package/build/types/web-vitals/inp.d.ts.map +1 -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} +3 -3
- 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 +5 -3
- 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/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.map +0 -1
- package/build/cjs/metrics/resourceTiming.js.map +0 -1
- package/build/cjs/metrics/userTiming.js.map +0 -1
- 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 -44
- 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 -16
- 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 -22
- 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/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.map +0 -1
- package/build/esm/metrics/resourceTiming.js.map +0 -1
- package/build/esm/metrics/userTiming.js.map +0 -1
- 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 -42
- 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 -14
- 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 -20
- 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.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.map +0 -1
- package/build/types/metrics/resourceTiming.d.ts.map +0 -1
- package/build/types/metrics/userTiming.d.ts.map +0 -1
- 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 -15
- 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/cjs/{instrument → instrumentation}/dom.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/cjs/{metrics → web-vitals}/lcp.js +0 -0
- /package/build/esm/{instrument → instrumentation}/dom.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/esm/{metrics → web-vitals}/lcp.js +0 -0
- /package/build/types/{instrument → instrumentation}/location.d.ts +0 -0
- /package/build/types/{metrics → performance}/elementTiming.d.ts +0 -0
- /package/build/types/{metrics → performance}/resourceTiming.d.ts +0 -0
- /package/build/types/{metrics → performance}/userTiming.d.ts +0 -0
- /package/build/types/{metrics → web-vitals}/lcp.d.ts +0 -0
|
@@ -1,56 +1,31 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const core = require('@sentry/core');
|
|
4
|
-
const
|
|
4
|
+
const attributes = require('@sentry/conventions/attributes');
|
|
5
|
+
const op = require('@sentry/conventions/op');
|
|
6
|
+
const performanceObserver = require('../instrumentation/performanceObserver.js');
|
|
5
7
|
const types = require('../types.js');
|
|
6
|
-
const instrument = require('./instrument.js');
|
|
7
|
-
const lcp = require('./lcp.js');
|
|
8
8
|
const resourceTiming = require('./resourceTiming.js');
|
|
9
9
|
const utils = require('./utils.js');
|
|
10
|
-
const getActivationStart = require('./web-vitals/lib/getActivationStart.js');
|
|
11
|
-
const getNavigationEntry = require('./web-vitals/lib/getNavigationEntry.js');
|
|
12
|
-
const getVisibilityWatcher = require('./web-vitals/lib/getVisibilityWatcher.js');
|
|
13
|
-
const debugBuild = require('../debug-build.js');
|
|
14
|
-
const attributes = require('@sentry/conventions/attributes');
|
|
15
|
-
const op = require('@sentry/conventions/op');
|
|
16
10
|
|
|
17
11
|
const MAX_INT_AS_BYTES = 2147483647;
|
|
18
12
|
let _performanceCursor = 0;
|
|
19
|
-
let _measurements = {};
|
|
20
|
-
let _lcpEntry;
|
|
21
|
-
let _clsEntry;
|
|
22
|
-
function startTrackingWebVitals({ trackCls, trackLcp }) {
|
|
23
|
-
const performance = utils.getBrowserPerformanceAPI();
|
|
24
|
-
if (performance && core.browserPerformanceTimeOrigin()) {
|
|
25
|
-
const lcpCleanupCallback = trackLcp ? _trackLCP() : void 0;
|
|
26
|
-
const clsCleanupCallback = trackCls ? _trackCLS() : void 0;
|
|
27
|
-
const ttfbCleanupCallback = _trackTtfb();
|
|
28
|
-
const fpFcpCleanupCallback = _trackFpFcp();
|
|
29
|
-
return () => {
|
|
30
|
-
ttfbCleanupCallback();
|
|
31
|
-
fpFcpCleanupCallback();
|
|
32
|
-
lcpCleanupCallback?.();
|
|
33
|
-
clsCleanupCallback?.();
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
return () => void 0;
|
|
37
|
-
}
|
|
38
13
|
function startTrackingLongTasks() {
|
|
39
|
-
|
|
14
|
+
performanceObserver.addPerformanceInstrumentationHandler("longtask", ({ entries }) => {
|
|
40
15
|
const parent = core.getActiveSpan();
|
|
41
16
|
if (!parent) {
|
|
42
17
|
return;
|
|
43
18
|
}
|
|
44
|
-
const {
|
|
19
|
+
const { attributes: parentAttributes, start_timestamp: parentStartTimestamp } = core.spanToJSON(parent);
|
|
45
20
|
for (const entry of entries) {
|
|
46
21
|
const startTime = utils.msToSec(core.browserPerformanceTimeOrigin() + entry.startTime);
|
|
47
22
|
const duration = utils.msToSec(entry.duration);
|
|
48
|
-
if (
|
|
23
|
+
if (parentAttributes[attributes.SENTRY_OP] === "navigation" && parentStartTimestamp && startTime < parentStartTimestamp) {
|
|
49
24
|
continue;
|
|
50
25
|
}
|
|
51
26
|
utils.startAndEndSpan(parent, startTime, startTime + duration, {
|
|
52
27
|
name: "Main UI thread blocked",
|
|
53
|
-
op:
|
|
28
|
+
op: op.UI_LONG_TASK,
|
|
54
29
|
attributes: {
|
|
55
30
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.browser.metrics"
|
|
56
31
|
}
|
|
@@ -69,106 +44,39 @@ function startTrackingLongAnimationFrames() {
|
|
|
69
44
|
continue;
|
|
70
45
|
}
|
|
71
46
|
const startTime = utils.msToSec(core.browserPerformanceTimeOrigin() + entry.startTime);
|
|
72
|
-
const {
|
|
47
|
+
const {
|
|
48
|
+
start_timestamp: parentStartTimestamp,
|
|
49
|
+
attributes: { [attributes.SENTRY_OP]: parentOp }
|
|
50
|
+
} = core.spanToJSON(parent);
|
|
73
51
|
if (parentOp === "navigation" && parentStartTimestamp && startTime < parentStartTimestamp) {
|
|
74
52
|
continue;
|
|
75
53
|
}
|
|
76
54
|
const duration = utils.msToSec(entry.duration);
|
|
77
|
-
const attributes = {
|
|
55
|
+
const attributes$1 = {
|
|
78
56
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.browser.metrics"
|
|
79
57
|
};
|
|
80
58
|
const initialScript = entry.scripts[0];
|
|
81
59
|
const { invoker, invokerType, sourceURL, sourceFunctionName, sourceCharPosition } = initialScript;
|
|
82
|
-
attributes["browser.script.invoker"] = invoker;
|
|
83
|
-
attributes["browser.script.invoker_type"] = invokerType;
|
|
60
|
+
attributes$1["browser.script.invoker"] = invoker;
|
|
61
|
+
attributes$1["browser.script.invoker_type"] = invokerType;
|
|
84
62
|
if (sourceURL) {
|
|
85
|
-
attributes[
|
|
63
|
+
attributes$1[attributes.CODE_FILE_PATH] = sourceURL;
|
|
86
64
|
}
|
|
87
65
|
if (sourceFunctionName) {
|
|
88
|
-
attributes[
|
|
66
|
+
attributes$1[attributes.CODE_FUNCTION_NAME] = sourceFunctionName;
|
|
89
67
|
}
|
|
90
68
|
if (sourceCharPosition !== -1) {
|
|
91
|
-
attributes["browser.script.source_char_position"] = sourceCharPosition;
|
|
69
|
+
attributes$1["browser.script.source_char_position"] = sourceCharPosition;
|
|
92
70
|
}
|
|
93
71
|
utils.startAndEndSpan(parent, startTime, startTime + duration, {
|
|
94
72
|
name: "Main UI thread blocked",
|
|
95
|
-
op:
|
|
96
|
-
attributes
|
|
73
|
+
op: op.UI_LONG_ANIMATION_FRAME,
|
|
74
|
+
attributes: attributes$1
|
|
97
75
|
});
|
|
98
76
|
}
|
|
99
77
|
});
|
|
100
78
|
observer.observe({ type: "long-animation-frame", buffered: true });
|
|
101
79
|
}
|
|
102
|
-
function startTrackingInteractions() {
|
|
103
|
-
instrument.addPerformanceInstrumentationHandler("event", ({ entries }) => {
|
|
104
|
-
const parent = core.getActiveSpan();
|
|
105
|
-
if (!parent) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
for (const entry of entries) {
|
|
109
|
-
if (entry.name === "click") {
|
|
110
|
-
const startTime = utils.msToSec(core.browserPerformanceTimeOrigin() + entry.startTime);
|
|
111
|
-
const duration = utils.msToSec(entry.duration);
|
|
112
|
-
const spanOptions = {
|
|
113
|
-
name: htmlTreeAsString.htmlTreeAsString(entry.target),
|
|
114
|
-
op: `ui.interaction.${entry.name}`,
|
|
115
|
-
startTime,
|
|
116
|
-
attributes: {
|
|
117
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.browser.metrics"
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
const componentName = core.getComponentName(entry.target);
|
|
121
|
-
if (componentName) {
|
|
122
|
-
spanOptions.attributes["ui.component_name"] = componentName;
|
|
123
|
-
}
|
|
124
|
-
utils.startAndEndSpan(parent, startTime, startTime + duration, spanOptions);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
function _trackCLS() {
|
|
130
|
-
return instrument.addClsInstrumentationHandler(({ metric }) => {
|
|
131
|
-
const entry = metric.entries[metric.entries.length - 1];
|
|
132
|
-
if (!entry) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
_measurements["cls"] = { value: metric.value, unit: "" };
|
|
136
|
-
_clsEntry = entry;
|
|
137
|
-
}, true);
|
|
138
|
-
}
|
|
139
|
-
function _trackLCP() {
|
|
140
|
-
return instrument.addLcpInstrumentationHandler(({ metric }) => {
|
|
141
|
-
const entry = metric.entries[metric.entries.length - 1];
|
|
142
|
-
if (!entry || !lcp.isValidLcpMetric(metric.value)) {
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
_measurements["lcp"] = { value: metric.value, unit: "millisecond" };
|
|
146
|
-
_lcpEntry = entry;
|
|
147
|
-
}, true);
|
|
148
|
-
}
|
|
149
|
-
function _trackTtfb() {
|
|
150
|
-
return instrument.addTtfbInstrumentationHandler(({ metric }) => {
|
|
151
|
-
const entry = metric.entries[metric.entries.length - 1];
|
|
152
|
-
if (!entry) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
_measurements["ttfb"] = { value: metric.value, unit: "millisecond" };
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
function _trackFpFcp() {
|
|
159
|
-
return instrument.addPerformanceInstrumentationHandler("paint", ({ entries }) => {
|
|
160
|
-
const firstHidden = getVisibilityWatcher.getVisibilityWatcher();
|
|
161
|
-
for (const entry of entries) {
|
|
162
|
-
const shouldRecord = entry.startTime < firstHidden.firstHiddenTime;
|
|
163
|
-
if (entry.name === "first-paint" && shouldRecord) {
|
|
164
|
-
_measurements["fp"] = { value: entry.startTime, unit: "millisecond" };
|
|
165
|
-
}
|
|
166
|
-
if (entry.name === "first-contentful-paint" && shouldRecord) {
|
|
167
|
-
_measurements["fcp"] = { value: entry.startTime, unit: "millisecond" };
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
80
|
function addPerformanceEntries(span, options) {
|
|
173
81
|
const performance = utils.getBrowserPerformanceAPI();
|
|
174
82
|
const origin = core.browserPerformanceTimeOrigin();
|
|
@@ -178,7 +86,7 @@ function addPerformanceEntries(span, options) {
|
|
|
178
86
|
const { spanStreamingEnabled, ignoreResourceSpans } = options;
|
|
179
87
|
const timeOrigin = utils.msToSec(origin);
|
|
180
88
|
const performanceEntries = performance.getEntries();
|
|
181
|
-
const {
|
|
89
|
+
const { attributes: attributes$1, start_timestamp: transactionStartTime } = core.spanToJSON(span);
|
|
182
90
|
performanceEntries.slice(_performanceCursor).forEach((entry) => {
|
|
183
91
|
const startTime = utils.msToSec(entry.startTime);
|
|
184
92
|
const duration = utils.msToSec(
|
|
@@ -188,7 +96,7 @@ function addPerformanceEntries(span, options) {
|
|
|
188
96
|
// TODO: Investigate why this happens and how to properly mitigate. For now, this is a workaround to prevent transactions being dropped due to negative duration spans.
|
|
189
97
|
Math.max(0, entry.duration)
|
|
190
98
|
);
|
|
191
|
-
if (
|
|
99
|
+
if (attributes$1[attributes.SENTRY_OP] === "navigation" && transactionStartTime && timeOrigin + startTime < transactionStartTime) {
|
|
192
100
|
return;
|
|
193
101
|
}
|
|
194
102
|
switch (entry.entryType) {
|
|
@@ -208,7 +116,8 @@ function addPerformanceEntries(span, options) {
|
|
|
208
116
|
startTime,
|
|
209
117
|
duration,
|
|
210
118
|
timeOrigin,
|
|
211
|
-
ignoreResourceSpans
|
|
119
|
+
ignoreResourceSpans,
|
|
120
|
+
spanStreamingEnabled
|
|
212
121
|
);
|
|
213
122
|
break;
|
|
214
123
|
}
|
|
@@ -217,61 +126,12 @@ function addPerformanceEntries(span, options) {
|
|
|
217
126
|
_performanceCursor = Math.max(performanceEntries.length - 1, 0);
|
|
218
127
|
_trackNavigator(span, spanStreamingEnabled);
|
|
219
128
|
}
|
|
220
|
-
function addWebVitalsToSpan(span, options) {
|
|
221
|
-
const origin = core.browserPerformanceTimeOrigin();
|
|
222
|
-
if (!utils.getBrowserPerformanceAPI()?.getEntries || !origin) {
|
|
223
|
-
resetWebVitalState();
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
const { spanStreamingEnabled, recordClsOnPageloadSpan, recordLcpOnPageloadSpan } = options;
|
|
227
|
-
const timeOrigin = utils.msToSec(origin);
|
|
228
|
-
if (core.spanToJSON(span).op === "pageload") {
|
|
229
|
-
_addTtfbRequestTimeToMeasurements(_measurements);
|
|
230
|
-
if (spanStreamingEnabled) {
|
|
231
|
-
const setAttr = (shortWebVitalName, value, customAttrName) => {
|
|
232
|
-
const attrKey = customAttrName ?? `browser.web_vital.${shortWebVitalName}.value`;
|
|
233
|
-
span.setAttribute(attrKey, value);
|
|
234
|
-
debugBuild.DEBUG_BUILD && core.debug.log("Setting web vital attribute", { [attrKey]: value }, "on pageload span");
|
|
235
|
-
};
|
|
236
|
-
["ttfb", "fp", "fcp"].forEach((measurementName) => {
|
|
237
|
-
if (_measurements[measurementName]) {
|
|
238
|
-
setAttr(measurementName, _measurements[measurementName].value);
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
if (_measurements["ttfb.requestTime"]) {
|
|
242
|
-
setAttr("ttfb.requestTime", _measurements["ttfb.requestTime"].value, "browser.web_vital.ttfb.request_time");
|
|
243
|
-
}
|
|
244
|
-
} else {
|
|
245
|
-
if (!recordClsOnPageloadSpan) {
|
|
246
|
-
delete _measurements.cls;
|
|
247
|
-
}
|
|
248
|
-
if (!recordLcpOnPageloadSpan) {
|
|
249
|
-
delete _measurements.lcp;
|
|
250
|
-
}
|
|
251
|
-
Object.entries(_measurements).forEach(([measurementName, measurement]) => {
|
|
252
|
-
core.setMeasurement(measurementName, measurement.value, measurement.unit, span);
|
|
253
|
-
});
|
|
254
|
-
_setWebVitalAttributes(span, options);
|
|
255
|
-
}
|
|
256
|
-
span.setAttribute(spanStreamingEnabled ? "browser.performance.time_origin" : "performance.timeOrigin", timeOrigin);
|
|
257
|
-
span.setAttribute(
|
|
258
|
-
spanStreamingEnabled ? "browser.performance.navigation.activation_start" : "performance.activationStart",
|
|
259
|
-
getActivationStart.getActivationStart()
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
resetWebVitalState();
|
|
263
|
-
}
|
|
264
|
-
function resetWebVitalState() {
|
|
265
|
-
_lcpEntry = void 0;
|
|
266
|
-
_clsEntry = void 0;
|
|
267
|
-
_measurements = {};
|
|
268
|
-
}
|
|
269
129
|
function _addPaintSpan(span, entry, startTime, duration, timeOrigin) {
|
|
270
130
|
const startTimestamp = timeOrigin + startTime;
|
|
271
131
|
utils.startAndEndSpan(span, startTimestamp, startTimestamp + duration, {
|
|
272
132
|
name: entry.name,
|
|
273
133
|
attributes: {
|
|
274
|
-
[attributes.SENTRY_OP]: op.
|
|
134
|
+
[attributes.SENTRY_OP]: op.BROWSER_PAINT,
|
|
275
135
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.resource.browser.metrics"
|
|
276
136
|
}
|
|
277
137
|
});
|
|
@@ -333,7 +193,7 @@ function _addRequest(span, entry, timeOrigin) {
|
|
|
333
193
|
});
|
|
334
194
|
}
|
|
335
195
|
}
|
|
336
|
-
function _addResourceSpans(span, entry, resourceUrl, startTime, duration, timeOrigin, ignoredResourceSpanOps) {
|
|
196
|
+
function _addResourceSpans(span, entry, resourceUrl, startTime, duration, timeOrigin, ignoredResourceSpanOps, spanStreamingEnabled) {
|
|
337
197
|
if (entry.initiatorType === "xmlhttprequest" || entry.initiatorType === "fetch") {
|
|
338
198
|
return;
|
|
339
199
|
}
|
|
@@ -346,19 +206,24 @@ function _addResourceSpans(span, entry, resourceUrl, startTime, duration, timeOr
|
|
|
346
206
|
};
|
|
347
207
|
const parsedUrl = core.parseUrl(resourceUrl);
|
|
348
208
|
if (parsedUrl.protocol) {
|
|
349
|
-
attributes$1[
|
|
209
|
+
attributes$1[attributes.URL_SCHEME] = parsedUrl.protocol.split(":").pop();
|
|
350
210
|
}
|
|
351
|
-
|
|
352
|
-
|
|
211
|
+
const host = parsedUrl.host?.replace(/^.*@/, "");
|
|
212
|
+
if (host) {
|
|
213
|
+
attributes$1[attributes.SERVER_ADDRESS] = host;
|
|
353
214
|
}
|
|
354
|
-
|
|
215
|
+
const domain = host?.replace(/:\d+$/, "");
|
|
216
|
+
if (domain) {
|
|
217
|
+
attributes$1[attributes.URL_DOMAIN] = domain;
|
|
218
|
+
}
|
|
219
|
+
attributes$1[attributes.HTTP_REQUEST_SAME_ORIGIN] = resourceUrl.includes(types.WINDOW.location.origin);
|
|
355
220
|
attributes$1[attributes.URL_FULL] = core.filterCollectedUrl(resourceUrl);
|
|
356
221
|
_setResourceRequestAttributes(entry, attributes$1, [
|
|
357
222
|
// https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus
|
|
358
|
-
["responseStatus",
|
|
359
|
-
["transferSize",
|
|
360
|
-
["encodedBodySize",
|
|
361
|
-
["decodedBodySize", "http.
|
|
223
|
+
["responseStatus", attributes.HTTP_RESPONSE_STATUS_CODE],
|
|
224
|
+
["transferSize", attributes.HTTP_RESPONSE_SIZE],
|
|
225
|
+
["encodedBodySize", attributes.HTTP_RESPONSE_BODY_SIZE],
|
|
226
|
+
["decodedBodySize", "http.response.body.decoded_size"],
|
|
362
227
|
// https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/renderBlockingStatus
|
|
363
228
|
["renderBlockingStatus", "resource.render_blocking_status"],
|
|
364
229
|
// https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/deliveryType
|
|
@@ -368,7 +233,8 @@ function _addResourceSpans(span, entry, resourceUrl, startTime, duration, timeOr
|
|
|
368
233
|
const startTimestamp = timeOrigin + startTime;
|
|
369
234
|
const endTimestamp = startTimestamp + duration;
|
|
370
235
|
utils.startAndEndSpan(span, startTimestamp, endTimestamp, {
|
|
371
|
-
|
|
236
|
+
// With span streaming, span names have to be low cardinality, so we can't fall back to the URL.
|
|
237
|
+
name: spanStreamingEnabled ? domain || core.RESOURCE_SPAN_NAME_FALLBACK : resourceUrl.replace(types.WINDOW.location.origin, ""),
|
|
372
238
|
op,
|
|
373
239
|
attributes: attributesWithResourceTiming
|
|
374
240
|
});
|
|
@@ -382,17 +248,17 @@ function _trackNavigator(span, spanStreamingEnabled) {
|
|
|
382
248
|
if (connection) {
|
|
383
249
|
if (connection.effectiveType) {
|
|
384
250
|
span.setAttribute(
|
|
385
|
-
spanStreamingEnabled ?
|
|
251
|
+
spanStreamingEnabled ? attributes.NETWORK_CONNECTION_EFFECTIVE_TYPE : "effectiveConnectionType",
|
|
386
252
|
connection.effectiveType
|
|
387
253
|
);
|
|
388
254
|
}
|
|
389
255
|
if (connection.type) {
|
|
390
|
-
span.setAttribute(spanStreamingEnabled ?
|
|
256
|
+
span.setAttribute(spanStreamingEnabled ? attributes.NETWORK_CONNECTION_TYPE : "connectionType", connection.type);
|
|
391
257
|
}
|
|
392
258
|
if (utils.isMeasurementValue(connection.rtt)) {
|
|
393
259
|
if (spanStreamingEnabled) {
|
|
394
|
-
span.setAttribute(
|
|
395
|
-
} else if (core.spanToJSON(span).
|
|
260
|
+
span.setAttribute(attributes.NETWORK_CONNECTION_RTT, connection.rtt);
|
|
261
|
+
} else if (core.spanToJSON(span).attributes[attributes.SENTRY_OP] === "pageload") {
|
|
396
262
|
core.setMeasurement("connection.rtt", connection.rtt, "millisecond");
|
|
397
263
|
}
|
|
398
264
|
}
|
|
@@ -412,31 +278,6 @@ function _trackNavigator(span, spanStreamingEnabled) {
|
|
|
412
278
|
}
|
|
413
279
|
}
|
|
414
280
|
}
|
|
415
|
-
function _setWebVitalAttributes(span, options) {
|
|
416
|
-
if (_lcpEntry && options.recordLcpOnPageloadSpan) {
|
|
417
|
-
if (_lcpEntry.element) {
|
|
418
|
-
span.setAttribute("lcp.element", htmlTreeAsString.htmlTreeAsString(_lcpEntry.element));
|
|
419
|
-
}
|
|
420
|
-
if (_lcpEntry.id) {
|
|
421
|
-
span.setAttribute("lcp.id", _lcpEntry.id);
|
|
422
|
-
}
|
|
423
|
-
if (_lcpEntry.url) {
|
|
424
|
-
span.setAttribute("lcp.url", _lcpEntry.url.trim().slice(0, 200));
|
|
425
|
-
}
|
|
426
|
-
if (_lcpEntry.loadTime != null) {
|
|
427
|
-
span.setAttribute("lcp.loadTime", _lcpEntry.loadTime);
|
|
428
|
-
}
|
|
429
|
-
if (_lcpEntry.renderTime != null) {
|
|
430
|
-
span.setAttribute("lcp.renderTime", _lcpEntry.renderTime);
|
|
431
|
-
}
|
|
432
|
-
span.setAttribute("lcp.size", _lcpEntry.size);
|
|
433
|
-
}
|
|
434
|
-
if (_clsEntry?.sources && options.recordClsOnPageloadSpan) {
|
|
435
|
-
_clsEntry.sources.forEach(
|
|
436
|
-
(source, index) => span.setAttribute(`cls.source.${index + 1}`, htmlTreeAsString.htmlTreeAsString(source.node))
|
|
437
|
-
);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
281
|
function _setResourceRequestAttributes(entry, attributes, properties) {
|
|
441
282
|
properties.forEach(([entryKey, attributeKey]) => {
|
|
442
283
|
const entryVal = entry[entryKey];
|
|
@@ -445,27 +286,11 @@ function _setResourceRequestAttributes(entry, attributes, properties) {
|
|
|
445
286
|
}
|
|
446
287
|
});
|
|
447
288
|
}
|
|
448
|
-
function _addTtfbRequestTimeToMeasurements(_measurements2) {
|
|
449
|
-
const navEntry = getNavigationEntry.getNavigationEntry(false);
|
|
450
|
-
if (!navEntry) {
|
|
451
|
-
return;
|
|
452
|
-
}
|
|
453
|
-
const { responseStart, requestStart } = navEntry;
|
|
454
|
-
if (requestStart <= responseStart) {
|
|
455
|
-
_measurements2["ttfb.requestTime"] = {
|
|
456
|
-
value: responseStart - requestStart,
|
|
457
|
-
unit: "millisecond"
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
289
|
|
|
462
290
|
exports._addNavigationSpans = _addNavigationSpans;
|
|
463
291
|
exports._addResourceSpans = _addResourceSpans;
|
|
464
292
|
exports._setResourceRequestAttributes = _setResourceRequestAttributes;
|
|
465
293
|
exports.addPerformanceEntries = addPerformanceEntries;
|
|
466
|
-
exports.addWebVitalsToSpan = addWebVitalsToSpan;
|
|
467
|
-
exports.startTrackingInteractions = startTrackingInteractions;
|
|
468
294
|
exports.startTrackingLongAnimationFrames = startTrackingLongAnimationFrames;
|
|
469
295
|
exports.startTrackingLongTasks = startTrackingLongTasks;
|
|
470
|
-
|
|
471
|
-
//# sourceMappingURL=browserMetrics.js.map
|
|
296
|
+
//# sourceMappingURL=entries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entries.js","sources":["../../../src/performance/entries.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Span, SpanAttributes } from '@sentry/core';\nimport {\n browserPerformanceTimeOrigin,\n getActiveSpan,\n parseUrl,\n RESOURCE_SPAN_NAME_FALLBACK,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n setMeasurement,\n spanToJSON,\n filterCollectedUrl,\n} from '@sentry/core';\nimport {\n CODE_FILE_PATH,\n CODE_FUNCTION_NAME,\n HTTP_REQUEST_SAME_ORIGIN,\n HTTP_RESPONSE_BODY_SIZE,\n HTTP_RESPONSE_SIZE,\n HTTP_RESPONSE_STATUS_CODE,\n NETWORK_CONNECTION_EFFECTIVE_TYPE,\n NETWORK_CONNECTION_RTT,\n NETWORK_CONNECTION_TYPE,\n SENTRY_OP,\n SERVER_ADDRESS,\n URL_DOMAIN,\n URL_FULL,\n URL_SCHEME,\n} from '@sentry/conventions/attributes';\nimport { BROWSER_PAINT, UI_LONG_ANIMATION_FRAME, UI_LONG_TASK } from '@sentry/conventions/op';\nimport {\n addPerformanceInstrumentationHandler,\n type PerformanceLongAnimationFrameTiming,\n} from '../instrumentation/performanceObserver';\nimport { WINDOW } from '../types';\nimport { resourceTimingToSpanAttributes } from './resourceTiming';\nimport { getBrowserPerformanceAPI, isMeasurementValue, msToSec, startAndEndSpan } from './utils';\n\ninterface NavigatorNetworkInformation {\n readonly connection?: NetworkInformation;\n}\n\n// http://wicg.github.io/netinfo/#connection-types\ntype ConnectionType = 'bluetooth' | 'cellular' | 'ethernet' | 'mixed' | 'none' | 'other' | 'unknown' | 'wifi' | 'wimax';\n\n// http://wicg.github.io/netinfo/#effectiveconnectiontype-enum\ntype EffectiveConnectionType = '2g' | '3g' | '4g' | 'slow-2g';\n\n// http://wicg.github.io/netinfo/#dom-megabit\ntype Megabit = number;\n// http://wicg.github.io/netinfo/#dom-millisecond\ntype Millisecond = number;\n\n// http://wicg.github.io/netinfo/#networkinformation-interface\ninterface NetworkInformation extends EventTarget {\n // http://wicg.github.io/netinfo/#type-attribute\n readonly type?: ConnectionType;\n // http://wicg.github.io/netinfo/#effectivetype-attribute\n readonly effectiveType?: EffectiveConnectionType;\n // http://wicg.github.io/netinfo/#downlinkmax-attribute\n readonly downlinkMax?: Megabit;\n // http://wicg.github.io/netinfo/#downlink-attribute\n readonly downlink?: Megabit;\n // http://wicg.github.io/netinfo/#rtt-attribute\n readonly rtt?: Millisecond;\n // http://wicg.github.io/netinfo/#savedata-attribute\n readonly saveData?: boolean;\n // http://wicg.github.io/netinfo/#handling-changes-to-the-underlying-connection\n onchange?: EventListener;\n}\n\n// https://w3c.github.io/device-memory/#sec-device-memory-js-api\ninterface NavigatorDeviceMemory {\n readonly deviceMemory?: number;\n}\n\nconst MAX_INT_AS_BYTES = 2147483647;\n\nlet _performanceCursor: number = 0;\n\n/**\n * Start tracking long tasks.\n */\nexport function startTrackingLongTasks(): void {\n addPerformanceInstrumentationHandler('longtask', ({ entries }) => {\n const parent = getActiveSpan();\n if (!parent) {\n return;\n }\n\n const { attributes: parentAttributes, start_timestamp: parentStartTimestamp } = spanToJSON(parent);\n\n for (const entry of entries) {\n const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);\n const duration = msToSec(entry.duration);\n\n if (parentAttributes[SENTRY_OP] === 'navigation' && parentStartTimestamp && startTime < parentStartTimestamp) {\n // Skip adding a span if the long task started before the navigation started.\n // `startAndEndSpan` will otherwise adjust the parent's start time to the span's start\n // time, potentially skewing the duration of the actual navigation as reported via our\n // routing instrumentations\n continue;\n }\n\n startAndEndSpan(parent, startTime, startTime + duration, {\n name: 'Main UI thread blocked',\n op: UI_LONG_TASK,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n },\n });\n }\n });\n}\n\n/**\n * Start tracking long animation frames.\n */\nexport function startTrackingLongAnimationFrames(): void {\n // NOTE: the current web-vitals version (3.5.2) does not support long-animation-frame, so\n // we directly observe `long-animation-frame` events instead of through the web-vitals\n // `observe` helper function.\n const observer = new PerformanceObserver(list => {\n const parent = getActiveSpan();\n if (!parent) {\n return;\n }\n for (const entry of list.getEntries() as PerformanceLongAnimationFrameTiming[]) {\n if (!entry.scripts[0]) {\n continue;\n }\n\n const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);\n\n const {\n start_timestamp: parentStartTimestamp,\n attributes: { [SENTRY_OP]: parentOp },\n } = spanToJSON(parent);\n\n if (parentOp === 'navigation' && parentStartTimestamp && startTime < parentStartTimestamp) {\n // Skip adding the span if the long animation frame started before the navigation started.\n // `startAndEndSpan` will otherwise adjust the parent's start time to the span's start\n // time, potentially skewing the duration of the actual navigation as reported via our\n // routing instrumentations\n continue;\n }\n const duration = msToSec(entry.duration);\n\n const attributes: SpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n };\n\n const initialScript = entry.scripts[0];\n const { invoker, invokerType, sourceURL, sourceFunctionName, sourceCharPosition } = initialScript;\n attributes['browser.script.invoker'] = invoker;\n attributes['browser.script.invoker_type'] = invokerType;\n if (sourceURL) {\n attributes[CODE_FILE_PATH] = sourceURL;\n }\n if (sourceFunctionName) {\n attributes[CODE_FUNCTION_NAME] = sourceFunctionName;\n }\n if (sourceCharPosition !== -1) {\n attributes['browser.script.source_char_position'] = sourceCharPosition;\n }\n\n startAndEndSpan(parent, startTime, startTime + duration, {\n name: 'Main UI thread blocked',\n op: UI_LONG_ANIMATION_FRAME,\n attributes,\n });\n }\n });\n\n observer.observe({ type: 'long-animation-frame', buffered: true });\n}\n\ninterface AddPerformanceEntriesOptions {\n /**\n * Resource spans with `op`s matching strings in the array will not be emitted.\n *\n * Default: []\n */\n ignoreResourceSpans: Array<'resource.script' | 'resource.css' | 'resource.img' | 'resource.other' | string>;\n\n /**\n * Whether span streaming is enabled.\n */\n spanStreamingEnabled?: boolean;\n}\n\n/** Add performance related spans to a transaction */\nexport function addPerformanceEntries(span: Span, options: AddPerformanceEntriesOptions): void {\n const performance = getBrowserPerformanceAPI();\n const origin = browserPerformanceTimeOrigin();\n if (!performance?.getEntries || !origin) {\n // Gatekeeper if performance API not available\n return;\n }\n\n const { spanStreamingEnabled, ignoreResourceSpans } = options;\n\n const timeOrigin = msToSec(origin);\n\n const performanceEntries = performance.getEntries();\n\n const { attributes, start_timestamp: transactionStartTime } = spanToJSON(span);\n\n performanceEntries.slice(_performanceCursor).forEach(entry => {\n const startTime = msToSec(entry.startTime);\n const duration = msToSec(\n // Inexplicably, Chrome sometimes emits a negative duration. We need to work around this.\n // There is a SO post attempting to explain this, but it leaves one with open questions: https://stackoverflow.com/questions/23191918/peformance-getentries-and-negative-duration-display\n // The way we clamp the value is probably not accurate, since we have observed this happen for things that may take a while to load, like for example the replay worker.\n // TODO: Investigate why this happens and how to properly mitigate. For now, this is a workaround to prevent transactions being dropped due to negative duration spans.\n Math.max(0, entry.duration),\n );\n\n if (\n attributes[SENTRY_OP] === 'navigation' &&\n transactionStartTime &&\n timeOrigin + startTime < transactionStartTime\n ) {\n return;\n }\n\n switch (entry.entryType) {\n case 'navigation': {\n _addNavigationSpans(span, entry as PerformanceNavigationTiming, timeOrigin);\n break;\n }\n case 'paint': {\n _addPaintSpan(span, entry, startTime, duration, timeOrigin);\n break;\n }\n case 'resource': {\n _addResourceSpans(\n span,\n entry as PerformanceResourceTiming,\n entry.name,\n startTime,\n duration,\n timeOrigin,\n ignoreResourceSpans,\n spanStreamingEnabled,\n );\n break;\n }\n // Ignore other entry types.\n }\n });\n\n _performanceCursor = Math.max(performanceEntries.length - 1, 0);\n\n _trackNavigator(span, spanStreamingEnabled);\n}\n\n/** Create a span for a browser paint performance entry. */\nfunction _addPaintSpan(\n span: Span,\n entry: PerformanceEntry,\n startTime: number,\n duration: number,\n timeOrigin: number,\n): void {\n const startTimestamp = timeOrigin + startTime;\n\n startAndEndSpan(span, startTimestamp, startTimestamp + duration, {\n name: entry.name,\n attributes: {\n [SENTRY_OP]: BROWSER_PAINT,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.resource.browser.metrics',\n },\n });\n}\n\n/**\n * Instrument navigation entries\n * exported only for tests\n */\nexport function _addNavigationSpans(span: Span, entry: PerformanceNavigationTiming, timeOrigin: number): void {\n _addPerformanceNavigationTiming(span, entry, 'unloadEvent', timeOrigin, 'unload_event');\n _addPerformanceNavigationTiming(span, entry, 'redirect', timeOrigin, 'redirect');\n _addPerformanceNavigationTiming(span, entry, 'domContentLoadedEvent', timeOrigin, 'dom_content_loaded_event');\n _addPerformanceNavigationTiming(span, entry, 'loadEvent', timeOrigin, 'load_event');\n _addPerformanceNavigationTiming(span, entry, 'connect', timeOrigin, 'connect');\n _addPerformanceNavigationTiming(span, entry, 'secureConnection', timeOrigin, 'tls_ssl');\n _addPerformanceNavigationTiming(span, entry, 'fetch', timeOrigin, 'cache');\n _addPerformanceNavigationTiming(span, entry, 'domainLookup', timeOrigin, 'dns');\n\n _addRequest(span, entry, timeOrigin);\n}\n\ntype StartEventName =\n | 'secureConnection'\n | 'fetch'\n | 'domainLookup'\n | 'unloadEvent'\n | 'redirect'\n | 'connect'\n | 'domContentLoadedEvent'\n | 'loadEvent';\n\ntype EndEventName =\n | 'domainLookupStart'\n | 'domainLookupEnd'\n | 'unloadEventEnd'\n | 'redirectEnd'\n | 'connectEnd'\n | 'domContentLoadedEventEnd'\n | 'loadEventEnd';\n\n/** Create performance navigation related spans */\nfunction _addPerformanceNavigationTiming(\n span: Span,\n entry: PerformanceNavigationTiming,\n event: StartEventName,\n timeOrigin: number,\n name: string = event,\n): void {\n const eventEnd = _getEndPropertyNameForNavigationTiming(event) satisfies keyof PerformanceNavigationTiming;\n const end = entry[eventEnd];\n const start = entry[`${event}Start`];\n if (!start || !end) {\n return;\n }\n startAndEndSpan(span, timeOrigin + msToSec(start), timeOrigin + msToSec(end), {\n op: `browser.${name}`,\n name: entry.name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n ...(event === 'redirect' && entry.redirectCount != null ? { 'http.redirect_count': entry.redirectCount } : {}),\n },\n });\n}\n\nfunction _getEndPropertyNameForNavigationTiming(event: StartEventName): EndEventName {\n if (event === 'secureConnection') {\n return 'connectEnd';\n }\n if (event === 'fetch') {\n return 'domainLookupStart';\n }\n return `${event}End`;\n}\n\n/** Create request and response related spans */\nfunction _addRequest(span: Span, entry: PerformanceNavigationTiming, timeOrigin: number): void {\n const requestStartTimestamp = timeOrigin + msToSec(entry.requestStart);\n const responseEndTimestamp = timeOrigin + msToSec(entry.responseEnd);\n const responseStartTimestamp = timeOrigin + msToSec(entry.responseStart);\n if (entry.responseEnd) {\n // It is possible that we are collecting these metrics when the page hasn't finished loading yet, for example when the HTML slowly streams in.\n // In this case, ie. when the document request hasn't finished yet, `entry.responseEnd` will be 0.\n // In order not to produce faulty spans, where the end timestamp is before the start timestamp, we will only collect\n // these spans when the responseEnd value is available. The backend (Relay) would drop the entire span if it contained faulty spans.\n startAndEndSpan(span, requestStartTimestamp, responseEndTimestamp, {\n op: 'browser.request',\n name: entry.name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n },\n });\n\n startAndEndSpan(span, responseStartTimestamp, responseEndTimestamp, {\n op: 'browser.response',\n name: entry.name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n },\n });\n }\n}\n\n/**\n * Create resource-related spans.\n * Exported only for tests.\n */\nexport function _addResourceSpans(\n span: Span,\n entry: PerformanceResourceTiming,\n resourceUrl: string,\n startTime: number,\n duration: number,\n timeOrigin: number,\n ignoredResourceSpanOps?: Array<string>,\n spanStreamingEnabled?: boolean,\n): void {\n // we already instrument based on fetch and xhr, so we don't need to\n // duplicate spans here.\n if (entry.initiatorType === 'xmlhttprequest' || entry.initiatorType === 'fetch') {\n return;\n }\n\n const op = entry.initiatorType ? `resource.${entry.initiatorType}` : 'resource.other';\n if (ignoredResourceSpanOps?.includes(op)) {\n return;\n }\n\n const attributes: SpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.resource.browser.metrics',\n };\n\n const parsedUrl = parseUrl(resourceUrl);\n\n if (parsedUrl.protocol) {\n attributes[URL_SCHEME] = parsedUrl.protocol.split(':').pop(); // the protocol returned by parseUrl includes a :, but OTEL spec does not, so we remove it.\n }\n\n // `host` is the URL authority, so it can carry userinfo, which doesn't belong on either attribute.\n const host = parsedUrl.host?.replace(/^.*@/, '');\n\n if (host) {\n attributes[SERVER_ADDRESS] = host;\n }\n\n // Unlike `server.address`, `url.domain` excludes the port.\n const domain = host?.replace(/:\\d+$/, '');\n\n if (domain) {\n attributes[URL_DOMAIN] = domain;\n }\n\n attributes[HTTP_REQUEST_SAME_ORIGIN] = resourceUrl.includes(WINDOW.location.origin);\n\n attributes[URL_FULL] = filterCollectedUrl(resourceUrl);\n\n _setResourceRequestAttributes(entry, attributes, [\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus\n ['responseStatus', HTTP_RESPONSE_STATUS_CODE],\n\n ['transferSize', HTTP_RESPONSE_SIZE],\n ['encodedBodySize', HTTP_RESPONSE_BODY_SIZE],\n ['decodedBodySize', 'http.response.body.decoded_size'],\n\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/renderBlockingStatus\n ['renderBlockingStatus', 'resource.render_blocking_status'],\n\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/deliveryType\n ['deliveryType', 'http.response_delivery_type'],\n ]);\n\n const attributesWithResourceTiming: SpanAttributes = { ...attributes, ...resourceTimingToSpanAttributes(entry) };\n\n const startTimestamp = timeOrigin + startTime;\n const endTimestamp = startTimestamp + duration;\n\n startAndEndSpan(span, startTimestamp, endTimestamp, {\n // With span streaming, span names have to be low cardinality, so we can't fall back to the URL.\n name: spanStreamingEnabled\n ? domain || RESOURCE_SPAN_NAME_FALLBACK\n : resourceUrl.replace(WINDOW.location.origin, ''),\n op,\n attributes: attributesWithResourceTiming,\n });\n}\n\n/**\n * Capture the information of the user agent.\n * TODO v11: Remove non-span-streaming attributes and measurements once we removed transactions\n */\nfunction _trackNavigator(span: Span, spanStreamingEnabled: boolean | undefined): void {\n const navigator = WINDOW.navigator as null | (Navigator & NavigatorNetworkInformation & NavigatorDeviceMemory);\n if (!navigator) {\n return;\n }\n\n // track network connectivity\n const connection = navigator.connection;\n if (connection) {\n if (connection.effectiveType) {\n span.setAttribute(\n spanStreamingEnabled ? NETWORK_CONNECTION_EFFECTIVE_TYPE : 'effectiveConnectionType',\n connection.effectiveType,\n );\n }\n\n if (connection.type) {\n span.setAttribute(spanStreamingEnabled ? NETWORK_CONNECTION_TYPE : 'connectionType', connection.type);\n }\n\n if (isMeasurementValue(connection.rtt)) {\n if (spanStreamingEnabled) {\n span.setAttribute(NETWORK_CONNECTION_RTT, connection.rtt);\n } else if (spanToJSON(span).attributes[SENTRY_OP] === 'pageload') {\n // Measurements are only recorded on the pageload span, matching the historical\n // behavior where `connection.rtt` was only flushed for pageload transactions.\n setMeasurement('connection.rtt', connection.rtt, 'millisecond');\n }\n }\n }\n\n if (isMeasurementValue(navigator.deviceMemory)) {\n if (spanStreamingEnabled) {\n span.setAttribute('device.memory.estimated_capacity', navigator.deviceMemory);\n } else {\n span.setAttribute('deviceMemory', `${navigator.deviceMemory} GB`);\n }\n }\n\n if (isMeasurementValue(navigator.hardwareConcurrency)) {\n if (spanStreamingEnabled) {\n span.setAttribute('device.processor_count', navigator.hardwareConcurrency);\n } else {\n span.setAttribute('hardwareConcurrency', String(navigator.hardwareConcurrency));\n }\n }\n}\n\ntype ExperimentalResourceTimingProperty =\n | 'renderBlockingStatus'\n | 'deliveryType'\n // For some reason, TS during build, errors on `responseStatus` not being a property of\n // PerformanceResourceTiming while it actually is. Hence, we're adding it here.\n // Perhaps because response status is not yet available in Webkit/Safari.\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus\n | 'responseStatus';\n\n/**\n * Use this to set any attributes we can take directly form the PerformanceResourceTiming entry.\n *\n * This is just a mapping function for entry->attribute to keep bundle-size minimal.\n * Experimental properties are also accepted (see {@link ExperimentalResourceTimingProperty}).\n * Assumes that all entry properties might be undefined for browser-specific differences.\n * Only accepts string and number values for now and also sets 0-values.\n */\nexport function _setResourceRequestAttributes(\n entry: Partial<PerformanceResourceTiming> & Partial<Record<ExperimentalResourceTimingProperty, number | string>>,\n attributes: SpanAttributes,\n properties: [keyof PerformanceResourceTiming | ExperimentalResourceTimingProperty, string][],\n): void {\n properties.forEach(([entryKey, attributeKey]) => {\n const entryVal = entry[entryKey];\n if (\n entryVal != null &&\n ((typeof entryVal === 'number' && entryVal < MAX_INT_AS_BYTES) || typeof entryVal === 'string')\n ) {\n attributes[attributeKey] = entryVal;\n }\n });\n}\n"],"names":["addPerformanceInstrumentationHandler","getActiveSpan","spanToJSON","msToSec","browserPerformanceTimeOrigin","SENTRY_OP","startAndEndSpan","UI_LONG_TASK","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","attributes","CODE_FILE_PATH","CODE_FUNCTION_NAME","UI_LONG_ANIMATION_FRAME","getBrowserPerformanceAPI","BROWSER_PAINT","parseUrl","URL_SCHEME","SERVER_ADDRESS","URL_DOMAIN","HTTP_REQUEST_SAME_ORIGIN","WINDOW","URL_FULL","filterCollectedUrl","HTTP_RESPONSE_STATUS_CODE","HTTP_RESPONSE_SIZE","HTTP_RESPONSE_BODY_SIZE","resourceTimingToSpanAttributes","RESOURCE_SPAN_NAME_FALLBACK","NETWORK_CONNECTION_EFFECTIVE_TYPE","NETWORK_CONNECTION_TYPE","isMeasurementValue","NETWORK_CONNECTION_RTT","setMeasurement"],"mappings":"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"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const attributes = require('@sentry/conventions/attributes');
|
|
4
|
+
const op = require('@sentry/conventions/op');
|
|
5
|
+
const core = require('@sentry/core');
|
|
6
|
+
const browser = require('@sentry/core/browser');
|
|
7
|
+
const debugBuild = require('../debug-build.js');
|
|
8
|
+
const htmlTreeAsString = require('../htmlTreeAsString.js');
|
|
9
|
+
const performanceObserver = require('../instrumentation/performanceObserver.js');
|
|
10
|
+
const isBotUserAgent = require('../isBotUserAgent.js');
|
|
11
|
+
const types = require('../types.js');
|
|
12
|
+
const utils = require('./utils.js');
|
|
13
|
+
const componentName = require('../component-name.js');
|
|
14
|
+
|
|
15
|
+
const INTEGRATION_NAME = "Interactions";
|
|
16
|
+
const _interactionsIntegration = ((options = {}) => {
|
|
17
|
+
return {
|
|
18
|
+
name: INTEGRATION_NAME,
|
|
19
|
+
setup(client) {
|
|
20
|
+
if (isBotUserAgent.isBotUserAgent()) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const latestRoute = { name: void 0, source: void 0 };
|
|
24
|
+
let inflightRouteSpan;
|
|
25
|
+
function trackRoute(span) {
|
|
26
|
+
const { name, attributes: attributes$1 } = core.spanToJSON(span);
|
|
27
|
+
latestRoute.name = name;
|
|
28
|
+
latestRoute.source = attributes$1[attributes.SENTRY_SOURCE] || attributes$1[attributes.SENTRY_SEGMENT_NAME_SOURCE];
|
|
29
|
+
}
|
|
30
|
+
client.on("spanStart", (span) => {
|
|
31
|
+
if (isRouteSpan(span)) {
|
|
32
|
+
inflightRouteSpan = span;
|
|
33
|
+
trackRoute(span);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
client.on("spanEnd", (span) => {
|
|
37
|
+
if (span !== inflightRouteSpan) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
inflightRouteSpan = void 0;
|
|
41
|
+
trackRoute(span);
|
|
42
|
+
});
|
|
43
|
+
registerInteractionListener(latestRoute, () => inflightRouteSpan, options);
|
|
44
|
+
trackInteractionsAsSpans();
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
const interactionsIntegration = core.defineIntegration(_interactionsIntegration);
|
|
49
|
+
function isRouteSpan(span) {
|
|
50
|
+
if (core.getRootSpan(span) !== span) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const op = core.spanToJSON(span).attributes[attributes.SENTRY_OP];
|
|
54
|
+
return op === "pageload" || op === "navigation";
|
|
55
|
+
}
|
|
56
|
+
function registerInteractionListener(latestRoute, getInflightRouteSpan, idleSpanOptions) {
|
|
57
|
+
if (!types.WINDOW.document) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
let inflightInteractionSpan;
|
|
61
|
+
addEventListener(
|
|
62
|
+
"click",
|
|
63
|
+
() => {
|
|
64
|
+
if (getInflightRouteSpan()) {
|
|
65
|
+
debugBuild.DEBUG_BUILD && core.debug.warn(
|
|
66
|
+
`[Tracing] Did not create ${op.UI_ACTION_CLICK} span because a pageload or navigation span is in progress.`
|
|
67
|
+
);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (inflightInteractionSpan) {
|
|
71
|
+
inflightInteractionSpan.setAttribute(attributes.SENTRY_IDLE_SPAN_FINISH_REASON, "interactionInterrupted");
|
|
72
|
+
inflightInteractionSpan.end();
|
|
73
|
+
inflightInteractionSpan = void 0;
|
|
74
|
+
}
|
|
75
|
+
if (!latestRoute.name) {
|
|
76
|
+
debugBuild.DEBUG_BUILD && core.debug.warn(`[Tracing] Did not create ${op.UI_ACTION_CLICK} span because the latest route name is missing.`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
inflightInteractionSpan = browser.startIdleSpan(
|
|
80
|
+
{
|
|
81
|
+
name: latestRoute.name,
|
|
82
|
+
attributes: {
|
|
83
|
+
[attributes.SENTRY_OP]: op.UI_ACTION_CLICK,
|
|
84
|
+
[attributes.SENTRY_SEGMENT_NAME_SOURCE]: latestRoute.source || "url",
|
|
85
|
+
[attributes.SENTRY_ORIGIN]: "auto.browser.interactions"
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
idleSpanOptions
|
|
89
|
+
);
|
|
90
|
+
},
|
|
91
|
+
{ capture: true }
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
function trackInteractionsAsSpans() {
|
|
95
|
+
performanceObserver.addPerformanceInstrumentationHandler("event", ({ entries }) => {
|
|
96
|
+
const parent = core.getActiveSpan();
|
|
97
|
+
if (!parent) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
for (const entry of entries) {
|
|
101
|
+
if (entry.name === "click") {
|
|
102
|
+
const startTime = utils.msToSec(core.browserPerformanceTimeOrigin() + entry.startTime);
|
|
103
|
+
const duration = utils.msToSec(entry.duration);
|
|
104
|
+
const spanOptions = {
|
|
105
|
+
name: htmlTreeAsString.htmlTreeAsString(entry.target),
|
|
106
|
+
startTime,
|
|
107
|
+
attributes: {
|
|
108
|
+
[attributes.SENTRY_OP]: op.UI_INTERACTION_CLICK,
|
|
109
|
+
[attributes.SENTRY_ORIGIN]: "auto.browser.interactions"
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const componentName$1 = componentName.getComponentName(entry.target);
|
|
113
|
+
if (componentName$1) {
|
|
114
|
+
spanOptions.attributes[attributes.UI_COMPONENT_NAME] = componentName$1;
|
|
115
|
+
}
|
|
116
|
+
utils.startAndEndSpan(parent, startTime, startTime + duration, spanOptions);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
exports.interactionsIntegration = interactionsIntegration;
|
|
123
|
+
//# sourceMappingURL=interactions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactions.js","sources":["../../../src/performance/interactions.ts"],"sourcesContent":["import {\n SENTRY_OP,\n SENTRY_ORIGIN,\n SENTRY_IDLE_SPAN_FINISH_REASON,\n UI_COMPONENT_NAME,\n SENTRY_SOURCE,\n SENTRY_SEGMENT_NAME_SOURCE,\n} from '@sentry/conventions/attributes';\nimport { UI_INTERACTION_CLICK, UI_ACTION_CLICK } from '@sentry/conventions/op';\nimport type { IntegrationFn, Span, StartSpanOptions, TransactionSource } from '@sentry/core';\nimport {\n browserPerformanceTimeOrigin,\n debug,\n defineIntegration,\n getActiveSpan,\n getRootSpan,\n spanToJSON,\n} from '@sentry/core';\nimport { startIdleSpan } from '@sentry/core/browser';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { htmlTreeAsString } from '../htmlTreeAsString';\nimport { addPerformanceInstrumentationHandler } from '../instrumentation/performanceObserver';\nimport { isBotUserAgent } from '../isBotUserAgent';\nimport { WINDOW } from '../types';\nimport { msToSec, startAndEndSpan } from './utils';\nimport { getComponentName } from '../component-name';\n\nconst INTEGRATION_NAME = 'Interactions';\n\ninterface InteractionsOptions {\n /**\n * The time that has to pass without any span being created.\n * If this time is exceeded, the interaction span will finish.\n *\n * Default: 1000 (ms)\n */\n idleTimeout?: number;\n\n /**\n * The max. time an interaction span may run.\n * If this time is exceeded, the interaction span will finish no matter what.\n *\n * Default: 30000 (ms)\n */\n finalTimeout?: number;\n\n /**\n * The max. time a child span of an interaction span may run.\n * If this time is exceeded, the interaction span will finish no matter what.\n *\n * Default: 15000 (ms)\n */\n childSpanTimeout?: number;\n}\n\ninterface RouteInfo {\n name: string | undefined;\n source: TransactionSource | undefined;\n}\n\nconst _interactionsIntegration = ((options: InteractionsOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setup(client) {\n if (isBotUserAgent()) {\n return;\n }\n\n const latestRoute: RouteInfo = { name: undefined, source: undefined };\n // The pageload/navigation span that is currently in progress, if any. Clicks that happen while one\n // is open are not turned into interaction spans, as they'd compete with the route span for children.\n let inflightRouteSpan: Span | undefined;\n\n function trackRoute(span: Span): void {\n const { name, attributes } = spanToJSON(span);\n latestRoute.name = name;\n // oxlint-disable-next-line typescript/no-deprecated\n latestRoute.source = (attributes[SENTRY_SOURCE] || attributes[SENTRY_SEGMENT_NAME_SOURCE]) as\n | TransactionSource\n | undefined;\n }\n\n client.on('spanStart', span => {\n if (isRouteSpan(span)) {\n inflightRouteSpan = span;\n trackRoute(span);\n }\n });\n\n client.on('spanEnd', span => {\n if (span !== inflightRouteSpan) {\n return;\n }\n inflightRouteSpan = undefined;\n // Re-read the route on end: routing instrumentation frequently renames the pageload or navigation\n // span once the route is resolved, so this is more accurate than what we saw at span start.\n trackRoute(span);\n });\n\n registerInteractionListener(latestRoute, () => inflightRouteSpan, options);\n\n trackInteractionsAsSpans();\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Captures user interactions as spans.\n *\n * Important: This integration is considered experimental and might lead to noisy spans. Use at your own risk.\n *\n *\n * Clicks that happen outside of an in-progress pageload or navigation start an idle `ui.action.click` span,\n * named after the last known route, which collects everything the interaction triggers (requests, child spans,\n * …). Additionally, `ui.interaction.click` spans are recorded for the browser's own `event` timing entries.\n *\n * The integration requires `browserTracingIntegration` (or another source of pageload/navigation spans)\n * to know which route an interaction belongs to.\n *\n * @example\n * ```ts\n * Sentry.init({\n * integrations: [Sentry.browserTracingIntegration(), Sentry.interactionsIntegration()],\n * });\n * ```\n */\nexport const interactionsIntegration = defineIntegration(_interactionsIntegration);\n\nfunction isRouteSpan(span: Span): boolean {\n if (getRootSpan(span) !== span) {\n return false;\n }\n const op = spanToJSON(span).attributes[SENTRY_OP];\n return op === 'pageload' || op === 'navigation';\n}\n\nfunction registerInteractionListener(\n latestRoute: RouteInfo,\n getInflightRouteSpan: () => Span | undefined,\n // `startIdleSpan` fills in `TRACING_DEFAULTS` for whatever is left out, which are the same defaults\n // `browserTracingIntegration` uses for its pageload and navigation spans.\n idleSpanOptions: InteractionsOptions,\n): void {\n // `document` is not available in all browser environments (e.g. web workers), and without it there is\n // nothing to click on.\n if (!WINDOW.document) {\n return;\n }\n\n let inflightInteractionSpan: Span | undefined;\n\n addEventListener(\n 'click',\n () => {\n if (getInflightRouteSpan()) {\n DEBUG_BUILD &&\n debug.warn(\n `[Tracing] Did not create ${UI_ACTION_CLICK} span because a pageload or navigation span is in progress.`,\n );\n return;\n }\n\n if (inflightInteractionSpan) {\n inflightInteractionSpan.setAttribute(SENTRY_IDLE_SPAN_FINISH_REASON, 'interactionInterrupted');\n inflightInteractionSpan.end();\n inflightInteractionSpan = undefined;\n }\n\n if (!latestRoute.name) {\n DEBUG_BUILD &&\n debug.warn(`[Tracing] Did not create ${UI_ACTION_CLICK} span because the latest route name is missing.`);\n return;\n }\n\n inflightInteractionSpan = startIdleSpan(\n {\n name: latestRoute.name,\n attributes: {\n [SENTRY_OP]: UI_ACTION_CLICK,\n [SENTRY_SEGMENT_NAME_SOURCE]: latestRoute.source || 'url',\n [SENTRY_ORIGIN]: 'auto.browser.interactions',\n },\n },\n idleSpanOptions,\n );\n },\n { capture: true },\n );\n}\n\n/**\n * Record the browser's `event` timing entries for clicks as spans on the currently active span.\n */\nfunction trackInteractionsAsSpans(): void {\n addPerformanceInstrumentationHandler('event', ({ entries }) => {\n const parent = getActiveSpan();\n if (!parent) {\n return;\n }\n for (const entry of entries) {\n if (entry.name === 'click') {\n const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);\n const duration = msToSec(entry.duration);\n\n const spanOptions: StartSpanOptions & Required<Pick<StartSpanOptions, 'attributes'>> = {\n name: htmlTreeAsString(entry.target),\n startTime: startTime,\n attributes: {\n [SENTRY_OP]: UI_INTERACTION_CLICK,\n [SENTRY_ORIGIN]: 'auto.browser.interactions',\n },\n };\n\n const componentName = getComponentName(entry.target);\n if (componentName) {\n spanOptions.attributes[UI_COMPONENT_NAME] = componentName;\n }\n\n startAndEndSpan(parent, startTime, startTime + duration, spanOptions);\n }\n }\n });\n}\n"],"names":["isBotUserAgent","attributes","spanToJSON","SENTRY_SOURCE","SENTRY_SEGMENT_NAME_SOURCE","defineIntegration","getRootSpan","SENTRY_OP","WINDOW","DEBUG_BUILD","debug","UI_ACTION_CLICK","SENTRY_IDLE_SPAN_FINISH_REASON","startIdleSpan","SENTRY_ORIGIN","addPerformanceInstrumentationHandler","getActiveSpan","msToSec","browserPerformanceTimeOrigin","htmlTreeAsString","UI_INTERACTION_CLICK","componentName","getComponentName","UI_COMPONENT_NAME","startAndEndSpan"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resourceTiming.js","sources":["../../../src/performance/resourceTiming.ts"],"sourcesContent":["import type { SpanAttributes } from '@sentry/core';\nimport { browserPerformanceTimeOrigin } from '@sentry/core';\nimport { extractNetworkProtocol, getBrowserPerformanceAPI } from './utils';\n\nfunction getAbsoluteTime(time: number | undefined): number | undefined {\n // falsy values should be preserved so that we can later on drop undefined values and\n // preserve 0 vals for cross-origin resources without proper `Timing-Allow-Origin` header.\n return time ? ((browserPerformanceTimeOrigin() || performance.timeOrigin) + time) / 1000 : time;\n}\n\n/**\n * Converts a PerformanceResourceTiming entry to span data for the resource span. Most importantly,\n * it converts the timing values from timestamps relative to the `performance.timeOrigin` to absolute timestamps\n * in seconds.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming#timestamps\n *\n * @param resourceTiming\n * @returns An array where the first element is the attribute name and the second element is the attribute value.\n */\nexport function resourceTimingToSpanAttributes(resourceTiming: PerformanceResourceTiming): SpanAttributes {\n const timingSpanData: SpanAttributes = {};\n // Checking for only `undefined` and `null` is intentional because it's\n // valid for `nextHopProtocol` to be an empty string.\n if (resourceTiming.nextHopProtocol != undefined) {\n const { name, version } = extractNetworkProtocol(resourceTiming.nextHopProtocol);\n timingSpanData['network.protocol.version'] = version;\n timingSpanData['network.protocol.name'] = name;\n }\n\n if (!(browserPerformanceTimeOrigin() || getBrowserPerformanceAPI()?.timeOrigin)) {\n return timingSpanData;\n }\n\n return dropUndefinedKeysFromObject({\n ...timingSpanData,\n\n 'http.request.redirect_start': getAbsoluteTime(resourceTiming.redirectStart),\n 'http.request.redirect_end': getAbsoluteTime(resourceTiming.redirectEnd),\n\n 'http.request.worker_start': getAbsoluteTime(resourceTiming.workerStart),\n\n 'http.request.fetch_start': getAbsoluteTime(resourceTiming.fetchStart),\n\n 'http.request.domain_lookup_start': getAbsoluteTime(resourceTiming.domainLookupStart),\n 'http.request.domain_lookup_end': getAbsoluteTime(resourceTiming.domainLookupEnd),\n\n 'http.request.connect_start': getAbsoluteTime(resourceTiming.connectStart),\n 'http.request.secure_connection_start': getAbsoluteTime(resourceTiming.secureConnectionStart),\n 'http.request.connection_end': getAbsoluteTime(resourceTiming.connectEnd),\n\n 'http.request.request_start': getAbsoluteTime(resourceTiming.requestStart),\n\n 'http.request.response_start': getAbsoluteTime(resourceTiming.responseStart),\n 'http.request.response_end': getAbsoluteTime(resourceTiming.responseEnd),\n\n // For TTFB we actually want the relative time from timeOrigin to responseStart\n // This way, TTFB always measures the \"first page load\" experience.\n // see: https://web.dev/articles/ttfb#measure-resource-requests\n 'http.request.time_to_first_byte':\n resourceTiming.responseStart != null ? resourceTiming.responseStart / 1000 : undefined,\n });\n}\n\n/**\n * Remove properties with `undefined` as value from an object.\n * In contrast to `dropUndefinedKeys` in core this funciton only works on first-level\n * key-value objects and does not recursively go into object properties or arrays.\n */\nfunction dropUndefinedKeysFromObject<T extends object>(attrs: T): Partial<T> {\n return Object.fromEntries(Object.entries(attrs).filter(([, value]) => value != null)) as Partial<T>;\n}\n"],"names":["browserPerformanceTimeOrigin","extractNetworkProtocol","getBrowserPerformanceAPI"],"mappings":";;;;;AAIA,SAAS,gBAAgB,IAAA,EAA8C;AAGrE,EAAA,OAAO,SAASA,iCAAA,EAA6B,IAAK,WAAA,CAAY,UAAA,IAAc,QAAQ,GAAA,GAAO,IAAA;AAC7F;AAYO,SAAS,+BAA+B,cAAA,EAA2D;AACxG,EAAA,MAAM,iBAAiC,EAAC;AAGxC,EAAA,IAAI,cAAA,CAAe,mBAAmB,MAAA,EAAW;AAC/C,IAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAQ,GAAIC,4BAAA,CAAuB,eAAe,eAAe,CAAA;AAC/E,IAAA,cAAA,CAAe,0BAA0B,CAAA,GAAI,OAAA;AAC7C,IAAA,cAAA,CAAe,uBAAuB,CAAA,GAAI,IAAA;AAAA,EAC5C;AAEA,EAAA,IAAI,EAAED,iCAAA,EAA6B,IAAKE,8BAAA,IAA4B,UAAA,CAAA,EAAa;AAC/E,IAAA,OAAO,cAAA;AAAA,EACT;AAEA,EAAA,OAAO,2BAAA,CAA4B;AAAA,IACjC,GAAG,cAAA;AAAA,IAEH,6BAAA,EAA+B,eAAA,CAAgB,cAAA,CAAe,aAAa,CAAA;AAAA,IAC3E,2BAAA,EAA6B,eAAA,CAAgB,cAAA,CAAe,WAAW,CAAA;AAAA,IAEvE,2BAAA,EAA6B,eAAA,CAAgB,cAAA,CAAe,WAAW,CAAA;AAAA,IAEvE,0BAAA,EAA4B,eAAA,CAAgB,cAAA,CAAe,UAAU,CAAA;AAAA,IAErE,kCAAA,EAAoC,eAAA,CAAgB,cAAA,CAAe,iBAAiB,CAAA;AAAA,IACpF,gCAAA,EAAkC,eAAA,CAAgB,cAAA,CAAe,eAAe,CAAA;AAAA,IAEhF,4BAAA,EAA8B,eAAA,CAAgB,cAAA,CAAe,YAAY,CAAA;AAAA,IACzE,sCAAA,EAAwC,eAAA,CAAgB,cAAA,CAAe,qBAAqB,CAAA;AAAA,IAC5F,6BAAA,EAA+B,eAAA,CAAgB,cAAA,CAAe,UAAU,CAAA;AAAA,IAExE,4BAAA,EAA8B,eAAA,CAAgB,cAAA,CAAe,YAAY,CAAA;AAAA,IAEzE,6BAAA,EAA+B,eAAA,CAAgB,cAAA,CAAe,aAAa,CAAA;AAAA,IAC3E,2BAAA,EAA6B,eAAA,CAAgB,cAAA,CAAe,WAAW,CAAA;AAAA;AAAA;AAAA;AAAA,IAKvE,mCACE,cAAA,CAAe,aAAA,IAAiB,IAAA,GAAO,cAAA,CAAe,gBAAgB,GAAA,GAAO;AAAA,GAChF,CAAA;AACH;AAOA,SAAS,4BAA8C,KAAA,EAAsB;AAC3E,EAAA,OAAO,MAAA,CAAO,WAAA,CAAY,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,CAAE,MAAA,CAAO,CAAC,GAAG,KAAK,CAAA,KAAM,KAAA,IAAS,IAAI,CAAC,CAAA;AACtF;;;;"}
|