@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.
Files changed (350) hide show
  1. package/build/cjs/htmlTreeAsString.js.map +1 -1
  2. package/build/cjs/index.js +30 -28
  3. package/build/cjs/index.js.map +1 -1
  4. package/build/cjs/instrumentation/dom.js.map +1 -0
  5. package/build/cjs/instrumentation/history.js.map +1 -0
  6. package/build/cjs/instrumentation/location.js.map +1 -0
  7. package/build/cjs/{metrics/instrument.js → instrumentation/performanceObserver.js} +44 -32
  8. package/build/cjs/instrumentation/performanceObserver.js.map +1 -0
  9. package/build/cjs/instrumentation/xhr.js.map +1 -0
  10. package/build/cjs/{metrics → performance}/elementTiming.js +2 -2
  11. package/build/cjs/performance/elementTiming.js.map +1 -0
  12. package/build/cjs/{metrics/browserMetrics.js → performance/entries.js} +43 -262
  13. package/build/cjs/performance/entries.js.map +1 -0
  14. package/build/cjs/performance/resourceTiming.js.map +1 -0
  15. package/build/cjs/performance/userTiming.js +119 -0
  16. package/build/cjs/performance/userTiming.js.map +1 -0
  17. package/build/cjs/performance/utils.js +68 -0
  18. package/build/cjs/performance/utils.js.map +1 -0
  19. package/build/cjs/{metrics → web-vitals}/inp.js +4 -61
  20. package/build/cjs/web-vitals/inp.js.map +1 -0
  21. package/build/cjs/web-vitals/lcp.js +10 -0
  22. package/build/cjs/web-vitals/lcp.js.map +1 -0
  23. package/build/cjs/web-vitals/reportEvents.js +31 -0
  24. package/build/cjs/web-vitals/reportEvents.js.map +1 -0
  25. package/build/cjs/{metrics/webVitalSpans.js → web-vitals/spans.js} +36 -19
  26. package/build/cjs/web-vitals/spans.js.map +1 -0
  27. package/build/cjs/web-vitals/tracking.js +164 -0
  28. package/build/cjs/web-vitals/tracking.js.map +1 -0
  29. package/build/cjs/web-vitals/utils.js +99 -0
  30. package/build/cjs/web-vitals/utils.js.map +1 -0
  31. package/build/esm/htmlTreeAsString.js.map +1 -1
  32. package/build/esm/index.js +14 -12
  33. package/build/esm/index.js.map +1 -1
  34. package/build/esm/instrumentation/dom.js.map +1 -0
  35. package/build/esm/instrumentation/history.js.map +1 -0
  36. package/build/esm/instrumentation/location.js.map +1 -0
  37. package/build/esm/{metrics/instrument.js → instrumentation/performanceObserver.js} +42 -30
  38. package/build/esm/instrumentation/performanceObserver.js.map +1 -0
  39. package/build/esm/instrumentation/xhr.js.map +1 -0
  40. package/build/esm/package.json +1 -1
  41. package/build/esm/{metrics → performance}/elementTiming.js +1 -1
  42. package/build/esm/performance/elementTiming.js.map +1 -0
  43. package/build/esm/{metrics/browserMetrics.js → performance/entries.js} +36 -252
  44. package/build/esm/performance/entries.js.map +1 -0
  45. package/build/esm/performance/resourceTiming.js.map +1 -0
  46. package/build/esm/performance/userTiming.js +116 -0
  47. package/build/esm/performance/userTiming.js.map +1 -0
  48. package/build/esm/performance/utils.js +61 -0
  49. package/build/esm/performance/utils.js.map +1 -0
  50. package/build/esm/{metrics → web-vitals}/inp.js +3 -57
  51. package/build/esm/web-vitals/inp.js.map +1 -0
  52. package/build/esm/web-vitals/lcp.js +7 -0
  53. package/build/esm/web-vitals/lcp.js.map +1 -0
  54. package/build/esm/web-vitals/reportEvents.js +29 -0
  55. package/build/esm/web-vitals/reportEvents.js.map +1 -0
  56. package/build/esm/{metrics/webVitalSpans.js → web-vitals/spans.js} +32 -15
  57. package/build/esm/web-vitals/spans.js.map +1 -0
  58. package/build/esm/web-vitals/tracking.js +161 -0
  59. package/build/esm/web-vitals/tracking.js.map +1 -0
  60. package/build/esm/web-vitals/utils.js +91 -0
  61. package/build/esm/web-vitals/utils.js.map +1 -0
  62. package/build/types/index.d.ts +13 -11
  63. package/build/types/index.d.ts.map +1 -1
  64. package/build/types/instrumentation/dom.d.ts.map +1 -0
  65. package/build/types/instrumentation/history.d.ts.map +1 -0
  66. package/build/types/instrumentation/location.d.ts.map +1 -0
  67. package/build/types/{metrics/instrument.d.ts → instrumentation/performanceObserver.d.ts} +3 -3
  68. package/build/types/instrumentation/performanceObserver.d.ts.map +1 -0
  69. package/build/types/instrumentation/xhr.d.ts.map +1 -0
  70. package/build/types/performance/elementTiming.d.ts.map +1 -0
  71. package/build/types/performance/entries.d.ts +49 -0
  72. package/build/types/performance/entries.d.ts.map +1 -0
  73. package/build/types/performance/resourceTiming.d.ts.map +1 -0
  74. package/build/types/performance/userTiming.d.ts +37 -0
  75. package/build/types/performance/userTiming.d.ts.map +1 -0
  76. package/build/types/performance/utils.d.ts +33 -0
  77. package/build/types/performance/utils.d.ts.map +1 -0
  78. package/build/types/types.d.ts +1 -1
  79. package/build/types/{metrics → web-vitals}/inp.d.ts +0 -13
  80. package/build/types/web-vitals/inp.d.ts.map +1 -0
  81. package/build/types/web-vitals/lcp.d.ts +6 -0
  82. package/build/types/web-vitals/lcp.d.ts.map +1 -0
  83. package/build/types/web-vitals/reportEvents.d.ts +18 -0
  84. package/build/types/web-vitals/reportEvents.d.ts.map +1 -0
  85. package/build/types/{metrics/webVitalSpans.d.ts → web-vitals/spans.d.ts} +18 -12
  86. package/build/types/web-vitals/spans.d.ts.map +1 -0
  87. package/build/types/web-vitals/tracking.d.ts +46 -0
  88. package/build/types/web-vitals/tracking.d.ts.map +1 -0
  89. package/build/types/{metrics/web-vitals/lib/globalListeners.d.ts → web-vitals/utils.d.ts} +16 -1
  90. package/build/types/web-vitals/utils.d.ts.map +1 -0
  91. package/package.json +8 -16
  92. package/build/cjs/instrument/dom.js.map +0 -1
  93. package/build/cjs/instrument/history.js.map +0 -1
  94. package/build/cjs/instrument/location.js.map +0 -1
  95. package/build/cjs/instrument/xhr.js.map +0 -1
  96. package/build/cjs/metrics/browserMetrics.js.map +0 -1
  97. package/build/cjs/metrics/cls.js +0 -64
  98. package/build/cjs/metrics/cls.js.map +0 -1
  99. package/build/cjs/metrics/elementTiming.js.map +0 -1
  100. package/build/cjs/metrics/inp.js.map +0 -1
  101. package/build/cjs/metrics/instrument.js.map +0 -1
  102. package/build/cjs/metrics/lcp.js +0 -77
  103. package/build/cjs/metrics/lcp.js.map +0 -1
  104. package/build/cjs/metrics/resourceTiming.js.map +0 -1
  105. package/build/cjs/metrics/utils.js +0 -137
  106. package/build/cjs/metrics/utils.js.map +0 -1
  107. package/build/cjs/metrics/web-vitals/getCLS.js +0 -46
  108. package/build/cjs/metrics/web-vitals/getCLS.js.map +0 -1
  109. package/build/cjs/metrics/web-vitals/getINP.js +0 -60
  110. package/build/cjs/metrics/web-vitals/getINP.js.map +0 -1
  111. package/build/cjs/metrics/web-vitals/getLCP.js +0 -62
  112. package/build/cjs/metrics/web-vitals/getLCP.js.map +0 -1
  113. package/build/cjs/metrics/web-vitals/lib/InteractionManager.js +0 -87
  114. package/build/cjs/metrics/web-vitals/lib/InteractionManager.js.map +0 -1
  115. package/build/cjs/metrics/web-vitals/lib/LCPEntryManager.js +0 -11
  116. package/build/cjs/metrics/web-vitals/lib/LCPEntryManager.js.map +0 -1
  117. package/build/cjs/metrics/web-vitals/lib/LayoutShiftManager.js +0 -27
  118. package/build/cjs/metrics/web-vitals/lib/LayoutShiftManager.js.map +0 -1
  119. package/build/cjs/metrics/web-vitals/lib/bindReporter.js +0 -31
  120. package/build/cjs/metrics/web-vitals/lib/bindReporter.js.map +0 -1
  121. package/build/cjs/metrics/web-vitals/lib/generateUniqueID.js +0 -8
  122. package/build/cjs/metrics/web-vitals/lib/generateUniqueID.js.map +0 -1
  123. package/build/cjs/metrics/web-vitals/lib/getActivationStart.js +0 -11
  124. package/build/cjs/metrics/web-vitals/lib/getActivationStart.js.map +0 -1
  125. package/build/cjs/metrics/web-vitals/lib/getNavigationEntry.js +0 -17
  126. package/build/cjs/metrics/web-vitals/lib/getNavigationEntry.js.map +0 -1
  127. package/build/cjs/metrics/web-vitals/lib/getVisibilityWatcher.js +0 -48
  128. package/build/cjs/metrics/web-vitals/lib/getVisibilityWatcher.js.map +0 -1
  129. package/build/cjs/metrics/web-vitals/lib/globalListeners.js +0 -18
  130. package/build/cjs/metrics/web-vitals/lib/globalListeners.js.map +0 -1
  131. package/build/cjs/metrics/web-vitals/lib/initMetric.js +0 -34
  132. package/build/cjs/metrics/web-vitals/lib/initMetric.js.map +0 -1
  133. package/build/cjs/metrics/web-vitals/lib/initUnique.js +0 -16
  134. package/build/cjs/metrics/web-vitals/lib/initUnique.js.map +0 -1
  135. package/build/cjs/metrics/web-vitals/lib/observe.js +0 -20
  136. package/build/cjs/metrics/web-vitals/lib/observe.js.map +0 -1
  137. package/build/cjs/metrics/web-vitals/lib/onHidden.js +0 -17
  138. package/build/cjs/metrics/web-vitals/lib/onHidden.js.map +0 -1
  139. package/build/cjs/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js +0 -32
  140. package/build/cjs/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js.map +0 -1
  141. package/build/cjs/metrics/web-vitals/lib/runOnce.js +0 -14
  142. package/build/cjs/metrics/web-vitals/lib/runOnce.js.map +0 -1
  143. package/build/cjs/metrics/web-vitals/lib/whenActivated.js +0 -14
  144. package/build/cjs/metrics/web-vitals/lib/whenActivated.js.map +0 -1
  145. package/build/cjs/metrics/web-vitals/lib/whenIdleOrHidden.js +0 -24
  146. package/build/cjs/metrics/web-vitals/lib/whenIdleOrHidden.js.map +0 -1
  147. package/build/cjs/metrics/web-vitals/onFCP.js +0 -37
  148. package/build/cjs/metrics/web-vitals/onFCP.js.map +0 -1
  149. package/build/cjs/metrics/web-vitals/onTTFB.js +0 -35
  150. package/build/cjs/metrics/web-vitals/onTTFB.js.map +0 -1
  151. package/build/cjs/metrics/webVitalSpans.js.map +0 -1
  152. package/build/esm/instrument/dom.js.map +0 -1
  153. package/build/esm/instrument/history.js.map +0 -1
  154. package/build/esm/instrument/location.js.map +0 -1
  155. package/build/esm/instrument/xhr.js.map +0 -1
  156. package/build/esm/metrics/browserMetrics.js.map +0 -1
  157. package/build/esm/metrics/cls.js +0 -61
  158. package/build/esm/metrics/cls.js.map +0 -1
  159. package/build/esm/metrics/elementTiming.js.map +0 -1
  160. package/build/esm/metrics/inp.js.map +0 -1
  161. package/build/esm/metrics/instrument.js.map +0 -1
  162. package/build/esm/metrics/lcp.js +0 -72
  163. package/build/esm/metrics/lcp.js.map +0 -1
  164. package/build/esm/metrics/resourceTiming.js.map +0 -1
  165. package/build/esm/metrics/utils.js +0 -128
  166. package/build/esm/metrics/utils.js.map +0 -1
  167. package/build/esm/metrics/web-vitals/getCLS.js +0 -43
  168. package/build/esm/metrics/web-vitals/getCLS.js.map +0 -1
  169. package/build/esm/metrics/web-vitals/getINP.js +0 -57
  170. package/build/esm/metrics/web-vitals/getINP.js.map +0 -1
  171. package/build/esm/metrics/web-vitals/getLCP.js +0 -59
  172. package/build/esm/metrics/web-vitals/getLCP.js.map +0 -1
  173. package/build/esm/metrics/web-vitals/lib/InteractionManager.js +0 -85
  174. package/build/esm/metrics/web-vitals/lib/InteractionManager.js.map +0 -1
  175. package/build/esm/metrics/web-vitals/lib/LCPEntryManager.js +0 -9
  176. package/build/esm/metrics/web-vitals/lib/LCPEntryManager.js.map +0 -1
  177. package/build/esm/metrics/web-vitals/lib/LayoutShiftManager.js +0 -25
  178. package/build/esm/metrics/web-vitals/lib/LayoutShiftManager.js.map +0 -1
  179. package/build/esm/metrics/web-vitals/lib/bindReporter.js +0 -29
  180. package/build/esm/metrics/web-vitals/lib/bindReporter.js.map +0 -1
  181. package/build/esm/metrics/web-vitals/lib/generateUniqueID.js +0 -6
  182. package/build/esm/metrics/web-vitals/lib/generateUniqueID.js.map +0 -1
  183. package/build/esm/metrics/web-vitals/lib/getActivationStart.js +0 -9
  184. package/build/esm/metrics/web-vitals/lib/getActivationStart.js.map +0 -1
  185. package/build/esm/metrics/web-vitals/lib/getNavigationEntry.js +0 -15
  186. package/build/esm/metrics/web-vitals/lib/getNavigationEntry.js.map +0 -1
  187. package/build/esm/metrics/web-vitals/lib/getVisibilityWatcher.js +0 -46
  188. package/build/esm/metrics/web-vitals/lib/getVisibilityWatcher.js.map +0 -1
  189. package/build/esm/metrics/web-vitals/lib/globalListeners.js +0 -15
  190. package/build/esm/metrics/web-vitals/lib/globalListeners.js.map +0 -1
  191. package/build/esm/metrics/web-vitals/lib/initMetric.js +0 -32
  192. package/build/esm/metrics/web-vitals/lib/initMetric.js.map +0 -1
  193. package/build/esm/metrics/web-vitals/lib/initUnique.js +0 -14
  194. package/build/esm/metrics/web-vitals/lib/initUnique.js.map +0 -1
  195. package/build/esm/metrics/web-vitals/lib/observe.js +0 -18
  196. package/build/esm/metrics/web-vitals/lib/observe.js.map +0 -1
  197. package/build/esm/metrics/web-vitals/lib/onHidden.js +0 -15
  198. package/build/esm/metrics/web-vitals/lib/onHidden.js.map +0 -1
  199. package/build/esm/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js +0 -29
  200. package/build/esm/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js.map +0 -1
  201. package/build/esm/metrics/web-vitals/lib/runOnce.js +0 -12
  202. package/build/esm/metrics/web-vitals/lib/runOnce.js.map +0 -1
  203. package/build/esm/metrics/web-vitals/lib/whenActivated.js +0 -12
  204. package/build/esm/metrics/web-vitals/lib/whenActivated.js.map +0 -1
  205. package/build/esm/metrics/web-vitals/lib/whenIdleOrHidden.js +0 -22
  206. package/build/esm/metrics/web-vitals/lib/whenIdleOrHidden.js.map +0 -1
  207. package/build/esm/metrics/web-vitals/onFCP.js +0 -34
  208. package/build/esm/metrics/web-vitals/onFCP.js.map +0 -1
  209. package/build/esm/metrics/web-vitals/onTTFB.js +0 -32
  210. package/build/esm/metrics/web-vitals/onTTFB.js.map +0 -1
  211. package/build/esm/metrics/webVitalSpans.js.map +0 -1
  212. package/build/types/instrument/dom.d.ts.map +0 -1
  213. package/build/types/instrument/history.d.ts.map +0 -1
  214. package/build/types/instrument/location.d.ts.map +0 -1
  215. package/build/types/instrument/xhr.d.ts.map +0 -1
  216. package/build/types/metrics/browserMetrics.d.ts +0 -116
  217. package/build/types/metrics/browserMetrics.d.ts.map +0 -1
  218. package/build/types/metrics/cls.d.ts +0 -17
  219. package/build/types/metrics/cls.d.ts.map +0 -1
  220. package/build/types/metrics/elementTiming.d.ts.map +0 -1
  221. package/build/types/metrics/inp.d.ts.map +0 -1
  222. package/build/types/metrics/instrument.d.ts.map +0 -1
  223. package/build/types/metrics/lcp.d.ts +0 -22
  224. package/build/types/metrics/lcp.d.ts.map +0 -1
  225. package/build/types/metrics/resourceTiming.d.ts.map +0 -1
  226. package/build/types/metrics/utils.d.ts +0 -73
  227. package/build/types/metrics/utils.d.ts.map +0 -1
  228. package/build/types/metrics/web-vitals/getCLS.d.ts +0 -26
  229. package/build/types/metrics/web-vitals/getCLS.d.ts.map +0 -1
  230. package/build/types/metrics/web-vitals/getINP.d.ts +0 -34
  231. package/build/types/metrics/web-vitals/getINP.d.ts.map +0 -1
  232. package/build/types/metrics/web-vitals/getLCP.d.ts +0 -16
  233. package/build/types/metrics/web-vitals/getLCP.d.ts.map +0 -1
  234. package/build/types/metrics/web-vitals/lib/InteractionManager.d.ts +0 -37
  235. package/build/types/metrics/web-vitals/lib/InteractionManager.d.ts.map +0 -1
  236. package/build/types/metrics/web-vitals/lib/LCPEntryManager.d.ts +0 -5
  237. package/build/types/metrics/web-vitals/lib/LCPEntryManager.d.ts.map +0 -1
  238. package/build/types/metrics/web-vitals/lib/LayoutShiftManager.d.ts +0 -7
  239. package/build/types/metrics/web-vitals/lib/LayoutShiftManager.d.ts.map +0 -1
  240. package/build/types/metrics/web-vitals/lib/bindReporter.d.ts +0 -7
  241. package/build/types/metrics/web-vitals/lib/bindReporter.d.ts.map +0 -1
  242. package/build/types/metrics/web-vitals/lib/generateUniqueID.d.ts +0 -7
  243. package/build/types/metrics/web-vitals/lib/generateUniqueID.d.ts.map +0 -1
  244. package/build/types/metrics/web-vitals/lib/getActivationStart.d.ts +0 -2
  245. package/build/types/metrics/web-vitals/lib/getActivationStart.d.ts.map +0 -1
  246. package/build/types/metrics/web-vitals/lib/getNavigationEntry.d.ts +0 -2
  247. package/build/types/metrics/web-vitals/lib/getNavigationEntry.d.ts.map +0 -1
  248. package/build/types/metrics/web-vitals/lib/getVisibilityWatcher.d.ts +0 -5
  249. package/build/types/metrics/web-vitals/lib/getVisibilityWatcher.d.ts.map +0 -1
  250. package/build/types/metrics/web-vitals/lib/globalListeners.d.ts.map +0 -1
  251. package/build/types/metrics/web-vitals/lib/initMetric.d.ts +0 -21
  252. package/build/types/metrics/web-vitals/lib/initMetric.d.ts.map +0 -1
  253. package/build/types/metrics/web-vitals/lib/initUnique.d.ts +0 -7
  254. package/build/types/metrics/web-vitals/lib/initUnique.d.ts.map +0 -1
  255. package/build/types/metrics/web-vitals/lib/observe.d.ts +0 -23
  256. package/build/types/metrics/web-vitals/lib/observe.d.ts.map +0 -1
  257. package/build/types/metrics/web-vitals/lib/onHidden.d.ts +0 -27
  258. package/build/types/metrics/web-vitals/lib/onHidden.d.ts.map +0 -1
  259. package/build/types/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.d.ts +0 -15
  260. package/build/types/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.d.ts.map +0 -1
  261. package/build/types/metrics/web-vitals/lib/runOnce.d.ts +0 -2
  262. package/build/types/metrics/web-vitals/lib/runOnce.d.ts.map +0 -1
  263. package/build/types/metrics/web-vitals/lib/whenActivated.d.ts +0 -2
  264. package/build/types/metrics/web-vitals/lib/whenActivated.d.ts.map +0 -1
  265. package/build/types/metrics/web-vitals/lib/whenIdleOrHidden.d.ts +0 -6
  266. package/build/types/metrics/web-vitals/lib/whenIdleOrHidden.d.ts.map +0 -1
  267. package/build/types/metrics/web-vitals/onFCP.d.ts +0 -11
  268. package/build/types/metrics/web-vitals/onFCP.d.ts.map +0 -1
  269. package/build/types/metrics/web-vitals/onTTFB.d.ts +0 -20
  270. package/build/types/metrics/web-vitals/onTTFB.d.ts.map +0 -1
  271. package/build/types/metrics/web-vitals/types/base.d.ts +0 -103
  272. package/build/types/metrics/web-vitals/types/base.d.ts.map +0 -1
  273. package/build/types/metrics/web-vitals/types/cls.d.ts +0 -58
  274. package/build/types/metrics/web-vitals/types/cls.d.ts.map +0 -1
  275. package/build/types/metrics/web-vitals/types/fcp.d.ts +0 -47
  276. package/build/types/metrics/web-vitals/types/fcp.d.ts.map +0 -1
  277. package/build/types/metrics/web-vitals/types/inp.d.ts +0 -150
  278. package/build/types/metrics/web-vitals/types/inp.d.ts.map +0 -1
  279. package/build/types/metrics/web-vitals/types/lcp.d.ts +0 -74
  280. package/build/types/metrics/web-vitals/types/lcp.d.ts.map +0 -1
  281. package/build/types/metrics/web-vitals/types/ttfb.d.ts +0 -60
  282. package/build/types/metrics/web-vitals/types/ttfb.d.ts.map +0 -1
  283. package/build/types/metrics/web-vitals/types.d.ts +0 -78
  284. package/build/types/metrics/web-vitals/types.d.ts.map +0 -1
  285. package/build/types/metrics/webVitalSpans.d.ts.map +0 -1
  286. package/build/types-ts3.8/debug-build.d.ts +0 -7
  287. package/build/types-ts3.8/getNativeImplementation.d.ts +0 -69
  288. package/build/types-ts3.8/htmlTreeAsString.d.ts +0 -11
  289. package/build/types-ts3.8/index.d.ts +0 -17
  290. package/build/types-ts3.8/instrument/dom.d.ts +0 -11
  291. package/build/types-ts3.8/instrument/history.d.ts +0 -15
  292. package/build/types-ts3.8/instrument/location.d.ts +0 -13
  293. package/build/types-ts3.8/instrument/xhr.d.ts +0 -14
  294. package/build/types-ts3.8/is.d.ts +0 -7
  295. package/build/types-ts3.8/metrics/browserMetrics.d.ts +0 -119
  296. package/build/types-ts3.8/metrics/cls.d.ts +0 -17
  297. package/build/types-ts3.8/metrics/elementTiming.d.ts +0 -21
  298. package/build/types-ts3.8/metrics/inp.d.ts +0 -35
  299. package/build/types-ts3.8/metrics/instrument.d.ts +0 -121
  300. package/build/types-ts3.8/metrics/lcp.d.ts +0 -22
  301. package/build/types-ts3.8/metrics/resourceTiming.d.ts +0 -13
  302. package/build/types-ts3.8/metrics/utils.d.ts +0 -73
  303. package/build/types-ts3.8/metrics/web-vitals/getCLS.d.ts +0 -26
  304. package/build/types-ts3.8/metrics/web-vitals/getINP.d.ts +0 -34
  305. package/build/types-ts3.8/metrics/web-vitals/getLCP.d.ts +0 -16
  306. package/build/types-ts3.8/metrics/web-vitals/lib/InteractionManager.d.ts +0 -37
  307. package/build/types-ts3.8/metrics/web-vitals/lib/LCPEntryManager.d.ts +0 -5
  308. package/build/types-ts3.8/metrics/web-vitals/lib/LayoutShiftManager.d.ts +0 -7
  309. package/build/types-ts3.8/metrics/web-vitals/lib/bindReporter.d.ts +0 -7
  310. package/build/types-ts3.8/metrics/web-vitals/lib/generateUniqueID.d.ts +0 -7
  311. package/build/types-ts3.8/metrics/web-vitals/lib/getActivationStart.d.ts +0 -2
  312. package/build/types-ts3.8/metrics/web-vitals/lib/getNavigationEntry.d.ts +0 -2
  313. package/build/types-ts3.8/metrics/web-vitals/lib/getVisibilityWatcher.d.ts +0 -5
  314. package/build/types-ts3.8/metrics/web-vitals/lib/globalListeners.d.ts +0 -11
  315. package/build/types-ts3.8/metrics/web-vitals/lib/initMetric.d.ts +0 -21
  316. package/build/types-ts3.8/metrics/web-vitals/lib/initUnique.d.ts +0 -7
  317. package/build/types-ts3.8/metrics/web-vitals/lib/observe.d.ts +0 -23
  318. package/build/types-ts3.8/metrics/web-vitals/lib/onHidden.d.ts +0 -27
  319. package/build/types-ts3.8/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.d.ts +0 -15
  320. package/build/types-ts3.8/metrics/web-vitals/lib/runOnce.d.ts +0 -2
  321. package/build/types-ts3.8/metrics/web-vitals/lib/whenActivated.d.ts +0 -2
  322. package/build/types-ts3.8/metrics/web-vitals/lib/whenIdleOrHidden.d.ts +0 -6
  323. package/build/types-ts3.8/metrics/web-vitals/onFCP.d.ts +0 -11
  324. package/build/types-ts3.8/metrics/web-vitals/onTTFB.d.ts +0 -20
  325. package/build/types-ts3.8/metrics/web-vitals/types/base.d.ts +0 -106
  326. package/build/types-ts3.8/metrics/web-vitals/types/cls.d.ts +0 -58
  327. package/build/types-ts3.8/metrics/web-vitals/types/fcp.d.ts +0 -47
  328. package/build/types-ts3.8/metrics/web-vitals/types/inp.d.ts +0 -150
  329. package/build/types-ts3.8/metrics/web-vitals/types/lcp.d.ts +0 -74
  330. package/build/types-ts3.8/metrics/web-vitals/types/ttfb.d.ts +0 -60
  331. package/build/types-ts3.8/metrics/web-vitals/types.d.ts +0 -78
  332. package/build/types-ts3.8/metrics/webVitalSpans.d.ts +0 -65
  333. package/build/types-ts3.8/networkUtils.d.ts +0 -28
  334. package/build/types-ts3.8/types.d.ts +0 -15
  335. /package/build/cjs/{instrument → instrumentation}/dom.js +0 -0
  336. /package/build/cjs/{instrument → instrumentation}/history.js +0 -0
  337. /package/build/cjs/{instrument → instrumentation}/location.js +0 -0
  338. /package/build/cjs/{instrument → instrumentation}/xhr.js +0 -0
  339. /package/build/cjs/{metrics → performance}/resourceTiming.js +0 -0
  340. /package/build/esm/{instrument → instrumentation}/dom.js +0 -0
  341. /package/build/esm/{instrument → instrumentation}/history.js +0 -0
  342. /package/build/esm/{instrument → instrumentation}/location.js +0 -0
  343. /package/build/esm/{instrument → instrumentation}/xhr.js +0 -0
  344. /package/build/esm/{metrics → performance}/resourceTiming.js +0 -0
  345. /package/build/types/{instrument → instrumentation}/dom.d.ts +0 -0
  346. /package/build/types/{instrument → instrumentation}/history.d.ts +0 -0
  347. /package/build/types/{instrument → instrumentation}/location.d.ts +0 -0
  348. /package/build/types/{instrument → instrumentation}/xhr.d.ts +0 -0
  349. /package/build/types/{metrics → performance}/elementTiming.d.ts +0 -0
  350. /package/build/types/{metrics → performance}/resourceTiming.d.ts +0 -0
