@sentry/browser 11.0.0-alpha.0 → 11.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/build/npm/cjs/dev/client.js.map +1 -1
  2. package/build/npm/cjs/dev/helpers.js +2 -1
  3. package/build/npm/cjs/dev/helpers.js.map +1 -1
  4. package/build/npm/cjs/dev/index.js +7 -4
  5. package/build/npm/cjs/dev/index.js.map +1 -1
  6. package/build/npm/cjs/dev/integrations/bfcache.js +113 -0
  7. package/build/npm/cjs/dev/integrations/bfcache.js.map +1 -0
  8. package/build/npm/cjs/dev/integrations/breadcrumbs.js +1 -1
  9. package/build/npm/cjs/dev/integrations/breadcrumbs.js.map +1 -1
  10. package/build/npm/cjs/dev/integrations/fetchStreamPerformance.js +11 -11
  11. package/build/npm/cjs/dev/integrations/fetchStreamPerformance.js.map +1 -1
  12. package/build/npm/cjs/dev/integrations/globalhandlers.js +2 -1
  13. package/build/npm/cjs/dev/integrations/globalhandlers.js.map +1 -1
  14. package/build/npm/cjs/dev/integrations/graphqlClient.js +3 -3
  15. package/build/npm/cjs/dev/integrations/graphqlClient.js.map +1 -1
  16. package/build/npm/cjs/dev/integrations/httpclient.js.map +1 -1
  17. package/build/npm/cjs/dev/integrations/reportingobserver.js +4 -1
  18. package/build/npm/cjs/dev/integrations/reportingobserver.js.map +1 -1
  19. package/build/npm/cjs/dev/integrations/spotlight.js +2 -1
  20. package/build/npm/cjs/dev/integrations/spotlight.js.map +1 -1
  21. package/build/npm/cjs/dev/integrations/view-hierarchy.js +2 -1
  22. package/build/npm/cjs/dev/integrations/view-hierarchy.js.map +1 -1
  23. package/build/npm/cjs/dev/profiling/index.js.map +1 -1
  24. package/build/npm/cjs/dev/profiling/integration.js +21 -91
  25. package/build/npm/cjs/dev/profiling/integration.js.map +1 -1
  26. package/build/npm/cjs/dev/profiling/utils.js +0 -283
  27. package/build/npm/cjs/dev/profiling/utils.js.map +1 -1
  28. package/build/npm/cjs/dev/sdk.js +0 -4
  29. package/build/npm/cjs/dev/sdk.js.map +1 -1
  30. package/build/npm/cjs/dev/tracing/backgroundtab.js +5 -1
  31. package/build/npm/cjs/dev/tracing/backgroundtab.js.map +1 -1
  32. package/build/npm/cjs/dev/tracing/browserTracingIntegration.js +30 -86
  33. package/build/npm/cjs/dev/tracing/browserTracingIntegration.js.map +1 -1
  34. package/build/npm/cjs/dev/tracing/linkedTraces.js +3 -3
  35. package/build/npm/cjs/dev/tracing/linkedTraces.js.map +1 -1
  36. package/build/npm/cjs/dev/tracing/request.js +7 -9
  37. package/build/npm/cjs/dev/tracing/request.js.map +1 -1
  38. package/build/npm/cjs/dev/utils/detectBrowserExtension.js +2 -1
  39. package/build/npm/cjs/dev/utils/detectBrowserExtension.js.map +1 -1
  40. package/build/npm/cjs/dev/utils/lazyLoadIntegration.js +1 -0
  41. package/build/npm/cjs/dev/utils/lazyLoadIntegration.js.map +1 -1
  42. package/build/npm/cjs/prod/client.js.map +1 -1
  43. package/build/npm/cjs/prod/helpers.js +2 -1
  44. package/build/npm/cjs/prod/helpers.js.map +1 -1
  45. package/build/npm/cjs/prod/index.js +7 -4
  46. package/build/npm/cjs/prod/index.js.map +1 -1
  47. package/build/npm/cjs/prod/integrations/bfcache.js +113 -0
  48. package/build/npm/cjs/prod/integrations/bfcache.js.map +1 -0
  49. package/build/npm/cjs/prod/integrations/breadcrumbs.js +1 -1
  50. package/build/npm/cjs/prod/integrations/breadcrumbs.js.map +1 -1
  51. package/build/npm/cjs/prod/integrations/fetchStreamPerformance.js +11 -11
  52. package/build/npm/cjs/prod/integrations/fetchStreamPerformance.js.map +1 -1
  53. package/build/npm/cjs/prod/integrations/globalhandlers.js +2 -1
  54. package/build/npm/cjs/prod/integrations/globalhandlers.js.map +1 -1
  55. package/build/npm/cjs/prod/integrations/graphqlClient.js +3 -3
  56. package/build/npm/cjs/prod/integrations/graphqlClient.js.map +1 -1
  57. package/build/npm/cjs/prod/integrations/httpclient.js.map +1 -1
  58. package/build/npm/cjs/prod/integrations/reportingobserver.js +4 -1
  59. package/build/npm/cjs/prod/integrations/reportingobserver.js.map +1 -1
  60. package/build/npm/cjs/prod/integrations/spotlight.js +2 -1
  61. package/build/npm/cjs/prod/integrations/spotlight.js.map +1 -1
  62. package/build/npm/cjs/prod/integrations/view-hierarchy.js +2 -1
  63. package/build/npm/cjs/prod/integrations/view-hierarchy.js.map +1 -1
  64. package/build/npm/cjs/prod/profiling/index.js.map +1 -1
  65. package/build/npm/cjs/prod/profiling/integration.js +21 -91
  66. package/build/npm/cjs/prod/profiling/integration.js.map +1 -1
  67. package/build/npm/cjs/prod/profiling/utils.js +0 -283
  68. package/build/npm/cjs/prod/profiling/utils.js.map +1 -1
  69. package/build/npm/cjs/prod/sdk.js +0 -4
  70. package/build/npm/cjs/prod/sdk.js.map +1 -1
  71. package/build/npm/cjs/prod/tracing/backgroundtab.js +5 -1
  72. package/build/npm/cjs/prod/tracing/backgroundtab.js.map +1 -1
  73. package/build/npm/cjs/prod/tracing/browserTracingIntegration.js +30 -86
  74. package/build/npm/cjs/prod/tracing/browserTracingIntegration.js.map +1 -1
  75. package/build/npm/cjs/prod/tracing/linkedTraces.js +3 -3
  76. package/build/npm/cjs/prod/tracing/linkedTraces.js.map +1 -1
  77. package/build/npm/cjs/prod/tracing/request.js +7 -9
  78. package/build/npm/cjs/prod/tracing/request.js.map +1 -1
  79. package/build/npm/cjs/prod/utils/detectBrowserExtension.js +2 -1
  80. package/build/npm/cjs/prod/utils/detectBrowserExtension.js.map +1 -1
  81. package/build/npm/cjs/prod/utils/lazyLoadIntegration.js +1 -0
  82. package/build/npm/cjs/prod/utils/lazyLoadIntegration.js.map +1 -1
  83. package/build/npm/esm/dev/client.js.map +1 -1
  84. package/build/npm/esm/dev/helpers.js +2 -1
  85. package/build/npm/esm/dev/helpers.js.map +1 -1
  86. package/build/npm/esm/dev/index.js +4 -4
  87. package/build/npm/esm/dev/integrations/bfcache.js +109 -0
  88. package/build/npm/esm/dev/integrations/bfcache.js.map +1 -0
  89. package/build/npm/esm/dev/integrations/breadcrumbs.js +2 -2
  90. package/build/npm/esm/dev/integrations/breadcrumbs.js.map +1 -1
  91. package/build/npm/esm/dev/integrations/fetchStreamPerformance.js +3 -3
  92. package/build/npm/esm/dev/integrations/fetchStreamPerformance.js.map +1 -1
  93. package/build/npm/esm/dev/integrations/globalhandlers.js +2 -1
  94. package/build/npm/esm/dev/integrations/globalhandlers.js.map +1 -1
  95. package/build/npm/esm/dev/integrations/graphqlClient.js +5 -5
  96. package/build/npm/esm/dev/integrations/graphqlClient.js.map +1 -1
  97. package/build/npm/esm/dev/integrations/httpclient.js.map +1 -1
  98. package/build/npm/esm/dev/integrations/reportingobserver.js +4 -1
  99. package/build/npm/esm/dev/integrations/reportingobserver.js.map +1 -1
  100. package/build/npm/esm/dev/integrations/spotlight.js +2 -1
  101. package/build/npm/esm/dev/integrations/spotlight.js.map +1 -1
  102. package/build/npm/esm/dev/integrations/view-hierarchy.js +2 -1
  103. package/build/npm/esm/dev/integrations/view-hierarchy.js.map +1 -1
  104. package/build/npm/esm/dev/package.json +1 -1
  105. package/build/npm/esm/dev/profiling/index.js.map +1 -1
  106. package/build/npm/esm/dev/profiling/integration.js +22 -92
  107. package/build/npm/esm/dev/profiling/integration.js.map +1 -1
  108. package/build/npm/esm/dev/profiling/utils.js +2 -272
  109. package/build/npm/esm/dev/profiling/utils.js.map +1 -1
  110. package/build/npm/esm/dev/sdk.js +0 -4
  111. package/build/npm/esm/dev/sdk.js.map +1 -1
  112. package/build/npm/esm/dev/tracing/backgroundtab.js +5 -1
  113. package/build/npm/esm/dev/tracing/backgroundtab.js.map +1 -1
  114. package/build/npm/esm/dev/tracing/browserTracingIntegration.js +32 -87
  115. package/build/npm/esm/dev/tracing/browserTracingIntegration.js.map +1 -1
  116. package/build/npm/esm/dev/tracing/linkedTraces.js +3 -3
  117. package/build/npm/esm/dev/tracing/linkedTraces.js.map +1 -1
  118. package/build/npm/esm/dev/tracing/request.js +9 -11
  119. package/build/npm/esm/dev/tracing/request.js.map +1 -1
  120. package/build/npm/esm/dev/utils/detectBrowserExtension.js +2 -1
  121. package/build/npm/esm/dev/utils/detectBrowserExtension.js.map +1 -1
  122. package/build/npm/esm/dev/utils/lazyLoadIntegration.js +1 -0
  123. package/build/npm/esm/dev/utils/lazyLoadIntegration.js.map +1 -1
  124. package/build/npm/esm/prod/client.js.map +1 -1
  125. package/build/npm/esm/prod/helpers.js +2 -1
  126. package/build/npm/esm/prod/helpers.js.map +1 -1
  127. package/build/npm/esm/prod/index.js +4 -4
  128. package/build/npm/esm/prod/integrations/bfcache.js +109 -0
  129. package/build/npm/esm/prod/integrations/bfcache.js.map +1 -0
  130. package/build/npm/esm/prod/integrations/breadcrumbs.js +2 -2
  131. package/build/npm/esm/prod/integrations/breadcrumbs.js.map +1 -1
  132. package/build/npm/esm/prod/integrations/fetchStreamPerformance.js +3 -3
  133. package/build/npm/esm/prod/integrations/fetchStreamPerformance.js.map +1 -1
  134. package/build/npm/esm/prod/integrations/globalhandlers.js +2 -1
  135. package/build/npm/esm/prod/integrations/globalhandlers.js.map +1 -1
  136. package/build/npm/esm/prod/integrations/graphqlClient.js +5 -5
  137. package/build/npm/esm/prod/integrations/graphqlClient.js.map +1 -1
  138. package/build/npm/esm/prod/integrations/httpclient.js.map +1 -1
  139. package/build/npm/esm/prod/integrations/reportingobserver.js +4 -1
  140. package/build/npm/esm/prod/integrations/reportingobserver.js.map +1 -1
  141. package/build/npm/esm/prod/integrations/spotlight.js +2 -1
  142. package/build/npm/esm/prod/integrations/spotlight.js.map +1 -1
  143. package/build/npm/esm/prod/integrations/view-hierarchy.js +2 -1
  144. package/build/npm/esm/prod/integrations/view-hierarchy.js.map +1 -1
  145. package/build/npm/esm/prod/package.json +1 -1
  146. package/build/npm/esm/prod/profiling/index.js.map +1 -1
  147. package/build/npm/esm/prod/profiling/integration.js +22 -92
  148. package/build/npm/esm/prod/profiling/integration.js.map +1 -1
  149. package/build/npm/esm/prod/profiling/utils.js +2 -272
  150. package/build/npm/esm/prod/profiling/utils.js.map +1 -1
  151. package/build/npm/esm/prod/sdk.js +0 -4
  152. package/build/npm/esm/prod/sdk.js.map +1 -1
  153. package/build/npm/esm/prod/tracing/backgroundtab.js +5 -1
  154. package/build/npm/esm/prod/tracing/backgroundtab.js.map +1 -1
  155. package/build/npm/esm/prod/tracing/browserTracingIntegration.js +32 -87
  156. package/build/npm/esm/prod/tracing/browserTracingIntegration.js.map +1 -1
  157. package/build/npm/esm/prod/tracing/linkedTraces.js +3 -3
  158. package/build/npm/esm/prod/tracing/linkedTraces.js.map +1 -1
  159. package/build/npm/esm/prod/tracing/request.js +9 -11
  160. package/build/npm/esm/prod/tracing/request.js.map +1 -1
  161. package/build/npm/esm/prod/utils/detectBrowserExtension.js +2 -1
  162. package/build/npm/esm/prod/utils/detectBrowserExtension.js.map +1 -1
  163. package/build/npm/esm/prod/utils/lazyLoadIntegration.js +1 -0
  164. package/build/npm/esm/prod/utils/lazyLoadIntegration.js.map +1 -1
  165. package/build/npm/types/client.d.ts +22 -1
  166. package/build/npm/types/client.d.ts.map +1 -1
  167. package/build/npm/types/exports.d.ts +2 -2
  168. package/build/npm/types/exports.d.ts.map +1 -1
  169. package/build/npm/types/helpers.d.ts.map +1 -1
  170. package/build/npm/types/index.bundle.d.ts +2 -2
  171. package/build/npm/types/index.bundle.d.ts.map +1 -1
  172. package/build/npm/types/index.bundle.feedback.d.ts +2 -2
  173. package/build/npm/types/index.bundle.feedback.d.ts.map +1 -1
  174. package/build/npm/types/index.bundle.logs.metrics.d.ts +1 -1
  175. package/build/npm/types/index.bundle.logs.metrics.d.ts.map +1 -1
  176. package/build/npm/types/index.bundle.replay.d.ts +2 -2
  177. package/build/npm/types/index.bundle.replay.d.ts.map +1 -1
  178. package/build/npm/types/index.bundle.replay.feedback.d.ts +2 -2
  179. package/build/npm/types/index.bundle.replay.feedback.d.ts.map +1 -1
  180. package/build/npm/types/index.bundle.replay.logs.metrics.d.ts +1 -1
  181. package/build/npm/types/index.bundle.replay.logs.metrics.d.ts.map +1 -1
  182. package/build/npm/types/index.bundle.tracing.d.ts +5 -4
  183. package/build/npm/types/index.bundle.tracing.d.ts.map +1 -1
  184. package/build/npm/types/index.bundle.tracing.logs.metrics.d.ts +4 -3
  185. package/build/npm/types/index.bundle.tracing.logs.metrics.d.ts.map +1 -1
  186. package/build/npm/types/index.bundle.tracing.replay.d.ts +5 -4
  187. package/build/npm/types/index.bundle.tracing.replay.d.ts.map +1 -1
  188. package/build/npm/types/index.bundle.tracing.replay.feedback.d.ts +5 -4
  189. package/build/npm/types/index.bundle.tracing.replay.feedback.d.ts.map +1 -1
  190. package/build/npm/types/index.bundle.tracing.replay.feedback.logs.metrics.d.ts +4 -3
  191. package/build/npm/types/index.bundle.tracing.replay.feedback.logs.metrics.d.ts.map +1 -1
  192. package/build/npm/types/index.bundle.tracing.replay.logs.metrics.d.ts +4 -3
  193. package/build/npm/types/index.bundle.tracing.replay.logs.metrics.d.ts.map +1 -1
  194. package/build/npm/types/index.d.ts +6 -5
  195. package/build/npm/types/index.d.ts.map +1 -1
  196. package/build/npm/types/integrations/bfcache.d.ts +42 -0
  197. package/build/npm/types/integrations/bfcache.d.ts.map +1 -0
  198. package/build/npm/types/integrations/breadcrumbs.d.ts.map +1 -1
  199. package/build/npm/types/integrations/graphqlClient.d.ts.map +1 -1
  200. package/build/npm/types/integrations/httpclient.d.ts.map +1 -1
  201. package/build/npm/types/integrations/interactions.d.ts +2 -0
  202. package/build/npm/types/integrations/interactions.d.ts.map +1 -0
  203. package/build/npm/types/integrations/reportingobserver.d.ts.map +1 -1
  204. package/build/npm/types/integrations/spotlight.d.ts.map +1 -1
  205. package/build/npm/types/integrations/view-hierarchy.d.ts.map +1 -1
  206. package/build/npm/types/profiling/index.d.ts.map +1 -1
  207. package/build/npm/types/profiling/integration.d.ts.map +1 -1
  208. package/build/npm/types/profiling/utils.d.ts +1 -74
  209. package/build/npm/types/profiling/utils.d.ts.map +1 -1
  210. package/build/npm/types/sdk.d.ts.map +1 -1
  211. package/build/npm/types/tracing/backgroundtab.d.ts.map +1 -1
  212. package/build/npm/types/tracing/browserTracingIntegration.d.ts +0 -19
  213. package/build/npm/types/tracing/browserTracingIntegration.d.ts.map +1 -1
  214. package/build/npm/types/tracing/linkedTraces.d.ts.map +1 -1
  215. package/build/npm/types/tracing/request.d.ts +1 -13
  216. package/build/npm/types/tracing/request.d.ts.map +1 -1
  217. package/build/npm/types/utils/detectBrowserExtension.d.ts.map +1 -1
  218. package/build/npm/types/utils/lazyLoadIntegration.d.ts +1 -1
  219. package/build/npm/types/utils/lazyLoadIntegration.d.ts.map +1 -1
  220. package/package.json +10 -9
  221. package/build/npm/cjs/dev/integrations/spanstreaming.js +0 -34
  222. package/build/npm/cjs/dev/integrations/spanstreaming.js.map +0 -1
  223. package/build/npm/cjs/dev/profiling/startProfileForSpan.js +0 -91
  224. package/build/npm/cjs/dev/profiling/startProfileForSpan.js.map +0 -1
  225. package/build/npm/cjs/prod/integrations/spanstreaming.js +0 -34
  226. package/build/npm/cjs/prod/integrations/spanstreaming.js.map +0 -1
  227. package/build/npm/cjs/prod/profiling/startProfileForSpan.js +0 -91
  228. package/build/npm/cjs/prod/profiling/startProfileForSpan.js.map +0 -1
  229. package/build/npm/esm/dev/integrations/spanstreaming.js +0 -31
  230. package/build/npm/esm/dev/integrations/spanstreaming.js.map +0 -1
  231. package/build/npm/esm/dev/profiling/startProfileForSpan.js +0 -89
  232. package/build/npm/esm/dev/profiling/startProfileForSpan.js.map +0 -1
  233. package/build/npm/esm/prod/integrations/spanstreaming.js +0 -31
  234. package/build/npm/esm/prod/integrations/spanstreaming.js.map +0 -1
  235. package/build/npm/esm/prod/profiling/startProfileForSpan.js +0 -89
  236. package/build/npm/esm/prod/profiling/startProfileForSpan.js.map +0 -1
  237. package/build/npm/types/integrations/spanstreaming.d.ts +0 -5
  238. package/build/npm/types/integrations/spanstreaming.d.ts.map +0 -1
  239. package/build/npm/types/profiling/startProfileForSpan.d.ts +0 -8
  240. package/build/npm/types/profiling/startProfileForSpan.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"fetchStreamPerformance.js","sources":["../../../../../src/integrations/fetchStreamPerformance.ts"],"sourcesContent":["import { URL_FULL } from '@sentry/conventions/attributes';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n defineIntegration,\n getSanitizedUrlStringFromUrlObject,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startInactiveSpan,\n stripDataUrlContent,\n filterCollectedUrl,\n} from '@sentry/core';\n\nconst responseToStreamSpan = new WeakMap<object, Span>();\nconst responseToFallbackTimeout = new WeakMap<object, ReturnType<typeof setTimeout>>();\n\n// Matches the max timeout in `resolveResponse` in packages/core/src/instrument/fetch.ts\nconst STREAM_RESOLVE_FALLBACK_MS = 90_000;\n\nconst STREAMING_CONTENT_TYPES = ['text/event-stream', 'application/x-ndjson', 'application/stream+json'];\n\n/**\n * Tracks streamed fetch response bodies by creating an `http.client.stream` sibling span.\n *\n * The regular `http.client` span ends when response headers arrive. This integration adds\n * a span that starts at header arrival and ends when the body fully resolves:\n *\n * ```\n * --------- pageload --------------------------------\n * -- http.client --\n * -- http.client.stream -------\n * ```\n */\nexport const fetchStreamPerformanceIntegration = defineIntegration(() => {\n return {\n name: 'FetchStreamPerformance' as const,\n\n setup() {\n // End the stream span when the response body finishes resolving\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const streamSpan = responseToStreamSpan.get(handlerData.response);\n if (streamSpan && handlerData.endTimestamp) {\n streamSpan.end(handlerData.endTimestamp);\n\n const fallbackTimeout = responseToFallbackTimeout.get(handlerData.response);\n if (fallbackTimeout) {\n clearTimeout(fallbackTimeout);\n }\n }\n }\n });\n\n addFetchInstrumentationHandler(handlerData => {\n // Only create the stream span once headers have arrived\n if (handlerData.endTimestamp && handlerData.response) {\n // Only create stream spans for responses that are likely streamed:\n // 1. No content-length header (streamed responses don't know the size upfront)\n // 2. Content-type is a known streaming type (avoids false positives on HTTP/2\n // where content-length is often omitted even for regular responses)\n const contentType = handlerData.response.headers?.get('content-type') || '';\n if (\n handlerData.response.headers?.get('content-length') ||\n !STREAMING_CONTENT_TYPES.some(t => contentType.startsWith(t))\n ) {\n return;\n }\n\n const url = handlerData.fetchData?.url || '';\n const method = handlerData.fetchData?.method || 'GET';\n\n const parsedUrl = parseStringToURLObject(url);\n const sanitizedUrl = url.startsWith('data:')\n ? stripDataUrlContent(url)\n : parsedUrl\n ? getSanitizedUrlStringFromUrlObject(parsedUrl)\n : url;\n\n const streamSpan = startInactiveSpan({\n name: `${method} ${sanitizedUrl}`,\n startTime: handlerData.endTimestamp,\n attributes: {\n [URL_FULL]: filterCollectedUrl(stripDataUrlContent(url)),\n 'http.method': method,\n type: 'fetch',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client.stream',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser.stream',\n },\n });\n\n responseToStreamSpan.set(handlerData.response, streamSpan);\n\n // prevent the span from leaking indefinitely if the body never resolves\n const fallbackTimeout = setTimeout(() => {\n if (streamSpan.isRecording()) {\n streamSpan.end();\n }\n }, STREAM_RESOLVE_FALLBACK_MS);\n\n responseToFallbackTimeout.set(handlerData.response, fallbackTimeout);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n"],"names":[],"mappings":";;;AAeA,MAAM,oBAAA,uBAA2B,OAAA,EAAsB;AACvD,MAAM,yBAAA,uBAAgC,OAAA,EAA+C;AAGrF,MAAM,0BAAA,GAA6B,GAAA;AAEnC,MAAM,uBAAA,GAA0B,CAAC,mBAAA,EAAqB,sBAAA,EAAwB,yBAAyB,CAAA;AAchG,MAAM,iCAAA,GAAoC,kBAAkB,MAAM;AACvE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,wBAAA;AAAA,IAEN,KAAA,GAAQ;AAEN,MAAA,iCAAA,CAAkC,CAAA,WAAA,KAAe;AAC/C,QAAA,IAAI,YAAY,QAAA,EAAU;AACxB,UAAA,MAAM,UAAA,GAAa,oBAAA,CAAqB,GAAA,CAAI,WAAA,CAAY,QAAQ,CAAA;AAChE,UAAA,IAAI,UAAA,IAAc,YAAY,YAAA,EAAc;AAC1C,YAAA,UAAA,CAAW,GAAA,CAAI,YAAY,YAAY,CAAA;AAEvC,YAAA,MAAM,eAAA,GAAkB,yBAAA,CAA0B,GAAA,CAAI,WAAA,CAAY,QAAQ,CAAA;AAC1E,YAAA,IAAI,eAAA,EAAiB;AACnB,cAAA,YAAA,CAAa,eAAe,CAAA;AAAA,YAC9B;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC,CAAA;AAED,MAAA,8BAAA,CAA+B,CAAA,WAAA,KAAe;AAE5C,QAAA,IAAI,WAAA,CAAY,YAAA,IAAgB,WAAA,CAAY,QAAA,EAAU;AAKpD,UAAA,MAAM,cAAc,WAAA,CAAY,QAAA,CAAS,OAAA,EAAS,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AACzE,UAAA,IACE,WAAA,CAAY,QAAA,CAAS,OAAA,EAAS,GAAA,CAAI,gBAAgB,CAAA,IAClD,CAAC,uBAAA,CAAwB,IAAA,CAAK,CAAA,CAAA,KAAK,WAAA,CAAY,UAAA,CAAW,CAAC,CAAC,CAAA,EAC5D;AACA,YAAA;AAAA,UACF;AAEA,UAAA,MAAM,GAAA,GAAM,WAAA,CAAY,SAAA,EAAW,GAAA,IAAO,EAAA;AAC1C,UAAA,MAAM,MAAA,GAAS,WAAA,CAAY,SAAA,EAAW,MAAA,IAAU,KAAA;AAEhD,UAAA,MAAM,SAAA,GAAY,uBAAuB,GAAG,CAAA;AAC5C,UAAA,MAAM,YAAA,GAAe,GAAA,CAAI,UAAA,CAAW,OAAO,CAAA,GACvC,mBAAA,CAAoB,GAAG,CAAA,GACvB,SAAA,GACE,kCAAA,CAAmC,SAAS,CAAA,GAC5C,GAAA;AAEN,UAAA,MAAM,aAAa,iBAAA,CAAkB;AAAA,YACnC,IAAA,EAAM,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AAAA,YAC/B,WAAW,WAAA,CAAY,YAAA;AAAA,YACvB,UAAA,EAAY;AAAA,cACV,CAAC,QAAQ,GAAG,kBAAA,CAAmB,mBAAA,CAAoB,GAAG,CAAC,CAAA;AAAA,cACvD,aAAA,EAAe,MAAA;AAAA,cACf,IAAA,EAAM,OAAA;AAAA,cACN,CAAC,4BAA4B,GAAG,oBAAA;AAAA,cAChC,CAAC,gCAAgC,GAAG;AAAA;AACtC,WACD,CAAA;AAED,UAAA,oBAAA,CAAqB,GAAA,CAAI,WAAA,CAAY,QAAA,EAAU,UAAU,CAAA;AAGzD,UAAA,MAAM,eAAA,GAAkB,WAAW,MAAM;AACvC,YAAA,IAAI,UAAA,CAAW,aAAY,EAAG;AAC5B,cAAA,UAAA,CAAW,GAAA,EAAI;AAAA,YACjB;AAAA,UACF,GAAG,0BAA0B,CAAA;AAE7B,UAAA,yBAAA,CAA0B,GAAA,CAAI,WAAA,CAAY,QAAA,EAAU,eAAe,CAAA;AAAA,QACrE;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"fetchStreamPerformance.js","sources":["../../../../../src/integrations/fetchStreamPerformance.ts"],"sourcesContent":["import { HTTP_REQUEST_METHOD, URL_FULL } from '@sentry/conventions/attributes';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n defineIntegration,\n getSanitizedUrlStringFromUrlObject,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n stripDataUrlContent,\n filterCollectedUrl,\n startInactiveSpan,\n} from '@sentry/core/browser';\n\nconst responseToStreamSpan = new WeakMap<object, Span>();\nconst responseToFallbackTimeout = new WeakMap<object, ReturnType<typeof setTimeout>>();\n\n// Matches the max timeout in `resolveResponse` in packages/core/src/instrument/fetch.ts\nconst STREAM_RESOLVE_FALLBACK_MS = 90_000;\n\nconst STREAMING_CONTENT_TYPES = ['text/event-stream', 'application/x-ndjson', 'application/stream+json'];\n\n/**\n * Tracks streamed fetch response bodies by creating an `http.client.stream` sibling span.\n *\n * The regular `http.client` span ends when response headers arrive. This integration adds\n * a span that starts at header arrival and ends when the body fully resolves:\n *\n * ```\n * --------- pageload --------------------------------\n * -- http.client --\n * -- http.client.stream -------\n * ```\n */\nexport const fetchStreamPerformanceIntegration = defineIntegration(() => {\n return {\n name: 'FetchStreamPerformance' as const,\n\n setup() {\n // End the stream span when the response body finishes resolving\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const streamSpan = responseToStreamSpan.get(handlerData.response);\n if (streamSpan && handlerData.endTimestamp) {\n streamSpan.end(handlerData.endTimestamp);\n\n const fallbackTimeout = responseToFallbackTimeout.get(handlerData.response);\n if (fallbackTimeout) {\n clearTimeout(fallbackTimeout);\n }\n }\n }\n });\n\n addFetchInstrumentationHandler(handlerData => {\n // Only create the stream span once headers have arrived\n if (handlerData.endTimestamp && handlerData.response) {\n // Only create stream spans for responses that are likely streamed:\n // 1. No content-length header (streamed responses don't know the size upfront)\n // 2. Content-type is a known streaming type (avoids false positives on HTTP/2\n // where content-length is often omitted even for regular responses)\n const contentType = handlerData.response.headers?.get('content-type') || '';\n if (\n handlerData.response.headers?.get('content-length') ||\n !STREAMING_CONTENT_TYPES.some(t => contentType.startsWith(t))\n ) {\n return;\n }\n\n const url = handlerData.fetchData?.url || '';\n const method = handlerData.fetchData?.method || 'GET';\n\n const parsedUrl = parseStringToURLObject(url);\n const sanitizedUrl = url.startsWith('data:')\n ? stripDataUrlContent(url)\n : parsedUrl\n ? getSanitizedUrlStringFromUrlObject(parsedUrl)\n : url;\n\n const streamSpan = startInactiveSpan({\n name: `${method} ${sanitizedUrl}`,\n startTime: handlerData.endTimestamp,\n attributes: {\n [URL_FULL]: filterCollectedUrl(stripDataUrlContent(url)),\n [HTTP_REQUEST_METHOD]: method,\n type: 'fetch',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client.stream',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser.stream',\n },\n });\n\n responseToStreamSpan.set(handlerData.response, streamSpan);\n\n // prevent the span from leaking indefinitely if the body never resolves\n const fallbackTimeout = setTimeout(() => {\n if (streamSpan.isRecording()) {\n streamSpan.end();\n }\n }, STREAM_RESOLVE_FALLBACK_MS);\n\n responseToFallbackTimeout.set(handlerData.response, fallbackTimeout);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n"],"names":[],"mappings":";;;AAeA,MAAM,oBAAA,uBAA2B,OAAA,EAAsB;AACvD,MAAM,yBAAA,uBAAgC,OAAA,EAA+C;AAGrF,MAAM,0BAAA,GAA6B,GAAA;AAEnC,MAAM,uBAAA,GAA0B,CAAC,mBAAA,EAAqB,sBAAA,EAAwB,yBAAyB,CAAA;AAchG,MAAM,iCAAA,GAAoC,kBAAkB,MAAM;AACvE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,wBAAA;AAAA,IAEN,KAAA,GAAQ;AAEN,MAAA,iCAAA,CAAkC,CAAA,WAAA,KAAe;AAC/C,QAAA,IAAI,YAAY,QAAA,EAAU;AACxB,UAAA,MAAM,UAAA,GAAa,oBAAA,CAAqB,GAAA,CAAI,WAAA,CAAY,QAAQ,CAAA;AAChE,UAAA,IAAI,UAAA,IAAc,YAAY,YAAA,EAAc;AAC1C,YAAA,UAAA,CAAW,GAAA,CAAI,YAAY,YAAY,CAAA;AAEvC,YAAA,MAAM,eAAA,GAAkB,yBAAA,CAA0B,GAAA,CAAI,WAAA,CAAY,QAAQ,CAAA;AAC1E,YAAA,IAAI,eAAA,EAAiB;AACnB,cAAA,YAAA,CAAa,eAAe,CAAA;AAAA,YAC9B;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC,CAAA;AAED,MAAA,8BAAA,CAA+B,CAAA,WAAA,KAAe;AAE5C,QAAA,IAAI,WAAA,CAAY,YAAA,IAAgB,WAAA,CAAY,QAAA,EAAU;AAKpD,UAAA,MAAM,cAAc,WAAA,CAAY,QAAA,CAAS,OAAA,EAAS,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AACzE,UAAA,IACE,WAAA,CAAY,QAAA,CAAS,OAAA,EAAS,GAAA,CAAI,gBAAgB,CAAA,IAClD,CAAC,uBAAA,CAAwB,IAAA,CAAK,CAAA,CAAA,KAAK,WAAA,CAAY,UAAA,CAAW,CAAC,CAAC,CAAA,EAC5D;AACA,YAAA;AAAA,UACF;AAEA,UAAA,MAAM,GAAA,GAAM,WAAA,CAAY,SAAA,EAAW,GAAA,IAAO,EAAA;AAC1C,UAAA,MAAM,MAAA,GAAS,WAAA,CAAY,SAAA,EAAW,MAAA,IAAU,KAAA;AAEhD,UAAA,MAAM,SAAA,GAAY,uBAAuB,GAAG,CAAA;AAC5C,UAAA,MAAM,YAAA,GAAe,GAAA,CAAI,UAAA,CAAW,OAAO,CAAA,GACvC,mBAAA,CAAoB,GAAG,CAAA,GACvB,SAAA,GACE,kCAAA,CAAmC,SAAS,CAAA,GAC5C,GAAA;AAEN,UAAA,MAAM,aAAa,iBAAA,CAAkB;AAAA,YACnC,IAAA,EAAM,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AAAA,YAC/B,WAAW,WAAA,CAAY,YAAA;AAAA,YACvB,UAAA,EAAY;AAAA,cACV,CAAC,QAAQ,GAAG,kBAAA,CAAmB,mBAAA,CAAoB,GAAG,CAAC,CAAA;AAAA,cACvD,CAAC,mBAAmB,GAAG,MAAA;AAAA,cACvB,IAAA,EAAM,OAAA;AAAA,cACN,CAAC,4BAA4B,GAAG,oBAAA;AAAA,cAChC,CAAC,gCAAgC,GAAG;AAAA;AACtC,WACD,CAAA;AAED,UAAA,oBAAA,CAAqB,GAAA,CAAI,WAAA,CAAY,QAAA,EAAU,UAAU,CAAA;AAGzD,UAAA,MAAM,eAAA,GAAkB,WAAW,MAAM;AACvC,YAAA,IAAI,UAAA,CAAW,aAAY,EAAG;AAC5B,cAAA,UAAA,CAAW,GAAA,EAAI;AAAA,YACjB;AAAA,UACF,GAAG,0BAA0B,CAAA;AAE7B,UAAA,yBAAA,CAA0B,GAAA,CAAI,WAAA,CAAY,QAAA,EAAU,eAAe,CAAA;AAAA,QACrE;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF,CAAC;;;;"}
