@sentry/browser-utils 11.0.0-alpha.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 (288) hide show
  1. package/build/cjs/index.js +29 -28
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/cjs/instrumentation/dom.js.map +1 -0
  4. package/build/cjs/instrumentation/history.js.map +1 -0
  5. package/build/cjs/instrumentation/location.js.map +1 -0
  6. package/build/cjs/{metrics/instrument.js → instrumentation/performanceObserver.js} +44 -32
  7. package/build/cjs/instrumentation/performanceObserver.js.map +1 -0
  8. package/build/cjs/instrumentation/xhr.js.map +1 -0
  9. package/build/cjs/{metrics → performance}/elementTiming.js +2 -2
  10. package/build/cjs/performance/elementTiming.js.map +1 -0
  11. package/build/cjs/{metrics/browserMetrics.js → performance/entries.js} +22 -175
  12. package/build/cjs/performance/entries.js.map +1 -0
  13. package/build/cjs/performance/resourceTiming.js.map +1 -0
  14. package/build/cjs/{metrics → performance}/userTiming.js +4 -3
  15. package/build/cjs/performance/userTiming.js.map +1 -0
  16. package/build/cjs/{metrics → performance}/utils.js +1 -27
  17. package/build/cjs/performance/utils.js.map +1 -0
  18. package/build/cjs/{metrics → web-vitals}/inp.js +4 -4
  19. package/build/cjs/web-vitals/inp.js.map +1 -0
  20. package/build/cjs/web-vitals/lcp.js.map +1 -0
  21. package/build/cjs/web-vitals/reportEvents.js +31 -0
  22. package/build/cjs/web-vitals/reportEvents.js.map +1 -0
  23. package/build/cjs/{metrics/webVitalSpans.js → web-vitals/spans.js} +11 -10
  24. package/build/cjs/web-vitals/spans.js.map +1 -0
  25. package/build/cjs/web-vitals/tracking.js +164 -0
  26. package/build/cjs/web-vitals/tracking.js.map +1 -0
  27. package/build/cjs/web-vitals/utils.js +99 -0
  28. package/build/cjs/web-vitals/utils.js.map +1 -0
  29. package/build/esm/index.js +14 -13
  30. package/build/esm/index.js.map +1 -1
  31. package/build/esm/instrumentation/dom.js.map +1 -0
  32. package/build/esm/instrumentation/history.js.map +1 -0
  33. package/build/esm/instrumentation/location.js.map +1 -0
  34. package/build/esm/{metrics/instrument.js → instrumentation/performanceObserver.js} +42 -30
  35. package/build/esm/instrumentation/performanceObserver.js.map +1 -0
  36. package/build/esm/instrumentation/xhr.js.map +1 -0
  37. package/build/esm/package.json +1 -1
  38. package/build/esm/{metrics → performance}/elementTiming.js +1 -1
  39. package/build/esm/performance/elementTiming.js.map +1 -0
  40. package/build/esm/{metrics/browserMetrics.js → performance/entries.js} +15 -166
  41. package/build/esm/performance/entries.js.map +1 -0
  42. package/build/esm/performance/resourceTiming.js.map +1 -0
  43. package/build/esm/{metrics → performance}/userTiming.js +4 -3
  44. package/build/esm/performance/userTiming.js.map +1 -0
  45. package/build/esm/{metrics → performance}/utils.js +3 -28
  46. package/build/esm/performance/utils.js.map +1 -0
  47. package/build/esm/{metrics → web-vitals}/inp.js +1 -1
  48. package/build/esm/web-vitals/inp.js.map +1 -0
  49. package/build/esm/web-vitals/lcp.js.map +1 -0
  50. package/build/esm/web-vitals/reportEvents.js +29 -0
  51. package/build/esm/web-vitals/reportEvents.js.map +1 -0
  52. package/build/esm/{metrics/webVitalSpans.js → web-vitals/spans.js} +7 -6
  53. package/build/esm/web-vitals/spans.js.map +1 -0
  54. package/build/esm/web-vitals/tracking.js +161 -0
  55. package/build/esm/web-vitals/tracking.js.map +1 -0
  56. package/build/esm/web-vitals/utils.js +91 -0
  57. package/build/esm/web-vitals/utils.js.map +1 -0
  58. package/build/types/index.d.ts +13 -12
  59. package/build/types/index.d.ts.map +1 -1
  60. package/build/types/instrumentation/dom.d.ts.map +1 -0
  61. package/build/types/instrumentation/history.d.ts.map +1 -0
  62. package/build/types/instrumentation/location.d.ts.map +1 -0
  63. package/build/types/{metrics/instrument.d.ts → instrumentation/performanceObserver.d.ts} +3 -3
  64. package/build/types/instrumentation/performanceObserver.d.ts.map +1 -0
  65. package/build/types/instrumentation/xhr.d.ts.map +1 -0
  66. package/build/types/performance/elementTiming.d.ts.map +1 -0
  67. package/build/types/{metrics/browserMetrics.d.ts → performance/entries.d.ts} +3 -46
  68. package/build/types/performance/entries.d.ts.map +1 -0
  69. package/build/types/performance/resourceTiming.d.ts.map +1 -0
  70. package/build/types/performance/userTiming.d.ts.map +1 -0
  71. package/build/types/{metrics → performance}/utils.d.ts +1 -17
  72. package/build/types/performance/utils.d.ts.map +1 -0
  73. package/build/types/web-vitals/inp.d.ts.map +1 -0
  74. package/build/types/web-vitals/lcp.d.ts.map +1 -0
  75. package/build/types/web-vitals/reportEvents.d.ts +18 -0
  76. package/build/types/web-vitals/reportEvents.d.ts.map +1 -0
  77. package/build/types/{metrics/webVitalSpans.d.ts → web-vitals/spans.d.ts} +3 -3
  78. package/build/types/web-vitals/spans.d.ts.map +1 -0
  79. package/build/types/web-vitals/tracking.d.ts +46 -0
  80. package/build/types/web-vitals/tracking.d.ts.map +1 -0
  81. package/build/types/{metrics/web-vitals/lib/globalListeners.d.ts → web-vitals/utils.d.ts} +16 -1
  82. package/build/types/web-vitals/utils.d.ts.map +1 -0
  83. package/package.json +4 -3
  84. package/build/cjs/instrument/dom.js.map +0 -1
  85. package/build/cjs/instrument/history.js.map +0 -1
  86. package/build/cjs/instrument/location.js.map +0 -1
  87. package/build/cjs/instrument/xhr.js.map +0 -1
  88. package/build/cjs/metrics/browserMetrics.js.map +0 -1
  89. package/build/cjs/metrics/elementTiming.js.map +0 -1
  90. package/build/cjs/metrics/inp.js.map +0 -1
  91. package/build/cjs/metrics/instrument.js.map +0 -1
  92. package/build/cjs/metrics/lcp.js.map +0 -1
  93. package/build/cjs/metrics/resourceTiming.js.map +0 -1
  94. package/build/cjs/metrics/userTiming.js.map +0 -1
  95. package/build/cjs/metrics/utils.js.map +0 -1
  96. package/build/cjs/metrics/web-vitals/getCLS.js +0 -46
  97. package/build/cjs/metrics/web-vitals/getCLS.js.map +0 -1
  98. package/build/cjs/metrics/web-vitals/getINP.js +0 -60
  99. package/build/cjs/metrics/web-vitals/getINP.js.map +0 -1
  100. package/build/cjs/metrics/web-vitals/getLCP.js +0 -62
  101. package/build/cjs/metrics/web-vitals/getLCP.js.map +0 -1
  102. package/build/cjs/metrics/web-vitals/lib/InteractionManager.js +0 -87
  103. package/build/cjs/metrics/web-vitals/lib/InteractionManager.js.map +0 -1
  104. package/build/cjs/metrics/web-vitals/lib/LCPEntryManager.js +0 -11
  105. package/build/cjs/metrics/web-vitals/lib/LCPEntryManager.js.map +0 -1
  106. package/build/cjs/metrics/web-vitals/lib/LayoutShiftManager.js +0 -27
  107. package/build/cjs/metrics/web-vitals/lib/LayoutShiftManager.js.map +0 -1
  108. package/build/cjs/metrics/web-vitals/lib/bindReporter.js +0 -31
  109. package/build/cjs/metrics/web-vitals/lib/bindReporter.js.map +0 -1
  110. package/build/cjs/metrics/web-vitals/lib/generateUniqueID.js +0 -8
  111. package/build/cjs/metrics/web-vitals/lib/generateUniqueID.js.map +0 -1
  112. package/build/cjs/metrics/web-vitals/lib/getActivationStart.js +0 -11
  113. package/build/cjs/metrics/web-vitals/lib/getActivationStart.js.map +0 -1
  114. package/build/cjs/metrics/web-vitals/lib/getNavigationEntry.js +0 -17
  115. package/build/cjs/metrics/web-vitals/lib/getNavigationEntry.js.map +0 -1
  116. package/build/cjs/metrics/web-vitals/lib/getVisibilityWatcher.js +0 -44
  117. package/build/cjs/metrics/web-vitals/lib/getVisibilityWatcher.js.map +0 -1
  118. package/build/cjs/metrics/web-vitals/lib/globalListeners.js +0 -18
  119. package/build/cjs/metrics/web-vitals/lib/globalListeners.js.map +0 -1
  120. package/build/cjs/metrics/web-vitals/lib/initMetric.js +0 -34
  121. package/build/cjs/metrics/web-vitals/lib/initMetric.js.map +0 -1
  122. package/build/cjs/metrics/web-vitals/lib/initUnique.js +0 -16
  123. package/build/cjs/metrics/web-vitals/lib/initUnique.js.map +0 -1
  124. package/build/cjs/metrics/web-vitals/lib/observe.js +0 -20
  125. package/build/cjs/metrics/web-vitals/lib/observe.js.map +0 -1
  126. package/build/cjs/metrics/web-vitals/lib/onHidden.js +0 -16
  127. package/build/cjs/metrics/web-vitals/lib/onHidden.js.map +0 -1
  128. package/build/cjs/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js +0 -32
  129. package/build/cjs/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js.map +0 -1
  130. package/build/cjs/metrics/web-vitals/lib/runOnce.js +0 -14
  131. package/build/cjs/metrics/web-vitals/lib/runOnce.js.map +0 -1
  132. package/build/cjs/metrics/web-vitals/lib/whenActivated.js +0 -14
  133. package/build/cjs/metrics/web-vitals/lib/whenActivated.js.map +0 -1
  134. package/build/cjs/metrics/web-vitals/lib/whenIdleOrHidden.js +0 -22
  135. package/build/cjs/metrics/web-vitals/lib/whenIdleOrHidden.js.map +0 -1
  136. package/build/cjs/metrics/web-vitals/onFCP.js +0 -37
  137. package/build/cjs/metrics/web-vitals/onFCP.js.map +0 -1
  138. package/build/cjs/metrics/web-vitals/onTTFB.js +0 -35
  139. package/build/cjs/metrics/web-vitals/onTTFB.js.map +0 -1
  140. package/build/cjs/metrics/webVitalSpans.js.map +0 -1
  141. package/build/esm/instrument/dom.js.map +0 -1
  142. package/build/esm/instrument/history.js.map +0 -1
  143. package/build/esm/instrument/location.js.map +0 -1
  144. package/build/esm/instrument/xhr.js.map +0 -1
  145. package/build/esm/metrics/browserMetrics.js.map +0 -1
  146. package/build/esm/metrics/elementTiming.js.map +0 -1
  147. package/build/esm/metrics/inp.js.map +0 -1
  148. package/build/esm/metrics/instrument.js.map +0 -1
  149. package/build/esm/metrics/lcp.js.map +0 -1
  150. package/build/esm/metrics/resourceTiming.js.map +0 -1
  151. package/build/esm/metrics/userTiming.js.map +0 -1
  152. package/build/esm/metrics/utils.js.map +0 -1
  153. package/build/esm/metrics/web-vitals/getCLS.js +0 -43
  154. package/build/esm/metrics/web-vitals/getCLS.js.map +0 -1
  155. package/build/esm/metrics/web-vitals/getINP.js +0 -57
  156. package/build/esm/metrics/web-vitals/getINP.js.map +0 -1
  157. package/build/esm/metrics/web-vitals/getLCP.js +0 -59
  158. package/build/esm/metrics/web-vitals/getLCP.js.map +0 -1
  159. package/build/esm/metrics/web-vitals/lib/InteractionManager.js +0 -85
  160. package/build/esm/metrics/web-vitals/lib/InteractionManager.js.map +0 -1
  161. package/build/esm/metrics/web-vitals/lib/LCPEntryManager.js +0 -9
  162. package/build/esm/metrics/web-vitals/lib/LCPEntryManager.js.map +0 -1
  163. package/build/esm/metrics/web-vitals/lib/LayoutShiftManager.js +0 -25
  164. package/build/esm/metrics/web-vitals/lib/LayoutShiftManager.js.map +0 -1
  165. package/build/esm/metrics/web-vitals/lib/bindReporter.js +0 -29
  166. package/build/esm/metrics/web-vitals/lib/bindReporter.js.map +0 -1
  167. package/build/esm/metrics/web-vitals/lib/generateUniqueID.js +0 -6
  168. package/build/esm/metrics/web-vitals/lib/generateUniqueID.js.map +0 -1
  169. package/build/esm/metrics/web-vitals/lib/getActivationStart.js +0 -9
  170. package/build/esm/metrics/web-vitals/lib/getActivationStart.js.map +0 -1
  171. package/build/esm/metrics/web-vitals/lib/getNavigationEntry.js +0 -15
  172. package/build/esm/metrics/web-vitals/lib/getNavigationEntry.js.map +0 -1
  173. package/build/esm/metrics/web-vitals/lib/getVisibilityWatcher.js +0 -42
  174. package/build/esm/metrics/web-vitals/lib/getVisibilityWatcher.js.map +0 -1
  175. package/build/esm/metrics/web-vitals/lib/globalListeners.js +0 -15
  176. package/build/esm/metrics/web-vitals/lib/globalListeners.js.map +0 -1
  177. package/build/esm/metrics/web-vitals/lib/initMetric.js +0 -32
  178. package/build/esm/metrics/web-vitals/lib/initMetric.js.map +0 -1
  179. package/build/esm/metrics/web-vitals/lib/initUnique.js +0 -14
  180. package/build/esm/metrics/web-vitals/lib/initUnique.js.map +0 -1
  181. package/build/esm/metrics/web-vitals/lib/observe.js +0 -18
  182. package/build/esm/metrics/web-vitals/lib/observe.js.map +0 -1
  183. package/build/esm/metrics/web-vitals/lib/onHidden.js +0 -14
  184. package/build/esm/metrics/web-vitals/lib/onHidden.js.map +0 -1
  185. package/build/esm/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js +0 -29
  186. package/build/esm/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js.map +0 -1
  187. package/build/esm/metrics/web-vitals/lib/runOnce.js +0 -12
  188. package/build/esm/metrics/web-vitals/lib/runOnce.js.map +0 -1
  189. package/build/esm/metrics/web-vitals/lib/whenActivated.js +0 -12
  190. package/build/esm/metrics/web-vitals/lib/whenActivated.js.map +0 -1
  191. package/build/esm/metrics/web-vitals/lib/whenIdleOrHidden.js +0 -20
  192. package/build/esm/metrics/web-vitals/lib/whenIdleOrHidden.js.map +0 -1
  193. package/build/esm/metrics/web-vitals/onFCP.js +0 -34
  194. package/build/esm/metrics/web-vitals/onFCP.js.map +0 -1
  195. package/build/esm/metrics/web-vitals/onTTFB.js +0 -32
  196. package/build/esm/metrics/web-vitals/onTTFB.js.map +0 -1
  197. package/build/esm/metrics/webVitalSpans.js.map +0 -1
  198. package/build/types/instrument/dom.d.ts.map +0 -1
  199. package/build/types/instrument/history.d.ts.map +0 -1
  200. package/build/types/instrument/location.d.ts.map +0 -1
  201. package/build/types/instrument/xhr.d.ts.map +0 -1
  202. package/build/types/metrics/browserMetrics.d.ts.map +0 -1
  203. package/build/types/metrics/elementTiming.d.ts.map +0 -1
  204. package/build/types/metrics/inp.d.ts.map +0 -1
  205. package/build/types/metrics/instrument.d.ts.map +0 -1
  206. package/build/types/metrics/lcp.d.ts.map +0 -1
  207. package/build/types/metrics/resourceTiming.d.ts.map +0 -1
  208. package/build/types/metrics/userTiming.d.ts.map +0 -1
  209. package/build/types/metrics/utils.d.ts.map +0 -1
  210. package/build/types/metrics/web-vitals/getCLS.d.ts +0 -26
  211. package/build/types/metrics/web-vitals/getCLS.d.ts.map +0 -1
  212. package/build/types/metrics/web-vitals/getINP.d.ts +0 -34
  213. package/build/types/metrics/web-vitals/getINP.d.ts.map +0 -1
  214. package/build/types/metrics/web-vitals/getLCP.d.ts +0 -16
  215. package/build/types/metrics/web-vitals/getLCP.d.ts.map +0 -1
  216. package/build/types/metrics/web-vitals/lib/InteractionManager.d.ts +0 -37
  217. package/build/types/metrics/web-vitals/lib/InteractionManager.d.ts.map +0 -1
  218. package/build/types/metrics/web-vitals/lib/LCPEntryManager.d.ts +0 -5
  219. package/build/types/metrics/web-vitals/lib/LCPEntryManager.d.ts.map +0 -1
  220. package/build/types/metrics/web-vitals/lib/LayoutShiftManager.d.ts +0 -7
  221. package/build/types/metrics/web-vitals/lib/LayoutShiftManager.d.ts.map +0 -1
  222. package/build/types/metrics/web-vitals/lib/bindReporter.d.ts +0 -7
  223. package/build/types/metrics/web-vitals/lib/bindReporter.d.ts.map +0 -1
  224. package/build/types/metrics/web-vitals/lib/generateUniqueID.d.ts +0 -7
  225. package/build/types/metrics/web-vitals/lib/generateUniqueID.d.ts.map +0 -1
  226. package/build/types/metrics/web-vitals/lib/getActivationStart.d.ts +0 -2
  227. package/build/types/metrics/web-vitals/lib/getActivationStart.d.ts.map +0 -1
  228. package/build/types/metrics/web-vitals/lib/getNavigationEntry.d.ts +0 -2
  229. package/build/types/metrics/web-vitals/lib/getNavigationEntry.d.ts.map +0 -1
  230. package/build/types/metrics/web-vitals/lib/getVisibilityWatcher.d.ts +0 -5
  231. package/build/types/metrics/web-vitals/lib/getVisibilityWatcher.d.ts.map +0 -1
  232. package/build/types/metrics/web-vitals/lib/globalListeners.d.ts.map +0 -1
  233. package/build/types/metrics/web-vitals/lib/initMetric.d.ts +0 -21
  234. package/build/types/metrics/web-vitals/lib/initMetric.d.ts.map +0 -1
  235. package/build/types/metrics/web-vitals/lib/initUnique.d.ts +0 -7
  236. package/build/types/metrics/web-vitals/lib/initUnique.d.ts.map +0 -1
  237. package/build/types/metrics/web-vitals/lib/observe.d.ts +0 -23
  238. package/build/types/metrics/web-vitals/lib/observe.d.ts.map +0 -1
  239. package/build/types/metrics/web-vitals/lib/onHidden.d.ts +0 -15
  240. package/build/types/metrics/web-vitals/lib/onHidden.d.ts.map +0 -1
  241. package/build/types/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.d.ts +0 -15
  242. package/build/types/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.d.ts.map +0 -1
  243. package/build/types/metrics/web-vitals/lib/runOnce.d.ts +0 -2
  244. package/build/types/metrics/web-vitals/lib/runOnce.d.ts.map +0 -1
  245. package/build/types/metrics/web-vitals/lib/whenActivated.d.ts +0 -2
  246. package/build/types/metrics/web-vitals/lib/whenActivated.d.ts.map +0 -1
  247. package/build/types/metrics/web-vitals/lib/whenIdleOrHidden.d.ts +0 -6
  248. package/build/types/metrics/web-vitals/lib/whenIdleOrHidden.d.ts.map +0 -1
  249. package/build/types/metrics/web-vitals/onFCP.d.ts +0 -11
  250. package/build/types/metrics/web-vitals/onFCP.d.ts.map +0 -1
  251. package/build/types/metrics/web-vitals/onTTFB.d.ts +0 -20
  252. package/build/types/metrics/web-vitals/onTTFB.d.ts.map +0 -1
  253. package/build/types/metrics/web-vitals/types/base.d.ts +0 -103
  254. package/build/types/metrics/web-vitals/types/base.d.ts.map +0 -1
  255. package/build/types/metrics/web-vitals/types/cls.d.ts +0 -58
  256. package/build/types/metrics/web-vitals/types/cls.d.ts.map +0 -1
  257. package/build/types/metrics/web-vitals/types/fcp.d.ts +0 -47
  258. package/build/types/metrics/web-vitals/types/fcp.d.ts.map +0 -1
  259. package/build/types/metrics/web-vitals/types/inp.d.ts +0 -150
  260. package/build/types/metrics/web-vitals/types/inp.d.ts.map +0 -1
  261. package/build/types/metrics/web-vitals/types/lcp.d.ts +0 -74
  262. package/build/types/metrics/web-vitals/types/lcp.d.ts.map +0 -1
  263. package/build/types/metrics/web-vitals/types/ttfb.d.ts +0 -60
  264. package/build/types/metrics/web-vitals/types/ttfb.d.ts.map +0 -1
  265. package/build/types/metrics/web-vitals/types.d.ts +0 -78
  266. package/build/types/metrics/web-vitals/types.d.ts.map +0 -1
  267. package/build/types/metrics/webVitalSpans.d.ts.map +0 -1
  268. /package/build/cjs/{instrument → instrumentation}/dom.js +0 -0
  269. /package/build/cjs/{instrument → instrumentation}/history.js +0 -0
  270. /package/build/cjs/{instrument → instrumentation}/location.js +0 -0
  271. /package/build/cjs/{instrument → instrumentation}/xhr.js +0 -0
  272. /package/build/cjs/{metrics → performance}/resourceTiming.js +0 -0
  273. /package/build/cjs/{metrics → web-vitals}/lcp.js +0 -0
  274. /package/build/esm/{instrument → instrumentation}/dom.js +0 -0
  275. /package/build/esm/{instrument → instrumentation}/history.js +0 -0
  276. /package/build/esm/{instrument → instrumentation}/location.js +0 -0
  277. /package/build/esm/{instrument → instrumentation}/xhr.js +0 -0
  278. /package/build/esm/{metrics → performance}/resourceTiming.js +0 -0
  279. /package/build/esm/{metrics → web-vitals}/lcp.js +0 -0
  280. /package/build/types/{instrument → instrumentation}/dom.d.ts +0 -0
  281. /package/build/types/{instrument → instrumentation}/history.d.ts +0 -0
  282. /package/build/types/{instrument → instrumentation}/location.d.ts +0 -0
  283. /package/build/types/{instrument → instrumentation}/xhr.d.ts +0 -0
  284. /package/build/types/{metrics → performance}/elementTiming.d.ts +0 -0
  285. /package/build/types/{metrics → performance}/resourceTiming.d.ts +0 -0
  286. /package/build/types/{metrics → performance}/userTiming.d.ts +0 -0
  287. /package/build/types/{metrics → web-vitals}/inp.d.ts +0 -0
  288. /package/build/types/{metrics → web-vitals}/lcp.d.ts +0 -0