@@ -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":["getBrowserPerformanceAPI","browserPerformanceTimeOrigin","addClsInstrumentationHandler","addLcpInstrumentationHandler","isValidLcpMetric","addTtfbInstrumentationHandler","addPerformanceInstrumentationHandler","getVisibilityWatcher","msToSec","spanToJSON","SENTRY_OP","DEBUG_BUILD","debug","setMeasurement","getActivationStart","htmlTreeAsString","_measurements","getNavigationEntry"],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const types = require('../types.js');
4
+
5
+ function addPageListener(type, listener, options) {
6
+ if (types.WINDOW.document) {
7
+ types.WINDOW.addEventListener(type, listener, options);
8
+ }
9
+ }
10
+ function removePageListener(type, listener, options) {
11
+ if (types.WINDOW.document) {
12
+ types.WINDOW.removeEventListener(type, listener, options);
13
+ }
14
+ }
15
+ const getNavigationEntry = (checkResponseStart = true) => {
16
+ const navigationEntry = types.WINDOW.performance?.getEntriesByType?.("navigation")[0];
17
+ if (
18
+ // sentry-specific change:
19
+ // We don't want to check for responseStart for our own use of `getNavigationEntry`
20
+ !checkResponseStart || navigationEntry && navigationEntry.responseStart > 0 && navigationEntry.responseStart < performance.now()
21
+ ) {
22
+ return navigationEntry;
23
+ }
24
+ };
25
+ const getActivationStart = () => {
26
+ const navEntry = getNavigationEntry();
27
+ return navEntry?.activationStart ?? 0;
28
+ };
29
+ const onHidden = (cb) => {
30
+ const onHiddenCallback = (event) => {
31
+ if (types.WINDOW.document?.visibilityState === "hidden") {
32
+ cb(event);
33
+ }
34
+ };
35
+ addPageListener("visibilitychange", onHiddenCallback, { capture: true });
36
+ };
37
+ let firstHiddenTime = -1;
38
+ const onHiddenFunctions = /* @__PURE__ */ new Set();
39
+ const initHiddenTime = () => {
40
+ return types.WINDOW.document?.visibilityState === "hidden" && !types.WINDOW.document?.prerendering ? 0 : Infinity;
41
+ };
42
+ const onVisibilityUpdate = (event) => {
43
+ if (types.WINDOW.document?.visibilityState === "hidden" && firstHiddenTime > -1) {
44
+ if (event.type === "visibilitychange") {
45
+ for (const onHiddenFunction of onHiddenFunctions) {
46
+ onHiddenFunction();
47
+ }
48
+ }
49
+ if (!isFinite(firstHiddenTime)) {
50
+ firstHiddenTime = event.type === "visibilitychange" ? event.timeStamp : 0;
51
+ removePageListener("prerenderingchange", onVisibilityUpdate, true);
52
+ }
53
+ }
54
+ };
55
+ const getVisibilityWatcher = () => {
56
+ if (types.WINDOW.document && firstHiddenTime < 0) {
57
+ const activationStart = getActivationStart();
58
+ const firstVisibilityStateHiddenTime = !types.WINDOW.document.prerendering ? globalThis.performance.getEntriesByType("visibility-state").filter((e) => e.name === "hidden" && e.startTime > activationStart)[0]?.startTime : void 0;
59
+ firstHiddenTime = firstVisibilityStateHiddenTime ?? initHiddenTime();
60
+ addPageListener("visibilitychange", onVisibilityUpdate, true);
61
+ addPageListener("prerenderingchange", onVisibilityUpdate, true);
62
+ }
63
+ return {
64
+ get firstHiddenTime() {
65
+ return firstHiddenTime;
66
+ },
67
+ onHidden(cb) {
68
+ onHiddenFunctions.add(cb);
69
+ }
70
+ };
71
+ };
72
+ const whenIdleOrHidden = (cb) => {
73
+ const rIC = types.WINDOW.requestIdleCallback || types.WINDOW.setTimeout;
74
+ if (types.WINDOW.document?.visibilityState === "hidden") {
75
+ cb();
76
+ } else {
77
+ let called = false;
78
+ const runOnce = () => {
79
+ if (!called) {
80
+ cb();
81
+ called = true;
82
+ }
83
+ };
84
+ addPageListener("visibilitychange", runOnce, { once: true, capture: true });
85
+ rIC(() => {
86
+ runOnce();
87
+ removePageListener("visibilitychange", runOnce, { capture: true });
88
+ });
89
+ }
90
+ };
91
+
92
+ exports.addPageListener = addPageListener;
93
+ exports.getActivationStart = getActivationStart;
94
+ exports.getNavigationEntry = getNavigationEntry;
95
+ exports.getVisibilityWatcher = getVisibilityWatcher;
96
+ exports.onHidden = onHidden;
97
+ exports.removePageListener = removePageListener;
98
+ exports.whenIdleOrHidden = whenIdleOrHidden;
99
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sources":["../../../src/web-vitals/utils.ts"],"sourcesContent":["/*\n * Portions of this file are derived from Google's web-vitals library.\n *\n * Copyright 2020-2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { WINDOW } from '../types';\n\n/**\n * web-vitals 5.1.0 switched listeners to be added on the window rather than the document.\n * Instead of having to check for window/document every time we add a listener, we can use this function.\n */\nexport function addPageListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions) {\n if (WINDOW.document) {\n WINDOW.addEventListener(type, listener, options);\n }\n}\n\n/**\n * web-vitals 5.1.0 switched listeners to be removed from the window rather than the document.\n * Instead of having to check for window/document every time we remove a listener, we can use this function.\n */\nexport function removePageListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions) {\n if (WINDOW.document) {\n WINDOW.removeEventListener(type, listener, options);\n }\n}\n\n// sentry-specific change:\n// add optional param to not check for responseStart (see comment below)\nexport const getNavigationEntry = (checkResponseStart = true): PerformanceNavigationTiming | void => {\n const navigationEntry = WINDOW.performance?.getEntriesByType?.('navigation')[0];\n // Check to ensure the `responseStart` property is present and valid.\n // In some cases a zero value is reported by the browser (for\n // privacy/security reasons), and in other cases (bugs) the value is\n // negative or is larger than the current page time. Ignore these cases:\n // - https://github.com/GoogleChrome/web-vitals/issues/137\n // - https://github.com/GoogleChrome/web-vitals/issues/162\n // - https://github.com/GoogleChrome/web-vitals/issues/275\n if (\n // sentry-specific change:\n // We don't want to check for responseStart for our own use of `getNavigationEntry`\n !checkResponseStart ||\n (navigationEntry && navigationEntry.responseStart > 0 && navigationEntry.responseStart < performance.now())\n ) {\n return navigationEntry;\n }\n};\n\nexport const getActivationStart = (): number => {\n const navEntry = getNavigationEntry();\n return navEntry?.activationStart ?? 0;\n};\n\nexport interface OnHiddenCallback {\n (event: Event): void;\n}\n\nexport const onHidden = (cb: OnHiddenCallback) => {\n const onHiddenCallback = (event: Event) => {\n if (WINDOW.document?.visibilityState === 'hidden') {\n cb(event);\n }\n };\n\n addPageListener('visibilitychange', onHiddenCallback, { capture: true });\n};\n\nlet firstHiddenTime = -1;\nconst onHiddenFunctions: Set<() => void> = new Set();\n\nconst initHiddenTime = () => {\n // If the document is hidden when this code runs, assume it was always\n // hidden and the page was loaded in the background, with the one exception\n // that visibility state is always 'hidden' during prerendering, so we have\n // to ignore that case until prerendering finishes (see: `prerenderingchange`\n // event logic below).\n return WINDOW.document?.visibilityState === 'hidden' && !WINDOW.document?.prerendering ? 0 : Infinity;\n};\n\nconst onVisibilityUpdate = (event: Event) => {\n // Handle changes to hidden state\n if (WINDOW.document?.visibilityState === 'hidden' && firstHiddenTime > -1) {\n // Call onHidden callbacks when the page becomes hidden\n if (event.type === 'visibilitychange') {\n for (const onHiddenFunction of onHiddenFunctions) {\n onHiddenFunction();\n }\n }\n\n // If the document is 'hidden' and no previous hidden timestamp has been\n // set (so is infinity), update it based on the current event data.\n if (!isFinite(firstHiddenTime)) {\n // If the event is a 'visibilitychange' event, it means the page was\n // visible prior to this change, so the event timestamp is the first\n // hidden time.\n // However, if the event is not a 'visibilitychange' event, then it must\n // be a 'prerenderingchange' event, and the fact that the document is\n // still 'hidden' from the above check means the tab was activated\n // in a background state and so has always been hidden.\n firstHiddenTime = event.type === 'visibilitychange' ? event.timeStamp : 0;\n\n // We no longer need the `prerenderingchange` event listener now we've\n // set an initial init time so remove that\n // (we'll keep the visibilitychange one for onHiddenFunction above)\n removePageListener('prerenderingchange', onVisibilityUpdate, true);\n }\n }\n};\n\nexport const getVisibilityWatcher = () => {\n if (WINDOW.document && firstHiddenTime < 0) {\n // Check if we have a previous hidden `visibility-state` performance entry.\n const activationStart = getActivationStart();\n const firstVisibilityStateHiddenTime = !WINDOW.document.prerendering\n ? globalThis.performance\n .getEntriesByType('visibility-state')\n .filter(e => e.name === 'hidden' && e.startTime > activationStart)[0]?.startTime\n : undefined;\n\n // Prefer that, but if it's not available and the document is hidden when\n // this code runs, assume it was hidden since navigation start. This isn't\n // a perfect heuristic, but it's the best we can do until the\n // `visibility-state` performance entry becomes available in all browsers.\n firstHiddenTime = firstVisibilityStateHiddenTime ?? initHiddenTime();\n // Listen for visibility changes so we can handle things like bfcache\n // restores and/or prerender without having to examine individual\n // timestamps in detail and also for onHidden function calls.\n addPageListener('visibilitychange', onVisibilityUpdate, true);\n\n // IMPORTANT: when a page is prerendering, its `visibilityState` is\n // 'hidden', so in order to account for cases where this module checks for\n // visibility during prerendering, an additional check after prerendering\n // completes is also required.\n addPageListener('prerenderingchange', onVisibilityUpdate, true);\n }\n\n return {\n get firstHiddenTime() {\n return firstHiddenTime;\n },\n onHidden(cb: () => void) {\n onHiddenFunctions.add(cb);\n },\n };\n};\n\n/**\n * Runs the passed callback during the next idle period, or immediately\n * if the browser's visibility state is (or becomes) hidden.\n */\nexport const whenIdleOrHidden = (cb: () => void) => {\n const rIC = WINDOW.requestIdleCallback || WINDOW.setTimeout;\n\n // If the document is hidden, run the callback immediately, otherwise\n // race an idle callback with the next `visibilitychange` event.\n if (WINDOW.document?.visibilityState === 'hidden') {\n cb();\n } else {\n // Ensure the callback only runs once, whichever of the two racers wins.\n let called = false;\n const runOnce = () => {\n if (!called) {\n cb();\n called = true;\n }\n };\n addPageListener('visibilitychange', runOnce, { once: true, capture: true });\n rIC(() => {\n runOnce();\n // Remove the above event listener since no longer required.\n // See: https://github.com/GoogleChrome/web-vitals/issues/622\n removePageListener('visibilitychange', runOnce, { capture: true });\n });\n }\n};\n"],"names":["WINDOW"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"htmlTreeAsString.js","sources":["../../src/htmlTreeAsString.ts"],"sourcesContent":["import { isString } from '@sentry/core';\n\nconst DEFAULT_MAX_STRING_LENGTH = 80;\n\ntype SimpleNode = {\n parentNode: SimpleNode;\n} | null;\n\n// Native DOM accessors cached at module load. Calling these instead of reading\n// instance properties bypasses user-defined getters that shadow the prototypes.\n// Stored unbound and rebound via .call(el) — the unbound-method lint is expected.\n// See https://github.com/getsentry/sentry-javascript/issues/21353\ntype AccessorKey = 'parentNode' | 'tagName' | 'id' | 'className' | 'getAttribute' | 'dataset';\nconst accessors: Partial<Record<AccessorKey, Function>> = {};\n\n// oxlint-disable typescript-eslint(unbound-method)\ntry {\n if (typeof Node !== 'undefined') {\n accessors.parentNode = Object.getOwnPropertyDescriptor(Node.prototype, 'parentNode')!.get!;\n }\n if (typeof Element !== 'undefined') {\n accessors.tagName = Object.getOwnPropertyDescriptor(Element.prototype, 'tagName')!.get!;\n accessors.id = Object.getOwnPropertyDescriptor(Element.prototype, 'id')!.get!;\n accessors.className = Object.getOwnPropertyDescriptor(Element.prototype, 'className')!.get!;\n accessors.getAttribute = Element.prototype.getAttribute;\n }\n if (typeof HTMLElement !== 'undefined') {\n accessors.dataset = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'dataset')!.get!;\n }\n} catch {\n // Polyfilled or stubbed prototypes may not have the expected descriptors.\n // _safeRead falls back to direct property access.\n}\n// oxlint-enable typescript-eslint(unbound-method)\n\nfunction _safeRead<T>(el: unknown, prop: AccessorKey, arg?: string): T {\n const fn = accessors[prop];\n if (fn) {\n try {\n return fn.call(el, arg) as T;\n } catch {\n // Fall through to direct access\n }\n }\n const val = (el as Record<string, unknown>)[prop];\n return typeof val === 'function' ? val.call(el, arg) : (val as T);\n}\n\n/**\n * Given a child DOM element, returns a query-selector statement describing that\n * and its ancestors\n * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]\n * @returns generated DOM path\n */\nexport function htmlTreeAsString(\n elem: unknown,\n options: string[] | { keyAttrs?: string[]; maxStringLength?: number } = {},\n): string {\n if (!elem) {\n return '<unknown>';\n }\n\n // try/catch both:\n // - accessing event.target (see getsentry/raven-js#838, #768)\n // - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly\n // - can throw an exception in some circumstances.\n try {\n let currentElem = elem as SimpleNode;\n const MAX_TRAVERSE_HEIGHT = 5;\n const out = [];\n let height = 0;\n let len = 0;\n const separator = ' > ';\n const sepLength = separator.length;\n let nextStr;\n const keyAttrs = Array.isArray(options) ? options : options.keyAttrs;\n const maxStringLength = (!Array.isArray(options) && options.maxStringLength) || DEFAULT_MAX_STRING_LENGTH;\n\n while (currentElem && height++ < MAX_TRAVERSE_HEIGHT) {\n nextStr = _htmlElementAsString(currentElem, keyAttrs);\n // bail out if\n // - nextStr is the 'html' element\n // - the length of the string that would be created exceeds maxStringLength\n // (ignore this limit if we are on the first iteration)\n if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= maxStringLength)) {\n break;\n }\n\n out.push(nextStr);\n\n len += nextStr.length;\n currentElem = _safeRead<SimpleNode>(currentElem, 'parentNode');\n }\n\n return out.reverse().join(separator);\n } catch {\n return '<unknown>';\n }\n}\n\n/**\n * Returns a simple, query-selector representation of a DOM element\n * e.g. [HTMLElement] => input#foo.btn[name=baz]\n * @returns generated DOM path\n */\nfunction _htmlElementAsString(el: unknown, keyAttrs?: string[]): string {\n const out = [];\n\n const tagName = _safeRead<string | undefined>(el, 'tagName');\n if (!tagName) {\n return '';\n }\n\n if (typeof HTMLElement !== 'undefined') {\n // If using the component name annotation plugin, this value may be available on the DOM node\n if (el instanceof HTMLElement) {\n const dataset = _safeRead<DOMStringMap | undefined>(el, 'dataset');\n if (dataset) {\n if (dataset['sentryComponent']) {\n return dataset['sentryComponent'];\n }\n if (dataset['sentryElement']) {\n return dataset['sentryElement'];\n }\n }\n }\n }\n\n out.push(tagName.toLowerCase());\n\n // Pairs of attribute keys defined in `serializeAttribute` and their values on element.\n const keyAttrPairs = keyAttrs?.length\n ? keyAttrs\n .filter(keyAttr => _safeRead<string | null>(el, 'getAttribute', keyAttr))\n .map(keyAttr => [keyAttr, _safeRead<string | null>(el, 'getAttribute', keyAttr)])\n : null;\n\n if (keyAttrPairs?.length) {\n keyAttrPairs.forEach(keyAttrPair => {\n out.push(`[${keyAttrPair[0]}=\"${keyAttrPair[1]}\"]`);\n });\n } else {\n const id = _safeRead<string | undefined>(el, 'id');\n if (id) {\n out.push(`#${id}`);\n }\n\n const className = _safeRead<string | undefined>(el, 'className');\n if (className && isString(className)) {\n const classes = className.split(/\\s+/);\n for (const c of classes) {\n out.push(`.${c}`);\n }\n }\n }\n for (const k of ['aria-label', 'type', 'name', 'title', 'alt']) {\n const attr = _safeRead<string | null>(el, 'getAttribute', k);\n if (attr) {\n out.push(`[${k}=\"${attr}\"]`);\n }\n }\n\n return out.join('');\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"htmlTreeAsString.js","sources":["../../src/htmlTreeAsString.ts"],"sourcesContent":["import { isString } from '@sentry/core';\n\nconst DEFAULT_MAX_STRING_LENGTH = 80;\n\ntype SimpleNode = {\n parentNode: SimpleNode;\n} | null;\n\n// Native DOM accessors cached at module load. Calling these instead of reading\n// instance properties bypasses user-defined getters that shadow the prototypes.\n// Stored unbound and rebound via .call(el) — the unbound-method lint is expected.\n// See https://github.com/getsentry/sentry-javascript/issues/21353\ntype AccessorKey = 'parentNode' | 'tagName' | 'id' | 'className' | 'getAttribute' | 'dataset';\nconst accessors: Partial<Record<AccessorKey, Function>> = {};\n\n// oxlint-disable typescript/unbound-method\ntry {\n if (typeof Node !== 'undefined') {\n accessors.parentNode = Object.getOwnPropertyDescriptor(Node.prototype, 'parentNode')!.get!;\n }\n if (typeof Element !== 'undefined') {\n accessors.tagName = Object.getOwnPropertyDescriptor(Element.prototype, 'tagName')!.get!;\n accessors.id = Object.getOwnPropertyDescriptor(Element.prototype, 'id')!.get!;\n accessors.className = Object.getOwnPropertyDescriptor(Element.prototype, 'className')!.get!;\n accessors.getAttribute = Element.prototype.getAttribute;\n }\n if (typeof HTMLElement !== 'undefined') {\n accessors.dataset = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'dataset')!.get!;\n }\n} catch {\n // Polyfilled or stubbed prototypes may not have the expected descriptors.\n // _safeRead falls back to direct property access.\n}\n// oxlint-enable typescript/unbound-method\n\nfunction _safeRead<T>(el: unknown, prop: AccessorKey, arg?: string): T {\n const fn = accessors[prop];\n if (fn) {\n try {\n return fn.call(el, arg) as T;\n } catch {\n // Fall through to direct access\n }\n }\n const val = (el as Record<string, unknown>)[prop];\n return typeof val === 'function' ? val.call(el, arg) : (val as T);\n}\n\n/**\n * Given a child DOM element, returns a query-selector statement describing that\n * and its ancestors\n * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]\n * @returns generated DOM path\n */\nexport function htmlTreeAsString(\n elem: unknown,\n options: string[] | { keyAttrs?: string[]; maxStringLength?: number } = {},\n): string {\n if (!elem) {\n return '<unknown>';\n }\n\n // try/catch both:\n // - accessing event.target (see getsentry/raven-js#838, #768)\n // - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly\n // - can throw an exception in some circumstances.\n try {\n let currentElem = elem as SimpleNode;\n const MAX_TRAVERSE_HEIGHT = 5;\n const out = [];\n let height = 0;\n let len = 0;\n const separator = ' > ';\n const sepLength = separator.length;\n let nextStr;\n const keyAttrs = Array.isArray(options) ? options : options.keyAttrs;\n const maxStringLength = (!Array.isArray(options) && options.maxStringLength) || DEFAULT_MAX_STRING_LENGTH;\n\n while (currentElem && height++ < MAX_TRAVERSE_HEIGHT) {\n nextStr = _htmlElementAsString(currentElem, keyAttrs);\n // bail out if\n // - nextStr is the 'html' element\n // - the length of the string that would be created exceeds maxStringLength\n // (ignore this limit if we are on the first iteration)\n if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= maxStringLength)) {\n break;\n }\n\n out.push(nextStr);\n\n len += nextStr.length;\n currentElem = _safeRead<SimpleNode>(currentElem, 'parentNode');\n }\n\n return out.reverse().join(separator);\n } catch {\n return '<unknown>';\n }\n}\n\n/**\n * Returns a simple, query-selector representation of a DOM element\n * e.g. [HTMLElement] => input#foo.btn[name=baz]\n * @returns generated DOM path\n */\nfunction _htmlElementAsString(el: unknown, keyAttrs?: string[]): string {\n const out = [];\n\n const tagName = _safeRead<string | undefined>(el, 'tagName');\n if (!tagName) {\n return '';\n }\n\n if (typeof HTMLElement !== 'undefined') {\n // If using the component name annotation plugin, this value may be available on the DOM node\n if (el instanceof HTMLElement) {\n const dataset = _safeRead<DOMStringMap | undefined>(el, 'dataset');\n if (dataset) {\n if (dataset['sentryComponent']) {\n return dataset['sentryComponent'];\n }\n if (dataset['sentryElement']) {\n return dataset['sentryElement'];\n }\n }\n }\n }\n\n out.push(tagName.toLowerCase());\n\n // Pairs of attribute keys defined in `serializeAttribute` and their values on element.\n const keyAttrPairs = keyAttrs?.length\n ? keyAttrs\n .filter(keyAttr => _safeRead<string | null>(el, 'getAttribute', keyAttr))\n .map(keyAttr => [keyAttr, _safeRead<string | null>(el, 'getAttribute', keyAttr)])\n : null;\n\n if (keyAttrPairs?.length) {\n keyAttrPairs.forEach(keyAttrPair => {\n out.push(`[${keyAttrPair[0]}=\"${keyAttrPair[1]}\"]`);\n });\n } else {\n const id = _safeRead<string | undefined>(el, 'id');\n if (id) {\n out.push(`#${id}`);\n }\n\n const className = _safeRead<string | undefined>(el, 'className');\n if (className && isString(className)) {\n const classes = className.split(/\\s+/);\n for (const c of classes) {\n out.push(`.${c}`);\n }\n }\n }\n for (const k of ['aria-label', 'type', 'name', 'title', 'alt']) {\n const attr = _safeRead<string | null>(el, 'getAttribute', k);\n if (attr) {\n out.push(`[${k}=\"${attr}\"]`);\n }\n }\n\n return out.join('');\n}\n"],"names":[],"mappings":"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"}
@@ -1,17 +1,19 @@
1
- export { addClsInstrumentationHandler, addInpInstrumentationHandler, addLcpInstrumentationHandler, addPerformanceInstrumentationHandler, addTtfbInstrumentationHandler } from './metrics/instrument.js';
2
- export { addPerformanceEntries, addWebVitalsToSpan, startTrackingInteractions, startTrackingLongAnimationFrames, startTrackingLongTasks, startTrackingWebVitals } from './metrics/browserMetrics.js';
3
- export { elementTimingIntegration, startTrackingElementTiming } from './metrics/elementTiming.js';
4
- export { extractNetworkProtocol } from './metrics/utils.js';
5
- export { trackClsAsSpan, trackInpAsSpan, trackLcpAsSpan } from './metrics/webVitalSpans.js';
6
- export { whenIdleOrHidden } from './metrics/web-vitals/lib/whenIdleOrHidden.js';
7
- export { addClickKeypressInstrumentationHandler } from './instrument/dom.js';
8
- export { addHistoryInstrumentationHandler } from './instrument/history.js';
1
+ export { addClsInstrumentationHandler, addInpInstrumentationHandler, addLcpInstrumentationHandler, addPerformanceInstrumentationHandler, addTtfbInstrumentationHandler } from './instrumentation/performanceObserver.js';
2
+ export { addPerformanceEntries, startTrackingInteractions, startTrackingLongAnimationFrames, startTrackingLongTasks } from './performance/entries.js';
3
+ export { addWebVitalsToSpan, startTrackingWebVitals } from './web-vitals/tracking.js';
4
+ export { elementTimingIntegration, startTrackingElementTiming } from './performance/elementTiming.js';
5
+ export { userTimingIntegration } from './performance/userTiming.js';
6
+ export { extractNetworkProtocol } from './performance/utils.js';
7
+ export { trackClsAsSpan, trackInpAsSpan, trackLcpAsSpan } from './web-vitals/spans.js';
8
+ export { whenIdleOrHidden } from './web-vitals/utils.js';
9
+ export { addClickKeypressInstrumentationHandler } from './instrumentation/dom.js';
10
+ export { addHistoryInstrumentationHandler } from './instrumentation/history.js';
9
11
  export { clearCachedImplementation, fetch, getNativeImplementation, setTimeout } from './getNativeImplementation.js';