@@ -1,5 +1,6 @@
1
- import { defineIntegration, addGlobalErrorInstrumentationHandler, getClient, captureEvent, debug, addGlobalUnhandledRejectionInstrumentationHandler, isPrimitive, UNKNOWN_FUNCTION, getLocationHref, isString, stripDataUrlContent } from '@sentry/core/browser';
1
+ import { defineIntegration, addGlobalErrorInstrumentationHandler, getClient, captureEvent, debug, addGlobalUnhandledRejectionInstrumentationHandler, isPrimitive, UNKNOWN_FUNCTION, isString, stripDataUrlContent } from '@sentry/core/browser';
2
2
  import { DEBUG_BUILD } from '../debug-build.js';
3
+ import { getLocationHref } from '@sentry/browser-utils';
3
4
  import { eventFromUnknownInput } from '../eventbuilder.js';
4
5
  import { shouldIgnoreOnError } from '../helpers.js';
5
6
 
@@ -1 +1 @@
1
- {"version":3,"file":"globalhandlers.js","sources":["../../../../../src/integrations/globalhandlers.ts"],"sourcesContent":["import type { Client, Event, IntegrationFn, Primitive, StackParser } from '@sentry/core/browser';\nimport {\n addGlobalErrorInstrumentationHandler,\n addGlobalUnhandledRejectionInstrumentationHandler,\n captureEvent,\n debug,\n defineIntegration,\n getClient,\n getLocationHref,\n isPrimitive,\n isString,\n stripDataUrlContent,\n UNKNOWN_FUNCTION,\n} from '@sentry/core/browser';\nimport type { BrowserClient } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { eventFromUnknownInput } from '../eventbuilder';\nimport { shouldIgnoreOnError } from '../helpers';\n\ntype GlobalHandlersIntegrationsOptionKeys = 'onerror' | 'onunhandledrejection';\n\ntype GlobalHandlersIntegrations = Record<GlobalHandlersIntegrationsOptionKeys, boolean>;\n\nconst INTEGRATION_NAME = 'GlobalHandlers' as const;\n\nconst _globalHandlersIntegration = ((options: Partial<GlobalHandlersIntegrations> = {}) => {\n const _options = {\n onerror: true,\n onunhandledrejection: true,\n ...options,\n };\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n Error.stackTraceLimit = 50;\n },\n setup(client) {\n if (_options.onerror) {\n _installGlobalOnErrorHandler(client);\n globalHandlerLog('onerror');\n }\n if (_options.onunhandledrejection) {\n _installGlobalOnUnhandledRejectionHandler(client);\n globalHandlerLog('onunhandledrejection');\n }\n },\n };\n}) satisfies IntegrationFn;\n\nexport const globalHandlersIntegration = defineIntegration(_globalHandlersIntegration);\n\nfunction _installGlobalOnErrorHandler(client: Client): void {\n addGlobalErrorInstrumentationHandler(data => {\n const { stackParser, attachStacktrace } = getOptions();\n\n if (getClient() !== client || shouldIgnoreOnError()) {\n return;\n }\n\n const { msg, url, line, column, error } = data;\n\n const event = _enhanceEventWithInitialFrame(\n eventFromUnknownInput(stackParser, error || msg, undefined, attachStacktrace, false),\n url,\n line,\n column,\n );\n\n event.level = 'error';\n\n captureEvent(event, {\n originalException: error,\n mechanism: {\n handled: false,\n type: 'auto.browser.global_handlers.onerror',\n },\n });\n });\n}\n\nfunction _installGlobalOnUnhandledRejectionHandler(client: Client): void {\n addGlobalUnhandledRejectionInstrumentationHandler(e => {\n const { stackParser, attachStacktrace } = getOptions();\n\n if (getClient() !== client || shouldIgnoreOnError()) {\n return;\n }\n\n const error = _getUnhandledRejectionError(e);\n\n const event = isPrimitive(error)\n ? _eventFromRejectionWithPrimitive(error)\n : eventFromUnknownInput(stackParser, error, undefined, attachStacktrace, true);\n\n event.level = 'error';\n\n captureEvent(event, {\n originalException: error,\n mechanism: {\n handled: false,\n type: 'auto.browser.global_handlers.onunhandledrejection',\n },\n });\n });\n}\n\n/**\n *\n */\nexport function _getUnhandledRejectionError(error: unknown): unknown {\n if (isPrimitive(error)) {\n return error;\n }\n\n // dig the object of the rejection out of known event types\n try {\n type ErrorWithReason = { reason: unknown };\n // PromiseRejectionEvents store the object of the rejection under 'reason'\n // see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent\n if ('reason' in (error as ErrorWithReason)) {\n return (error as ErrorWithReason).reason;\n }\n\n type CustomEventWithDetail = { detail: { reason: unknown } };\n // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents\n // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into\n // the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec\n // see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and\n // https://github.com/getsentry/sentry-javascript/issues/2380\n if ('detail' in (error as CustomEventWithDetail) && 'reason' in (error as CustomEventWithDetail).detail) {\n return (error as CustomEventWithDetail).detail.reason;\n }\n } catch {} // eslint-disable-line no-empty\n\n return error;\n}\n\n/**\n * Create an event from a promise rejection where the `reason` is a primitive.\n *\n * @param reason: The `reason` property of the promise rejection\n * @returns An Event object with an appropriate `exception` value\n */\nexport function _eventFromRejectionWithPrimitive(reason: Primitive): Event {\n return {\n exception: {\n values: [\n {\n type: 'UnhandledRejection',\n // String() is needed because the Primitive type includes symbols (which can't be automatically stringified)\n value: `Non-Error promise rejection captured with value: ${String(reason)}`,\n },\n ],\n },\n };\n}\n\nfunction _enhanceEventWithInitialFrame(\n event: Event,\n url: string | undefined,\n lineno: number | undefined,\n colno: number | undefined,\n): Event {\n // event.exception\n const e = (event.exception = event.exception || {});\n // event.exception.values\n const ev = (e.values = e.values || []);\n // event.exception.values[0]\n const ev0 = (ev[0] = ev[0] || {});\n // event.exception.values[0].stacktrace\n const ev0s = (ev0.stacktrace = ev0.stacktrace || {});\n // event.exception.values[0].stacktrace.frames\n const ev0sf = (ev0s.frames = ev0s.frames || []);\n\n if (ev0sf.length === 0) {\n ev0sf.push({\n colno,\n lineno,\n filename: getFilenameFromUrl(url) ?? getLocationHref(),\n function: UNKNOWN_FUNCTION,\n in_app: true,\n });\n }\n\n return event;\n}\n\nfunction globalHandlerLog(type: string): void {\n DEBUG_BUILD && debug.log(`Global Handler attached: ${type}`);\n}\n\nfunction getOptions(): { stackParser: StackParser; attachStacktrace?: boolean } {\n const client = getClient<BrowserClient>();\n const options = client?.getOptions() || {\n stackParser: () => [],\n attachStacktrace: false,\n };\n return options;\n}\n\nfunction getFilenameFromUrl(url: string | undefined): string | undefined {\n if (!isString(url) || url.length === 0) {\n return undefined;\n }\n\n // Strip data URL content to avoid long base64 strings in stack frames\n // (e.g. when initializing a Worker with a base64 encoded script)\n // Don't include data prefix for filenames as it's not useful for stack traces\n // Wrap with < > to indicate it's a placeholder\n if (url.startsWith('data:')) {\n return `<${stripDataUrlContent(url, false)}>`;\n }\n\n return url;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"globalhandlers.js","sources":["../../../../../src/integrations/globalhandlers.ts"],"sourcesContent":["import type { Client, Event, IntegrationFn, Primitive, StackParser } from '@sentry/core/browser';\nimport {\n addGlobalErrorInstrumentationHandler,\n addGlobalUnhandledRejectionInstrumentationHandler,\n captureEvent,\n debug,\n defineIntegration,\n getClient,\n isPrimitive,\n isString,\n stripDataUrlContent,\n UNKNOWN_FUNCTION,\n} from '@sentry/core/browser';\nimport type { BrowserClient } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { getLocationHref } from '@sentry/browser-utils';\nimport { eventFromUnknownInput } from '../eventbuilder';\nimport { shouldIgnoreOnError } from '../helpers';\n\ntype GlobalHandlersIntegrationsOptionKeys = 'onerror' | 'onunhandledrejection';\n\ntype GlobalHandlersIntegrations = Record<GlobalHandlersIntegrationsOptionKeys, boolean>;\n\nconst INTEGRATION_NAME = 'GlobalHandlers' as const;\n\nconst _globalHandlersIntegration = ((options: Partial<GlobalHandlersIntegrations> = {}) => {\n const _options = {\n onerror: true,\n onunhandledrejection: true,\n ...options,\n };\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n Error.stackTraceLimit = 50;\n },\n setup(client) {\n if (_options.onerror) {\n _installGlobalOnErrorHandler(client);\n globalHandlerLog('onerror');\n }\n if (_options.onunhandledrejection) {\n _installGlobalOnUnhandledRejectionHandler(client);\n globalHandlerLog('onunhandledrejection');\n }\n },\n };\n}) satisfies IntegrationFn;\n\nexport const globalHandlersIntegration = defineIntegration(_globalHandlersIntegration);\n\nfunction _installGlobalOnErrorHandler(client: Client): void {\n addGlobalErrorInstrumentationHandler(data => {\n const { stackParser, attachStacktrace } = getOptions();\n\n if (getClient() !== client || shouldIgnoreOnError()) {\n return;\n }\n\n const { msg, url, line, column, error } = data;\n\n const event = _enhanceEventWithInitialFrame(\n eventFromUnknownInput(stackParser, error || msg, undefined, attachStacktrace, false),\n url,\n line,\n column,\n );\n\n event.level = 'error';\n\n captureEvent(event, {\n originalException: error,\n mechanism: {\n handled: false,\n type: 'auto.browser.global_handlers.onerror',\n },\n });\n });\n}\n\nfunction _installGlobalOnUnhandledRejectionHandler(client: Client): void {\n addGlobalUnhandledRejectionInstrumentationHandler(e => {\n const { stackParser, attachStacktrace } = getOptions();\n\n if (getClient() !== client || shouldIgnoreOnError()) {\n return;\n }\n\n const error = _getUnhandledRejectionError(e);\n\n const event = isPrimitive(error)\n ? _eventFromRejectionWithPrimitive(error)\n : eventFromUnknownInput(stackParser, error, undefined, attachStacktrace, true);\n\n event.level = 'error';\n\n captureEvent(event, {\n originalException: error,\n mechanism: {\n handled: false,\n type: 'auto.browser.global_handlers.onunhandledrejection',\n },\n });\n });\n}\n\n/**\n *\n */\nexport function _getUnhandledRejectionError(error: unknown): unknown {\n if (isPrimitive(error)) {\n return error;\n }\n\n // dig the object of the rejection out of known event types\n try {\n type ErrorWithReason = { reason: unknown };\n // PromiseRejectionEvents store the object of the rejection under 'reason'\n // see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent\n if ('reason' in (error as ErrorWithReason)) {\n return (error as ErrorWithReason).reason;\n }\n\n type CustomEventWithDetail = { detail: { reason: unknown } };\n // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents\n // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into\n // the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec\n // see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and\n // https://github.com/getsentry/sentry-javascript/issues/2380\n if ('detail' in (error as CustomEventWithDetail) && 'reason' in (error as CustomEventWithDetail).detail) {\n return (error as CustomEventWithDetail).detail.reason;\n }\n } catch {} // eslint-disable-line no-empty\n\n return error;\n}\n\n/**\n * Create an event from a promise rejection where the `reason` is a primitive.\n *\n * @param reason: The `reason` property of the promise rejection\n * @returns An Event object with an appropriate `exception` value\n */\nexport function _eventFromRejectionWithPrimitive(reason: Primitive): Event {\n return {\n exception: {\n values: [\n {\n type: 'UnhandledRejection',\n // String() is needed because the Primitive type includes symbols (which can't be automatically stringified)\n value: `Non-Error promise rejection captured with value: ${String(reason)}`,\n },\n ],\n },\n };\n}\n\nfunction _enhanceEventWithInitialFrame(\n event: Event,\n url: string | undefined,\n lineno: number | undefined,\n colno: number | undefined,\n): Event {\n // event.exception\n const e = (event.exception = event.exception || {});\n // event.exception.values\n const ev = (e.values = e.values || []);\n // event.exception.values[0]\n const ev0 = (ev[0] = ev[0] || {});\n // event.exception.values[0].stacktrace\n const ev0s = (ev0.stacktrace = ev0.stacktrace || {});\n // event.exception.values[0].stacktrace.frames\n const ev0sf = (ev0s.frames = ev0s.frames || []);\n\n if (ev0sf.length === 0) {\n ev0sf.push({\n colno,\n lineno,\n filename: getFilenameFromUrl(url) ?? getLocationHref(),\n function: UNKNOWN_FUNCTION,\n in_app: true,\n });\n }\n\n return event;\n}\n\nfunction globalHandlerLog(type: string): void {\n DEBUG_BUILD && debug.log(`Global Handler attached: ${type}`);\n}\n\nfunction getOptions(): { stackParser: StackParser; attachStacktrace?: boolean } {\n const client = getClient<BrowserClient>();\n const options = client?.getOptions() || {\n stackParser: () => [],\n attachStacktrace: false,\n };\n return options;\n}\n\nfunction getFilenameFromUrl(url: string | undefined): string | undefined {\n if (!isString(url) || url.length === 0) {\n return undefined;\n }\n\n // Strip data URL content to avoid long base64 strings in stack frames\n // (e.g. when initializing a Worker with a base64 encoded script)\n // Don't include data prefix for filenames as it's not useful for stack traces\n // Wrap with < > to indicate it's a placeholder\n if (url.startsWith('data:')) {\n return `<${stripDataUrlContent(url, false)}>`;\n }\n\n return url;\n}\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { defineIntegration, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD, isString, stringMatchesSomePattern, isObjectLike } from '@sentry/core/browser';
1
+ import { defineIntegration, spanToJSON, SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD, isString, stringMatchesSomePattern, isObjectLike } from '@sentry/core/browser';
2
2
  import { SENTRY_XHR_DATA_KEY, getBodyString, getFetchRequestArgBody } from '@sentry/browser-utils';
3
- import { URL_FULL, GRAPHQL_DOCUMENT } from '@sentry/conventions/attributes';
3
+ import { SENTRY_OP, URL_FULL, HTTP_METHOD, GRAPHQL_DOCUMENT } from '@sentry/conventions/attributes';
4
4
 
5
5
  const INTEGRATION_NAME = "GraphQLClient";
6
6
  const _graphqlClientIntegration = ((options) => {
@@ -15,14 +15,14 @@ const _graphqlClientIntegration = ((options) => {
15
15
  function _updateSpanWithGraphQLData(client, options) {
16
16
  client.on("beforeOutgoingRequestSpan", (span, hint) => {
17
17
  const spanJSON = spanToJSON(span);
18
- const spanAttributes = spanJSON.data || {};
19
- const spanOp = spanAttributes[SEMANTIC_ATTRIBUTE_SENTRY_OP];
18
+ const spanAttributes = spanJSON.attributes;
19
+ const spanOp = spanAttributes[SENTRY_OP];
20
20
  const isHttpClientSpan = spanOp === "http.client";
21
21
  if (!isHttpClientSpan) {
22
22
  return;
23
23
  }
24
24
  const httpUrl = spanAttributes[URL_FULL];
25
- const httpMethod = spanAttributes[SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD] || spanAttributes["http.method"];
25
+ const httpMethod = spanAttributes[SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD] || spanAttributes[HTTP_METHOD];
26
26
  if (!isString(httpUrl) || !isString(httpMethod)) {
27
27
  return;
28
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"graphqlClient.js","sources":["../../../../../src/integrations/graphqlClient.ts"],"sourcesContent":["import type { Client, IntegrationFn } from '@sentry/core/browser';\nimport {\n defineIntegration,\n isObjectLike,\n isString,\n SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n spanToJSON,\n stringMatchesSomePattern,\n} from '@sentry/core/browser';\nimport type { FetchHint, XhrHint } from '@sentry/browser-utils';\nimport { getBodyString, getFetchRequestArgBody, SENTRY_XHR_DATA_KEY } from '@sentry/browser-utils';\nimport { GRAPHQL_DOCUMENT, URL_FULL } from '@sentry/conventions/attributes';\n\ninterface GraphQLClientOptions {\n endpoints: Array<string | RegExp>;\n}\n\n/** Standard graphql request shape: https://graphql.org/learn/serving-over-http/#post-request-and-body */\ninterface GraphQLStandardRequest {\n query: string;\n operationName?: string;\n variables?: Record<string, unknown>;\n extensions?: Record<string, unknown>;\n}\n\n/** Persisted operation request */\ninterface GraphQLPersistedRequest {\n operationName: string;\n variables?: Record<string, unknown>;\n extensions: {\n persistedQuery: {\n version: number;\n sha256Hash: string;\n };\n } & Record<string, unknown>;\n}\n\ntype GraphQLRequestPayload = GraphQLStandardRequest | GraphQLPersistedRequest;\n\ninterface GraphQLOperation {\n operationType?: string;\n operationName?: string;\n}\n\nconst INTEGRATION_NAME = 'GraphQLClient' as const;\n\nconst _graphqlClientIntegration = ((options: GraphQLClientOptions) => {\n return {\n name: INTEGRATION_NAME,\n setup(client: Client) {\n _updateSpanWithGraphQLData(client, options);\n _updateBreadcrumbWithGraphQLData(client, options);\n },\n };\n}) satisfies IntegrationFn;\n\nfunction _updateSpanWithGraphQLData(client: Client, options: GraphQLClientOptions): void {\n client.on('beforeOutgoingRequestSpan', (span, hint) => {\n const spanJSON = spanToJSON(span);\n\n const spanAttributes = spanJSON.data || {};\n const spanOp = spanAttributes[SEMANTIC_ATTRIBUTE_SENTRY_OP];\n\n const isHttpClientSpan = spanOp === 'http.client';\n\n if (!isHttpClientSpan) {\n return;\n }\n\n const httpUrl = spanAttributes[URL_FULL];\n const httpMethod = spanAttributes[SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD] || spanAttributes['http.method'];\n\n if (!isString(httpUrl) || !isString(httpMethod)) {\n return;\n }\n\n const { endpoints } = options;\n const isTracedGraphqlEndpoint = stringMatchesSomePattern(httpUrl, endpoints);\n const payload = getRequestPayloadXhrOrFetch(hint as XhrHint | FetchHint);\n\n if (isTracedGraphqlEndpoint && payload) {\n const graphqlBody = getGraphQLRequestPayload(payload);\n\n if (graphqlBody) {\n const operationInfo = _getGraphQLOperation(graphqlBody);\n span.updateName(`${httpMethod} ${httpUrl} (${operationInfo})`);\n\n // Handle standard requests - capture the query document when enabled via dataCollection (default true)\n if (isStandardRequest(graphqlBody) && client.getDataCollectionOptions().graphQL.document === true) {\n span.setAttribute(GRAPHQL_DOCUMENT, graphqlBody.query);\n }\n\n // Handle persisted operations - capture hash for debugging\n if (isPersistedRequest(graphqlBody)) {\n span.setAttribute('graphql.persisted_query.hash.sha256', graphqlBody.extensions.persistedQuery.sha256Hash);\n span.setAttribute('graphql.persisted_query.version', graphqlBody.extensions.persistedQuery.version);\n }\n }\n }\n });\n}\n\nfunction _updateBreadcrumbWithGraphQLData(client: Client, options: GraphQLClientOptions): void {\n client.on('beforeOutgoingRequestBreadcrumb', (breadcrumb, handlerData) => {\n const { category, type, data } = breadcrumb;\n\n const isFetch = category === 'fetch';\n const isXhr = category === 'xhr';\n const isHttpBreadcrumb = type === 'http';\n\n if (isHttpBreadcrumb && (isFetch || isXhr)) {\n const httpUrl = data?.url;\n const { endpoints } = options;\n\n const isTracedGraphqlEndpoint = stringMatchesSomePattern(httpUrl, endpoints);\n const payload = getRequestPayloadXhrOrFetch(handlerData as XhrHint | FetchHint);\n\n if (isTracedGraphqlEndpoint && data && payload) {\n const graphqlBody = getGraphQLRequestPayload(payload);\n\n if (!data.graphql && graphqlBody) {\n const operationInfo = _getGraphQLOperation(graphqlBody);\n\n data['graphql.operation'] = operationInfo;\n\n if (isStandardRequest(graphqlBody) && client.getDataCollectionOptions().graphQL.document === true) {\n data[GRAPHQL_DOCUMENT] = graphqlBody.query;\n }\n\n if (isPersistedRequest(graphqlBody)) {\n data['graphql.persisted_query.hash.sha256'] = graphqlBody.extensions.persistedQuery.sha256Hash;\n data['graphql.persisted_query.version'] = graphqlBody.extensions.persistedQuery.version;\n }\n }\n }\n }\n });\n}\n\n/**\n * @param requestBody - GraphQL request\n * @returns A formatted version of the request: 'TYPE NAME' or 'TYPE' or 'persisted NAME'\n */\nexport function _getGraphQLOperation(requestBody: GraphQLRequestPayload): string {\n // Handle persisted operations\n if (isPersistedRequest(requestBody)) {\n return `persisted ${requestBody.operationName}`;\n }\n\n // Handle standard GraphQL requests\n if (isStandardRequest(requestBody)) {\n const { query: graphqlQuery, operationName: graphqlOperationName } = requestBody;\n const { operationName = graphqlOperationName, operationType } = parseGraphQLQuery(graphqlQuery);\n const operationInfo = operationName ? `${operationType} ${operationName}` : `${operationType}`;\n return operationInfo;\n }\n\n // Fallback for unknown request types\n return 'unknown';\n}\n\n/**\n * Get the request body/payload based on the shape of the hint.\n *\n * Exported for tests only.\n */\nexport function getRequestPayloadXhrOrFetch(hint: XhrHint | FetchHint): string | undefined {\n const isXhr = 'xhr' in hint;\n\n let body: string | undefined;\n\n if (isXhr) {\n const sentryXhrData = hint.xhr[SENTRY_XHR_DATA_KEY];\n body = sentryXhrData && getBodyString(sentryXhrData.body)[0];\n } else {\n const sentryFetchData = getFetchRequestArgBody(hint.input);\n body = getBodyString(sentryFetchData)[0];\n }\n\n return body;\n}\n\n/**\n * Extract the name and type of the operation from the GraphQL query.\n *\n * Exported for tests only.\n */\nexport function parseGraphQLQuery(query: string): GraphQLOperation {\n const namedQueryRe = /^(?:\\s*)(query|mutation|subscription)(?:\\s*)(\\w+)(?:\\s*)[{(]/;\n const unnamedQueryRe = /^(?:\\s*)(query|mutation|subscription)(?:\\s*)[{(]/;\n\n const namedMatch = query.match(namedQueryRe);\n if (namedMatch) {\n return {\n operationType: namedMatch[1],\n operationName: namedMatch[2],\n };\n }\n\n const unnamedMatch = query.match(unnamedQueryRe);\n if (unnamedMatch) {\n return {\n operationType: unnamedMatch[1],\n operationName: undefined,\n };\n }\n return {\n operationType: undefined,\n operationName: undefined,\n };\n}\n\n/**\n * Helper to safely check if a value is a non-null object\n */\n\n/**\n * Type guard to check if a request is a standard GraphQL request\n */\nfunction isStandardRequest(payload: unknown): payload is GraphQLStandardRequest {\n return isObjectLike(payload) && typeof payload.query === 'string';\n}\n\n/**\n * Type guard to check if a request is a persisted operation request\n */\nfunction isPersistedRequest(payload: unknown): payload is GraphQLPersistedRequest {\n return (\n isObjectLike(payload) &&\n typeof payload.operationName === 'string' &&\n isObjectLike(payload.extensions) &&\n isObjectLike(payload.extensions.persistedQuery) &&\n typeof payload.extensions.persistedQuery.sha256Hash === 'string' &&\n typeof payload.extensions.persistedQuery.version === 'number'\n );\n}\n\n/**\n * Extract the payload of a request if it's GraphQL.\n * Exported for tests only.\n * @param payload - A valid JSON string\n * @returns A POJO or undefined\n */\nexport function getGraphQLRequestPayload(payload: string): GraphQLRequestPayload | undefined {\n try {\n const requestBody = JSON.parse(payload);\n\n // Return any valid GraphQL request (standard, persisted, or APQ retry with both)\n if (isStandardRequest(requestBody) || isPersistedRequest(requestBody)) {\n return requestBody;\n }\n\n // Not a GraphQL request\n return undefined;\n } catch {\n // Invalid JSON\n return undefined;\n }\n}\n\n/**\n * This integration ensures that GraphQL requests made in the browser\n * have their GraphQL-specific data captured and attached to spans and breadcrumbs.\n */\nexport const graphqlClientIntegration = defineIntegration(_graphqlClientIntegration);\n"],"names":[],"mappings":";;;;AA6CA,MAAM,gBAAA,GAAmB,eAAA;AAEzB,MAAM,yBAAA,IAA6B,CAAC,OAAA,KAAkC;AACpE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,MAAM,MAAA,EAAgB;AACpB,MAAA,0BAAA,CAA2B,QAAQ,OAAO,CAAA;AAC1C,MAAA,gCAAA,CAAiC,QAAQ,OAAO,CAAA;AAAA,IAClD;AAAA,GACF;AACF,CAAA,CAAA;AAEA,SAAS,0BAAA,CAA2B,QAAgB,OAAA,EAAqC;AACvF,EAAA,MAAA,CAAO,EAAA,CAAG,2BAAA,EAA6B,CAAC,IAAA,EAAM,IAAA,KAAS;AACrD,IAAA,MAAM,QAAA,GAAW,WAAW,IAAI,CAAA;AAEhC,IAAA,MAAM,cAAA,GAAiB,QAAA,CAAS,IAAA,IAAQ,EAAC;AACzC,IAAA,MAAM,MAAA,GAAS,eAAe,4BAA4B,CAAA;AAE1D,IAAA,MAAM,mBAAmB,MAAA,KAAW,aAAA;AAEpC,IAAA,IAAI,CAAC,gBAAA,EAAkB;AACrB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,eAAe,QAAQ,CAAA;AACvC,IAAA,MAAM,UAAA,GAAa,cAAA,CAAe,sCAAsC,CAAA,IAAK,eAAe,aAAa,CAAA;AAEzG,IAAA,IAAI,CAAC,QAAA,CAAS,OAAO,KAAK,CAAC,QAAA,CAAS,UAAU,CAAA,EAAG;AAC/C,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,WAAU,GAAI,OAAA;AACtB,IAAA,MAAM,uBAAA,GAA0B,wBAAA,CAAyB,OAAA,EAAS,SAAS,CAAA;AAC3E,IAAA,MAAM,OAAA,GAAU,4BAA4B,IAA2B,CAAA;AAEvE,IAAA,IAAI,2BAA2B,OAAA,EAAS;AACtC,MAAA,MAAM,WAAA,GAAc,yBAAyB,OAAO,CAAA;AAEpD,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,aAAA,GAAgB,qBAAqB,WAAW,CAAA;AACtD,QAAA,IAAA,CAAK,WAAW,CAAA,EAAG,UAAU,IAAI,OAAO,CAAA,EAAA,EAAK,aAAa,CAAA,CAAA,CAAG,CAAA;AAG7D,QAAA,IAAI,iBAAA,CAAkB,WAAW,CAAA,IAAK,MAAA,CAAO,0BAAyB,CAAE,OAAA,CAAQ,aAAa,IAAA,EAAM;AACjG,UAAA,IAAA,CAAK,YAAA,CAAa,gBAAA,EAAkB,WAAA,CAAY,KAAK,CAAA;AAAA,QACvD;AAGA,QAAA,IAAI,kBAAA,CAAmB,WAAW,CAAA,EAAG;AACnC,UAAA,IAAA,CAAK,YAAA,CAAa,qCAAA,EAAuC,WAAA,CAAY,UAAA,CAAW,eAAe,UAAU,CAAA;AACzG,UAAA,IAAA,CAAK,YAAA,CAAa,iCAAA,EAAmC,WAAA,CAAY,UAAA,CAAW,eAAe,OAAO,CAAA;AAAA,QACpG;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AACH;AAEA,SAAS,gCAAA,CAAiC,QAAgB,OAAA,EAAqC;AAC7F,EAAA,MAAA,CAAO,EAAA,CAAG,iCAAA,EAAmC,CAAC,UAAA,EAAY,WAAA,KAAgB;AACxE,IAAA,MAAM,EAAE,QAAA,EAAU,IAAA,EAAM,IAAA,EAAK,GAAI,UAAA;AAEjC,IAAA,MAAM,UAAU,QAAA,KAAa,OAAA;AAC7B,IAAA,MAAM,QAAQ,QAAA,KAAa,KAAA;AAC3B,IAAA,MAAM,mBAAmB,IAAA,KAAS,MAAA;AAElC,IAAA,IAAI,gBAAA,KAAqB,WAAW,KAAA,CAAA,EAAQ;AAC1C,MAAA,MAAM,UAAU,IAAA,EAAM,GAAA;AACtB,MAAA,MAAM,EAAE,WAAU,GAAI,OAAA;AAEtB,MAAA,MAAM,uBAAA,GAA0B,wBAAA,CAAyB,OAAA,EAAS,SAAS,CAAA;AAC3E,MAAA,MAAM,OAAA,GAAU,4BAA4B,WAAkC,CAAA;AAE9E,MAAA,IAAI,uBAAA,IAA2B,QAAQ,OAAA,EAAS;AAC9C,QAAA,MAAM,WAAA,GAAc,yBAAyB,OAAO,CAAA;AAEpD,QAAA,IAAI,CAAC,IAAA,CAAK,OAAA,IAAW,WAAA,EAAa;AAChC,UAAA,MAAM,aAAA,GAAgB,qBAAqB,WAAW,CAAA;AAEtD,UAAA,IAAA,CAAK,mBAAmB,CAAA,GAAI,aAAA;AAE5B,UAAA,IAAI,iBAAA,CAAkB,WAAW,CAAA,IAAK,MAAA,CAAO,0BAAyB,CAAE,OAAA,CAAQ,aAAa,IAAA,EAAM;AACjG,YAAA,IAAA,CAAK,gBAAgB,IAAI,WAAA,CAAY,KAAA;AAAA,UACvC;AAEA,UAAA,IAAI,kBAAA,CAAmB,WAAW,CAAA,EAAG;AACnC,YAAA,IAAA,CAAK,qCAAqC,CAAA,GAAI,WAAA,CAAY,UAAA,CAAW,cAAA,CAAe,UAAA;AACpF,YAAA,IAAA,CAAK,iCAAiC,CAAA,GAAI,WAAA,CAAY,UAAA,CAAW,cAAA,CAAe,OAAA;AAAA,UAClF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AACH;AAMO,SAAS,qBAAqB,WAAA,EAA4C;AAE/E,EAAA,IAAI,kBAAA,CAAmB,WAAW,CAAA,EAAG;AACnC,IAAA,OAAO,CAAA,UAAA,EAAa,YAAY,aAAa,CAAA,CAAA;AAAA,EAC/C;AAGA,EAAA,IAAI,iBAAA,CAAkB,WAAW,CAAA,EAAG;AAClC,IAAA,MAAM,EAAE,KAAA,EAAO,YAAA,EAAc,aAAA,EAAe,sBAAqB,GAAI,WAAA;AACrE,IAAA,MAAM,EAAE,aAAA,GAAgB,oBAAA,EAAsB,aAAA,EAAc,GAAI,kBAAkB,YAAY,CAAA;AAC9F,IAAA,MAAM,aAAA,GAAgB,gBAAgB,CAAA,EAAG,aAAa,IAAI,aAAa,CAAA,CAAA,GAAK,GAAG,aAAa,CAAA,CAAA;AAC5F,IAAA,OAAO,aAAA;AAAA,EACT;AAGA,EAAA,OAAO,SAAA;AACT;AAOO,SAAS,4BAA4B,IAAA,EAA+C;AACzF,EAAA,MAAM,QAAQ,KAAA,IAAS,IAAA;AAEvB,EAAA,IAAI,IAAA;AAEJ,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,GAAA,CAAI,mBAAmB,CAAA;AAClD,IAAA,IAAA,GAAO,aAAA,IAAiB,aAAA,CAAc,aAAA,CAAc,IAAI,EAAE,CAAC,CAAA;AAAA,EAC7D,CAAA,MAAO;AACL,IAAA,MAAM,eAAA,GAAkB,sBAAA,CAAuB,IAAA,CAAK,KAAK,CAAA;AACzD,IAAA,IAAA,GAAO,aAAA,CAAc,eAAe,CAAA,CAAE,CAAC,CAAA;AAAA,EACzC;AAEA,EAAA,OAAO,IAAA;AACT;AAOO,SAAS,kBAAkB,KAAA,EAAiC;AACjE,EAAA,MAAM,YAAA,GAAe,8DAAA;AACrB,EAAA,MAAM,cAAA,GAAiB,kDAAA;AAEvB,EAAA,MAAM,UAAA,GAAa,KAAA,CAAM,KAAA,CAAM,YAAY,CAAA;AAC3C,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,OAAO;AAAA,MACL,aAAA,EAAe,WAAW,CAAC,CAAA;AAAA,MAC3B,aAAA,EAAe,WAAW,CAAC;AAAA,KAC7B;AAAA,EACF;AAEA,EAAA,MAAM,YAAA,GAAe,KAAA,CAAM,KAAA,CAAM,cAAc,CAAA;AAC/C,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,OAAO;AAAA,MACL,aAAA,EAAe,aAAa,CAAC,CAAA;AAAA,MAC7B,aAAA,EAAe;AAAA,KACjB;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,aAAA,EAAe,MAAA;AAAA,IACf,aAAA,EAAe;AAAA,GACjB;AACF;AASA,SAAS,kBAAkB,OAAA,EAAqD;AAC9E,EAAA,OAAO,YAAA,CAAa,OAAO,CAAA,IAAK,OAAO,QAAQ,KAAA,KAAU,QAAA;AAC3D;AAKA,SAAS,mBAAmB,OAAA,EAAsD;AAChF,EAAA,OACE,YAAA,CAAa,OAAO,CAAA,IACpB,OAAO,OAAA,CAAQ,aAAA,KAAkB,QAAA,IACjC,YAAA,CAAa,OAAA,CAAQ,UAAU,CAAA,IAC/B,YAAA,CAAa,OAAA,CAAQ,WAAW,cAAc,CAAA,IAC9C,OAAO,OAAA,CAAQ,UAAA,CAAW,cAAA,CAAe,UAAA,KAAe,QAAA,IACxD,OAAO,OAAA,CAAQ,UAAA,CAAW,cAAA,CAAe,OAAA,KAAY,QAAA;AAEzD;AAQO,SAAS,yBAAyB,OAAA,EAAoD;AAC3F,EAAA,IAAI;AACF,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA;AAGtC,IAAA,IAAI,iBAAA,CAAkB,WAAW,CAAA,IAAK,kBAAA,CAAmB,WAAW,CAAA,EAAG;AACrE,MAAA,OAAO,WAAA;AAAA,IACT;AAGA,IAAA,OAAO,KAAA,CAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAMO,MAAM,wBAAA,GAA2B,kBAAkB,yBAAyB;;;;"}
1
+ {"version":3,"file":"graphqlClient.js","sources":["../../../../../src/integrations/graphqlClient.ts"],"sourcesContent":["import type { Client, IntegrationFn } from '@sentry/core/browser';\nimport {\n defineIntegration,\n isObjectLike,\n isString,\n SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD,\n spanToJSON,\n stringMatchesSomePattern,\n} from '@sentry/core/browser';\nimport type { FetchHint, XhrHint } from '@sentry/browser-utils';\nimport { getBodyString, getFetchRequestArgBody, SENTRY_XHR_DATA_KEY } from '@sentry/browser-utils';\nimport { GRAPHQL_DOCUMENT, HTTP_METHOD, SENTRY_OP, URL_FULL } from '@sentry/conventions/attributes';\n\ninterface GraphQLClientOptions {\n endpoints: Array<string | RegExp>;\n}\n\n/** Standard graphql request shape: https://graphql.org/learn/serving-over-http/#post-request-and-body */\ninterface GraphQLStandardRequest {\n query: string;\n operationName?: string;\n variables?: Record<string, unknown>;\n extensions?: Record<string, unknown>;\n}\n\n/** Persisted operation request */\ninterface GraphQLPersistedRequest {\n operationName: string;\n variables?: Record<string, unknown>;\n extensions: {\n persistedQuery: {\n version: number;\n sha256Hash: string;\n };\n } & Record<string, unknown>;\n}\n\ntype GraphQLRequestPayload = GraphQLStandardRequest | GraphQLPersistedRequest;\n\ninterface GraphQLOperation {\n operationType?: string;\n operationName?: string;\n}\n\nconst INTEGRATION_NAME = 'GraphQLClient' as const;\n\nconst _graphqlClientIntegration = ((options: GraphQLClientOptions) => {\n return {\n name: INTEGRATION_NAME,\n setup(client: Client) {\n _updateSpanWithGraphQLData(client, options);\n _updateBreadcrumbWithGraphQLData(client, options);\n },\n };\n}) satisfies IntegrationFn;\n\nfunction _updateSpanWithGraphQLData(client: Client, options: GraphQLClientOptions): void {\n client.on('beforeOutgoingRequestSpan', (span, hint) => {\n const spanJSON = spanToJSON(span);\n\n const spanAttributes = spanJSON.attributes;\n const spanOp = spanAttributes[SENTRY_OP];\n\n const isHttpClientSpan = spanOp === 'http.client';\n\n if (!isHttpClientSpan) {\n return;\n }\n\n const httpUrl = spanAttributes[URL_FULL];\n // oxlint-disable-next-line typescript/no-deprecated\n const httpMethod = spanAttributes[SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD] || spanAttributes[HTTP_METHOD];\n\n if (!isString(httpUrl) || !isString(httpMethod)) {\n return;\n }\n\n const { endpoints } = options;\n const isTracedGraphqlEndpoint = stringMatchesSomePattern(httpUrl, endpoints);\n const payload = getRequestPayloadXhrOrFetch(hint as XhrHint | FetchHint);\n\n if (isTracedGraphqlEndpoint && payload) {\n const graphqlBody = getGraphQLRequestPayload(payload);\n\n if (graphqlBody) {\n const operationInfo = _getGraphQLOperation(graphqlBody);\n span.updateName(`${httpMethod} ${httpUrl} (${operationInfo})`);\n\n // Handle standard requests - capture the query document when enabled via dataCollection (default true)\n if (isStandardRequest(graphqlBody) && client.getDataCollectionOptions().graphQL.document === true) {\n span.setAttribute(GRAPHQL_DOCUMENT, graphqlBody.query);\n }\n\n // Handle persisted operations - capture hash for debugging\n if (isPersistedRequest(graphqlBody)) {\n span.setAttribute('graphql.persisted_query.hash.sha256', graphqlBody.extensions.persistedQuery.sha256Hash);\n span.setAttribute('graphql.persisted_query.version', graphqlBody.extensions.persistedQuery.version);\n }\n }\n }\n });\n}\n\nfunction _updateBreadcrumbWithGraphQLData(client: Client, options: GraphQLClientOptions): void {\n client.on('beforeOutgoingRequestBreadcrumb', (breadcrumb, handlerData) => {\n const { category, type, data } = breadcrumb;\n\n const isFetch = category === 'fetch';\n const isXhr = category === 'xhr';\n const isHttpBreadcrumb = type === 'http';\n\n if (isHttpBreadcrumb && (isFetch || isXhr)) {\n const httpUrl = data?.url;\n const { endpoints } = options;\n\n const isTracedGraphqlEndpoint = stringMatchesSomePattern(httpUrl, endpoints);\n const payload = getRequestPayloadXhrOrFetch(handlerData as XhrHint | FetchHint);\n\n if (isTracedGraphqlEndpoint && data && payload) {\n const graphqlBody = getGraphQLRequestPayload(payload);\n\n if (!data.graphql && graphqlBody) {\n const operationInfo = _getGraphQLOperation(graphqlBody);\n\n data['graphql.operation'] = operationInfo;\n\n if (isStandardRequest(graphqlBody) && client.getDataCollectionOptions().graphQL.document === true) {\n data[GRAPHQL_DOCUMENT] = graphqlBody.query;\n }\n\n if (isPersistedRequest(graphqlBody)) {\n data['graphql.persisted_query.hash.sha256'] = graphqlBody.extensions.persistedQuery.sha256Hash;\n data['graphql.persisted_query.version'] = graphqlBody.extensions.persistedQuery.version;\n }\n }\n }\n }\n });\n}\n\n/**\n * @param requestBody - GraphQL request\n * @returns A formatted version of the request: 'TYPE NAME' or 'TYPE' or 'persisted NAME'\n */\nexport function _getGraphQLOperation(requestBody: GraphQLRequestPayload): string {\n // Handle persisted operations\n if (isPersistedRequest(requestBody)) {\n return `persisted ${requestBody.operationName}`;\n }\n\n // Handle standard GraphQL requests\n if (isStandardRequest(requestBody)) {\n const { query: graphqlQuery, operationName: graphqlOperationName } = requestBody;\n const { operationName = graphqlOperationName, operationType } = parseGraphQLQuery(graphqlQuery);\n const operationInfo = operationName ? `${operationType} ${operationName}` : `${operationType}`;\n return operationInfo;\n }\n\n // Fallback for unknown request types\n return 'unknown';\n}\n\n/**\n * Get the request body/payload based on the shape of the hint.\n *\n * Exported for tests only.\n */\nexport function getRequestPayloadXhrOrFetch(hint: XhrHint | FetchHint): string | undefined {\n const isXhr = 'xhr' in hint;\n\n let body: string | undefined;\n\n if (isXhr) {\n const sentryXhrData = hint.xhr[SENTRY_XHR_DATA_KEY];\n body = sentryXhrData && getBodyString(sentryXhrData.body)[0];\n } else {\n const sentryFetchData = getFetchRequestArgBody(hint.input);\n body = getBodyString(sentryFetchData)[0];\n }\n\n return body;\n}\n\n/**\n * Extract the name and type of the operation from the GraphQL query.\n *\n * Exported for tests only.\n */\nexport function parseGraphQLQuery(query: string): GraphQLOperation {\n const namedQueryRe = /^(?:\\s*)(query|mutation|subscription)(?:\\s*)(\\w+)(?:\\s*)[{(]/;\n const unnamedQueryRe = /^(?:\\s*)(query|mutation|subscription)(?:\\s*)[{(]/;\n\n const namedMatch = query.match(namedQueryRe);\n if (namedMatch) {\n return {\n operationType: namedMatch[1],\n operationName: namedMatch[2],\n };\n }\n\n const unnamedMatch = query.match(unnamedQueryRe);\n if (unnamedMatch) {\n return {\n operationType: unnamedMatch[1],\n operationName: undefined,\n };\n }\n return {\n operationType: undefined,\n operationName: undefined,\n };\n}\n\n/**\n * Helper to safely check if a value is a non-null object\n */\n\n/**\n * Type guard to check if a request is a standard GraphQL request\n */\nfunction isStandardRequest(payload: unknown): payload is GraphQLStandardRequest {\n return isObjectLike(payload) && typeof payload.query === 'string';\n}\n\n/**\n * Type guard to check if a request is a persisted operation request\n */\nfunction isPersistedRequest(payload: unknown): payload is GraphQLPersistedRequest {\n return (\n isObjectLike(payload) &&\n typeof payload.operationName === 'string' &&\n isObjectLike(payload.extensions) &&\n isObjectLike(payload.extensions.persistedQuery) &&\n typeof payload.extensions.persistedQuery.sha256Hash === 'string' &&\n typeof payload.extensions.persistedQuery.version === 'number'\n );\n}\n\n/**\n * Extract the payload of a request if it's GraphQL.\n * Exported for tests only.\n * @param payload - A valid JSON string\n * @returns A POJO or undefined\n */\nexport function getGraphQLRequestPayload(payload: string): GraphQLRequestPayload | undefined {\n try {\n const requestBody = JSON.parse(payload);\n\n // Return any valid GraphQL request (standard, persisted, or APQ retry with both)\n if (isStandardRequest(requestBody) || isPersistedRequest(requestBody)) {\n return requestBody;\n }\n\n // Not a GraphQL request\n return undefined;\n } catch {\n // Invalid JSON\n return undefined;\n }\n}\n\n/**\n * This integration ensures that GraphQL requests made in the browser\n * have their GraphQL-specific data captured and attached to spans and breadcrumbs.\n */\nexport const graphqlClientIntegration = defineIntegration(_graphqlClientIntegration);\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"httpclient.js","sources":["../../../../../src/integrations/httpclient.ts"],"sourcesContent":["import type { Client, Event as SentryEvent, IntegrationFn, SentryWrappedXMLHttpRequest } from '@sentry/core/browser';\nimport {\n _INTERNAL_filterCookies,\n _INTERNAL_filterKeyValueData,\n addExceptionMechanism,\n addFetchInstrumentationHandler,\n captureEvent,\n debug,\n defineIntegration,\n getClient,\n GLOBAL_OBJ,\n isSentryRequestUrl,\n supportsNativeFetch,\n} from '@sentry/core/browser';\nimport { addXhrInstrumentationHandler, SENTRY_XHR_DATA_KEY } from '@sentry/browser-utils';\nimport { DEBUG_BUILD } from '../debug-build';\n\nexport type HttpStatusCodeRange = [number, number] | number;\nexport type HttpRequestTarget = string | RegExp;\n\nconst INTEGRATION_NAME = 'HttpClient' as const;\n\ninterface HttpClientOptions {\n /**\n * HTTP status codes that should be considered failed.\n * This array can contain tuples of `[begin, end]` (both inclusive),\n * single status codes, or a combinations of both\n *\n * Example: [[500, 505], 507]\n * Default: [[500, 599]]\n */\n failedRequestStatusCodes: HttpStatusCodeRange[];\n\n /**\n * Targets to track for failed requests.\n * This array can contain strings or regular expressions.\n *\n * Example: ['http://localhost', /api\\/.*\\/]\n * Default: [/.*\\/]\n */\n failedRequestTargets: HttpRequestTarget[];\n}\n\nconst _httpClientIntegration = ((options: Partial<HttpClientOptions> = {}) => {\n const _options: HttpClientOptions = {\n failedRequestStatusCodes: [[500, 599]],\n failedRequestTargets: [/.*/],\n ...options,\n };\n\n return {\n name: INTEGRATION_NAME,\n setup(client): void {\n _wrapFetch(client, _options);\n _wrapXHR(client, _options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Create events for failed client side HTTP requests.\n */\nexport const httpClientIntegration = defineIntegration(_httpClientIntegration);\n\n/**\n * Interceptor function for fetch requests\n *\n * @param requestInfo The Fetch API request info\n * @param response The Fetch API response\n * @param requestInit The request init object\n */\nfunction _fetchResponseHandler(\n options: HttpClientOptions,\n requestInfo: RequestInfo,\n response: Response,\n requestInit?: RequestInit,\n error?: unknown,\n): void {\n if (_shouldCaptureResponse(options, response.status, response.url)) {\n const request = _getRequest(requestInfo, requestInit);\n\n let requestHeaders, responseHeaders, requestCookies, responseCookies;\n\n const dc = _getDataCollectionSettings();\n\n if (dc.requestHeaders !== false) {\n requestHeaders = _INTERNAL_filterKeyValueData(_extractFetchHeaders(request.headers), dc.requestHeaders);\n }\n if (dc.responseHeaders !== false) {\n responseHeaders = _INTERNAL_filterKeyValueData(_extractFetchHeaders(response.headers), dc.responseHeaders);\n }\n if (dc.cookies !== false) {\n const reqCookieStr = request.headers.get('Cookie') || undefined;\n if (reqCookieStr) {\n const filtered = _INTERNAL_filterCookies(reqCookieStr, dc.cookies);\n if (typeof filtered === 'object') {\n requestCookies = filtered;\n }\n }\n const resCookieStr = response.headers.get('Set-Cookie') || undefined;\n if (resCookieStr) {\n const filtered = _INTERNAL_filterCookies(resCookieStr, dc.cookies);\n if (typeof filtered === 'object') {\n responseCookies = filtered;\n }\n }\n }\n\n const event = _createEvent({\n url: request.url,\n method: request.method,\n status: response.status,\n requestHeaders,\n responseHeaders,\n requestCookies,\n responseCookies,\n error,\n type: 'fetch',\n });\n\n captureEvent(event);\n }\n}\n\n/**\n * Interceptor function for XHR requests\n *\n * @param xhr The XHR request\n * @param method The HTTP method\n * @param headers The HTTP headers\n */\nfunction _xhrResponseHandler(\n options: HttpClientOptions,\n xhr: XMLHttpRequest,\n method: string,\n headers: Record<string, string>,\n error?: unknown,\n): void {\n if (_shouldCaptureResponse(options, xhr.status, xhr.responseURL)) {\n let requestHeaders, responseCookies, responseHeaders;\n\n const dc = _getDataCollectionSettings();\n\n if (dc.cookies !== false) {\n try {\n const cookieString = xhr.getResponseHeader('Set-Cookie') || xhr.getResponseHeader('set-cookie') || undefined;\n if (cookieString) {\n const filtered = _INTERNAL_filterCookies(cookieString, dc.cookies);\n if (typeof filtered === 'object') {\n responseCookies = filtered;\n }\n }\n } catch {\n // ignore it if parsing fails\n }\n }\n\n if (dc.responseHeaders !== false) {\n try {\n responseHeaders = _INTERNAL_filterKeyValueData(_getXHRResponseHeaders(xhr), dc.responseHeaders);\n } catch {\n // ignore it if parsing fails\n }\n }\n\n if (dc.requestHeaders !== false) {\n requestHeaders = _INTERNAL_filterKeyValueData(headers, dc.requestHeaders);\n }\n\n const event = _createEvent({\n url: xhr.responseURL,\n method,\n status: xhr.status,\n requestHeaders,\n // Can't access request cookies from XHR\n responseHeaders,\n responseCookies,\n error,\n type: 'xhr',\n });\n\n captureEvent(event);\n }\n}\n\n/**\n * Extracts response size from `Content-Length` header when possible\n *\n * @param headers\n * @returns The response size in bytes or undefined\n */\nfunction _getResponseSizeFromHeaders(headers?: Record<string, string>): number | undefined {\n if (headers) {\n const contentLength = headers['Content-Length'] || headers['content-length'];\n\n if (contentLength) {\n return parseInt(contentLength, 10);\n }\n }\n\n return undefined;\n}\n\n/**\n * Extracts the headers as an object from the given Fetch API request or response object\n *\n * @param headers The headers to extract\n * @returns The extracted headers as an object\n */\nfunction _extractFetchHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {};\n\n headers.forEach((value, key) => {\n result[key] = value;\n });\n\n return result;\n}\n\n/**\n * Extracts the response headers as an object from the given XHR object\n *\n * @param xhr The XHR object to extract the response headers from\n * @returns The response headers as an object\n */\nfunction _getXHRResponseHeaders(xhr: XMLHttpRequest): Record<string, string> {\n const headers = xhr.getAllResponseHeaders();\n\n if (!headers) {\n return {};\n }\n\n return headers.split('\\r\\n').reduce((acc: Record<string, string>, line: string) => {\n const [key, value] = line.split(': ');\n if (key && value) {\n acc[key] = value;\n }\n return acc;\n }, {});\n}\n\n/**\n * Checks if the given target url is in the given list of targets\n *\n * @param target The target url to check\n * @returns true if the target url is in the given list of targets, false otherwise\n */\nfunction _isInGivenRequestTargets(\n failedRequestTargets: HttpClientOptions['failedRequestTargets'],\n target: string,\n): boolean {\n return failedRequestTargets.some((givenRequestTarget: HttpRequestTarget) => {\n if (typeof givenRequestTarget === 'string') {\n return target.includes(givenRequestTarget);\n }\n\n return givenRequestTarget.test(target);\n });\n}\n\n/**\n * Checks if the given status code is in the given range\n *\n * @param status The status code to check\n * @returns true if the status code is in the given range, false otherwise\n */\nfunction _isInGivenStatusRanges(\n failedRequestStatusCodes: HttpClientOptions['failedRequestStatusCodes'],\n status: number,\n): boolean {\n return failedRequestStatusCodes.some((range: HttpStatusCodeRange) => {\n if (typeof range === 'number') {\n return range === status;\n }\n\n return status >= range[0] && status <= range[1];\n });\n}\n\n/**\n * Wraps `fetch` function to capture request and response data\n */\nfunction _wrapFetch(client: Client, options: HttpClientOptions): void {\n if (!supportsNativeFetch()) {\n return;\n }\n\n addFetchInstrumentationHandler(handlerData => {\n if (getClient() !== client) {\n return;\n }\n\n const { response, args, error, virtualError } = handlerData;\n const [requestInfo, requestInit] = args as [RequestInfo, RequestInit | undefined];\n\n if (!response) {\n return;\n }\n\n _fetchResponseHandler(options, requestInfo, response as Response, requestInit, error || virtualError);\n });\n}\n\n/**\n * Wraps XMLHttpRequest to capture request and response data\n */\nfunction _wrapXHR(client: Client, options: HttpClientOptions): void {\n if (!('XMLHttpRequest' in GLOBAL_OBJ)) {\n return;\n }\n\n addXhrInstrumentationHandler(handlerData => {\n if (getClient() !== client) {\n return;\n }\n\n const { error, virtualError } = handlerData;\n\n const xhr = handlerData.xhr as SentryWrappedXMLHttpRequest & XMLHttpRequest;\n\n const sentryXhrData = xhr[SENTRY_XHR_DATA_KEY];\n\n if (!sentryXhrData) {\n return;\n }\n\n const { method, request_headers: headers } = sentryXhrData;\n\n try {\n _xhrResponseHandler(options, xhr, method, headers, error || virtualError);\n } catch (e) {\n DEBUG_BUILD && debug.warn('Error while extracting response event form XHR response', e);\n }\n });\n}\n\n/**\n * Checks whether to capture given response as an event\n *\n * @param status response status code\n * @param url response url\n */\nfunction _shouldCaptureResponse(options: HttpClientOptions, status: number, url: string): boolean {\n return (\n _isInGivenStatusRanges(options.failedRequestStatusCodes, status) &&\n _isInGivenRequestTargets(options.failedRequestTargets, url) &&\n !isSentryRequestUrl(url, getClient())\n );\n}\n\n/**\n * Creates a synthetic Sentry event from given response data\n *\n * @param data response data\n * @returns event\n */\nfunction _createEvent(data: {\n url: string;\n method: string;\n status: number;\n type: 'fetch' | 'xhr';\n responseHeaders?: Record<string, string>;\n responseCookies?: Record<string, string>;\n requestHeaders?: Record<string, string>;\n requestCookies?: Record<string, string>;\n error?: unknown;\n}): SentryEvent {\n const client = getClient();\n const virtualStackTrace = client && data.error && data.error instanceof Error ? data.error.stack : undefined;\n // Remove the first frame from the stack as it's the HttpClient call\n const stack = virtualStackTrace && client ? client.getOptions().stackParser(virtualStackTrace, 0, 1) : undefined;\n const message = `HTTP Client Error with status code: ${data.status}`;\n\n const event: SentryEvent = {\n message,\n exception: {\n values: [\n {\n type: 'Error',\n value: message,\n stacktrace: stack ? { frames: stack } : undefined,\n },\n ],\n },\n request: {\n url: data.url,\n method: data.method,\n headers: data.requestHeaders,\n cookies: data.requestCookies,\n },\n contexts: {\n response: {\n status_code: data.status,\n headers: data.responseHeaders,\n cookies: data.responseCookies,\n body_size: _getResponseSizeFromHeaders(data.responseHeaders),\n },\n },\n };\n\n addExceptionMechanism(event, {\n type: `auto.http.client.${data.type}`,\n handled: false,\n });\n\n return event;\n}\n\nfunction _getRequest(requestInfo: RequestInfo, requestInit?: RequestInit): Request {\n if (!requestInit && requestInfo instanceof Request) {\n return requestInfo;\n }\n\n // If both are set, we try to construct a new Request with the given arguments\n // However, if e.g. the original request has a `body`, this will throw an error because it was already accessed\n // In this case, as a fallback, we just use the original request - using both is rather an edge case\n if (requestInfo instanceof Request && requestInfo.bodyUsed) {\n return requestInfo;\n }\n\n return new Request(requestInfo, requestInit);\n}\n\nfunction _getDataCollectionSettings() {\n const client = getClient();\n if (!client) {\n return { cookies: false, requestHeaders: false, responseHeaders: false };\n }\n\n const { cookies, httpHeaders } = client.getDataCollectionOptions();\n return { cookies, requestHeaders: httpHeaders.request, responseHeaders: httpHeaders.response };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"httpclient.js","sources":["../../../../../src/integrations/httpclient.ts"],"sourcesContent":["import type { Client, Event as SentryEvent, IntegrationFn } from '@sentry/core/browser';\nimport {\n _INTERNAL_filterCookies,\n _INTERNAL_filterKeyValueData,\n addExceptionMechanism,\n addFetchInstrumentationHandler,\n captureEvent,\n debug,\n defineIntegration,\n getClient,\n GLOBAL_OBJ,\n isSentryRequestUrl,\n supportsNativeFetch,\n} from '@sentry/core/browser';\nimport type { SentryWrappedXMLHttpRequest } from '@sentry/browser-utils';\nimport { addXhrInstrumentationHandler, SENTRY_XHR_DATA_KEY } from '@sentry/browser-utils';\nimport { DEBUG_BUILD } from '../debug-build';\n\nexport type HttpStatusCodeRange = [number, number] | number;\nexport type HttpRequestTarget = string | RegExp;\n\nconst INTEGRATION_NAME = 'HttpClient' as const;\n\ninterface HttpClientOptions {\n /**\n * HTTP status codes that should be considered failed.\n * This array can contain tuples of `[begin, end]` (both inclusive),\n * single status codes, or a combinations of both\n *\n * Example: [[500, 505], 507]\n * Default: [[500, 599]]\n */\n failedRequestStatusCodes: HttpStatusCodeRange[];\n\n /**\n * Targets to track for failed requests.\n * This array can contain strings or regular expressions.\n *\n * Example: ['http://localhost', /api\\/.*\\/]\n * Default: [/.*\\/]\n */\n failedRequestTargets: HttpRequestTarget[];\n}\n\nconst _httpClientIntegration = ((options: Partial<HttpClientOptions> = {}) => {\n const _options: HttpClientOptions = {\n failedRequestStatusCodes: [[500, 599]],\n failedRequestTargets: [/.*/],\n ...options,\n };\n\n return {\n name: INTEGRATION_NAME,\n setup(client): void {\n _wrapFetch(client, _options);\n _wrapXHR(client, _options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Create events for failed client side HTTP requests.\n */\nexport const httpClientIntegration = defineIntegration(_httpClientIntegration);\n\n/**\n * Interceptor function for fetch requests\n *\n * @param requestInfo The Fetch API request info\n * @param response The Fetch API response\n * @param requestInit The request init object\n */\nfunction _fetchResponseHandler(\n options: HttpClientOptions,\n requestInfo: RequestInfo,\n response: Response,\n requestInit?: RequestInit,\n error?: unknown,\n): void {\n if (_shouldCaptureResponse(options, response.status, response.url)) {\n const request = _getRequest(requestInfo, requestInit);\n\n let requestHeaders, responseHeaders, requestCookies, responseCookies;\n\n const dc = _getDataCollectionSettings();\n\n if (dc.requestHeaders !== false) {\n requestHeaders = _INTERNAL_filterKeyValueData(_extractFetchHeaders(request.headers), dc.requestHeaders);\n }\n if (dc.responseHeaders !== false) {\n responseHeaders = _INTERNAL_filterKeyValueData(_extractFetchHeaders(response.headers), dc.responseHeaders);\n }\n if (dc.cookies !== false) {\n const reqCookieStr = request.headers.get('Cookie') || undefined;\n if (reqCookieStr) {\n const filtered = _INTERNAL_filterCookies(reqCookieStr, dc.cookies);\n if (typeof filtered === 'object') {\n requestCookies = filtered;\n }\n }\n const resCookieStr = response.headers.get('Set-Cookie') || undefined;\n if (resCookieStr) {\n const filtered = _INTERNAL_filterCookies(resCookieStr, dc.cookies);\n if (typeof filtered === 'object') {\n responseCookies = filtered;\n }\n }\n }\n\n const event = _createEvent({\n url: request.url,\n method: request.method,\n status: response.status,\n requestHeaders,\n responseHeaders,\n requestCookies,\n responseCookies,\n error,\n type: 'fetch',\n });\n\n captureEvent(event);\n }\n}\n\n/**\n * Interceptor function for XHR requests\n *\n * @param xhr The XHR request\n * @param method The HTTP method\n * @param headers The HTTP headers\n */\nfunction _xhrResponseHandler(\n options: HttpClientOptions,\n xhr: XMLHttpRequest,\n method: string,\n headers: Record<string, string>,\n error?: unknown,\n): void {\n if (_shouldCaptureResponse(options, xhr.status, xhr.responseURL)) {\n let requestHeaders, responseCookies, responseHeaders;\n\n const dc = _getDataCollectionSettings();\n\n if (dc.cookies !== false) {\n try {\n const cookieString = xhr.getResponseHeader('Set-Cookie') || xhr.getResponseHeader('set-cookie') || undefined;\n if (cookieString) {\n const filtered = _INTERNAL_filterCookies(cookieString, dc.cookies);\n if (typeof filtered === 'object') {\n responseCookies = filtered;\n }\n }\n } catch {\n // ignore it if parsing fails\n }\n }\n\n if (dc.responseHeaders !== false) {\n try {\n responseHeaders = _INTERNAL_filterKeyValueData(_getXHRResponseHeaders(xhr), dc.responseHeaders);\n } catch {\n // ignore it if parsing fails\n }\n }\n\n if (dc.requestHeaders !== false) {\n requestHeaders = _INTERNAL_filterKeyValueData(headers, dc.requestHeaders);\n }\n\n const event = _createEvent({\n url: xhr.responseURL,\n method,\n status: xhr.status,\n requestHeaders,\n // Can't access request cookies from XHR\n responseHeaders,\n responseCookies,\n error,\n type: 'xhr',\n });\n\n captureEvent(event);\n }\n}\n\n/**\n * Extracts response size from `Content-Length` header when possible\n *\n * @param headers\n * @returns The response size in bytes or undefined\n */\nfunction _getResponseSizeFromHeaders(headers?: Record<string, string>): number | undefined {\n if (headers) {\n const contentLength = headers['Content-Length'] || headers['content-length'];\n\n if (contentLength) {\n return parseInt(contentLength, 10);\n }\n }\n\n return undefined;\n}\n\n/**\n * Extracts the headers as an object from the given Fetch API request or response object\n *\n * @param headers The headers to extract\n * @returns The extracted headers as an object\n */\nfunction _extractFetchHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {};\n\n headers.forEach((value, key) => {\n result[key] = value;\n });\n\n return result;\n}\n\n/**\n * Extracts the response headers as an object from the given XHR object\n *\n * @param xhr The XHR object to extract the response headers from\n * @returns The response headers as an object\n */\nfunction _getXHRResponseHeaders(xhr: XMLHttpRequest): Record<string, string> {\n const headers = xhr.getAllResponseHeaders();\n\n if (!headers) {\n return {};\n }\n\n return headers.split('\\r\\n').reduce((acc: Record<string, string>, line: string) => {\n const [key, value] = line.split(': ');\n if (key && value) {\n acc[key] = value;\n }\n return acc;\n }, {});\n}\n\n/**\n * Checks if the given target url is in the given list of targets\n *\n * @param target The target url to check\n * @returns true if the target url is in the given list of targets, false otherwise\n */\nfunction _isInGivenRequestTargets(\n failedRequestTargets: HttpClientOptions['failedRequestTargets'],\n target: string,\n): boolean {\n return failedRequestTargets.some((givenRequestTarget: HttpRequestTarget) => {\n if (typeof givenRequestTarget === 'string') {\n return target.includes(givenRequestTarget);\n }\n\n return givenRequestTarget.test(target);\n });\n}\n\n/**\n * Checks if the given status code is in the given range\n *\n * @param status The status code to check\n * @returns true if the status code is in the given range, false otherwise\n */\nfunction _isInGivenStatusRanges(\n failedRequestStatusCodes: HttpClientOptions['failedRequestStatusCodes'],\n status: number,\n): boolean {\n return failedRequestStatusCodes.some((range: HttpStatusCodeRange) => {\n if (typeof range === 'number') {\n return range === status;\n }\n\n return status >= range[0] && status <= range[1];\n });\n}\n\n/**\n * Wraps `fetch` function to capture request and response data\n */\nfunction _wrapFetch(client: Client, options: HttpClientOptions): void {\n if (!supportsNativeFetch()) {\n return;\n }\n\n addFetchInstrumentationHandler(handlerData => {\n if (getClient() !== client) {\n return;\n }\n\n const { response, args, error, virtualError } = handlerData;\n const [requestInfo, requestInit] = args as [RequestInfo, RequestInit | undefined];\n\n if (!response) {\n return;\n }\n\n _fetchResponseHandler(options, requestInfo, response as Response, requestInit, error || virtualError);\n });\n}\n\n/**\n * Wraps XMLHttpRequest to capture request and response data\n */\nfunction _wrapXHR(client: Client, options: HttpClientOptions): void {\n if (!('XMLHttpRequest' in GLOBAL_OBJ)) {\n return;\n }\n\n addXhrInstrumentationHandler(handlerData => {\n if (getClient() !== client) {\n return;\n }\n\n const { error, virtualError } = handlerData;\n\n const xhr = handlerData.xhr as SentryWrappedXMLHttpRequest & XMLHttpRequest;\n\n const sentryXhrData = xhr[SENTRY_XHR_DATA_KEY];\n\n if (!sentryXhrData) {\n return;\n }\n\n const { method, request_headers: headers } = sentryXhrData;\n\n try {\n _xhrResponseHandler(options, xhr, method, headers, error || virtualError);\n } catch (e) {\n DEBUG_BUILD && debug.warn('Error while extracting response event form XHR response', e);\n }\n });\n}\n\n/**\n * Checks whether to capture given response as an event\n *\n * @param status response status code\n * @param url response url\n */\nfunction _shouldCaptureResponse(options: HttpClientOptions, status: number, url: string): boolean {\n return (\n _isInGivenStatusRanges(options.failedRequestStatusCodes, status) &&\n _isInGivenRequestTargets(options.failedRequestTargets, url) &&\n !isSentryRequestUrl(url, getClient())\n );\n}\n\n/**\n * Creates a synthetic Sentry event from given response data\n *\n * @param data response data\n * @returns event\n */\nfunction _createEvent(data: {\n url: string;\n method: string;\n status: number;\n type: 'fetch' | 'xhr';\n responseHeaders?: Record<string, string>;\n responseCookies?: Record<string, string>;\n requestHeaders?: Record<string, string>;\n requestCookies?: Record<string, string>;\n error?: unknown;\n}): SentryEvent {\n const client = getClient();\n const virtualStackTrace = client && data.error && data.error instanceof Error ? data.error.stack : undefined;\n // Remove the first frame from the stack as it's the HttpClient call\n const stack = virtualStackTrace && client ? client.getOptions().stackParser(virtualStackTrace, 0, 1) : undefined;\n const message = `HTTP Client Error with status code: ${data.status}`;\n\n const event: SentryEvent = {\n message,\n exception: {\n values: [\n {\n type: 'Error',\n value: message,\n stacktrace: stack ? { frames: stack } : undefined,\n },\n ],\n },\n request: {\n url: data.url,\n method: data.method,\n headers: data.requestHeaders,\n cookies: data.requestCookies,\n },\n contexts: {\n response: {\n status_code: data.status,\n headers: data.responseHeaders,\n cookies: data.responseCookies,\n body_size: _getResponseSizeFromHeaders(data.responseHeaders),\n },\n },\n };\n\n addExceptionMechanism(event, {\n type: `auto.http.client.${data.type}`,\n handled: false,\n });\n\n return event;\n}\n\nfunction _getRequest(requestInfo: RequestInfo, requestInit?: RequestInit): Request {\n if (!requestInit && requestInfo instanceof Request) {\n return requestInfo;\n }\n\n // If both are set, we try to construct a new Request with the given arguments\n // However, if e.g. the original request has a `body`, this will throw an error because it was already accessed\n // In this case, as a fallback, we just use the original request - using both is rather an edge case\n if (requestInfo instanceof Request && requestInfo.bodyUsed) {\n return requestInfo;\n }\n\n return new Request(requestInfo, requestInit);\n}\n\nfunction _getDataCollectionSettings() {\n const client = getClient();\n if (!client) {\n return { cookies: false, requestHeaders: false, responseHeaders: false };\n }\n\n const { cookies, httpHeaders } = client.getDataCollectionOptions();\n return { cookies, requestHeaders: httpHeaders.request, responseHeaders: httpHeaders.response };\n}\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,9 @@
1
- import { defineIntegration, supportsReportingObserver, GLOBAL_OBJ, getClient, withScope, captureMessage } from '@sentry/core/browser';
1
+ import { defineIntegration, GLOBAL_OBJ, getClient, withScope, captureMessage } from '@sentry/core/browser';
2
2
 
3
3
  const WINDOW = GLOBAL_OBJ;
4
+ function supportsReportingObserver() {
5
+ return "ReportingObserver" in WINDOW;
6
+ }
4
7
  const INTEGRATION_NAME = "ReportingObserver";
5
8
  const SETUP_CLIENTS = /* @__PURE__ */ new WeakMap();
6
9
  const _reportingObserverIntegration = ((options = {}) => {
@@ -1 +1 @@
1
- {"version":3,"file":"reportingobserver.js","sources":["../../../../../src/integrations/reportingobserver.ts"],"sourcesContent":["import type { Client, IntegrationFn } from '@sentry/core/browser';\nimport {\n captureMessage,\n defineIntegration,\n getClient,\n GLOBAL_OBJ,\n supportsReportingObserver,\n withScope,\n} from '@sentry/core/browser';\n\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\nconst INTEGRATION_NAME = 'ReportingObserver' as const;\n\ninterface Report {\n [key: string]: unknown;\n type: ReportTypes;\n url: string;\n body?: ReportBody;\n}\n\ntype ReportTypes = 'crash' | 'deprecation' | 'intervention';\n\ntype ReportBody = CrashReportBody | DeprecationReportBody | InterventionReportBody;\n\ninterface CrashReportBody {\n [key: string]: unknown;\n crashId: string;\n reason?: string;\n}\n\ninterface DeprecationReportBody {\n [key: string]: unknown;\n id: string;\n anticipatedRemoval?: Date;\n message: string;\n sourceFile?: string;\n lineNumber?: number;\n columnNumber?: number;\n}\n\ninterface InterventionReportBody {\n [key: string]: unknown;\n id: string;\n message: string;\n sourceFile?: string;\n lineNumber?: number;\n columnNumber?: number;\n}\n\ninterface ReportingObserverOptions {\n types?: ReportTypes[];\n}\n\n/** This is experimental and the types are not included with TypeScript, sadly. */\ninterface ReportingObserverClass {\n new (\n handler: (reports: Report[]) => void,\n options: { buffered?: boolean; types?: ReportTypes[] },\n ): {\n observe: () => void;\n };\n}\n\nconst SETUP_CLIENTS = new WeakMap<Client, boolean>();\n\nconst _reportingObserverIntegration = ((options: ReportingObserverOptions = {}) => {\n const types = options.types || ['crash', 'deprecation', 'intervention'];\n\n /** Handler for the reporting observer. */\n function handler(reports: Report[]): void {\n if (!SETUP_CLIENTS.has(getClient() as Client)) {\n return;\n }\n\n for (const report of reports) {\n withScope(scope => {\n scope.setExtra('url', report.url);\n\n const label = `ReportingObserver [${report.type}]`;\n let details = 'No details available';\n\n if (report.body) {\n // Object.keys doesn't work on ReportBody, as all properties are inherited\n const plainBody: {\n [key: string]: unknown;\n } = {};\n\n // eslint-disable-next-line guard-for-in\n for (const prop in report.body) {\n plainBody[prop] = report.body[prop];\n }\n\n scope.setExtra('body', plainBody);\n\n if (report.type === 'crash') {\n const body = report.body as CrashReportBody;\n // A fancy way to create a message out of crashId OR reason OR both OR fallback\n details = [body.crashId || '', body.reason || ''].join(' ').trim() || details;\n } else {\n const body = report.body as DeprecationReportBody | InterventionReportBody;\n details = body.message || details;\n }\n }\n\n captureMessage(`${label}: ${details}`);\n });\n }\n }\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n if (!supportsReportingObserver()) {\n return;\n }\n\n const observer = new (WINDOW as typeof WINDOW & { ReportingObserver: ReportingObserverClass }).ReportingObserver(\n handler,\n {\n buffered: true,\n types,\n },\n );\n\n observer.observe();\n },\n\n setup(client): void {\n SETUP_CLIENTS.set(client, true);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Reporting API integration - https://w3c.github.io/reporting/\n */\nexport const reportingObserverIntegration = defineIntegration(_reportingObserverIntegration);\n"],"names":[],"mappings":";;AAUA,MAAM,MAAA,GAAS,UAAA;AAEf,MAAM,gBAAA,GAAmB,mBAAA;AAoDzB,MAAM,aAAA,uBAAoB,OAAA,EAAyB;AAEnD,MAAM,6BAAA,IAAiC,CAAC,OAAA,GAAoC,EAAC,KAAM;AACjF,EAAA,MAAM,QAAQ,OAAA,CAAQ,KAAA,IAAS,CAAC,OAAA,EAAS,eAAe,cAAc,CAAA;AAGtE,EAAA,SAAS,QAAQ,OAAA,EAAyB;AACxC,IAAA,IAAI,CAAC,aAAA,CAAc,GAAA,CAAI,SAAA,EAAqB,CAAA,EAAG;AAC7C,MAAA;AAAA,IACF;AAEA,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,SAAA,CAAU,CAAA,KAAA,KAAS;AACjB,QAAA,KAAA,CAAM,QAAA,CAAS,KAAA,EAAO,MAAA,CAAO,GAAG,CAAA;AAEhC,QAAA,MAAM,KAAA,GAAQ,CAAA,mBAAA,EAAsB,MAAA,CAAO,IAAI,CAAA,CAAA,CAAA;AAC/C,QAAA,IAAI,OAAA,GAAU,sBAAA;AAEd,QAAA,IAAI,OAAO,IAAA,EAAM;AAEf,UAAA,MAAM,YAEF,EAAC;AAGL,UAAA,KAAA,MAAW,IAAA,IAAQ,OAAO,IAAA,EAAM;AAC9B,YAAA,SAAA,CAAU,IAAI,CAAA,GAAI,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA;AAAA,UACpC;AAEA,UAAA,KAAA,CAAM,QAAA,CAAS,QAAQ,SAAS,CAAA;AAEhC,UAAA,IAAI,MAAA,CAAO,SAAS,OAAA,EAAS;AAC3B,YAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AAEpB,YAAA,OAAA,GAAU,CAAC,IAAA,CAAK,OAAA,IAAW,EAAA,EAAI,IAAA,CAAK,MAAA,IAAU,EAAE,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,CAAE,IAAA,EAAK,IAAK,OAAA;AAAA,UACxE,CAAA,MAAO;AACL,YAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AACpB,YAAA,OAAA,GAAU,KAAK,OAAA,IAAW,OAAA;AAAA,UAC5B;AAAA,QACF;AAEA,QAAA,cAAA,CAAe,CAAA,EAAG,KAAK,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AAAA,MACvC,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,SAAA,GAAY;AACV,MAAA,IAAI,CAAC,2BAA0B,EAAG;AAChC,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAW,IAAK,MAAA,CAAyE,iBAAA;AAAA,QAC7F,OAAA;AAAA,QACA;AAAA,UACE,QAAA,EAAU,IAAA;AAAA,UACV;AAAA;AACF,OACF;AAEA,MAAA,QAAA,CAAS,OAAA,EAAQ;AAAA,IACnB,CAAA;AAAA,IAEA,MAAM,MAAA,EAAc;AAClB,MAAA,aAAA,CAAc,GAAA,CAAI,QAAQ,IAAI,CAAA;AAAA,IAChC;AAAA,GACF;AACF,CAAA,CAAA;AAKO,MAAM,4BAAA,GAA+B,kBAAkB,6BAA6B;;;;"}
1
+ {"version":3,"file":"reportingobserver.js","sources":["../../../../../src/integrations/reportingobserver.ts"],"sourcesContent":["import type { Client, IntegrationFn } from '@sentry/core/browser';\nimport { captureMessage, defineIntegration, getClient, GLOBAL_OBJ, withScope } from '@sentry/core/browser';\n\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\n/**\n * Tells whether current environment supports ReportingObserver API\n * {@link supportsReportingObserver}.\n *\n * @returns Answer to the given question.\n */\nfunction supportsReportingObserver(): boolean {\n return 'ReportingObserver' in WINDOW;\n}\n\nconst INTEGRATION_NAME = 'ReportingObserver' as const;\n\ninterface Report {\n [key: string]: unknown;\n type: ReportTypes;\n url: string;\n body?: ReportBody;\n}\n\ntype ReportTypes = 'crash' | 'deprecation' | 'intervention';\n\ntype ReportBody = CrashReportBody | DeprecationReportBody | InterventionReportBody;\n\ninterface CrashReportBody {\n [key: string]: unknown;\n crashId: string;\n reason?: string;\n}\n\ninterface DeprecationReportBody {\n [key: string]: unknown;\n id: string;\n anticipatedRemoval?: Date;\n message: string;\n sourceFile?: string;\n lineNumber?: number;\n columnNumber?: number;\n}\n\ninterface InterventionReportBody {\n [key: string]: unknown;\n id: string;\n message: string;\n sourceFile?: string;\n lineNumber?: number;\n columnNumber?: number;\n}\n\ninterface ReportingObserverOptions {\n types?: ReportTypes[];\n}\n\n/** This is experimental and the types are not included with TypeScript, sadly. */\ninterface ReportingObserverClass {\n new (\n handler: (reports: Report[]) => void,\n options: { buffered?: boolean; types?: ReportTypes[] },\n ): {\n observe: () => void;\n };\n}\n\nconst SETUP_CLIENTS = new WeakMap<Client, boolean>();\n\nconst _reportingObserverIntegration = ((options: ReportingObserverOptions = {}) => {\n const types = options.types || ['crash', 'deprecation', 'intervention'];\n\n /** Handler for the reporting observer. */\n function handler(reports: Report[]): void {\n if (!SETUP_CLIENTS.has(getClient() as Client)) {\n return;\n }\n\n for (const report of reports) {\n withScope(scope => {\n scope.setExtra('url', report.url);\n\n const label = `ReportingObserver [${report.type}]`;\n let details = 'No details available';\n\n if (report.body) {\n // Object.keys doesn't work on ReportBody, as all properties are inherited\n const plainBody: {\n [key: string]: unknown;\n } = {};\n\n // eslint-disable-next-line guard-for-in\n for (const prop in report.body) {\n plainBody[prop] = report.body[prop];\n }\n\n scope.setExtra('body', plainBody);\n\n if (report.type === 'crash') {\n const body = report.body as CrashReportBody;\n // A fancy way to create a message out of crashId OR reason OR both OR fallback\n details = [body.crashId || '', body.reason || ''].join(' ').trim() || details;\n } else {\n const body = report.body as DeprecationReportBody | InterventionReportBody;\n details = body.message || details;\n }\n }\n\n captureMessage(`${label}: ${details}`);\n });\n }\n }\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n if (!supportsReportingObserver()) {\n return;\n }\n\n const observer = new (WINDOW as typeof WINDOW & { ReportingObserver: ReportingObserverClass }).ReportingObserver(\n handler,\n {\n buffered: true,\n types,\n },\n );\n\n observer.observe();\n },\n\n setup(client): void {\n SETUP_CLIENTS.set(client, true);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Reporting API integration - https://w3c.github.io/reporting/\n */\nexport const reportingObserverIntegration = defineIntegration(_reportingObserverIntegration);\n"],"names":[],"mappings":";;AAGA,MAAM,MAAA,GAAS,UAAA;AAQf,SAAS,yBAAA,GAAqC;AAC5C,EAAA,OAAO,mBAAA,IAAuB,MAAA;AAChC;AAEA,MAAM,gBAAA,GAAmB,mBAAA;AAoDzB,MAAM,aAAA,uBAAoB,OAAA,EAAyB;AAEnD,MAAM,6BAAA,IAAiC,CAAC,OAAA,GAAoC,EAAC,KAAM;AACjF,EAAA,MAAM,QAAQ,OAAA,CAAQ,KAAA,IAAS,CAAC,OAAA,EAAS,eAAe,cAAc,CAAA;AAGtE,EAAA,SAAS,QAAQ,OAAA,EAAyB;AACxC,IAAA,IAAI,CAAC,aAAA,CAAc,GAAA,CAAI,SAAA,EAAqB,CAAA,EAAG;AAC7C,MAAA;AAAA,IACF;AAEA,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,SAAA,CAAU,CAAA,KAAA,KAAS;AACjB,QAAA,KAAA,CAAM,QAAA,CAAS,KAAA,EAAO,MAAA,CAAO,GAAG,CAAA;AAEhC,QAAA,MAAM,KAAA,GAAQ,CAAA,mBAAA,EAAsB,MAAA,CAAO,IAAI,CAAA,CAAA,CAAA;AAC/C,QAAA,IAAI,OAAA,GAAU,sBAAA;AAEd,QAAA,IAAI,OAAO,IAAA,EAAM;AAEf,UAAA,MAAM,YAEF,EAAC;AAGL,UAAA,KAAA,MAAW,IAAA,IAAQ,OAAO,IAAA,EAAM;AAC9B,YAAA,SAAA,CAAU,IAAI,CAAA,GAAI,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA;AAAA,UACpC;AAEA,UAAA,KAAA,CAAM,QAAA,CAAS,QAAQ,SAAS,CAAA;AAEhC,UAAA,IAAI,MAAA,CAAO,SAAS,OAAA,EAAS;AAC3B,YAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AAEpB,YAAA,OAAA,GAAU,CAAC,IAAA,CAAK,OAAA,IAAW,EAAA,EAAI,IAAA,CAAK,MAAA,IAAU,EAAE,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,CAAE,IAAA,EAAK,IAAK,OAAA;AAAA,UACxE,CAAA,MAAO;AACL,YAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AACpB,YAAA,OAAA,GAAU,KAAK,OAAA,IAAW,OAAA;AAAA,UAC5B;AAAA,QACF;AAEA,QAAA,cAAA,CAAe,CAAA,EAAG,KAAK,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AAAA,MACvC,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,SAAA,GAAY;AACV,MAAA,IAAI,CAAC,2BAA0B,EAAG;AAChC,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAW,IAAK,MAAA,CAAyE,iBAAA;AAAA,QAC7F,OAAA;AAAA,QACA;AAAA,UACE,QAAA,EAAU,IAAA;AAAA,UACV;AAAA;AACF,OACF;AAEA,MAAA,QAAA,CAAS,OAAA,EAAQ;AAAA,IACnB,CAAA;AAAA,IAEA,MAAM,MAAA,EAAc;AAClB,MAAA,aAAA,CAAc,GAAA,CAAI,QAAQ,IAAI,CAAA;AAAA,IAChC;AAAA,GACF;AACF,CAAA,CAAA;AAKO,MAAM,4BAAA,GAA+B,kBAAkB,6BAA6B;;;;"}
@@ -1,9 +1,10 @@
1
1
  import { defineIntegration, debug, serializeEnvelope } from '@sentry/core/browser';
2
2
  import { getNativeImplementation } from '@sentry/browser-utils';
3
+ import { UI_INTERACTION_CLICK } from '@sentry/conventions/op';
3
4
  import { DEBUG_BUILD } from '../debug-build.js';
4
5
 
5
6
  const INTEGRATION_NAME = "SpotlightBrowser";
6
- const SPOTLIGHT_IGNORE_SPANS = [{ op: "ui.interaction.click", name: "#sentry-spotlight" }];
7
+ const SPOTLIGHT_IGNORE_SPANS = [{ op: UI_INTERACTION_CLICK, name: "#sentry-spotlight" }];
7
8
  const _spotlightIntegration = ((options = {}) => {
8
9
  const sidecarUrl = options.sidecarUrl || "http://localhost:8969/stream";
9
10
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"spotlight.js","sources":["../../../../../src/integrations/spotlight.ts"],"sourcesContent":["import type { Client, Envelope, IntegrationFn } from '@sentry/core/browser';\nimport { debug, defineIntegration, serializeEnvelope } from '@sentry/core/browser';\nimport { getNativeImplementation } from '@sentry/browser-utils';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { WINDOW } from '../helpers';\n\nexport type SpotlightConnectionOptions = {\n /**\n * Set this if the Spotlight Sidecar is not running on localhost:8969\n * By default, the Url is set to http://localhost:8969/stream\n */\n sidecarUrl?: string;\n};\n\nexport const INTEGRATION_NAME = 'SpotlightBrowser' as const;\n\nexport const SPOTLIGHT_IGNORE_SPANS = [{ op: 'ui.interaction.click', name: '#sentry-spotlight' }];\n\nconst _spotlightIntegration = ((options: Partial<SpotlightConnectionOptions> = {}) => {\n const sidecarUrl = options.sidecarUrl || 'http://localhost:8969/stream';\n\n return {\n name: INTEGRATION_NAME,\n setup: () => {\n DEBUG_BUILD && debug.log('Using Sidecar URL', sidecarUrl);\n },\n beforeSetup(client: Client) {\n const opts = client.getOptions();\n opts.ignoreSpans = [...(opts.ignoreSpans || []), ...SPOTLIGHT_IGNORE_SPANS];\n },\n afterAllSetup: (client: Client) => {\n setupSidecarForwarding(client, sidecarUrl);\n },\n };\n}) satisfies IntegrationFn;\n\nfunction setupSidecarForwarding(client: Client, sidecarUrl: string): void {\n const makeFetch: typeof WINDOW.fetch | undefined = getNativeImplementation('fetch');\n let failCount = 0;\n\n client.on('beforeEnvelope', (envelope: Envelope) => {\n if (failCount > 3) {\n debug.warn('[Spotlight] Disabled Sentry -> Spotlight integration due to too many failed requests:', failCount);\n return;\n }\n\n makeFetch(sidecarUrl, {\n method: 'POST',\n body: serializeEnvelope(envelope) as BodyInit,\n headers: {\n 'Content-Type': 'application/x-sentry-envelope',\n },\n mode: 'cors',\n }).then(\n res => {\n if (res.status >= 200 && res.status < 400) {\n // Reset failed requests counter on success\n failCount = 0;\n }\n },\n err => {\n failCount++;\n debug.error(\n \"Sentry SDK can't connect to Sidecar is it running? See: https://spotlightjs.com/sidecar/npx/\",\n err,\n );\n },\n );\n });\n}\n\n/**\n * Use this integration to send errors and transactions to Spotlight.\n *\n * Learn more about spotlight at https://spotlightjs.com\n */\nexport const spotlightBrowserIntegration = defineIntegration(_spotlightIntegration);\n"],"names":[],"mappings":";;;;AAcO,MAAM,gBAAA,GAAmB;AAEzB,MAAM,yBAAyB,CAAC,EAAE,IAAI,sBAAA,EAAwB,IAAA,EAAM,qBAAqB;AAEhG,MAAM,qBAAA,IAAyB,CAAC,OAAA,GAA+C,EAAC,KAAM;AACpF,EAAA,MAAM,UAAA,GAAa,QAAQ,UAAA,IAAc,8BAAA;AAEzC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,OAAO,MAAM;AACX,MAAA,WAAA,IAAe,KAAA,CAAM,GAAA,CAAI,mBAAA,EAAqB,UAAU,CAAA;AAAA,IAC1D,CAAA;AAAA,IACA,YAAY,MAAA,EAAgB;AAC1B,MAAA,MAAM,IAAA,GAAO,OAAO,UAAA,EAAW;AAC/B,MAAA,IAAA,CAAK,WAAA,GAAc,CAAC,GAAI,IAAA,CAAK,eAAe,EAAC,EAAI,GAAG,sBAAsB,CAAA;AAAA,IAC5E,CAAA;AAAA,IACA,aAAA,EAAe,CAAC,MAAA,KAAmB;AACjC,MAAA,sBAAA,CAAuB,QAAQ,UAAU,CAAA;AAAA,IAC3C;AAAA,GACF;AACF,CAAA,CAAA;AAEA,SAAS,sBAAA,CAAuB,QAAgB,UAAA,EAA0B;AACxE,EAAA,MAAM,SAAA,GAA6C,wBAAwB,OAAO,CAAA;AAClF,EAAA,IAAI,SAAA,GAAY,CAAA;AAEhB,EAAA,MAAA,CAAO,EAAA,CAAG,gBAAA,EAAkB,CAAC,QAAA,KAAuB;AAClD,IAAA,IAAI,YAAY,CAAA,EAAG;AACjB,MAAA,KAAA,CAAM,IAAA,CAAK,yFAAyF,SAAS,CAAA;AAC7G,MAAA;AAAA,IACF;AAEA,IAAA,SAAA,CAAU,UAAA,EAAY;AAAA,MACpB,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,kBAAkB,QAAQ,CAAA;AAAA,MAChC,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB;AAAA,OAClB;AAAA,MACA,IAAA,EAAM;AAAA,KACP,CAAA,CAAE,IAAA;AAAA,MACD,CAAA,GAAA,KAAO;AACL,QAAA,IAAI,GAAA,CAAI,MAAA,IAAU,GAAA,IAAO,GAAA,CAAI,SAAS,GAAA,EAAK;AAEzC,UAAA,SAAA,GAAY,CAAA;AAAA,QACd;AAAA,MACF,CAAA;AAAA,MACA,CAAA,GAAA,KAAO;AACL,QAAA,SAAA,EAAA;AACA,QAAA,KAAA,CAAM,KAAA;AAAA,UACJ,8FAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF;AAAA,KACF;AAAA,EACF,CAAC,CAAA;AACH;AAOO,MAAM,2BAAA,GAA8B,kBAAkB,qBAAqB;;;;"}
1
+ {"version":3,"file":"spotlight.js","sources":["../../../../../src/integrations/spotlight.ts"],"sourcesContent":["import type { Client, Envelope, IntegrationFn } from '@sentry/core/browser';\nimport { debug, defineIntegration, serializeEnvelope } from '@sentry/core/browser';\nimport { getNativeImplementation } from '@sentry/browser-utils';\nimport { UI_INTERACTION_CLICK } from '@sentry/conventions/op';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { WINDOW } from '../helpers';\n\nexport type SpotlightConnectionOptions = {\n /**\n * Set this if the Spotlight Sidecar is not running on localhost:8969\n * By default, the Url is set to http://localhost:8969/stream\n */\n sidecarUrl?: string;\n};\n\nexport const INTEGRATION_NAME = 'SpotlightBrowser' as const;\n\nexport const SPOTLIGHT_IGNORE_SPANS = [{ op: UI_INTERACTION_CLICK, name: '#sentry-spotlight' }];\n\nconst _spotlightIntegration = ((options: Partial<SpotlightConnectionOptions> = {}) => {\n const sidecarUrl = options.sidecarUrl || 'http://localhost:8969/stream';\n\n return {\n name: INTEGRATION_NAME,\n setup: () => {\n DEBUG_BUILD && debug.log('Using Sidecar URL', sidecarUrl);\n },\n beforeSetup(client: Client) {\n const opts = client.getOptions();\n opts.ignoreSpans = [...(opts.ignoreSpans || []), ...SPOTLIGHT_IGNORE_SPANS];\n },\n afterAllSetup: (client: Client) => {\n setupSidecarForwarding(client, sidecarUrl);\n },\n };\n}) satisfies IntegrationFn;\n\nfunction setupSidecarForwarding(client: Client, sidecarUrl: string): void {\n const makeFetch: typeof WINDOW.fetch | undefined = getNativeImplementation('fetch');\n let failCount = 0;\n\n client.on('beforeEnvelope', (envelope: Envelope) => {\n if (failCount > 3) {\n debug.warn('[Spotlight] Disabled Sentry -> Spotlight integration due to too many failed requests:', failCount);\n return;\n }\n\n makeFetch(sidecarUrl, {\n method: 'POST',\n body: serializeEnvelope(envelope) as BodyInit,\n headers: {\n 'Content-Type': 'application/x-sentry-envelope',\n },\n mode: 'cors',\n }).then(\n res => {\n if (res.status >= 200 && res.status < 400) {\n // Reset failed requests counter on success\n failCount = 0;\n }\n },\n err => {\n failCount++;\n debug.error(\n \"Sentry SDK can't connect to Sidecar is it running? See: https://spotlightjs.com/sidecar/npx/\",\n err,\n );\n },\n );\n });\n}\n\n/**\n * Use this integration to send errors and transactions to Spotlight.\n *\n * Learn more about spotlight at https://spotlightjs.com\n */\nexport const spotlightBrowserIntegration = defineIntegration(_spotlightIntegration);\n"],"names":[],"mappings":";;;;;AAeO,MAAM,gBAAA,GAAmB;AAEzB,MAAM,yBAAyB,CAAC,EAAE,IAAI,oBAAA,EAAsB,IAAA,EAAM,qBAAqB;AAE9F,MAAM,qBAAA,IAAyB,CAAC,OAAA,GAA+C,EAAC,KAAM;AACpF,EAAA,MAAM,UAAA,GAAa,QAAQ,UAAA,IAAc,8BAAA;AAEzC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,OAAO,MAAM;AACX,MAAA,WAAA,IAAe,KAAA,CAAM,GAAA,CAAI,mBAAA,EAAqB,UAAU,CAAA;AAAA,IAC1D,CAAA;AAAA,IACA,YAAY,MAAA,EAAgB;AAC1B,MAAA,MAAM,IAAA,GAAO,OAAO,UAAA,EAAW;AAC/B,MAAA,IAAA,CAAK,WAAA,GAAc,CAAC,GAAI,IAAA,CAAK,eAAe,EAAC,EAAI,GAAG,sBAAsB,CAAA;AAAA,IAC5E,CAAA;AAAA,IACA,aAAA,EAAe,CAAC,MAAA,KAAmB;AACjC,MAAA,sBAAA,CAAuB,QAAQ,UAAU,CAAA;AAAA,IAC3C;AAAA,GACF;AACF,CAAA,CAAA;AAEA,SAAS,sBAAA,CAAuB,QAAgB,UAAA,EAA0B;AACxE,EAAA,MAAM,SAAA,GAA6C,wBAAwB,OAAO,CAAA;AAClF,EAAA,IAAI,SAAA,GAAY,CAAA;AAEhB,EAAA,MAAA,CAAO,EAAA,CAAG,gBAAA,EAAkB,CAAC,QAAA,KAAuB;AAClD,IAAA,IAAI,YAAY,CAAA,EAAG;AACjB,MAAA,KAAA,CAAM,IAAA,CAAK,yFAAyF,SAAS,CAAA;AAC7G,MAAA;AAAA,IACF;AAEA,IAAA,SAAA,CAAU,UAAA,EAAY;AAAA,MACpB,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,kBAAkB,QAAQ,CAAA;AAAA,MAChC,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB;AAAA,OAClB;AAAA,MACA,IAAA,EAAM;AAAA,KACP,CAAA,CAAE,IAAA;AAAA,MACD,CAAA,GAAA,KAAO;AACL,QAAA,IAAI,GAAA,CAAI,MAAA,IAAU,GAAA,IAAO,GAAA,CAAI,SAAS,GAAA,EAAK;AAEzC,UAAA,SAAA,GAAY,CAAA;AAAA,QACd;AAAA,MACF,CAAA;AAAA,MACA,CAAA,GAAA,KAAO;AACL,QAAA,SAAA,EAAA;AACA,QAAA,KAAA,CAAM,KAAA;AAAA,UACJ,8FAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF;AAAA,KACF;AAAA,EACF,CAAC,CAAA;AACH;AAOO,MAAM,2BAAA,GAA8B,kBAAkB,qBAAqB;;;;"}
@@ -1,4 +1,5 @@
1
- import { defineIntegration, getComponentName } from '@sentry/core/browser';
1
+ import { defineIntegration } from '@sentry/core/browser';
2
+ import { getComponentName } from '@sentry/browser-utils';
2
3
  import { WINDOW } from '../helpers.js';
3
4
 
4
5
  const viewHierarchyIntegration = defineIntegration((options = {}) => {
@@ -1 +1 @@
1
- {"version":3,"file":"view-hierarchy.js","sources":["../../../../../src/integrations/view-hierarchy.ts"],"sourcesContent":["import type { Attachment, Event, EventHint, ViewHierarchyData, ViewHierarchyWindow } from '@sentry/core/browser';\nimport { defineIntegration, getComponentName } from '@sentry/core/browser';\nimport { WINDOW } from '../helpers';\n\ninterface OnElementArgs {\n /**\n * The element being processed.\n */\n element: HTMLElement;\n /**\n * Lowercase tag name of the element.\n */\n tagName: string;\n /**\n * The component name of the element.\n */\n componentName?: string;\n\n /**\n * The current depth of the element in the view hierarchy. The root element will have a depth of 0.\n *\n * This allows you to limit the traversal depth for large DOM trees.\n */\n depth?: number;\n}\n\ninterface Options {\n /**\n * Whether to attach the view hierarchy to the event.\n *\n * Default: Always attach.\n */\n shouldAttach?: (event: Event, hint: EventHint) => boolean;\n\n /**\n * A function that returns the root element to start walking the DOM from.\n *\n * Default: `window.document.body`\n */\n rootElement?: () => HTMLElement | undefined;\n\n /**\n * Called for each HTMLElement as we walk the DOM.\n *\n * Return an object to include the element with any additional properties.\n * Return `skip` to exclude the element and its children.\n * Return `children` to skip the element but include its children.\n */\n onElement?: (prop: OnElementArgs) => Record<string, string | number | boolean> | 'skip' | 'children';\n}\n\n/**\n * An integration to include a view hierarchy attachment which contains the DOM.\n */\nexport const viewHierarchyIntegration = defineIntegration((options: Options = {}) => {\n const skipHtmlTags = ['script'];\n\n /** Walk an element */\n function walk(element: HTMLElement, windows: ViewHierarchyWindow[], depth = 0): void {\n if (!element) {\n return;\n }\n\n // With Web Components, we need to walk into shadow DOMs\n const children = 'shadowRoot' in element && element.shadowRoot ? element.shadowRoot.children : element.children;\n\n for (const child of children) {\n if (!(child instanceof HTMLElement)) {\n continue;\n }\n\n const componentName = getComponentName(child, 1) || undefined;\n const tagName = child.tagName.toLowerCase();\n\n if (skipHtmlTags.includes(tagName)) {\n continue;\n }\n\n const result = options.onElement?.({ element: child, componentName, tagName, depth }) || {};\n\n if (result === 'skip') {\n continue;\n }\n\n // Skip this element but include its children\n if (result === 'children') {\n walk(child, windows, depth + 1);\n continue;\n }\n\n const { x, y, width, height } = child.getBoundingClientRect();\n\n const window: ViewHierarchyWindow = {\n // oxlint-disable-next-line typescript/no-unnecessary-type-assertion -- rule false positive: the cast drops `undefined` to satisfy `identifier: string`; tsc errors without it\n identifier: (child.id || undefined) as string,\n type: componentName || tagName,\n visible: true,\n alpha: 1,\n height,\n width,\n x,\n y,\n ...result,\n };\n\n const children: ViewHierarchyWindow[] = [];\n window.children = children;\n\n // Recursively walk the children\n walk(child, window.children, depth + 1);\n\n windows.push(window);\n }\n }\n\n return {\n name: 'ViewHierarchy' as const,\n processEvent: (event, hint) => {\n // only capture for error events\n if (event.type !== undefined || options.shouldAttach?.(event, hint) === false) {\n return event;\n }\n\n const root: ViewHierarchyData = {\n rendering_system: 'DOM',\n positioning: 'absolute',\n windows: [],\n };\n\n walk(options.rootElement?.() || WINDOW.document.body, root.windows);\n\n const attachment: Attachment = {\n filename: 'view-hierarchy.json',\n attachmentType: 'event.view_hierarchy',\n contentType: 'application/json',\n data: JSON.stringify(root),\n };\n\n hint.attachments = hint.attachments || [];\n hint.attachments.push(attachment);\n\n return event;\n },\n };\n});\n"],"names":["children"],"mappings":"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"}
1
+ {"version":3,"file":"view-hierarchy.js","sources":["../../../../../src/integrations/view-hierarchy.ts"],"sourcesContent":["import type { Attachment, Event, EventHint, ViewHierarchyData, ViewHierarchyWindow } from '@sentry/core/browser';\nimport { defineIntegration } from '@sentry/core/browser';\nimport { getComponentName } from '@sentry/browser-utils';\nimport { WINDOW } from '../helpers';\n\ninterface OnElementArgs {\n /**\n * The element being processed.\n */\n element: HTMLElement;\n /**\n * Lowercase tag name of the element.\n */\n tagName: string;\n /**\n * The component name of the element.\n */\n componentName?: string;\n\n /**\n * The current depth of the element in the view hierarchy. The root element will have a depth of 0.\n *\n * This allows you to limit the traversal depth for large DOM trees.\n */\n depth?: number;\n}\n\ninterface Options {\n /**\n * Whether to attach the view hierarchy to the event.\n *\n * Default: Always attach.\n */\n shouldAttach?: (event: Event, hint: EventHint) => boolean;\n\n /**\n * A function that returns the root element to start walking the DOM from.\n *\n * Default: `window.document.body`\n */\n rootElement?: () => HTMLElement | undefined;\n\n /**\n * Called for each HTMLElement as we walk the DOM.\n *\n * Return an object to include the element with any additional properties.\n * Return `skip` to exclude the element and its children.\n * Return `children` to skip the element but include its children.\n */\n onElement?: (prop: OnElementArgs) => Record<string, string | number | boolean> | 'skip' | 'children';\n}\n\n/**\n * An integration to include a view hierarchy attachment which contains the DOM.\n */\nexport const viewHierarchyIntegration = defineIntegration((options: Options = {}) => {\n const skipHtmlTags = ['script'];\n\n /** Walk an element */\n function walk(element: HTMLElement, windows: ViewHierarchyWindow[], depth = 0): void {\n if (!element) {\n return;\n }\n\n // With Web Components, we need to walk into shadow DOMs\n const children = 'shadowRoot' in element && element.shadowRoot ? element.shadowRoot.children : element.children;\n\n for (const child of children) {\n if (!(child instanceof HTMLElement)) {\n continue;\n }\n\n const componentName = getComponentName(child, 1) || undefined;\n const tagName = child.tagName.toLowerCase();\n\n if (skipHtmlTags.includes(tagName)) {\n continue;\n }\n\n const result = options.onElement?.({ element: child, componentName, tagName, depth }) || {};\n\n if (result === 'skip') {\n continue;\n }\n\n // Skip this element but include its children\n if (result === 'children') {\n walk(child, windows, depth + 1);\n continue;\n }\n\n const { x, y, width, height } = child.getBoundingClientRect();\n\n const window: ViewHierarchyWindow = {\n // oxlint-disable-next-line typescript/no-unnecessary-type-assertion -- rule false positive: the cast drops `undefined` to satisfy `identifier: string`; tsc errors without it\n identifier: (child.id || undefined) as string,\n type: componentName || tagName,\n visible: true,\n alpha: 1,\n height,\n width,\n x,\n y,\n ...result,\n };\n\n const children: ViewHierarchyWindow[] = [];\n window.children = children;\n\n // Recursively walk the children\n walk(child, window.children, depth + 1);\n\n windows.push(window);\n }\n }\n\n return {\n name: 'ViewHierarchy' as const,\n processEvent: (event, hint) => {\n // only capture for error events\n if (event.type !== undefined || options.shouldAttach?.(event, hint) === false) {\n return event;\n }\n\n const root: ViewHierarchyData = {\n rendering_system: 'DOM',\n positioning: 'absolute',\n windows: [],\n };\n\n walk(options.rootElement?.() || WINDOW.document.body, root.windows);\n\n const attachment: Attachment = {\n filename: 'view-hierarchy.json',\n attachmentType: 'event.view_hierarchy',\n contentType: 'application/json',\n data: JSON.stringify(root),\n };\n\n hint.attachments = hint.attachments || [];\n hint.attachments.push(attachment);\n\n return event;\n },\n };\n});\n"],"names":["children"],"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.2","sideEffects":false}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../../src/profiling/index.ts"],"sourcesContent":["import type { Profiler } from '@sentry/core/browser';\nimport { debug, getClient } from '@sentry/core/browser';\nimport { DEBUG_BUILD } from '../debug-build';\n\n/**\n * Starts the Sentry UI profiler.\n * This mode is exclusive with the transaction profiler and will only work if the profilesSampleRate is set to a falsy value.\n * In UI profiling mode, the profiler will keep reporting profile chunks to Sentry until it is stopped, which allows for continuous profiling of the application.\n */\nfunction startProfiler(): void {\n const client = getClient();\n if (!client) {\n DEBUG_BUILD && debug.warn('No Sentry client available, profiling is not started');\n return;\n }\n\n const integration = client.getIntegrationByName('BrowserProfiling');\n\n if (!integration) {\n DEBUG_BUILD && debug.warn('BrowserProfiling integration is not available');\n return;\n }\n\n client.emit('startUIProfiler');\n}\n\n/**\n * Stops the Sentry UI profiler.\n * Calls to stop will stop the profiler and flush the currently collected profile data to Sentry.\n */\nfunction stopProfiler(): void {\n const client = getClient();\n if (!client) {\n DEBUG_BUILD && debug.warn('No Sentry client available, profiling is not started');\n return;\n }\n\n const integration = client.getIntegrationByName('BrowserProfiling');\n if (!integration) {\n DEBUG_BUILD && debug.warn('ProfilingIntegration is not available');\n return;\n }\n\n client.emit('stopUIProfiler');\n}\n\n/**\n * Profiler namespace for controlling the JS profiler in 'manual' mode.\n *\n * Requires the `browserProfilingIntegration` from the `@sentry/browser` package.\n */\nexport const uiProfiler: Profiler = {\n startProfiler,\n stopProfiler,\n};\n"],"names":[],"mappings":";;;AASA,SAAS,aAAA,GAAsB;AAC7B,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,WAAA,IAAe,KAAA,CAAM,KAAK,sDAAsD,CAAA;AAChF,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,oBAAA,CAAqB,kBAAkB,CAAA;AAElE,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,WAAA,IAAe,KAAA,CAAM,KAAK,+CAA+C,CAAA;AACzE,IAAA;AAAA,EACF;AAEA,EAAA,MAAA,CAAO,KAAK,iBAAiB,CAAA;AAC/B;AAMA,SAAS,YAAA,GAAqB;AAC5B,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,WAAA,IAAe,KAAA,CAAM,KAAK,sDAAsD,CAAA;AAChF,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,oBAAA,CAAqB,kBAAkB,CAAA;AAClE,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,WAAA,IAAe,KAAA,CAAM,KAAK,uCAAuC,CAAA;AACjE,IAAA;AAAA,EACF;AAEA,EAAA,MAAA,CAAO,KAAK,gBAAgB,CAAA;AAC9B;AAOO,MAAM,UAAA,GAAuB;AAAA,EAClC,aAAA;AAAA,EACA;AACF;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../../../src/profiling/index.ts"],"sourcesContent":["import type { Profiler } from '@sentry/core/browser';\nimport { debug, getClient } from '@sentry/core/browser';\nimport { DEBUG_BUILD } from '../debug-build';\n\n/**\n * Starts a manually controlled Sentry UI profiling session.\n *\n * Profiling starts only when the integration sampled the current session and `profileLifecycle` is `manual`.\n * While running, the profiler periodically sends profile chunks to Sentry until `stopProfiler()` is called.\n */\nfunction startProfiler(): void {\n const client = getClient();\n if (!client) {\n DEBUG_BUILD && debug.warn('No Sentry client available, profiling is not started');\n return;\n }\n\n const integration = client.getIntegrationByName('BrowserProfiling');\n\n if (!integration) {\n DEBUG_BUILD && debug.warn('BrowserProfiling integration is not available');\n return;\n }\n\n client.emit('startUIProfiler');\n}\n\n/**\n * Stops a manually controlled Sentry UI profiling session.\n *\n * Calls to stop will stop the profiler and flush the currently collected profile data to Sentry.\n */\nfunction stopProfiler(): void {\n const client = getClient();\n if (!client) {\n DEBUG_BUILD && debug.warn('No Sentry client available, profiling is not started');\n return;\n }\n\n const integration = client.getIntegrationByName('BrowserProfiling');\n if (!integration) {\n DEBUG_BUILD && debug.warn('ProfilingIntegration is not available');\n return;\n }\n\n client.emit('stopUIProfiler');\n}\n\n/**\n * Profiler namespace for controlling the JS profiler in 'manual' mode.\n *\n * Requires the `browserProfilingIntegration` from the `@sentry/browser` package.\n */\nexport const uiProfiler: Profiler = {\n startProfiler,\n stopProfiler,\n};\n"],"names":[],"mappings":";;;AAUA,SAAS,aAAA,GAAsB;AAC7B,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,WAAA,IAAe,KAAA,CAAM,KAAK,sDAAsD,CAAA;AAChF,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,oBAAA,CAAqB,kBAAkB,CAAA;AAElE,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,WAAA,IAAe,KAAA,CAAM,KAAK,+CAA+C,CAAA;AACzE,IAAA;AAAA,EACF;AAEA,EAAA,MAAA,CAAO,KAAK,iBAAiB,CAAA;AAC/B;AAOA,SAAS,YAAA,GAAqB;AAC5B,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,WAAA,IAAe,KAAA,CAAM,KAAK,sDAAsD,CAAA;AAChF,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,oBAAA,CAAqB,kBAAkB,CAAA;AAClE,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,WAAA,IAAe,KAAA,CAAM,KAAK,uCAAuC,CAAA;AACjE,IAAA;AAAA,EACF;AAEA,EAAA,MAAA,CAAO,KAAK,gBAAgB,CAAA;AAC9B;AAOO,MAAM,UAAA,GAAuB;AAAA,EAClC,aAAA;AAAA,EACA;AACF;;;;"}
@@ -1,9 +1,7 @@
1
- import { defineIntegration, debug, getActiveSpan, getRootSpan, hasSpansEnabled } from '@sentry/core/browser';
1
+ import { defineIntegration, getActiveSpan, getRootSpan, hasSpansEnabled, debug } from '@sentry/core/browser';
2
2
  import { DEBUG_BUILD } from '../debug-build.js';
3
3
  import { WINDOW } from '../helpers.js';
4
- import { startProfileForSpan } from './startProfileForSpan.js';
5
4
  import { UIProfiler } from './UIProfiler.js';
6
- import { hasLegacyProfiling, isAutomatedPageLoadSpan, shouldProfileSpanLegacy, PROFILED_ROOT_SPANS, setThreadAttributes, getActiveProfilesCount, findProfiledTransactionsFromEnvelope, takeProfileFromGlobalCache, createProfilingEvent, addProfilesToEnvelope } from './utils.js';
7
5
 
8
6
  const INTEGRATION_NAME = "BrowserProfiling";
9
7
  const _browserProfilingIntegration = (() => {
@@ -12,102 +10,34 @@ const _browserProfilingIntegration = (() => {
12
10
  setup(client) {
13
11
  const options = client.getOptions();
14
12
  const profiler = new UIProfiler();
15
- if (!hasLegacyProfiling(options) && !options.profileLifecycle) {
13
+ if (!options.profileLifecycle) {
16
14
  options.profileLifecycle = "manual";
17
15
  }
18
- if (hasLegacyProfiling(options) && !options.profilesSampleRate) {
19
- DEBUG_BUILD && debug.log("[Profiling] Profiling disabled, no profiling options found.");
20
- return;
21
- }
22
16
  const activeSpan = getActiveSpan();
23
17
  const rootSpan = activeSpan && getRootSpan(activeSpan);
24
- if (hasLegacyProfiling(options) && options.profileSessionSampleRate !== void 0) {
25
- DEBUG_BUILD && debug.warn(
26
- "[Profiling] Both legacy profiling (`profilesSampleRate`) and UI profiling settings are defined. `profileSessionSampleRate` has no effect when legacy profiling is enabled."
27
- );
28
- }
29
- if (!hasLegacyProfiling(options)) {
30
- const lifecycleMode = options.profileLifecycle;
31
- client.on("startUIProfiler", () => profiler.start());
32
- client.on("stopUIProfiler", () => profiler.stop());
33
- if (lifecycleMode === "manual") {
34
- profiler.initialize(client);
35
- } else if (lifecycleMode === "trace") {
36
- if (!hasSpansEnabled(options)) {
37
- DEBUG_BUILD && debug.warn(
38
- "[Profiling] `profileLifecycle` is 'trace' but tracing is disabled. Set a `tracesSampleRate` or `tracesSampler` to enable span tracing."
39
- );
40
- return;
41
- }
42
- profiler.initialize(client);
43
- if (rootSpan) {
44
- profiler.notifyRootSpanActive(rootSpan);
45
- }
46
- WINDOW.setTimeout(() => {
47
- const laterActiveSpan = getActiveSpan();
48
- const laterRootSpan = laterActiveSpan && getRootSpan(laterActiveSpan);
49
- if (laterRootSpan) {
50
- profiler.notifyRootSpanActive(laterRootSpan);
51
- }
52
- }, 0);
18
+ const lifecycleMode = options.profileLifecycle;
19
+ client.on("startUIProfiler", () => profiler.start());
20
+ client.on("stopUIProfiler", () => profiler.stop());
21
+ if (lifecycleMode === "manual") {
22
+ profiler.initialize(client);
23
+ } else if (lifecycleMode === "trace") {
24
+ if (!hasSpansEnabled(options)) {
25
+ DEBUG_BUILD && debug.warn(
26
+ "[Profiling] `profileLifecycle` is 'trace' but tracing is disabled. Set a `tracesSampleRate` or `tracesSampler` to enable span tracing."
27
+ );
28
+ return;
53
29
  }
54
- } else {
55
- if (rootSpan && isAutomatedPageLoadSpan(rootSpan)) {
56
- if (shouldProfileSpanLegacy(rootSpan)) {
57
- startProfileForSpan(rootSpan);
58
- }
30
+ profiler.initialize(client);
31
+ if (rootSpan) {
32
+ profiler.notifyRootSpanActive(rootSpan);
59
33
  }
60
- client.on("spanStart", (span) => {
61
- const rootSpan2 = getRootSpan(span);
62
- if (span === rootSpan2) {
63
- if (shouldProfileSpanLegacy(span)) {
64
- startProfileForSpan(span);
65
- }
66
- } else if (PROFILED_ROOT_SPANS.has(rootSpan2)) {
67
- setThreadAttributes(span);
68
- }
69
- });
70
- client.on("beforeEnvelope", (envelope) => {
71
- if (!getActiveProfilesCount()) {
72
- return;
73
- }
74
- const profiledTransactionEvents = findProfiledTransactionsFromEnvelope(envelope);
75
- if (!profiledTransactionEvents.length) {
76
- return;
77
- }
78
- const profilesToAddToEnvelope = [];
79
- for (const profiledTransaction of profiledTransactionEvents) {
80
- const context = profiledTransaction?.contexts;
81
- const profile_id = context?.profile?.["profile_id"];
82
- const start_timestamp = context?.profile?.["start_timestamp"];
83
- if (typeof profile_id !== "string") {
84
- DEBUG_BUILD && debug.log("[Profiling] cannot find profile for a span without a profile context");
85
- continue;
86
- }
87
- if (!profile_id) {
88
- DEBUG_BUILD && debug.log("[Profiling] cannot find profile for a span without a profile context");
89
- continue;
90
- }
91
- if (context?.profile) {
92
- delete context.profile;
93
- }
94
- const profile = takeProfileFromGlobalCache(profile_id);
95
- if (!profile) {
96
- DEBUG_BUILD && debug.log(`[Profiling] Could not retrieve profile for span: ${profile_id}`);
97
- continue;
98
- }
99
- const profileEvent = createProfilingEvent(
100
- profile_id,
101
- start_timestamp,
102
- profile,
103
- profiledTransaction
104
- );
105
- if (profileEvent) {
106
- profilesToAddToEnvelope.push(profileEvent);
107
- }
34
+ WINDOW.setTimeout(() => {
35
+ const laterActiveSpan = getActiveSpan();
36
+ const laterRootSpan = laterActiveSpan && getRootSpan(laterActiveSpan);
37
+ if (laterRootSpan) {
38
+ profiler.notifyRootSpanActive(laterRootSpan);
108
39
  }
109
- addProfilesToEnvelope(envelope, profilesToAddToEnvelope);
110
- });
40
+ }, 0);
111
41
  }
112
42
  }
113
43
  };