@@ -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":"11.0.0-alpha.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;;;;"}
@@ -1,49 +1,25 @@
1
- import { browserPerformanceTimeOrigin, spanToJSON, setMeasurement, getActiveSpan, parseUrl, filterCollectedUrl, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, debug, getComponentName } from '@sentry/core';
1
+ import { browserPerformanceTimeOrigin, spanToJSON, getActiveSpan, parseUrl, filterCollectedUrl, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, setMeasurement, getComponentName } from '@sentry/core';
2
+ import { SENTRY_OP, URL_FULL } from '@sentry/conventions/attributes';
3
+ import { BROWSER_BROWSER_PAINT_SPAN_OP } from '@sentry/conventions/op';
2
4
  import { htmlTreeAsString } from '../htmlTreeAsString.js';
5
+ import { addPerformanceInstrumentationHandler } from '../instrumentation/performanceObserver.js';
3
6
  import { WINDOW } from '../types.js';
4
- import { addPerformanceInstrumentationHandler, addLcpInstrumentationHandler, addClsInstrumentationHandler, addTtfbInstrumentationHandler } from './instrument.js';
5
- import { isValidLcpMetric } from './lcp.js';
6
7
  import { resourceTimingToSpanAttributes } from './resourceTiming.js';
7
8
  import { getBrowserPerformanceAPI, msToSec, startAndEndSpan, isMeasurementValue } from './utils.js';