10
- export { SENTRY_XHR_DATA_KEY, addXhrInstrumentationHandler } from './instrument/xhr.js';
12
+ export { SENTRY_XHR_DATA_KEY, addXhrInstrumentationHandler } from './instrumentation/xhr.js';
11
13
  export { getBodyString, getFetchRequestArgBody, parseXhrResponseHeaders, serializeFormData } from './networkUtils.js';
12
- export { resourceTimingToSpanAttributes } from './metrics/resourceTiming.js';
14
+ export { resourceTimingToSpanAttributes } from './performance/resourceTiming.js';
13
15
  export { htmlTreeAsString } from './htmlTreeAsString.js';
14
16
  export { isElement } from './is.js';
15
- export { getAbsoluteUrl } from './instrument/location.js';
16
- export { registerInpInteractionListener, startTrackingINP } from './metrics/inp.js';
17
+ export { getAbsoluteUrl } from './instrumentation/location.js';
18
+ export { registerInpInteractionListener } from './web-vitals/inp.js';
17
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom.js","sources":["../../../src/instrumentation/dom.ts"],"sourcesContent":["import type { HandlerDataDom } from '@sentry/core';\nimport { addHandler, addNonEnumerableProperty, fill, maybeInstrument, triggerHandlers, uuid4 } from '@sentry/core';\nimport { WINDOW } from '../types';\n\ntype SentryWrappedTarget = HTMLElement & { _sentryId?: string };\n\ntype AddEventListener = (\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n) => void;\ntype RemoveEventListener = (\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n) => void;\n\ntype InstrumentedElement = Element & {\n __sentry_instrumentation_handlers__?: {\n [key in 'click' | 'keypress']?: {\n handler?: unknown;\n /** The number of custom listeners attached to this element */\n refCount: number;\n };\n };\n};\n\nconst DEBOUNCE_DURATION = 1000;\n\nlet debounceTimerID: number | undefined;\nlet lastCapturedEventType: string | undefined;\nlet lastCapturedEventTargetId: string | undefined;\n\n/**\n * Add an instrumentation handler for when a click or a keypress happens.\n *\n * Use at your own risk, this might break without changelog notice, only used internally.\n * @hidden\n */\nexport function addClickKeypressInstrumentationHandler(handler: (data: HandlerDataDom) => void): void {\n const type = 'dom';\n addHandler(type, handler);\n maybeInstrument(type, instrumentDOM);\n}\n\n/** Exported for tests only. */\nexport function instrumentDOM(): void {\n if (!WINDOW.document) {\n return;\n }\n\n // Make it so that any click or keypress that is unhandled / bubbled up all the way to the document triggers our dom\n // handlers. (Normally we have only one, which captures a breadcrumb for each click or keypress.) Do this before\n // we instrument `addEventListener` so that we don't end up attaching this handler twice.\n const triggerDOMHandler = triggerHandlers.bind(null, 'dom');\n const globalDOMEventHandler = makeDOMEventHandler(triggerDOMHandler, true);\n WINDOW.document.addEventListener('click', globalDOMEventHandler, false);\n WINDOW.document.addEventListener('keypress', globalDOMEventHandler, false);\n\n // After hooking into click and keypress events bubbled up to `document`, we also hook into user-handled\n // clicks & keypresses, by adding an event listener of our own to any element to which they add a listener. That\n // way, whenever one of their handlers is triggered, ours will be, too. (This is needed because their handler\n // could potentially prevent the event from bubbling up to our global listeners. This way, our handler are still\n // guaranteed to fire at least once.)\n ['EventTarget', 'Node'].forEach((target: string) => {\n const globalObject = WINDOW as unknown as Record<string, { prototype?: object }>;\n const proto = globalObject[target]?.prototype;\n\n // eslint-disable-next-line no-prototype-builtins\n if (!proto?.hasOwnProperty?.('addEventListener')) {\n return;\n }\n\n fill(proto, 'addEventListener', function (originalAddEventListener: AddEventListener): AddEventListener {\n return function (this: InstrumentedElement, type, listener, options): AddEventListener {\n if (type === 'click' || type == 'keypress') {\n try {\n const handlers = (this.__sentry_instrumentation_handlers__ =\n this.__sentry_instrumentation_handlers__ || {});\n const handlerForType = (handlers[type] = handlers[type] || { refCount: 0 });\n\n if (!handlerForType.handler) {\n const handler = makeDOMEventHandler(triggerDOMHandler);\n handlerForType.handler = handler;\n originalAddEventListener.call(this, type, handler, options);\n }\n\n handlerForType.refCount++;\n } catch {\n // Accessing dom properties is always fragile.\n // Also allows us to skip `addEventListeners` calls with no proper `this` context.\n }\n }\n\n return originalAddEventListener.call(this, type, listener, options);\n };\n });\n\n fill(\n proto,\n 'removeEventListener',\n function (originalRemoveEventListener: RemoveEventListener): RemoveEventListener {\n return function (this: InstrumentedElement, type, listener, options): () => void {\n if (type === 'click' || type == 'keypress') {\n try {\n const handlers = this.__sentry_instrumentation_handlers__ || {};\n const handlerForType = handlers[type];\n\n if (handlerForType) {\n handlerForType.refCount--;\n // If there are no longer any custom handlers of the current type on this element, we can remove ours, too.\n if (handlerForType.refCount <= 0) {\n originalRemoveEventListener.call(this, type, handlerForType.handler, options);\n handlerForType.handler = undefined;\n delete handlers[type]; // eslint-disable-line @typescript-eslint/no-dynamic-delete\n }\n\n // If there are no longer any custom handlers of any type on this element, cleanup everything.\n if (Object.keys(handlers).length === 0) {\n delete this.__sentry_instrumentation_handlers__;\n }\n }\n } catch {\n // Accessing dom properties is always fragile.\n // Also allows us to skip `addEventListeners` calls with no proper `this` context.\n }\n }\n\n return originalRemoveEventListener.call(this, type, listener, options);\n };\n },\n );\n });\n}\n\n/**\n * Check whether the event is similar to the last captured one. For example, two click events on the same button.\n */\nfunction isSimilarToLastCapturedEvent(event: Event): boolean {\n // If both events have different type, then user definitely performed two separate actions. e.g. click + keypress.\n if (event.type !== lastCapturedEventType) {\n return false;\n }\n\n try {\n // If both events have the same type, it's still possible that actions were performed on different targets.\n // e.g. 2 clicks on different buttons.\n if (!event.target || (event.target as SentryWrappedTarget)._sentryId !== lastCapturedEventTargetId) {\n return false;\n }\n } catch {\n // just accessing `target` property can throw an exception in some rare circumstances\n // see: https://github.com/getsentry/sentry-javascript/issues/838\n }\n\n // If both events have the same type _and_ same `target` (an element which triggered an event, _not necessarily_\n // to which an event listener was attached), we treat them as the same action, as we want to capture\n // only one breadcrumb. e.g. multiple clicks on the same button, or typing inside a user input box.\n return true;\n}\n\n/**\n * Decide whether an event should be captured.\n * @param event event to be captured\n */\nfunction shouldSkipDOMEvent(eventType: string, target: SentryWrappedTarget | null): boolean {\n // We are only interested in filtering `keypress` events for now.\n if (eventType !== 'keypress') {\n return false;\n }\n\n if (!target?.tagName) {\n return true;\n }\n\n // Only consider keypress events on actual input elements. This will disregard keypresses targeting body\n // e.g.tabbing through elements, hotkeys, etc.\n if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Wraps addEventListener to capture UI breadcrumbs\n */\nfunction makeDOMEventHandler(\n handler: (data: HandlerDataDom) => void,\n globalListener: boolean = false,\n): (event: Event) => void {\n return (event: Event & { _sentryCaptured?: true }): void => {\n // It's possible this handler might trigger multiple times for the same\n // event (e.g. event propagation through node ancestors).\n // Ignore if we've already captured that event.\n if (!event || event['_sentryCaptured']) {\n return;\n }\n\n const target = getEventTarget(event);\n\n // We always want to skip _some_ events.\n if (shouldSkipDOMEvent(event.type, target)) {\n return;\n }\n\n // Mark event as \"seen\"\n addNonEnumerableProperty(event, '_sentryCaptured', true);\n\n if (target && !target._sentryId) {\n // Add UUID to event target so we can identify if\n addNonEnumerableProperty(target, '_sentryId', uuid4());\n }\n\n const name = event.type === 'keypress' ? 'input' : event.type;\n\n // If there is no last captured event, it means that we can safely capture the new event and store it for future comparisons.\n // If there is a last captured event, see if the new event is different enough to treat it as a unique one.\n // If that's the case, emit the previous event and store locally the newly-captured DOM event.\n if (!isSimilarToLastCapturedEvent(event)) {\n const handlerData: HandlerDataDom = { event, name, global: globalListener };\n handler(handlerData);\n lastCapturedEventType = event.type;\n lastCapturedEventTargetId = target ? target._sentryId : undefined;\n }\n\n // Start a new debounce timer that will prevent us from capturing multiple events that should be grouped together.\n clearTimeout(debounceTimerID);\n debounceTimerID = WINDOW.setTimeout(() => {\n lastCapturedEventTargetId = undefined;\n lastCapturedEventType = undefined;\n }, DEBOUNCE_DURATION);\n };\n}\n\nfunction getEventTarget(event: Event): SentryWrappedTarget | null {\n try {\n return event.target as SentryWrappedTarget | null;\n } catch {\n // just accessing `target` property can throw an exception in some rare circumstances\n // see: https://github.com/getsentry/sentry-javascript/issues/838\n return null;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sources":["../../../src/instrumentation/history.ts"],"sourcesContent":["import type { HandlerDataHistory } from '@sentry/core';\nimport { addHandler, fill, maybeInstrument, supportsHistory, triggerHandlers } from '@sentry/core';\nimport { WINDOW } from '../types';\n\nlet lastHref: string | undefined;\n\n/**\n * Add an instrumentation handler for when a fetch request happens.\n * The handler function is called once when the request starts and once when it ends,\n * which can be identified by checking if it has an `endTimestamp`.\n *\n * Use at your own risk, this might break without changelog notice, only used internally.\n * @hidden\n */\nexport function addHistoryInstrumentationHandler(handler: (data: HandlerDataHistory) => void): void {\n const type = 'history';\n addHandler(type, handler);\n maybeInstrument(type, instrumentHistory);\n}\n\n/**\n * Exported just for testing\n */\nexport function instrumentHistory(): void {\n // The `popstate` event may also be triggered on `pushState`, but it may not always reliably be emitted by the browser\n // Which is why we also monkey-patch methods below, in addition to this\n WINDOW.addEventListener('popstate', () => {\n const to = WINDOW.location.href;\n // keep track of the current URL state, as we always receive only the updated state\n const from = lastHref;\n lastHref = to;\n\n if (from === to) {\n return;\n }\n\n const handlerData = { from, to } satisfies HandlerDataHistory;\n triggerHandlers('history', handlerData);\n });\n\n // Just guard against this not being available, in weird environments\n if (!supportsHistory()) {\n return;\n }\n\n function historyReplacementFunction(originalHistoryFunction: () => void): () => void {\n return function (this: History, ...args: unknown[]): void {\n const url = args.length > 2 ? args[2] : undefined;\n if (url) {\n const from = lastHref;\n\n // Ensure the URL is absolute\n // this can be either a path, then it is relative to the current origin\n // or a full URL of the current origin - other origins are not allowed\n // See: https://developer.mozilla.org/en-US/docs/Web/API/History/pushState#url\n // coerce to string (this is what pushState does)\n const to = getAbsoluteUrl(String(url));\n\n // keep track of the current URL state, as we always receive only the updated state\n lastHref = to;\n\n if (from === to) {\n return originalHistoryFunction.apply(this, args);\n }\n\n const handlerData = { from, to } satisfies HandlerDataHistory;\n triggerHandlers('history', handlerData);\n }\n return originalHistoryFunction.apply(this, args);\n };\n }\n\n fill(WINDOW.history, 'pushState', historyReplacementFunction);\n fill(WINDOW.history, 'replaceState', historyReplacementFunction);\n}\n\nfunction getAbsoluteUrl(urlOrPath: string): string {\n try {\n const url = new URL(urlOrPath, WINDOW.location.origin);\n return url.toString();\n } catch {\n // fallback, just do nothing\n return urlOrPath;\n }\n}\n"],"names":[],"mappings":";;;AAIA,IAAI,QAAA;AAUG,SAAS,iCAAiC,OAAA,EAAmD;AAClG,EAAA,MAAM,IAAA,GAAO,SAAA;AACb,EAAA,UAAA,CAAW,MAAM,OAAO,CAAA;AACxB,EAAA,eAAA,CAAgB,MAAM,iBAAiB,CAAA;AACzC;AAKO,SAAS,iBAAA,GAA0B;AAGxC,EAAA,MAAA,CAAO,gBAAA,CAAiB,YAAY,MAAM;AACxC,IAAA,MAAM,EAAA,GAAK,OAAO,QAAA,CAAS,IAAA;AAE3B,IAAA,MAAM,IAAA,GAAO,QAAA;AACb,IAAA,QAAA,GAAW,EAAA;AAEX,IAAA,IAAI,SAAS,EAAA,EAAI;AACf,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,WAAA,GAAc,EAAE,IAAA,EAAM,EAAA,EAAG;AAC/B,IAAA,eAAA,CAAgB,WAAW,WAAW,CAAA;AAAA,EACxC,CAAC,CAAA;AAGD,EAAA,IAAI,CAAC,iBAAgB,EAAG;AACtB,IAAA;AAAA,EACF;AAEA,EAAA,SAAS,2BAA2B,uBAAA,EAAiD;AACnF,IAAA,OAAO,YAA4B,IAAA,EAAuB;AACxD,MAAA,MAAM,MAAM,IAAA,CAAK,MAAA,GAAS,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA,GAAI,MAAA;AACxC,MAAA,IAAI,GAAA,EAAK;AACP,QAAA,MAAM,IAAA,GAAO,QAAA;AAOb,QAAA,MAAM,EAAA,GAAK,cAAA,CAAe,MAAA,CAAO,GAAG,CAAC,CAAA;AAGrC,QAAA,QAAA,GAAW,EAAA;AAEX,QAAA,IAAI,SAAS,EAAA,EAAI;AACf,UAAA,OAAO,uBAAA,CAAwB,KAAA,CAAM,IAAA,EAAM,IAAI,CAAA;AAAA,QACjD;AAEA,QAAA,MAAM,WAAA,GAAc,EAAE,IAAA,EAAM,EAAA,EAAG;AAC/B,QAAA,eAAA,CAAgB,WAAW,WAAW,CAAA;AAAA,MACxC;AACA,MAAA,OAAO,uBAAA,CAAwB,KAAA,CAAM,IAAA,EAAM,IAAI,CAAA;AAAA,IACjD,CAAA;AAAA,EACF;AAEA,EAAA,IAAA,CAAK,MAAA,CAAO,OAAA,EAAS,WAAA,EAAa,0BAA0B,CAAA;AAC5D,EAAA,IAAA,CAAK,MAAA,CAAO,OAAA,EAAS,cAAA,EAAgB,0BAA0B,CAAA;AACjE;AAEA,SAAS,eAAe,SAAA,EAA2B;AACjD,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,IAAI,GAAA,CAAI,SAAA,EAAW,MAAA,CAAO,SAAS,MAAM,CAAA;AACrD,IAAA,OAAO,IAAI,QAAA,EAAS;AAAA,EACtB,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAO,SAAA;AAAA,EACT;AACF;;;;"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"location.js","sources":["../../../src/instrumentation/location.ts"],"sourcesContent":["import { WINDOW } from '../types';\n\n/**\n *\n * @param urlOrPath - The URL or path to convert to an absolute URL.\n *\n * @return the absolute URL when handed a relative URL path, by\n * combining the current `window.location.origin` with param urlOrPath.\n *\n * If param urlOrPath is already a full or an invalid URL,\n * or URL determination fails, the original param urlOrPath is returned unchanged.\n *\n */\nexport function getAbsoluteUrl(urlOrPath: string): string {\n try {\n const url = new URL(urlOrPath, WINDOW.location.origin);\n return url.toString();\n } catch {\n // fallback, just do nothing\n return urlOrPath;\n }\n}\n"],"names":[],"mappings":";;AAaO,SAAS,eAAe,SAAA,EAA2B;AACxD,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,IAAI,GAAA,CAAI,SAAA,EAAW,MAAA,CAAO,SAAS,MAAM,CAAA;AACrD,IAAA,OAAO,IAAI,QAAA,EAAS;AAAA,EACtB,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAO,SAAA;AAAA,EACT;AACF;;;;"}
@@ -1,10 +1,6 @@
1
1
  import { debug, getFunctionName } from '@sentry/core';
2
+ import { onCLS, onLCP, onTTFB, onINP } from 'web-vitals';
2
3
  import { DEBUG_BUILD } from '../debug-build.js';
3
- import { onCLS } from './web-vitals/getCLS.js';
4
- import { onINP } from './web-vitals/getINP.js';
5
- import { onLCP } from './web-vitals/getLCP.js';
6
- import { observe } from './web-vitals/lib/observe.js';
7
- import { onTTFB } from './web-vitals/onTTFB.js';
8
4
 
9
5
  const handlers = {};
10
6
  const instrumented = {};
@@ -51,14 +47,22 @@ Error:`,
51
47
  }
52
48
  }
53
49
  }
50
+ function withoutBfcache(callback) {
51
+ return (metric) => {
52
+ if (metric.navigationType === "back-forward-cache") {
53
+ return;
54
+ }
55
+ callback(metric);
56
+ };
57
+ }
54
58
  function instrumentCls() {
55
59
  return onCLS(
56
- (metric) => {
60
+ withoutBfcache((metric) => {
57
61
  triggerHandlers("cls", {
58
62
  metric
59
63
  });
60
64
  _previousCls = metric;
61
- },
65
+ }),
62
66
  // We want the callback to be called whenever the CLS value updates.
63
67
  // By default, the callback is only called when the tab goes to the background.
64
68
  { reportAllChanges: true }
@@ -66,32 +70,36 @@ function instrumentCls() {
66
70
  }
67
71
  function instrumentLcp() {
68
72
  return onLCP(
69
- (metric) => {
73
+ withoutBfcache((metric) => {
70
74
  triggerHandlers("lcp", {
71
75
  metric
72
76
  });
73
77
  _previousLcp = metric;
74
- },
78
+ }),
75
79
  // We want the callback to be called whenever the LCP value updates.
76
80
  // By default, the callback is only called when the tab goes to the background.
77
81
  { reportAllChanges: true }
78
82
  );
79
83
  }
80
84
  function instrumentTtfb() {
81
- return onTTFB((metric) => {
82
- triggerHandlers("ttfb", {
83
- metric
84
- });
85
- _previousTtfb = metric;
86
- });
85
+ return onTTFB(
86
+ withoutBfcache((metric) => {
87
+ triggerHandlers("ttfb", {
88
+ metric
89
+ });
90
+ _previousTtfb = metric;
91
+ })
92
+ );
87
93
  }
88
94
  function instrumentInp() {
89
- return onINP((metric) => {
90
- triggerHandlers("inp", {
91
- metric
92
- });
93
- _previousInp = metric;
94
- });
95
+ return onINP(
96
+ withoutBfcache((metric) => {
97
+ triggerHandlers("inp", {
98
+ metric
99
+ });
100
+ _previousInp = metric;
101
+ })
102
+ );
95
103
  }
96
104
  function addMetricObserver(type, callback, instrumentFn, previousValue, stopOnCallback = false) {
97
105
  addHandler(type, callback);
@@ -106,17 +114,21 @@ function addMetricObserver(type, callback, instrumentFn, previousValue, stopOnCa
106
114
  return getCleanupCallback(type, callback, stopOnCallback ? stopListening : void 0);
107
115
  }
108
116
  function instrumentPerformanceObserver(type) {
109
- const options = {};
117
+ const options = { type, buffered: true };
110
118
  if (type === "event") {
111
119
  options.durationThreshold = 0;
112
120
  }
113
- observe(
114
- type,
115
- (entries) => {
116
- triggerHandlers(type, { entries });
117
- },
118
- options
119
- );
121
+ try {
122
+ if (PerformanceObserver.supportedEntryTypes.includes(type)) {
123
+ const po = new PerformanceObserver((list) => {
124
+ void Promise.resolve().then(() => {
125
+ triggerHandlers(type, { entries: list.getEntries() });
126
+ });
127
+ });
128
+ po.observe(options);
129
+ }
130
+ } catch {
131
+ }
120
132
  }
121
133
  function addHandler(type, handler) {
122
134
  handlers[type] = handlers[type] || [];
@@ -142,4 +154,4 @@ function isPerformanceEventTiming(entry) {
142
154
  }
143
155
 
144
156
  export { addClsInstrumentationHandler, addInpInstrumentationHandler, addLcpInstrumentationHandler, addPerformanceInstrumentationHandler, addTtfbInstrumentationHandler, isPerformanceEventTiming };
145
- //# sourceMappingURL=instrument.js.map
157
+ //# sourceMappingURL=performanceObserver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performanceObserver.js","sources":["../../../src/instrumentation/performanceObserver.ts"],"sourcesContent":["import { debug, getFunctionName } from '@sentry/core';\nimport { onCLS, onINP, onLCP, onTTFB } from 'web-vitals';\nimport { DEBUG_BUILD } from '../debug-build';\n\ntype InstrumentHandlerTypePerformanceObserver =\n | 'longtask'\n | 'event'\n | 'navigation'\n | 'paint'\n | 'resource'\n | 'element'\n // fist-input is still needed for INP\n | 'first-input';\n\ntype InstrumentHandlerTypeMetric = 'cls' | 'lcp' | 'ttfb' | 'inp';\n\n// We provide this here manually instead of relying on a global, as this is not available in non-browser environements\n// And we do not want to expose such types\ninterface PerformanceEntry {\n readonly duration: number;\n readonly entryType: string;\n readonly name: string;\n readonly startTime: number;\n toJSON(): Record<string, unknown>;\n}\nexport interface PerformanceEventTiming extends PerformanceEntry {\n processingStart: number;\n processingEnd: number;\n duration: number;\n cancelable?: boolean;\n target?: unknown | null;\n interactionId?: number;\n}\n\ninterface PerformanceScriptTiming extends PerformanceEntry {\n sourceURL: string;\n sourceFunctionName: string;\n sourceCharPosition: number;\n invoker: string;\n invokerType: string;\n}\nexport interface PerformanceLongAnimationFrameTiming extends PerformanceEntry {\n scripts: PerformanceScriptTiming[];\n}\n\n// Locally-defined to match web-vitals' `Metric` shape without importing it: web-vitals' type\n// entrypoint carries a `declare global` block that references DOM globals not present in every\n// TypeScript lib version (e.g. `NavigationType`), which leaks into and breaks consumers on older\n// TS. Keeping this local keeps web-vitals' global augmentations out of our published types.\ninterface Metric {\n /**\n * The name of the metric (in acronym form).\n */\n name: 'CLS' | 'FCP' | 'INP' | 'LCP' | 'TTFB';\n\n /**\n * The current value of the metric.\n */\n value: number;\n\n /**\n * The rating as to whether the metric value is within the \"good\",\n * \"needs improvement\", or \"poor\" thresholds of the metric.\n */\n rating: 'good' | 'needs-improvement' | 'poor';\n\n /**\n * The delta between the current value and the last-reported value.\n * On the first report, `delta` and `value` will always be the same.\n */\n delta: number;\n\n /**\n * A unique ID representing this particular metric instance. This ID can\n * be used by an analytics tool to dedupe multiple values sent for the same\n * metric instance, or to group multiple deltas together and calculate a\n * total. It can also be used to differentiate multiple different metric\n * instances sent from the same page, which can happen if the page is\n * restored from the back/forward cache (in that case new metrics object\n * get created).\n */\n id: string;\n\n /**\n * Any performance entries relevant to the metric value calculation.\n * The array may also be empty if the metric value was not based on any\n * entries (e.g. a CLS value of 0 given no layout shifts).\n */\n entries: PerformanceEntry[];\n\n /**\n * The type of navigation.\n *\n * Navigation Timing API (or `undefined` if the browser doesn't\n * support that API). For pages that are restored from the bfcache, this\n * value will be 'back-forward-cache'.\n */\n navigationType:\n | 'navigate'\n | 'reload'\n | 'back-forward'\n | 'back-forward-cache'\n | 'prerender'\n | 'restore'\n | 'soft-navigation';\n}\n\ntype InstrumentHandlerType = InstrumentHandlerTypeMetric | InstrumentHandlerTypePerformanceObserver;\n\ntype StopListening = undefined | void | (() => void);\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InstrumentHandlerCallback = (data: any) => void;\n\ntype CleanupHandlerCallback = () => void;\n\nconst handlers: { [key in InstrumentHandlerType]?: InstrumentHandlerCallback[] } = {};\nconst instrumented: { [key in InstrumentHandlerType]?: boolean } = {};\n\nlet _previousCls: Metric | undefined;\nlet _previousLcp: Metric | undefined;\nlet _previousTtfb: Metric | undefined;\nlet _previousInp: Metric | undefined;\n\n/**\n * Add a callback that will be triggered when a CLS metric is available.\n * Returns a cleanup callback which can be called to remove the instrumentation handler.\n *\n * Pass `stopOnCallback = true` to stop listening for CLS when the cleanup callback is called.\n * This will lead to the CLS being finalized and frozen.\n */\nexport function addClsInstrumentationHandler(\n callback: (data: { metric: Metric }) => void,\n stopOnCallback = false,\n): CleanupHandlerCallback {\n return addMetricObserver('cls', callback, instrumentCls, _previousCls, stopOnCallback);\n}\n\n/**\n * Add a callback that will be triggered when a LCP metric is available.\n * Returns a cleanup callback which can be called to remove the instrumentation handler.\n *\n * Pass `stopOnCallback = true` to stop listening for LCP when the cleanup callback is called.\n * This will lead to the LCP being finalized and frozen.\n */\nexport function addLcpInstrumentationHandler(\n callback: (data: { metric: Metric }) => void,\n stopOnCallback = false,\n): CleanupHandlerCallback {\n return addMetricObserver('lcp', callback, instrumentLcp, _previousLcp, stopOnCallback);\n}\n\n/**\n * Add a callback that will be triggered when a TTFD metric is available.\n */\nexport function addTtfbInstrumentationHandler(callback: (data: { metric: Metric }) => void): CleanupHandlerCallback {\n return addMetricObserver('ttfb', callback, instrumentTtfb, _previousTtfb);\n}\n\nexport type InstrumentationHandlerCallback = (data: {\n metric: Omit<Metric, 'entries'> & {\n entries: PerformanceEventTiming[];\n };\n}) => void;\n\n/**\n * Add a callback that will be triggered when a INP metric is available.\n * Returns a cleanup callback which can be called to remove the instrumentation handler.\n */\nexport function addInpInstrumentationHandler(callback: InstrumentationHandlerCallback): CleanupHandlerCallback {\n return addMetricObserver('inp', callback, instrumentInp, _previousInp);\n}\n\nexport function addPerformanceInstrumentationHandler(\n type: 'event',\n callback: (data: { entries: ((PerformanceEntry & { target?: unknown | null }) | PerformanceEventTiming)[] }) => void,\n): CleanupHandlerCallback;\nexport function addPerformanceInstrumentationHandler(\n type: InstrumentHandlerTypePerformanceObserver,\n callback: (data: { entries: PerformanceEntry[] }) => void,\n): CleanupHandlerCallback;\n\n/**\n * Add a callback that will be triggered when a performance observer is triggered,\n * and receives the entries of the observer.\n * Returns a cleanup callback which can be called to remove the instrumentation handler.\n */\nexport function addPerformanceInstrumentationHandler(\n type: InstrumentHandlerTypePerformanceObserver,\n callback: (data: { entries: PerformanceEntry[] }) => void,\n): CleanupHandlerCallback {\n addHandler(type, callback);\n\n if (!instrumented[type]) {\n instrumentPerformanceObserver(type);\n instrumented[type] = true;\n }\n\n return getCleanupCallback(type, callback);\n}\n\n/** Trigger all handlers of a given type. */\nfunction triggerHandlers(type: InstrumentHandlerType, data: unknown): void {\n const typeHandlers = handlers[type];\n\n if (!typeHandlers?.length) {\n return;\n }\n\n for (const handler of typeHandlers) {\n try {\n handler(data);\n } catch (e) {\n DEBUG_BUILD &&\n debug.error(\n `Error while triggering instrumentation handler.\\nType: ${type}\\nName: ${getFunctionName(handler)}\\nError:`,\n e,\n );\n }\n }\n}\n\n/**\n * Wraps a metric callback so that metrics reported after a back/forward-cache restore are ignored.\n *\n * web-vitals re-reports each metric after a bfcache restore (tagged with a `back-forward-cache`\n * navigation type). We intentionally drop those for now: our reporting assumes one set of vitals\n * per page load, so surfacing bfcache re-reports would skew the data until we're ready to model\n * and communicate them.\n */\nfunction withoutBfcache(callback: (metric: Metric) => void): (metric: Metric) => void {\n return metric => {\n if (metric.navigationType === 'back-forward-cache') {\n return;\n }\n callback(metric);\n };\n}\n\nfunction instrumentCls(): StopListening {\n return onCLS(\n withoutBfcache(metric => {\n triggerHandlers('cls', {\n metric,\n });\n _previousCls = metric;\n }),\n // We want the callback to be called whenever the CLS value updates.\n // By default, the callback is only called when the tab goes to the background.\n { reportAllChanges: true },\n );\n}\n\nfunction instrumentLcp(): StopListening {\n return onLCP(\n withoutBfcache(metric => {\n triggerHandlers('lcp', {\n metric,\n });\n _previousLcp = metric;\n }),\n // We want the callback to be called whenever the LCP value updates.\n // By default, the callback is only called when the tab goes to the background.\n { reportAllChanges: true },\n );\n}\n\nfunction instrumentTtfb(): StopListening {\n return onTTFB(\n withoutBfcache(metric => {\n triggerHandlers('ttfb', {\n metric,\n });\n _previousTtfb = metric;\n }),\n );\n}\n\nfunction instrumentInp(): StopListening {\n return onINP(\n withoutBfcache(metric => {\n triggerHandlers('inp', {\n metric,\n });\n _previousInp = metric;\n }),\n );\n}\n\nfunction addMetricObserver(\n type: InstrumentHandlerTypeMetric,\n callback: InstrumentHandlerCallback,\n instrumentFn: () => StopListening,\n previousValue: Metric | undefined,\n stopOnCallback = false,\n): CleanupHandlerCallback {\n addHandler(type, callback);\n\n let stopListening: StopListening | undefined;\n\n if (!instrumented[type]) {\n stopListening = instrumentFn();\n instrumented[type] = true;\n }\n\n if (previousValue) {\n callback({ metric: previousValue });\n }\n\n return getCleanupCallback(type, callback, stopOnCallback ? stopListening : undefined);\n}\n\nfunction instrumentPerformanceObserver(type: InstrumentHandlerTypePerformanceObserver): void {\n const options: PerformanceObserverInit = { type, buffered: true };\n\n // Special per-type options we want to use\n if (type === 'event') {\n (options as PerformanceObserverInit & { durationThreshold?: number }).durationThreshold = 0;\n }\n\n try {\n if (PerformanceObserver.supportedEntryTypes.includes(type)) {\n const po = new PerformanceObserver(list => {\n // Delay by a microtask to work around a bug in Safari where the\n // callback is invoked synchronously rather than in a separate task.\n // See: https://github.com/GoogleChrome/web-vitals/issues/277\n void Promise.resolve().then(() => {\n triggerHandlers(type, { entries: list.getEntries() });\n });\n });\n po.observe(options);\n }\n } catch {\n // Unsupported entry type; nothing to observe.\n }\n}\n\nfunction addHandler(type: InstrumentHandlerType, handler: InstrumentHandlerCallback): void {\n handlers[type] = handlers[type] || [];\n handlers[type].push(handler);\n}\n\n// Get a callback which can be called to remove the instrumentation handler\nfunction getCleanupCallback(\n type: InstrumentHandlerType,\n callback: InstrumentHandlerCallback,\n stopListening: StopListening,\n): CleanupHandlerCallback {\n return () => {\n if (stopListening) {\n stopListening();\n }\n\n const typeHandlers = handlers[type];\n\n if (!typeHandlers) {\n return;\n }\n\n const index = typeHandlers.indexOf(callback);\n if (index !== -1) {\n typeHandlers.splice(index, 1);\n }\n };\n}\n\n/**\n * Check if a PerformanceEntry is a PerformanceEventTiming by checking for the `duration` property.\n */\nexport function isPerformanceEventTiming(entry: PerformanceEntry): entry is PerformanceEventTiming {\n return 'duration' in entry;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xhr.js","sources":["../../../src/instrumentation/xhr.ts"],"sourcesContent":["import type { HandlerDataXhr, SentryWrappedXMLHttpRequest } from '@sentry/core';\nimport { addHandler, isString, maybeInstrument, timestampInSeconds, triggerHandlers } from '@sentry/core';\nimport { WINDOW } from '../types';\n\nexport const SENTRY_XHR_DATA_KEY = '__sentry_xhr_v3__';\n\ntype WindowWithXhr = Window & { XMLHttpRequest?: typeof XMLHttpRequest };\n\n/**\n * Add an instrumentation handler for when an XHR request happens.\n * The handler function is called once when the request starts and once when it ends,\n * which can be identified by checking if it has an `endTimestamp`.\n *\n * Use at your own risk, this might break without changelog notice, only used internally.\n * @hidden\n */\nexport function addXhrInstrumentationHandler(handler: (data: HandlerDataXhr) => void): void {\n const type = 'xhr';\n addHandler(type, handler);\n maybeInstrument(type, instrumentXHR);\n}\n\n/** Exported only for tests. */\nexport function instrumentXHR(): void {\n if (!(WINDOW as WindowWithXhr).XMLHttpRequest) {\n return;\n }\n\n const xhrproto = XMLHttpRequest.prototype;\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n xhrproto.open = new Proxy(xhrproto.open, {\n apply(\n originalOpen,\n xhrOpenThisArg: XMLHttpRequest & SentryWrappedXMLHttpRequest,\n xhrOpenArgArray:\n | [method: string, url: string | URL]\n | [method: string, url: string | URL, async: boolean, username?: string | null, password?: string | null],\n ) {\n // NOTE: If you are a Sentry user, and you are seeing this stack frame,\n // it means the error, that was caused by your XHR call did not\n // have a stack trace. If you are using HttpClient integration,\n // this is the expected behavior, as we are using this virtual error to capture\n // the location of your XHR call, and group your HttpClient events accordingly.\n const virtualError = new Error();\n\n const startTimestamp = timestampInSeconds() * 1000;\n\n // open() should always be called with two or more arguments\n // But to be on the safe side, we actually validate this and bail out if we don't have a method & url\n const method = isString(xhrOpenArgArray[0]) ? xhrOpenArgArray[0].toUpperCase() : undefined;\n const url = parseXhrUrlArg(xhrOpenArgArray[1]);\n\n if (!method || !url) {\n return originalOpen.apply(xhrOpenThisArg, xhrOpenArgArray);\n }\n\n xhrOpenThisArg[SENTRY_XHR_DATA_KEY] = {\n method,\n url,\n request_headers: {},\n };\n\n // if Sentry key appears in URL, don't capture it as a request\n if (method === 'POST' && url.match(/sentry_key/)) {\n xhrOpenThisArg.__sentry_own_request__ = true;\n }\n\n const onreadystatechangeHandler: () => void = () => {\n // For whatever reason, this is not the same instance here as from the outer method\n const xhrInfo = xhrOpenThisArg[SENTRY_XHR_DATA_KEY];\n\n if (!xhrInfo) {\n return;\n }\n\n if (xhrOpenThisArg.readyState === 4) {\n try {\n // touching statusCode in some platforms throws\n // an exception\n xhrInfo.status_code = xhrOpenThisArg.status;\n } catch {\n /* do nothing */\n }\n\n const handlerData: HandlerDataXhr = {\n endTimestamp: timestampInSeconds() * 1000,\n startTimestamp,\n xhr: xhrOpenThisArg,\n virtualError,\n };\n triggerHandlers('xhr', handlerData);\n\n // In the `addEventListener` branch below, this handler is the only\n // `readystatechange` listener we add, so detach it once the request is\n // done to avoid pinning the XMLHttpRequest and its captured\n // `virtualError` per HTTP call on long-lived pages. In the\n // `onreadystatechange` proxy branch the handler isn't registered via\n // `addEventListener`, so this is a harmless no-op there.\n xhrOpenThisArg.removeEventListener('readystatechange', onreadystatechangeHandler);\n }\n };\n\n if ('onreadystatechange' in xhrOpenThisArg && typeof xhrOpenThisArg.onreadystatechange === 'function') {\n xhrOpenThisArg.onreadystatechange = new Proxy(xhrOpenThisArg.onreadystatechange, {\n apply(originalOnreadystatechange, onreadystatechangeThisArg, onreadystatechangeArgArray: unknown[]) {\n onreadystatechangeHandler();\n return originalOnreadystatechange.apply(onreadystatechangeThisArg, onreadystatechangeArgArray);\n },\n });\n } else {\n xhrOpenThisArg.addEventListener('readystatechange', onreadystatechangeHandler);\n }\n\n // Intercepting `setRequestHeader` to access the request headers of XHR instance.\n // This will only work for user/library defined headers, not for the default/browser-assigned headers.\n // Request cookies are also unavailable for XHR, as `Cookie` header can't be defined by `setRequestHeader`.\n xhrOpenThisArg.setRequestHeader = new Proxy(xhrOpenThisArg.setRequestHeader, {\n apply(\n originalSetRequestHeader,\n setRequestHeaderThisArg: SentryWrappedXMLHttpRequest,\n setRequestHeaderArgArray: unknown[],\n ) {\n const [header, value] = setRequestHeaderArgArray;\n\n const xhrInfo = setRequestHeaderThisArg[SENTRY_XHR_DATA_KEY];\n\n if (xhrInfo && isString(header) && isString(value)) {\n xhrInfo.request_headers[header.toLowerCase()] = value;\n }\n\n return originalSetRequestHeader.apply(setRequestHeaderThisArg, setRequestHeaderArgArray);\n },\n });\n\n return originalOpen.apply(xhrOpenThisArg, xhrOpenArgArray);\n },\n });\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n xhrproto.send = new Proxy(xhrproto.send, {\n apply(originalSend, sendThisArg: XMLHttpRequest & SentryWrappedXMLHttpRequest, sendArgArray: unknown[]) {\n const sentryXhrData = sendThisArg[SENTRY_XHR_DATA_KEY];\n\n if (!sentryXhrData) {\n return originalSend.apply(sendThisArg, sendArgArray);\n }\n\n if (sendArgArray[0] !== undefined) {\n sentryXhrData.body = sendArgArray[0];\n }\n\n const handlerData: HandlerDataXhr = {\n startTimestamp: timestampInSeconds() * 1000,\n xhr: sendThisArg,\n };\n triggerHandlers('xhr', handlerData);\n\n return originalSend.apply(sendThisArg, sendArgArray);\n },\n });\n}\n\n/**\n * Parses the URL argument of a XHR method to a string.\n *\n * See: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open#url\n * url: A string or any other object with a stringifier — including a URL object — that provides the URL of the resource to send the request to.\n *\n * @param url - The URL argument of an XHR method\n * @returns The parsed URL string or undefined if the URL is invalid\n */\nfunction parseXhrUrlArg(url: unknown): string | undefined {\n if (isString(url)) {\n return url;\n }\n\n try {\n // If the passed in argument is not a string, it should have a `toString` method as a stringifier.\n // If that fails, we just return undefined (like in IE11 where URL is not available)\n return (url as URL).toString();\n } catch {} // eslint-disable-line no-empty\n\n return undefined;\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"type":"module","version":"10.70.0","sideEffects":false}
1
+ {"type":"module","version":"11.0.0-alpha.1","sideEffects":false}
@@ -1,5 +1,5 @@
1
1
  import { defineIntegration, browserPerformanceTimeOrigin, metrics } from '@sentry/core';
2
- import { addPerformanceInstrumentationHandler } from './instrument.js';
2
+ import { addPerformanceInstrumentationHandler } from '../instrumentation/performanceObserver.js';
3
3
  import { getBrowserPerformanceAPI } from './utils.js';
4
4
 
5
5
  const INTEGRATION_NAME = "ElementTiming";
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementTiming.js","sources":["../../../src/performance/elementTiming.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { browserPerformanceTimeOrigin, defineIntegration, metrics } from '@sentry/core';\nimport { addPerformanceInstrumentationHandler } from '../instrumentation/performanceObserver';\nimport { getBrowserPerformanceAPI } from './utils';\n\n// ElementTiming interface based on the W3C spec\ninterface PerformanceElementTiming extends PerformanceEntry {\n renderTime: number;\n loadTime: number;\n intersectionRect: DOMRectReadOnly;\n identifier: string;\n naturalWidth: number;\n naturalHeight: number;\n id: string;\n element: Element | null;\n url?: string;\n}\n\nconst INTEGRATION_NAME = 'ElementTiming';\n\nconst _elementTimingIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setup() {\n const performance = getBrowserPerformanceAPI();\n if (!performance || !browserPerformanceTimeOrigin()) {\n return;\n }\n\n addPerformanceInstrumentationHandler('element', ({ entries }) => {\n for (const entry of entries) {\n const elementEntry = entry as PerformanceElementTiming;\n\n if (!elementEntry.identifier) {\n continue;\n }\n\n const identifier = elementEntry.identifier;\n const paintType = elementEntry.name as 'image-paint' | 'text-paint' | undefined;\n const renderTime = elementEntry.renderTime;\n const loadTime = elementEntry.loadTime;\n\n const metricAttributes: Record<string, string | number> = {\n 'sentry.origin': 'auto.ui.browser.element_timing',\n 'ui.element.identifier': identifier,\n };\n\n if (paintType) {\n metricAttributes['ui.element.paint_type'] = paintType;\n }\n\n if (elementEntry.id) {\n metricAttributes['ui.element.id'] = elementEntry.id;\n }\n\n if (elementEntry.element) {\n metricAttributes['ui.element.type'] = elementEntry.element.tagName.toLowerCase();\n }\n\n if (elementEntry.url) {\n metricAttributes['ui.element.url'] = elementEntry.url;\n }\n\n if (elementEntry.naturalWidth) {\n metricAttributes['ui.element.width'] = elementEntry.naturalWidth;\n }\n\n if (elementEntry.naturalHeight) {\n metricAttributes['ui.element.height'] = elementEntry.naturalHeight;\n }\n\n if (renderTime > 0) {\n metrics.distribution(`ui.element.render_time`, renderTime, {\n unit: 'millisecond',\n attributes: metricAttributes,\n });\n }\n\n if (loadTime > 0) {\n metrics.distribution(`ui.element.load_time`, loadTime, {\n unit: 'millisecond',\n attributes: metricAttributes,\n });\n }\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Captures [Element Timing API](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceElementTiming)\n * data as Sentry metrics.\n *\n * To mark an element for tracking, add the `elementtiming` HTML attribute:\n * ```html\n * <img src=\"hero.jpg\" elementtiming=\"hero-image\" />\n * <p elementtiming=\"hero-text\">Welcome!</p>\n * ```\n *\n * This emits `ui.element.render_time` and `ui.element.load_time` (for images)\n * as distribution metrics, tagged with the element's identifier and paint type.\n */\nexport const elementTimingIntegration = defineIntegration(_elementTimingIntegration);\n\n/**\n * @deprecated Use `elementTimingIntegration` instead. This function is a no-op and will be removed in a future version.\n */\nexport function startTrackingElementTiming(): () => void {\n return () => undefined;\n}\n"],"names":[],"mappings":";;;;AAkBA,MAAM,gBAAA,GAAmB,eAAA;AAEzB,MAAM,6BAA6B,MAAM;AACvC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,KAAA,GAAQ;AACN,MAAA,MAAM,cAAc,wBAAA,EAAyB;AAC7C,MAAA,IAAI,CAAC,WAAA,IAAe,CAAC,4BAAA,EAA6B,EAAG;AACnD,QAAA;AAAA,MACF;AAEA,MAAA,oCAAA,CAAqC,SAAA,EAAW,CAAC,EAAE,OAAA,EAAQ,KAAM;AAC/D,QAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,UAAA,MAAM,YAAA,GAAe,KAAA;AAErB,UAAA,IAAI,CAAC,aAAa,UAAA,EAAY;AAC5B,YAAA;AAAA,UACF;AAEA,UAAA,MAAM,aAAa,YAAA,CAAa,UAAA;AAChC,UAAA,MAAM,YAAY,YAAA,CAAa,IAAA;AAC/B,UAAA,MAAM,aAAa,YAAA,CAAa,UAAA;AAChC,UAAA,MAAM,WAAW,YAAA,CAAa,QAAA;AAE9B,UAAA,MAAM,gBAAA,GAAoD;AAAA,YACxD,eAAA,EAAiB,gCAAA;AAAA,YACjB,uBAAA,EAAyB;AAAA,WAC3B;AAEA,UAAA,IAAI,SAAA,EAAW;AACb,YAAA,gBAAA,CAAiB,uBAAuB,CAAA,GAAI,SAAA;AAAA,UAC9C;AAEA,UAAA,IAAI,aAAa,EAAA,EAAI;AACnB,YAAA,gBAAA,CAAiB,eAAe,IAAI,YAAA,CAAa,EAAA;AAAA,UACnD;AAEA,UAAA,IAAI,aAAa,OAAA,EAAS;AACxB,YAAA,gBAAA,CAAiB,iBAAiB,CAAA,GAAI,YAAA,CAAa,OAAA,CAAQ,QAAQ,WAAA,EAAY;AAAA,UACjF;AAEA,UAAA,IAAI,aAAa,GAAA,EAAK;AACpB,YAAA,gBAAA,CAAiB,gBAAgB,IAAI,YAAA,CAAa,GAAA;AAAA,UACpD;AAEA,UAAA,IAAI,aAAa,YAAA,EAAc;AAC7B,YAAA,gBAAA,CAAiB,kBAAkB,IAAI,YAAA,CAAa,YAAA;AAAA,UACtD;AAEA,UAAA,IAAI,aAAa,aAAA,EAAe;AAC9B,YAAA,gBAAA,CAAiB,mBAAmB,IAAI,YAAA,CAAa,aAAA;AAAA,UACvD;AAEA,UAAA,IAAI,aAAa,CAAA,EAAG;AAClB,YAAA,OAAA,CAAQ,YAAA,CAAa,0BAA0B,UAAA,EAAY;AAAA,cACzD,IAAA,EAAM,aAAA;AAAA,cACN,UAAA,EAAY;AAAA,aACb,CAAA;AAAA,UACH;AAEA,UAAA,IAAI,WAAW,CAAA,EAAG;AAChB,YAAA,OAAA,CAAQ,YAAA,CAAa,wBAAwB,QAAA,EAAU;AAAA,cACrD,IAAA,EAAM,aAAA;AAAA,cACN,UAAA,EAAY;AAAA,aACb,CAAA;AAAA,UACH;AAAA,QACF;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF,CAAA,CAAA;AAeO,MAAM,wBAAA,GAA2B,kBAAkB,yBAAyB;AAK5E,SAAS,0BAAA,GAAyC;AACvD,EAAA,OAAO,MAAM,MAAA;AACf;;;;"}