8
- import { getActivationStart } from './web-vitals/lib/getActivationStart.js';
9
- import { getNavigationEntry } from './web-vitals/lib/getNavigationEntry.js';
10
- import { getVisibilityWatcher } from './web-vitals/lib/getVisibilityWatcher.js';
11
- import { DEBUG_BUILD } from '../debug-build.js';
12
- import { URL_FULL, SENTRY_OP } from '@sentry/conventions/attributes';
13
- import { BROWSER_BROWSER_PAINT_SPAN_OP } from '@sentry/conventions/op';
14
9
 
15
10
  const MAX_INT_AS_BYTES = 2147483647;
16
11
  let _performanceCursor = 0;
17
- let _measurements = {};
18
- let _lcpEntry;
19
- let _clsEntry;
20
- function startTrackingWebVitals({ trackCls, trackLcp }) {
21
- const performance = getBrowserPerformanceAPI();
22
- if (performance && browserPerformanceTimeOrigin()) {
23
- const lcpCleanupCallback = trackLcp ? _trackLCP() : void 0;
24
- const clsCleanupCallback = trackCls ? _trackCLS() : void 0;
25
- const ttfbCleanupCallback = _trackTtfb();
26
- const fpFcpCleanupCallback = _trackFpFcp();
27
- return () => {
28
- ttfbCleanupCallback();
29
- fpFcpCleanupCallback();
30
- lcpCleanupCallback?.();
31
- clsCleanupCallback?.();
32
- };
33
- }
34
- return () => void 0;
35
- }
36
12
  function startTrackingLongTasks() {
37
13
  addPerformanceInstrumentationHandler("longtask", ({ entries }) => {
38
14
  const parent = getActiveSpan();
39
15
  if (!parent) {
40
16
  return;
41
17
  }
42
- const { op: parentOp, start_timestamp: parentStartTimestamp } = spanToJSON(parent);
18
+ const { attributes: parentAttributes, start_timestamp: parentStartTimestamp } = spanToJSON(parent);
43
19
  for (const entry of entries) {
44
20
  const startTime = msToSec(browserPerformanceTimeOrigin() + entry.startTime);
45
21
  const duration = msToSec(entry.duration);
46
- if (parentOp === "navigation" && parentStartTimestamp && startTime < parentStartTimestamp) {
22
+ if (parentAttributes[SENTRY_OP] === "navigation" && parentStartTimestamp && startTime < parentStartTimestamp) {
47
23
  continue;
48
24
  }
49
25
  startAndEndSpan(parent, startTime, startTime + duration, {
@@ -67,7 +43,10 @@ function startTrackingLongAnimationFrames() {
67
43
  continue;
68
44
  }
69
45
  const startTime = msToSec(browserPerformanceTimeOrigin() + entry.startTime);
70
- const { start_timestamp: parentStartTimestamp, op: parentOp } = spanToJSON(parent);
46
+ const {
47
+ start_timestamp: parentStartTimestamp,
48
+ attributes: { [SENTRY_OP]: parentOp }
49
+ } = spanToJSON(parent);
71
50
  if (parentOp === "navigation" && parentStartTimestamp && startTime < parentStartTimestamp) {
72
51
  continue;
73
52
  }
@@ -124,49 +103,6 @@ function startTrackingInteractions() {
124
103
  }
125
104
  });
126
105
  }
127
- function _trackCLS() {
128
- return addClsInstrumentationHandler(({ metric }) => {
129
- const entry = metric.entries[metric.entries.length - 1];
130
- if (!entry) {
131
- return;
132
- }
133
- _measurements["cls"] = { value: metric.value, unit: "" };
134
- _clsEntry = entry;
135
- }, true);
136
- }
137
- function _trackLCP() {
138
- return addLcpInstrumentationHandler(({ metric }) => {
139
- const entry = metric.entries[metric.entries.length - 1];
140
- if (!entry || !isValidLcpMetric(metric.value)) {
141
- return;
142
- }
143
- _measurements["lcp"] = { value: metric.value, unit: "millisecond" };
144
- _lcpEntry = entry;
145
- }, true);
146
- }
147
- function _trackTtfb() {
148
- return addTtfbInstrumentationHandler(({ metric }) => {
149
- const entry = metric.entries[metric.entries.length - 1];
150
- if (!entry) {
151
- return;
152
- }
153
- _measurements["ttfb"] = { value: metric.value, unit: "millisecond" };
154
- });
155
- }
156
- function _trackFpFcp() {
157
- return addPerformanceInstrumentationHandler("paint", ({ entries }) => {
158
- const firstHidden = getVisibilityWatcher();
159
- for (const entry of entries) {
160
- const shouldRecord = entry.startTime < firstHidden.firstHiddenTime;
161
- if (entry.name === "first-paint" && shouldRecord) {
162
- _measurements["fp"] = { value: entry.startTime, unit: "millisecond" };
163
- }
164
- if (entry.name === "first-contentful-paint" && shouldRecord) {
165
- _measurements["fcp"] = { value: entry.startTime, unit: "millisecond" };
166
- }
167
- }
168
- });
169
- }
170
106
  function addPerformanceEntries(span, options) {
171
107
  const performance = getBrowserPerformanceAPI();
172
108
  const origin = browserPerformanceTimeOrigin();
@@ -176,7 +112,7 @@ function addPerformanceEntries(span, options) {
176
112
  const { spanStreamingEnabled, ignoreResourceSpans } = options;
177
113
  const timeOrigin = msToSec(origin);
178
114
  const performanceEntries = performance.getEntries();
179
- const { op, start_timestamp: transactionStartTime } = spanToJSON(span);
115
+ const { attributes, start_timestamp: transactionStartTime } = spanToJSON(span);
180
116
  performanceEntries.slice(_performanceCursor).forEach((entry) => {
181
117
  const startTime = msToSec(entry.startTime);
182
118
  const duration = msToSec(
@@ -186,7 +122,7 @@ function addPerformanceEntries(span, options) {
186
122
  // TODO: Investigate why this happens and how to properly mitigate. For now, this is a workaround to prevent transactions being dropped due to negative duration spans.
187
123
  Math.max(0, entry.duration)
188
124
  );
189
- if (op === "navigation" && transactionStartTime && timeOrigin + startTime < transactionStartTime) {
125
+ if (attributes[SENTRY_OP] === "navigation" && transactionStartTime && timeOrigin + startTime < transactionStartTime) {
190
126
  return;
191
127
  }
192
128
  switch (entry.entryType) {
@@ -215,55 +151,6 @@ function addPerformanceEntries(span, options) {
215
151
  _performanceCursor = Math.max(performanceEntries.length - 1, 0);
216
152
  _trackNavigator(span, spanStreamingEnabled);
217
153
  }
218
- function addWebVitalsToSpan(span, options) {
219
- const origin = browserPerformanceTimeOrigin();
220
- if (!getBrowserPerformanceAPI()?.getEntries || !origin) {
221
- resetWebVitalState();
222
- return;
223
- }
224
- const { spanStreamingEnabled, recordClsOnPageloadSpan, recordLcpOnPageloadSpan } = options;
225
- const timeOrigin = msToSec(origin);
226
- if (spanToJSON(span).op === "pageload") {
227
- _addTtfbRequestTimeToMeasurements(_measurements);
228
- if (spanStreamingEnabled) {
229
- const setAttr = (shortWebVitalName, value, customAttrName) => {
230
- const attrKey = customAttrName ?? `browser.web_vital.${shortWebVitalName}.value`;
231
- span.setAttribute(attrKey, value);
232
- DEBUG_BUILD && debug.log("Setting web vital attribute", { [attrKey]: value }, "on pageload span");
233
- };
234
- ["ttfb", "fp", "fcp"].forEach((measurementName) => {
235
- if (_measurements[measurementName]) {
236
- setAttr(measurementName, _measurements[measurementName].value);
237
- }
238
- });
239
- if (_measurements["ttfb.requestTime"]) {
240
- setAttr("ttfb.requestTime", _measurements["ttfb.requestTime"].value, "browser.web_vital.ttfb.request_time");
241
- }
242
- } else {
243
- if (!recordClsOnPageloadSpan) {
244
- delete _measurements.cls;
245
- }
246
- if (!recordLcpOnPageloadSpan) {
247
- delete _measurements.lcp;
248
- }
249
- Object.entries(_measurements).forEach(([measurementName, measurement]) => {
250
- setMeasurement(measurementName, measurement.value, measurement.unit, span);
251
- });
252
- _setWebVitalAttributes(span, options);
253
- }
254
- span.setAttribute(spanStreamingEnabled ? "browser.performance.time_origin" : "performance.timeOrigin", timeOrigin);
255
- span.setAttribute(
256
- spanStreamingEnabled ? "browser.performance.navigation.activation_start" : "performance.activationStart",
257
- getActivationStart()
258
- );
259
- }
260
- resetWebVitalState();
261
- }
262
- function resetWebVitalState() {
263
- _lcpEntry = void 0;
264
- _clsEntry = void 0;
265
- _measurements = {};
266
- }
267
154
  function _addPaintSpan(span, entry, startTime, duration, timeOrigin) {
268
155
  const startTimestamp = timeOrigin + startTime;
269
156
  startAndEndSpan(span, startTimestamp, startTimestamp + duration, {
@@ -390,7 +277,7 @@ function _trackNavigator(span, spanStreamingEnabled) {
390
277
  if (isMeasurementValue(connection.rtt)) {
391
278
  if (spanStreamingEnabled) {
392
279
  span.setAttribute("network.connection.rtt", connection.rtt);
393
- } else if (spanToJSON(span).op === "pageload") {
280
+ } else if (spanToJSON(span).attributes[SENTRY_OP] === "pageload") {
394
281
  setMeasurement("connection.rtt", connection.rtt, "millisecond");
395
282
  }
396
283
  }
@@ -410,31 +297,6 @@ function _trackNavigator(span, spanStreamingEnabled) {
410
297
  }
411
298
  }
412
299
  }
413
- function _setWebVitalAttributes(span, options) {
414
- if (_lcpEntry && options.recordLcpOnPageloadSpan) {
415
- if (_lcpEntry.element) {
416
- span.setAttribute("lcp.element", htmlTreeAsString(_lcpEntry.element));
417
- }
418
- if (_lcpEntry.id) {
419
- span.setAttribute("lcp.id", _lcpEntry.id);
420
- }
421
- if (_lcpEntry.url) {
422
- span.setAttribute("lcp.url", _lcpEntry.url.trim().slice(0, 200));
423
- }
424
- if (_lcpEntry.loadTime != null) {
425
- span.setAttribute("lcp.loadTime", _lcpEntry.loadTime);
426
- }
427
- if (_lcpEntry.renderTime != null) {
428
- span.setAttribute("lcp.renderTime", _lcpEntry.renderTime);
429
- }
430
- span.setAttribute("lcp.size", _lcpEntry.size);
431
- }
432
- if (_clsEntry?.sources && options.recordClsOnPageloadSpan) {
433
- _clsEntry.sources.forEach(
434
- (source, index) => span.setAttribute(`cls.source.${index + 1}`, htmlTreeAsString(source.node))
435
- );
436
- }
437
- }
438
300
  function _setResourceRequestAttributes(entry, attributes, properties) {
439
301
  properties.forEach(([entryKey, attributeKey]) => {
440
302
  const entryVal = entry[entryKey];
@@ -443,19 +305,6 @@ function _setResourceRequestAttributes(entry, attributes, properties) {
443
305
  }
444
306
  });
445
307
  }
446
- function _addTtfbRequestTimeToMeasurements(_measurements2) {
447
- const navEntry = getNavigationEntry(false);
448
- if (!navEntry) {
449
- return;
450
- }
451
- const { responseStart, requestStart } = navEntry;
452
- if (requestStart <= responseStart) {
453
- _measurements2["ttfb.requestTime"] = {
454
- value: responseStart - requestStart,
455
- unit: "millisecond"
456
- };
457
- }
458
- }
459
308
 
460
- export { _addNavigationSpans, _addResourceSpans, _setResourceRequestAttributes, addPerformanceEntries, addWebVitalsToSpan, startTrackingInteractions, startTrackingLongAnimationFrames, startTrackingLongTasks, startTrackingWebVitals };
461
- //# sourceMappingURL=browserMetrics.js.map
309
+ export { _addNavigationSpans, _addResourceSpans, _setResourceRequestAttributes, addPerformanceEntries, startTrackingInteractions, startTrackingLongAnimationFrames, startTrackingLongTasks };
310
+ //# sourceMappingURL=entries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entries.js","sources":["../../../src/performance/entries.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Span, SpanAttributes, StartSpanOptions } from '@sentry/core';\nimport {\n browserPerformanceTimeOrigin,\n getActiveSpan,\n getComponentName,\n parseUrl,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n setMeasurement,\n spanToJSON,\n filterCollectedUrl,\n} from '@sentry/core';\nimport { SENTRY_OP, URL_FULL } from '@sentry/conventions/attributes';\nimport { BROWSER_BROWSER_PAINT_SPAN_OP } from '@sentry/conventions/op';\nimport { htmlTreeAsString } from '../htmlTreeAsString';\nimport {\n addPerformanceInstrumentationHandler,\n type PerformanceLongAnimationFrameTiming,\n} from '../instrumentation/performanceObserver';\nimport { WINDOW } from '../types';\nimport { resourceTimingToSpanAttributes } from './resourceTiming';\nimport { getBrowserPerformanceAPI, isMeasurementValue, msToSec, startAndEndSpan } from './utils';\n\ninterface NavigatorNetworkInformation {\n readonly connection?: NetworkInformation;\n}\n\n// http://wicg.github.io/netinfo/#connection-types\ntype ConnectionType = 'bluetooth' | 'cellular' | 'ethernet' | 'mixed' | 'none' | 'other' | 'unknown' | 'wifi' | 'wimax';\n\n// http://wicg.github.io/netinfo/#effectiveconnectiontype-enum\ntype EffectiveConnectionType = '2g' | '3g' | '4g' | 'slow-2g';\n\n// http://wicg.github.io/netinfo/#dom-megabit\ntype Megabit = number;\n// http://wicg.github.io/netinfo/#dom-millisecond\ntype Millisecond = number;\n\n// http://wicg.github.io/netinfo/#networkinformation-interface\ninterface NetworkInformation extends EventTarget {\n // http://wicg.github.io/netinfo/#type-attribute\n readonly type?: ConnectionType;\n // http://wicg.github.io/netinfo/#effectivetype-attribute\n readonly effectiveType?: EffectiveConnectionType;\n // http://wicg.github.io/netinfo/#downlinkmax-attribute\n readonly downlinkMax?: Megabit;\n // http://wicg.github.io/netinfo/#downlink-attribute\n readonly downlink?: Megabit;\n // http://wicg.github.io/netinfo/#rtt-attribute\n readonly rtt?: Millisecond;\n // http://wicg.github.io/netinfo/#savedata-attribute\n readonly saveData?: boolean;\n // http://wicg.github.io/netinfo/#handling-changes-to-the-underlying-connection\n onchange?: EventListener;\n}\n\n// https://w3c.github.io/device-memory/#sec-device-memory-js-api\ninterface NavigatorDeviceMemory {\n readonly deviceMemory?: number;\n}\n\nconst MAX_INT_AS_BYTES = 2147483647;\n\nlet _performanceCursor: number = 0;\n\n/**\n * Start tracking long tasks.\n */\nexport function startTrackingLongTasks(): void {\n addPerformanceInstrumentationHandler('longtask', ({ entries }) => {\n const parent = getActiveSpan();\n if (!parent) {\n return;\n }\n\n const { attributes: parentAttributes, start_timestamp: parentStartTimestamp } = spanToJSON(parent);\n\n for (const entry of entries) {\n const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);\n const duration = msToSec(entry.duration);\n\n if (parentAttributes[SENTRY_OP] === 'navigation' && parentStartTimestamp && startTime < parentStartTimestamp) {\n // Skip adding a span if the long task started before the navigation started.\n // `startAndEndSpan` will otherwise adjust the parent's start time to the span's start\n // time, potentially skewing the duration of the actual navigation as reported via our\n // routing instrumentations\n continue;\n }\n\n startAndEndSpan(parent, startTime, startTime + duration, {\n name: 'Main UI thread blocked',\n op: 'ui.long_task',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n },\n });\n }\n });\n}\n\n/**\n * Start tracking long animation frames.\n */\nexport function startTrackingLongAnimationFrames(): void {\n // NOTE: the current web-vitals version (3.5.2) does not support long-animation-frame, so\n // we directly observe `long-animation-frame` events instead of through the web-vitals\n // `observe` helper function.\n const observer = new PerformanceObserver(list => {\n const parent = getActiveSpan();\n if (!parent) {\n return;\n }\n for (const entry of list.getEntries() as PerformanceLongAnimationFrameTiming[]) {\n if (!entry.scripts[0]) {\n continue;\n }\n\n const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);\n\n const {\n start_timestamp: parentStartTimestamp,\n attributes: { [SENTRY_OP]: parentOp },\n } = spanToJSON(parent);\n\n if (parentOp === 'navigation' && parentStartTimestamp && startTime < parentStartTimestamp) {\n // Skip adding the span if the long animation frame started before the navigation started.\n // `startAndEndSpan` will otherwise adjust the parent's start time to the span's start\n // time, potentially skewing the duration of the actual navigation as reported via our\n // routing instrumentations\n continue;\n }\n const duration = msToSec(entry.duration);\n\n const attributes: SpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n };\n\n const initialScript = entry.scripts[0];\n const { invoker, invokerType, sourceURL, sourceFunctionName, sourceCharPosition } = initialScript;\n attributes['browser.script.invoker'] = invoker;\n attributes['browser.script.invoker_type'] = invokerType;\n if (sourceURL) {\n attributes['code.filepath'] = sourceURL;\n }\n if (sourceFunctionName) {\n attributes['code.function'] = sourceFunctionName;\n }\n if (sourceCharPosition !== -1) {\n attributes['browser.script.source_char_position'] = sourceCharPosition;\n }\n\n startAndEndSpan(parent, startTime, startTime + duration, {\n name: 'Main UI thread blocked',\n op: 'ui.long_animation_frame',\n attributes,\n });\n }\n });\n\n observer.observe({ type: 'long-animation-frame', buffered: true });\n}\n\n/**\n * Start tracking interaction events.\n */\nexport function startTrackingInteractions(): void {\n addPerformanceInstrumentationHandler('event', ({ entries }) => {\n const parent = getActiveSpan();\n if (!parent) {\n return;\n }\n for (const entry of entries) {\n if (entry.name === 'click') {\n const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);\n const duration = msToSec(entry.duration);\n\n const spanOptions: StartSpanOptions & Required<Pick<StartSpanOptions, 'attributes'>> = {\n name: htmlTreeAsString(entry.target),\n op: `ui.interaction.${entry.name}`,\n startTime: startTime,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n },\n };\n\n const componentName = getComponentName(entry.target);\n if (componentName) {\n spanOptions.attributes['ui.component_name'] = componentName;\n }\n\n startAndEndSpan(parent, startTime, startTime + duration, spanOptions);\n }\n }\n });\n}\n\ninterface AddPerformanceEntriesOptions {\n /**\n * Resource spans with `op`s matching strings in the array will not be emitted.\n *\n * Default: []\n */\n ignoreResourceSpans: Array<'resource.script' | 'resource.css' | 'resource.img' | 'resource.other' | string>;\n\n /**\n * Whether span streaming is enabled.\n */\n spanStreamingEnabled?: boolean;\n}\n\n/** Add performance related spans to a transaction */\nexport function addPerformanceEntries(span: Span, options: AddPerformanceEntriesOptions): void {\n const performance = getBrowserPerformanceAPI();\n const origin = browserPerformanceTimeOrigin();\n if (!performance?.getEntries || !origin) {\n // Gatekeeper if performance API not available\n return;\n }\n\n const { spanStreamingEnabled, ignoreResourceSpans } = options;\n\n const timeOrigin = msToSec(origin);\n\n const performanceEntries = performance.getEntries();\n\n const { attributes, start_timestamp: transactionStartTime } = spanToJSON(span);\n\n performanceEntries.slice(_performanceCursor).forEach(entry => {\n const startTime = msToSec(entry.startTime);\n const duration = msToSec(\n // Inexplicably, Chrome sometimes emits a negative duration. We need to work around this.\n // There is a SO post attempting to explain this, but it leaves one with open questions: https://stackoverflow.com/questions/23191918/peformance-getentries-and-negative-duration-display\n // The way we clamp the value is probably not accurate, since we have observed this happen for things that may take a while to load, like for example the replay worker.\n // TODO: Investigate why this happens and how to properly mitigate. For now, this is a workaround to prevent transactions being dropped due to negative duration spans.\n Math.max(0, entry.duration),\n );\n\n if (\n attributes[SENTRY_OP] === 'navigation' &&\n transactionStartTime &&\n timeOrigin + startTime < transactionStartTime\n ) {\n return;\n }\n\n switch (entry.entryType) {\n case 'navigation': {\n _addNavigationSpans(span, entry as PerformanceNavigationTiming, timeOrigin);\n break;\n }\n case 'paint': {\n _addPaintSpan(span, entry, startTime, duration, timeOrigin);\n break;\n }\n case 'resource': {\n _addResourceSpans(\n span,\n entry as PerformanceResourceTiming,\n entry.name,\n startTime,\n duration,\n timeOrigin,\n ignoreResourceSpans,\n );\n break;\n }\n // Ignore other entry types.\n }\n });\n\n _performanceCursor = Math.max(performanceEntries.length - 1, 0);\n\n _trackNavigator(span, spanStreamingEnabled);\n}\n\n/** Create a span for a browser paint performance entry. */\nfunction _addPaintSpan(\n span: Span,\n entry: PerformanceEntry,\n startTime: number,\n duration: number,\n timeOrigin: number,\n): void {\n const startTimestamp = timeOrigin + startTime;\n\n startAndEndSpan(span, startTimestamp, startTimestamp + duration, {\n name: entry.name,\n attributes: {\n [SENTRY_OP]: BROWSER_BROWSER_PAINT_SPAN_OP,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.resource.browser.metrics',\n },\n });\n}\n\n/**\n * Instrument navigation entries\n * exported only for tests\n */\nexport function _addNavigationSpans(span: Span, entry: PerformanceNavigationTiming, timeOrigin: number): void {\n _addPerformanceNavigationTiming(span, entry, 'unloadEvent', timeOrigin, 'unload_event');\n _addPerformanceNavigationTiming(span, entry, 'redirect', timeOrigin, 'redirect');\n _addPerformanceNavigationTiming(span, entry, 'domContentLoadedEvent', timeOrigin, 'dom_content_loaded_event');\n _addPerformanceNavigationTiming(span, entry, 'loadEvent', timeOrigin, 'load_event');\n _addPerformanceNavigationTiming(span, entry, 'connect', timeOrigin, 'connect');\n _addPerformanceNavigationTiming(span, entry, 'secureConnection', timeOrigin, 'tls_ssl');\n _addPerformanceNavigationTiming(span, entry, 'fetch', timeOrigin, 'cache');\n _addPerformanceNavigationTiming(span, entry, 'domainLookup', timeOrigin, 'dns');\n\n _addRequest(span, entry, timeOrigin);\n}\n\ntype StartEventName =\n | 'secureConnection'\n | 'fetch'\n | 'domainLookup'\n | 'unloadEvent'\n | 'redirect'\n | 'connect'\n | 'domContentLoadedEvent'\n | 'loadEvent';\n\ntype EndEventName =\n | 'domainLookupStart'\n | 'domainLookupEnd'\n | 'unloadEventEnd'\n | 'redirectEnd'\n | 'connectEnd'\n | 'domContentLoadedEventEnd'\n | 'loadEventEnd';\n\n/** Create performance navigation related spans */\nfunction _addPerformanceNavigationTiming(\n span: Span,\n entry: PerformanceNavigationTiming,\n event: StartEventName,\n timeOrigin: number,\n name: string = event,\n): void {\n const eventEnd = _getEndPropertyNameForNavigationTiming(event) satisfies keyof PerformanceNavigationTiming;\n const end = entry[eventEnd];\n const start = entry[`${event}Start`];\n if (!start || !end) {\n return;\n }\n startAndEndSpan(span, timeOrigin + msToSec(start), timeOrigin + msToSec(end), {\n op: `browser.${name}`,\n name: entry.name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n ...(event === 'redirect' && entry.redirectCount != null ? { 'http.redirect_count': entry.redirectCount } : {}),\n },\n });\n}\n\nfunction _getEndPropertyNameForNavigationTiming(event: StartEventName): EndEventName {\n if (event === 'secureConnection') {\n return 'connectEnd';\n }\n if (event === 'fetch') {\n return 'domainLookupStart';\n }\n return `${event}End`;\n}\n\n/** Create request and response related spans */\nfunction _addRequest(span: Span, entry: PerformanceNavigationTiming, timeOrigin: number): void {\n const requestStartTimestamp = timeOrigin + msToSec(entry.requestStart);\n const responseEndTimestamp = timeOrigin + msToSec(entry.responseEnd);\n const responseStartTimestamp = timeOrigin + msToSec(entry.responseStart);\n if (entry.responseEnd) {\n // It is possible that we are collecting these metrics when the page hasn't finished loading yet, for example when the HTML slowly streams in.\n // In this case, ie. when the document request hasn't finished yet, `entry.responseEnd` will be 0.\n // In order not to produce faulty spans, where the end timestamp is before the start timestamp, we will only collect\n // these spans when the responseEnd value is available. The backend (Relay) would drop the entire span if it contained faulty spans.\n startAndEndSpan(span, requestStartTimestamp, responseEndTimestamp, {\n op: 'browser.request',\n name: entry.name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n },\n });\n\n startAndEndSpan(span, responseStartTimestamp, responseEndTimestamp, {\n op: 'browser.response',\n name: entry.name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n },\n });\n }\n}\n\n/**\n * Create resource-related spans.\n * Exported only for tests.\n */\nexport function _addResourceSpans(\n span: Span,\n entry: PerformanceResourceTiming,\n resourceUrl: string,\n startTime: number,\n duration: number,\n timeOrigin: number,\n ignoredResourceSpanOps?: Array<string>,\n): void {\n // we already instrument based on fetch and xhr, so we don't need to\n // duplicate spans here.\n if (entry.initiatorType === 'xmlhttprequest' || entry.initiatorType === 'fetch') {\n return;\n }\n\n const op = entry.initiatorType ? `resource.${entry.initiatorType}` : 'resource.other';\n if (ignoredResourceSpanOps?.includes(op)) {\n return;\n }\n\n const attributes: SpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.resource.browser.metrics',\n };\n\n const parsedUrl = parseUrl(resourceUrl);\n\n if (parsedUrl.protocol) {\n attributes['url.scheme'] = parsedUrl.protocol.split(':').pop(); // the protocol returned by parseUrl includes a :, but OTEL spec does not, so we remove it.\n }\n\n if (parsedUrl.host) {\n attributes['server.address'] = parsedUrl.host;\n }\n\n attributes['url.same_origin'] = resourceUrl.includes(WINDOW.location.origin);\n\n attributes[URL_FULL] = filterCollectedUrl(resourceUrl);\n\n _setResourceRequestAttributes(entry, attributes, [\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus\n ['responseStatus', 'http.response.status_code'],\n\n ['transferSize', 'http.response_transfer_size'],\n ['encodedBodySize', 'http.response_content_length'],\n ['decodedBodySize', 'http.decoded_response_content_length'],\n\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/renderBlockingStatus\n ['renderBlockingStatus', 'resource.render_blocking_status'],\n\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/deliveryType\n ['deliveryType', 'http.response_delivery_type'],\n ]);\n\n const attributesWithResourceTiming: SpanAttributes = { ...attributes, ...resourceTimingToSpanAttributes(entry) };\n\n const startTimestamp = timeOrigin + startTime;\n const endTimestamp = startTimestamp + duration;\n\n startAndEndSpan(span, startTimestamp, endTimestamp, {\n name: resourceUrl.replace(WINDOW.location.origin, ''),\n op,\n attributes: attributesWithResourceTiming,\n });\n}\n\n/**\n * Capture the information of the user agent.\n * TODO v11: Remove non-span-streaming attributes and measurements once we removed transactions\n */\nfunction _trackNavigator(span: Span, spanStreamingEnabled: boolean | undefined): void {\n const navigator = WINDOW.navigator as null | (Navigator & NavigatorNetworkInformation & NavigatorDeviceMemory);\n if (!navigator) {\n return;\n }\n\n // track network connectivity\n const connection = navigator.connection;\n if (connection) {\n if (connection.effectiveType) {\n span.setAttribute(\n spanStreamingEnabled ? 'network.connection.effective_type' : 'effectiveConnectionType',\n connection.effectiveType,\n );\n }\n\n if (connection.type) {\n span.setAttribute(spanStreamingEnabled ? 'network.connection.type' : 'connectionType', connection.type);\n }\n\n if (isMeasurementValue(connection.rtt)) {\n if (spanStreamingEnabled) {\n span.setAttribute('network.connection.rtt', connection.rtt);\n } else if (spanToJSON(span).attributes[SENTRY_OP] === 'pageload') {\n // Measurements are only recorded on the pageload span, matching the historical\n // behavior where `connection.rtt` was only flushed for pageload transactions.\n setMeasurement('connection.rtt', connection.rtt, 'millisecond');\n }\n }\n }\n\n if (isMeasurementValue(navigator.deviceMemory)) {\n if (spanStreamingEnabled) {\n span.setAttribute('device.memory.estimated_capacity', navigator.deviceMemory);\n } else {\n span.setAttribute('deviceMemory', `${navigator.deviceMemory} GB`);\n }\n }\n\n if (isMeasurementValue(navigator.hardwareConcurrency)) {\n if (spanStreamingEnabled) {\n span.setAttribute('device.processor_count', navigator.hardwareConcurrency);\n } else {\n span.setAttribute('hardwareConcurrency', String(navigator.hardwareConcurrency));\n }\n }\n}\n\ntype ExperimentalResourceTimingProperty =\n | 'renderBlockingStatus'\n | 'deliveryType'\n // For some reason, TS during build, errors on `responseStatus` not being a property of\n // PerformanceResourceTiming while it actually is. Hence, we're adding it here.\n // Perhaps because response status is not yet available in Webkit/Safari.\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus\n | 'responseStatus';\n\n/**\n * Use this to set any attributes we can take directly form the PerformanceResourceTiming entry.\n *\n * This is just a mapping function for entry->attribute to keep bundle-size minimal.\n * Experimental properties are also accepted (see {@link ExperimentalResourceTimingProperty}).\n * Assumes that all entry properties might be undefined for browser-specific differences.\n * Only accepts string and number values for now and also sets 0-values.\n */\nexport function _setResourceRequestAttributes(\n entry: Partial<PerformanceResourceTiming> & Partial<Record<ExperimentalResourceTimingProperty, number | string>>,\n attributes: SpanAttributes,\n properties: [keyof PerformanceResourceTiming | ExperimentalResourceTimingProperty, string][],\n): void {\n properties.forEach(([entryKey, attributeKey]) => {\n const entryVal = entry[entryKey];\n if (\n entryVal != null &&\n ((typeof entryVal === 'number' && entryVal < MAX_INT_AS_BYTES) || typeof entryVal === 'string')\n ) {\n attributes[attributeKey] = entryVal;\n }\n });\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceTiming.js","sources":["../../../src/performance/resourceTiming.ts"],"sourcesContent":["import type { SpanAttributes } from '@sentry/core';\nimport { browserPerformanceTimeOrigin } from '@sentry/core';\nimport { extractNetworkProtocol, getBrowserPerformanceAPI } from './utils';\n\nfunction getAbsoluteTime(time: number | undefined): number | undefined {\n // falsy values should be preserved so that we can later on drop undefined values and\n // preserve 0 vals for cross-origin resources without proper `Timing-Allow-Origin` header.\n return time ? ((browserPerformanceTimeOrigin() || performance.timeOrigin) + time) / 1000 : time;\n}\n\n/**\n * Converts a PerformanceResourceTiming entry to span data for the resource span. Most importantly,\n * it converts the timing values from timestamps relative to the `performance.timeOrigin` to absolute timestamps\n * in seconds.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming#timestamps\n *\n * @param resourceTiming\n * @returns An array where the first element is the attribute name and the second element is the attribute value.\n */\nexport function resourceTimingToSpanAttributes(resourceTiming: PerformanceResourceTiming): SpanAttributes {\n const timingSpanData: SpanAttributes = {};\n // Checking for only `undefined` and `null` is intentional because it's\n // valid for `nextHopProtocol` to be an empty string.\n if (resourceTiming.nextHopProtocol != undefined) {\n const { name, version } = extractNetworkProtocol(resourceTiming.nextHopProtocol);\n timingSpanData['network.protocol.version'] = version;\n timingSpanData['network.protocol.name'] = name;\n }\n\n if (!(browserPerformanceTimeOrigin() || getBrowserPerformanceAPI()?.timeOrigin)) {\n return timingSpanData;\n }\n\n return dropUndefinedKeysFromObject({\n ...timingSpanData,\n\n 'http.request.redirect_start': getAbsoluteTime(resourceTiming.redirectStart),\n 'http.request.redirect_end': getAbsoluteTime(resourceTiming.redirectEnd),\n\n 'http.request.worker_start': getAbsoluteTime(resourceTiming.workerStart),\n\n 'http.request.fetch_start': getAbsoluteTime(resourceTiming.fetchStart),\n\n 'http.request.domain_lookup_start': getAbsoluteTime(resourceTiming.domainLookupStart),\n 'http.request.domain_lookup_end': getAbsoluteTime(resourceTiming.domainLookupEnd),\n\n 'http.request.connect_start': getAbsoluteTime(resourceTiming.connectStart),\n 'http.request.secure_connection_start': getAbsoluteTime(resourceTiming.secureConnectionStart),\n 'http.request.connection_end': getAbsoluteTime(resourceTiming.connectEnd),\n\n 'http.request.request_start': getAbsoluteTime(resourceTiming.requestStart),\n\n 'http.request.response_start': getAbsoluteTime(resourceTiming.responseStart),\n 'http.request.response_end': getAbsoluteTime(resourceTiming.responseEnd),\n\n // For TTFB we actually want the relative time from timeOrigin to responseStart\n // This way, TTFB always measures the \"first page load\" experience.\n // see: https://web.dev/articles/ttfb#measure-resource-requests\n 'http.request.time_to_first_byte':\n resourceTiming.responseStart != null ? resourceTiming.responseStart / 1000 : undefined,\n });\n}\n\n/**\n * Remove properties with `undefined` as value from an object.\n * In contrast to `dropUndefinedKeys` in core this funciton only works on first-level\n * key-value objects and does not recursively go into object properties or arrays.\n */\nfunction dropUndefinedKeysFromObject<T extends object>(attrs: T): Partial<T> {\n return Object.fromEntries(Object.entries(attrs).filter(([, value]) => value != null)) as Partial<T>;\n}\n"],"names":[],"mappings":";;;AAIA,SAAS,gBAAgB,IAAA,EAA8C;AAGrE,EAAA,OAAO,SAAS,4BAAA,EAA6B,IAAK,WAAA,CAAY,UAAA,IAAc,QAAQ,GAAA,GAAO,IAAA;AAC7F;AAYO,SAAS,+BAA+B,cAAA,EAA2D;AACxG,EAAA,MAAM,iBAAiC,EAAC;AAGxC,EAAA,IAAI,cAAA,CAAe,mBAAmB,MAAA,EAAW;AAC/C,IAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAQ,GAAI,sBAAA,CAAuB,eAAe,eAAe,CAAA;AAC/E,IAAA,cAAA,CAAe,0BAA0B,CAAA,GAAI,OAAA;AAC7C,IAAA,cAAA,CAAe,uBAAuB,CAAA,GAAI,IAAA;AAAA,EAC5C;AAEA,EAAA,IAAI,EAAE,4BAAA,EAA6B,IAAK,wBAAA,IAA4B,UAAA,CAAA,EAAa;AAC/E,IAAA,OAAO,cAAA;AAAA,EACT;AAEA,EAAA,OAAO,2BAAA,CAA4B;AAAA,IACjC,GAAG,cAAA;AAAA,IAEH,6BAAA,EAA+B,eAAA,CAAgB,cAAA,CAAe,aAAa,CAAA;AAAA,IAC3E,2BAAA,EAA6B,eAAA,CAAgB,cAAA,CAAe,WAAW,CAAA;AAAA,IAEvE,2BAAA,EAA6B,eAAA,CAAgB,cAAA,CAAe,WAAW,CAAA;AAAA,IAEvE,0BAAA,EAA4B,eAAA,CAAgB,cAAA,CAAe,UAAU,CAAA;AAAA,IAErE,kCAAA,EAAoC,eAAA,CAAgB,cAAA,CAAe,iBAAiB,CAAA;AAAA,IACpF,gCAAA,EAAkC,eAAA,CAAgB,cAAA,CAAe,eAAe,CAAA;AAAA,IAEhF,4BAAA,EAA8B,eAAA,CAAgB,cAAA,CAAe,YAAY,CAAA;AAAA,IACzE,sCAAA,EAAwC,eAAA,CAAgB,cAAA,CAAe,qBAAqB,CAAA;AAAA,IAC5F,6BAAA,EAA+B,eAAA,CAAgB,cAAA,CAAe,UAAU,CAAA;AAAA,IAExE,4BAAA,EAA8B,eAAA,CAAgB,cAAA,CAAe,YAAY,CAAA;AAAA,IAEzE,6BAAA,EAA+B,eAAA,CAAgB,cAAA,CAAe,aAAa,CAAA;AAAA,IAC3E,2BAAA,EAA6B,eAAA,CAAgB,cAAA,CAAe,WAAW,CAAA;AAAA;AAAA;AAAA;AAAA,IAKvE,mCACE,cAAA,CAAe,aAAA,IAAiB,IAAA,GAAO,cAAA,CAAe,gBAAgB,GAAA,GAAO;AAAA,GAChF,CAAA;AACH;AAOA,SAAS,4BAA8C,KAAA,EAAsB;AAC3E,EAAA,OAAO,MAAA,CAAO,WAAA,CAAY,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,CAAE,MAAA,CAAO,CAAC,GAAG,KAAK,CAAA,KAAM,KAAA,IAAS,IAAI,CAAC,CAAA;AACtF;;;;"}
@@ -1,7 +1,7 @@
1
- import { SENTRY_ORIGIN } from '@sentry/conventions/attributes';
1
+ import { SENTRY_OP, SENTRY_ORIGIN } from '@sentry/conventions/attributes';
2
2
  import { defineIntegration, browserPerformanceTimeOrigin, spanToJSON, stringMatchesSomePattern, isPrimitive } from '@sentry/core';
3
3
  import { getBrowserPerformanceAPI, msToSec, startAndEndSpan } from './utils.js';
4
- import { getNavigationEntry } from './web-vitals/lib/getNavigationEntry.js';
4
+ import { getNavigationEntry } from '../web-vitals/utils.js';
5
5
 
6
6
  const INTEGRATION_NAME = "UserTiming";
7
7
  const _userTimingIntegration = ((options = {}) => {
@@ -16,7 +16,8 @@ const _userTimingIntegration = ((options = {}) => {
16
16
  const timeOriginInSeconds = msToSec(timeOrigin);
17
17
  let performanceCursor = 0;
18
18
  client.on("beforeIdleSpanEnd", (idleSpan) => {
19
- const { op: parentOp, start_timestamp: parentStartTimestamp } = spanToJSON(idleSpan);
19
+ const { attributes, start_timestamp: parentStartTimestamp } = spanToJSON(idleSpan);
20
+ const parentOp = attributes[SENTRY_OP];
20
21
  if (parentOp !== "pageload" && parentOp !== "navigation") {
21
22
  return;
22
23
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"userTiming.js","sources":["../../../src/performance/userTiming.ts"],"sourcesContent":["import { SENTRY_OP, SENTRY_ORIGIN } from '@sentry/conventions/attributes';\nimport type { IntegrationFn, Span, SpanAttributes, SpanAttributeValue } from '@sentry/core';\nimport {\n browserPerformanceTimeOrigin,\n defineIntegration,\n isPrimitive,\n spanToJSON,\n stringMatchesSomePattern,\n} from '@sentry/core';\nimport { getBrowserPerformanceAPI, msToSec, startAndEndSpan } from './utils';\nimport { getNavigationEntry } from '../web-vitals/utils';\n\ninterface UserTimingOptions {\n /**\n * User Timing entries with names matching any of these strings or regular expressions will not be emitted.\n *\n * Default: []\n */\n ignore?: Array<string | RegExp>;\n}\n\nconst INTEGRATION_NAME = 'UserTiming';\n\nconst _userTimingIntegration = ((options: UserTimingOptions = {}) => {\n return {\n name: INTEGRATION_NAME,\n setup(client) {\n const performance = getBrowserPerformanceAPI();\n const timeOrigin = browserPerformanceTimeOrigin();\n if (!performance?.getEntries || !timeOrigin) {\n return;\n }\n const timeOriginInSeconds = msToSec(timeOrigin);\n let performanceCursor = 0;\n\n client.on('beforeIdleSpanEnd', idleSpan => {\n const { attributes, start_timestamp: parentStartTimestamp } = spanToJSON(idleSpan);\n const parentOp = attributes[SENTRY_OP];\n\n if (parentOp !== 'pageload' && parentOp !== 'navigation') {\n return;\n }\n\n const requestTime = msToSec(getNavigationEntry(false)?.requestStart ?? 0);\n const performanceEntries = performance.getEntries();\n\n for (const entry of performanceEntries.slice(performanceCursor)) {\n if (entry.entryType !== 'mark' && entry.entryType !== 'measure') {\n continue;\n }\n\n const startTime = msToSec(entry.startTime);\n const absoluteStartTime = timeOriginInSeconds + startTime;\n\n if (parentOp === 'navigation' && parentStartTimestamp && absoluteStartTime < parentStartTimestamp) {\n continue;\n }\n\n _addUserTimingSpan(\n idleSpan,\n entry,\n startTime,\n msToSec(Math.max(0, entry.duration)),\n timeOriginInSeconds,\n requestTime,\n options.ignore ?? [],\n );\n }\n\n performanceCursor = performanceEntries.length;\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Captures spans created with the browser's User Timing APIs, `performance.mark` and `performance.measure`.\n *\n * The integration must be explicitly added to `Sentry.init`. Entries are attached to the active pageload or\n * navigation span when it ends.\n *\n * @example\n * ```ts\n * Sentry.init({\n * integrations: [\n * Sentry.browserTracingIntegration(),\n * Sentry.userTimingIntegration({\n * ignore: ['third-party-mark', /framework-measure/],\n * }),\n * ],\n * });\n * ```\n */\nexport const userTimingIntegration = defineIntegration(_userTimingIntegration);\n\n/**\n * Creates a span for a browser User Timing entry.\n * Exported only for tests.\n */\nexport function _addUserTimingSpan(\n parentSpan: Span,\n entry: PerformanceEntry,\n startTime: number,\n duration: number,\n timeOrigin: number,\n requestTime: number,\n ignore: Array<string | RegExp>,\n): void {\n if (isReact19MeasureEntry(entry) || stringMatchesSomePattern(entry.name, ignore)) {\n return;\n }\n\n // Measures can reference arbitrary timestamps, including timestamps before the page request started.\n const spanStartTimestamp = timeOrigin + Math.max(startTime, requestTime);\n const originalStartTimestamp = timeOrigin + startTime;\n const spanEndTimestamp = originalStartTimestamp + duration;\n\n const attributes: SpanAttributes = {\n [SENTRY_ORIGIN]: `auto.browser.user_timing.${entry.entryType}`,\n };\n\n if (spanStartTimestamp !== originalStartTimestamp) {\n attributes['sentry.browser.measure_happened_before_request'] = true;\n attributes['sentry.browser.measure_start_time'] = spanStartTimestamp;\n }\n\n addDetailToSpanAttributes(attributes, entry as PerformanceMeasure);\n\n // Third-party measurements can contain timestamps which would produce invalid spans.\n if (spanStartTimestamp <= spanEndTimestamp) {\n startAndEndSpan(parentSpan, spanStartTimestamp, spanEndTimestamp, {\n name: entry.name,\n op: entry.entryType,\n attributes,\n });\n }\n}\n\n/**\n * React 19.2+ creates performance.measure entries for component renders.\n * We can identify them by the `detail.devtools.track` property being set to 'Components ⚛'.\n * See https://react.dev/reference/dev-tools/react-performance-tracks.\n */\nfunction isReact19MeasureEntry(entry: PerformanceEntry): boolean | void {\n if (entry.entryType !== 'measure') {\n return;\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n return (entry as PerformanceMeasure).detail.devtools.track === 'Components ⚛';\n } catch {\n return;\n }\n}\n\nfunction addDetailToSpanAttributes(attributes: SpanAttributes, entry: PerformanceMeasure): void {\n try {\n // Accessing detail can throw in some browsers due to security restrictions.\n const detail = entry.detail;\n if (!detail) {\n return;\n }\n\n if (typeof detail === 'object') {\n for (const [key, value] of Object.entries(detail)) {\n if (value && isPrimitive(value)) {\n attributes[`sentry.browser.measure.detail.${key}`] = value as SpanAttributeValue;\n } else if (value !== undefined) {\n try {\n attributes[`sentry.browser.measure.detail.${key}`] = JSON.stringify(value);\n } catch {\n // User-provided detail values are not guaranteed to be serializable.\n }\n }\n }\n return;\n }\n\n if (isPrimitive(detail)) {\n attributes['sentry.browser.measure.detail'] = detail as SpanAttributeValue;\n return;\n }\n\n try {\n attributes['sentry.browser.measure.detail'] = JSON.stringify(detail);\n } catch {\n // User-provided detail values are not guaranteed to be serializable.\n }\n } catch {\n // Accessing detail can throw in some browsers due to security restrictions.\n }\n}\n"],"names":[],"mappings":"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"}