@sentry/cloudflare 11.0.0-alpha.1 → 11.0.0-beta.0

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 (415) hide show
  1. package/build/cjs/dev/baseSdk.js +20 -8
  2. package/build/cjs/dev/baseSdk.js.map +1 -1
  3. package/build/cjs/dev/client.js +118 -25
  4. package/build/cjs/dev/client.js.map +1 -1
  5. package/build/cjs/dev/clientCache.js +15 -0
  6. package/build/cjs/dev/clientCache.js.map +1 -0
  7. package/build/cjs/dev/defineCloudflareOptions.js.map +1 -1
  8. package/build/cjs/dev/durableobject.js +4 -62
  9. package/build/cjs/dev/durableobject.js.map +1 -1
  10. package/build/cjs/dev/flush.js +6 -4
  11. package/build/cjs/dev/flush.js.map +1 -1
  12. package/build/cjs/dev/index.js +8 -7
  13. package/build/cjs/dev/index.js.map +1 -1
  14. package/build/cjs/dev/instrumentations/agents/instrumentAgentCallableRpc.js +3 -1
  15. package/build/cjs/dev/instrumentations/agents/instrumentAgentCallableRpc.js.map +1 -1
  16. package/build/cjs/dev/instrumentations/instrumentDurableObjectHandlers.js +123 -0
  17. package/build/cjs/dev/instrumentations/instrumentDurableObjectHandlers.js.map +1 -0
  18. package/build/cjs/dev/instrumentations/instrumentDurableObjectNamespace.js +4 -4
  19. package/build/cjs/dev/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
  20. package/build/cjs/dev/instrumentations/instrumentDurableObjectStorage.js +3 -1
  21. package/build/cjs/dev/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
  22. package/build/cjs/dev/instrumentations/instrumentDurableObjectSyncKvStorage.js +3 -1
  23. package/build/cjs/dev/instrumentations/instrumentDurableObjectSyncKvStorage.js.map +1 -1
  24. package/build/cjs/dev/instrumentations/instrumentSqlStorage.js +6 -3
  25. package/build/cjs/dev/instrumentations/instrumentSqlStorage.js.map +1 -1
  26. package/build/cjs/dev/instrumentations/instrumentWorkerEntrypoint.js +9 -16
  27. package/build/cjs/dev/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
  28. package/build/cjs/dev/instrumentations/worker/instrumentD1.js +10 -3
  29. package/build/cjs/dev/instrumentations/worker/instrumentD1.js.map +1 -1
  30. package/build/cjs/dev/instrumentations/worker/instrumentEmail.js +4 -2
  31. package/build/cjs/dev/instrumentations/worker/instrumentEmail.js.map +1 -1
  32. package/build/cjs/dev/instrumentations/worker/instrumentEnv.js +5 -12
  33. package/build/cjs/dev/instrumentations/worker/instrumentEnv.js.map +1 -1
  34. package/build/cjs/dev/instrumentations/worker/instrumentFetch.js +8 -8
  35. package/build/cjs/dev/instrumentations/worker/instrumentFetch.js.map +1 -1
  36. package/build/cjs/dev/instrumentations/worker/instrumentQueue.js +4 -2
  37. package/build/cjs/dev/instrumentations/worker/instrumentQueue.js.map +1 -1
  38. package/build/cjs/dev/instrumentations/worker/instrumentQueueProducer.js +3 -2
  39. package/build/cjs/dev/instrumentations/worker/instrumentQueueProducer.js.map +1 -1
  40. package/build/cjs/dev/instrumentations/worker/instrumentR2.js +21 -18
  41. package/build/cjs/dev/instrumentations/worker/instrumentR2.js.map +1 -1
  42. package/build/cjs/dev/instrumentations/worker/instrumentScheduled.js +4 -2
  43. package/build/cjs/dev/instrumentations/worker/instrumentScheduled.js.map +1 -1
  44. package/build/cjs/dev/instrumentations/worker/instrumentTail.js +2 -0
  45. package/build/cjs/dev/instrumentations/worker/instrumentTail.js.map +1 -1
  46. package/build/cjs/dev/integrations/fetch.js +1 -11
  47. package/build/cjs/dev/integrations/fetch.js.map +1 -1
  48. package/build/cjs/dev/opentelemetry/tracer.js +2 -40
  49. package/build/cjs/dev/opentelemetry/tracer.js.map +1 -1
  50. package/build/cjs/dev/pages-plugin.js +2 -2
  51. package/build/cjs/dev/pages-plugin.js.map +1 -1
  52. package/build/cjs/dev/request.js +2 -123
  53. package/build/cjs/dev/request.js.map +1 -1
  54. package/build/cjs/dev/sdk.js +11 -6
  55. package/build/cjs/dev/sdk.js.map +1 -1
  56. package/build/cjs/dev/transport.js +1 -1
  57. package/build/cjs/dev/transport.js.map +1 -1
  58. package/build/cjs/dev/utils/invocationContext.js +41 -0
  59. package/build/cjs/dev/utils/invocationContext.js.map +1 -0
  60. package/build/cjs/dev/utils/invocationScope.js +7 -2
  61. package/build/cjs/dev/utils/invocationScope.js.map +1 -1
  62. package/build/cjs/dev/utils/isBinding.js +0 -4
  63. package/build/cjs/dev/utils/isBinding.js.map +1 -1
  64. package/build/cjs/dev/utils/rpcPropagation.js +15 -0
  65. package/build/cjs/dev/utils/rpcPropagation.js.map +1 -0
  66. package/build/cjs/dev/vendor/stacktrace.js +2 -1
  67. package/build/cjs/dev/vendor/stacktrace.js.map +1 -1
  68. package/build/cjs/dev/vite/autoInstrument.js +2 -1
  69. package/build/cjs/dev/vite/autoInstrument.js.map +1 -1
  70. package/build/cjs/dev/vite/index.js.map +1 -1
  71. package/build/cjs/dev/vite/transform.js +30 -5
  72. package/build/cjs/dev/vite/transform.js.map +1 -1
  73. package/build/cjs/dev/vite/wranglerConfig.js +21 -1
  74. package/build/cjs/dev/vite/wranglerConfig.js.map +1 -1
  75. package/build/cjs/dev/withSentry.js.map +1 -1
  76. package/build/cjs/dev/workflows.js +45 -33
  77. package/build/cjs/dev/workflows.js.map +1 -1
  78. package/build/cjs/dev/wrapMethodWithSentry.js +51 -15
  79. package/build/cjs/dev/wrapMethodWithSentry.js.map +1 -1
  80. package/build/cjs/dev/wrapRequestHandlerWithInit.js +134 -0
  81. package/build/cjs/dev/wrapRequestHandlerWithInit.js.map +1 -0
  82. package/build/cjs/prod/baseSdk.js +20 -8
  83. package/build/cjs/prod/baseSdk.js.map +1 -1
  84. package/build/cjs/prod/client.js +118 -25
  85. package/build/cjs/prod/client.js.map +1 -1
  86. package/build/cjs/prod/clientCache.js +15 -0
  87. package/build/cjs/prod/clientCache.js.map +1 -0
  88. package/build/cjs/prod/defineCloudflareOptions.js.map +1 -1
  89. package/build/cjs/prod/durableobject.js +4 -62
  90. package/build/cjs/prod/durableobject.js.map +1 -1
  91. package/build/cjs/prod/flush.js +6 -4
  92. package/build/cjs/prod/flush.js.map +1 -1
  93. package/build/cjs/prod/index.js +8 -7
  94. package/build/cjs/prod/index.js.map +1 -1
  95. package/build/cjs/prod/instrumentations/agents/instrumentAgentCallableRpc.js +3 -1
  96. package/build/cjs/prod/instrumentations/agents/instrumentAgentCallableRpc.js.map +1 -1
  97. package/build/cjs/prod/instrumentations/instrumentDurableObjectHandlers.js +123 -0
  98. package/build/cjs/prod/instrumentations/instrumentDurableObjectHandlers.js.map +1 -0
  99. package/build/cjs/prod/instrumentations/instrumentDurableObjectNamespace.js +4 -4
  100. package/build/cjs/prod/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
  101. package/build/cjs/prod/instrumentations/instrumentDurableObjectStorage.js +3 -1
  102. package/build/cjs/prod/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
  103. package/build/cjs/prod/instrumentations/instrumentDurableObjectSyncKvStorage.js +3 -1
  104. package/build/cjs/prod/instrumentations/instrumentDurableObjectSyncKvStorage.js.map +1 -1
  105. package/build/cjs/prod/instrumentations/instrumentSqlStorage.js +6 -3
  106. package/build/cjs/prod/instrumentations/instrumentSqlStorage.js.map +1 -1
  107. package/build/cjs/prod/instrumentations/instrumentWorkerEntrypoint.js +9 -16
  108. package/build/cjs/prod/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
  109. package/build/cjs/prod/instrumentations/worker/instrumentD1.js +10 -3
  110. package/build/cjs/prod/instrumentations/worker/instrumentD1.js.map +1 -1
  111. package/build/cjs/prod/instrumentations/worker/instrumentEmail.js +4 -2
  112. package/build/cjs/prod/instrumentations/worker/instrumentEmail.js.map +1 -1
  113. package/build/cjs/prod/instrumentations/worker/instrumentEnv.js +5 -12
  114. package/build/cjs/prod/instrumentations/worker/instrumentEnv.js.map +1 -1
  115. package/build/cjs/prod/instrumentations/worker/instrumentFetch.js +8 -8
  116. package/build/cjs/prod/instrumentations/worker/instrumentFetch.js.map +1 -1
  117. package/build/cjs/prod/instrumentations/worker/instrumentQueue.js +4 -2
  118. package/build/cjs/prod/instrumentations/worker/instrumentQueue.js.map +1 -1
  119. package/build/cjs/prod/instrumentations/worker/instrumentQueueProducer.js +3 -2
  120. package/build/cjs/prod/instrumentations/worker/instrumentQueueProducer.js.map +1 -1
  121. package/build/cjs/prod/instrumentations/worker/instrumentR2.js +21 -18
  122. package/build/cjs/prod/instrumentations/worker/instrumentR2.js.map +1 -1
  123. package/build/cjs/prod/instrumentations/worker/instrumentScheduled.js +4 -2
  124. package/build/cjs/prod/instrumentations/worker/instrumentScheduled.js.map +1 -1
  125. package/build/cjs/prod/instrumentations/worker/instrumentTail.js +2 -0
  126. package/build/cjs/prod/instrumentations/worker/instrumentTail.js.map +1 -1
  127. package/build/cjs/prod/integrations/fetch.js +1 -11
  128. package/build/cjs/prod/integrations/fetch.js.map +1 -1
  129. package/build/cjs/prod/opentelemetry/tracer.js +2 -40
  130. package/build/cjs/prod/opentelemetry/tracer.js.map +1 -1
  131. package/build/cjs/prod/pages-plugin.js +2 -2
  132. package/build/cjs/prod/pages-plugin.js.map +1 -1
  133. package/build/cjs/prod/request.js +2 -123
  134. package/build/cjs/prod/request.js.map +1 -1
  135. package/build/cjs/prod/sdk.js +11 -6
  136. package/build/cjs/prod/sdk.js.map +1 -1
  137. package/build/cjs/prod/transport.js +1 -1
  138. package/build/cjs/prod/transport.js.map +1 -1
  139. package/build/cjs/prod/utils/invocationContext.js +41 -0
  140. package/build/cjs/prod/utils/invocationContext.js.map +1 -0
  141. package/build/cjs/prod/utils/invocationScope.js +7 -2
  142. package/build/cjs/prod/utils/invocationScope.js.map +1 -1
  143. package/build/cjs/prod/utils/isBinding.js +0 -4
  144. package/build/cjs/prod/utils/isBinding.js.map +1 -1
  145. package/build/cjs/prod/utils/rpcPropagation.js +15 -0
  146. package/build/cjs/prod/utils/rpcPropagation.js.map +1 -0
  147. package/build/cjs/prod/vendor/stacktrace.js +2 -1
  148. package/build/cjs/prod/vendor/stacktrace.js.map +1 -1
  149. package/build/cjs/prod/vite/autoInstrument.js +2 -1
  150. package/build/cjs/prod/vite/autoInstrument.js.map +1 -1
  151. package/build/cjs/prod/vite/index.js.map +1 -1
  152. package/build/cjs/prod/vite/transform.js +30 -5
  153. package/build/cjs/prod/vite/transform.js.map +1 -1
  154. package/build/cjs/prod/vite/wranglerConfig.js +21 -1
  155. package/build/cjs/prod/vite/wranglerConfig.js.map +1 -1
  156. package/build/cjs/prod/withSentry.js.map +1 -1
  157. package/build/cjs/prod/workflows.js +45 -33
  158. package/build/cjs/prod/workflows.js.map +1 -1
  159. package/build/cjs/prod/wrapMethodWithSentry.js +51 -15
  160. package/build/cjs/prod/wrapMethodWithSentry.js.map +1 -1
  161. package/build/cjs/prod/wrapRequestHandlerWithInit.js +134 -0
  162. package/build/cjs/prod/wrapRequestHandlerWithInit.js.map +1 -0
  163. package/build/esm/dev/baseSdk.js +21 -9
  164. package/build/esm/dev/baseSdk.js.map +1 -1
  165. package/build/esm/dev/client.js +118 -25
  166. package/build/esm/dev/client.js.map +1 -1
  167. package/build/esm/dev/clientCache.js +12 -0
  168. package/build/esm/dev/clientCache.js.map +1 -0
  169. package/build/esm/dev/defineCloudflareOptions.js.map +1 -1
  170. package/build/esm/dev/durableobject.js +5 -63
  171. package/build/esm/dev/durableobject.js.map +1 -1
  172. package/build/esm/dev/flush.js +6 -4
  173. package/build/esm/dev/flush.js.map +1 -1
  174. package/build/esm/dev/index.js +4 -4
  175. package/build/esm/dev/instrumentations/agents/instrumentAgentCallableRpc.js +4 -2
  176. package/build/esm/dev/instrumentations/agents/instrumentAgentCallableRpc.js.map +1 -1
  177. package/build/esm/dev/instrumentations/instrumentDurableObjectHandlers.js +121 -0
  178. package/build/esm/dev/instrumentations/instrumentDurableObjectHandlers.js.map +1 -0
  179. package/build/esm/dev/instrumentations/instrumentDurableObjectNamespace.js +4 -4
  180. package/build/esm/dev/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
  181. package/build/esm/dev/instrumentations/instrumentDurableObjectStorage.js +3 -1
  182. package/build/esm/dev/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
  183. package/build/esm/dev/instrumentations/instrumentDurableObjectSyncKvStorage.js +3 -1
  184. package/build/esm/dev/instrumentations/instrumentDurableObjectSyncKvStorage.js.map +1 -1
  185. package/build/esm/dev/instrumentations/instrumentSqlStorage.js +5 -2
  186. package/build/esm/dev/instrumentations/instrumentSqlStorage.js.map +1 -1
  187. package/build/esm/dev/instrumentations/instrumentWorkerEntrypoint.js +9 -16
  188. package/build/esm/dev/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
  189. package/build/esm/dev/instrumentations/worker/instrumentD1.js +11 -4
  190. package/build/esm/dev/instrumentations/worker/instrumentD1.js.map +1 -1
  191. package/build/esm/dev/instrumentations/worker/instrumentEmail.js +7 -5
  192. package/build/esm/dev/instrumentations/worker/instrumentEmail.js.map +1 -1
  193. package/build/esm/dev/instrumentations/worker/instrumentEnv.js +6 -13
  194. package/build/esm/dev/instrumentations/worker/instrumentEnv.js.map +1 -1
  195. package/build/esm/dev/instrumentations/worker/instrumentFetch.js +1 -1
  196. package/build/esm/dev/instrumentations/worker/instrumentFetch.js.map +1 -1
  197. package/build/esm/dev/instrumentations/worker/instrumentQueue.js +7 -5
  198. package/build/esm/dev/instrumentations/worker/instrumentQueue.js.map +1 -1
  199. package/build/esm/dev/instrumentations/worker/instrumentQueueProducer.js +4 -3
  200. package/build/esm/dev/instrumentations/worker/instrumentQueueProducer.js.map +1 -1
  201. package/build/esm/dev/instrumentations/worker/instrumentR2.js +22 -19
  202. package/build/esm/dev/instrumentations/worker/instrumentR2.js.map +1 -1
  203. package/build/esm/dev/instrumentations/worker/instrumentScheduled.js +7 -5
  204. package/build/esm/dev/instrumentations/worker/instrumentScheduled.js.map +1 -1
  205. package/build/esm/dev/instrumentations/worker/instrumentTail.js +2 -0
  206. package/build/esm/dev/instrumentations/worker/instrumentTail.js.map +1 -1
  207. package/build/esm/dev/integrations/fetch.js +2 -12
  208. package/build/esm/dev/integrations/fetch.js.map +1 -1
  209. package/build/esm/dev/opentelemetry/tracer.js +2 -40
  210. package/build/esm/dev/opentelemetry/tracer.js.map +1 -1
  211. package/build/esm/dev/package.json +1 -1
  212. package/build/esm/dev/pages-plugin.js +1 -1
  213. package/build/esm/dev/pages-plugin.js.map +1 -1
  214. package/build/esm/dev/request.js +2 -122
  215. package/build/esm/dev/request.js.map +1 -1
  216. package/build/esm/dev/sdk.js +11 -7
  217. package/build/esm/dev/sdk.js.map +1 -1
  218. package/build/esm/dev/transport.js +1 -1
  219. package/build/esm/dev/transport.js.map +1 -1
  220. package/build/esm/dev/utils/invocationContext.js +37 -0
  221. package/build/esm/dev/utils/invocationContext.js.map +1 -0
  222. package/build/esm/dev/utils/invocationScope.js +7 -2
  223. package/build/esm/dev/utils/invocationScope.js.map +1 -1
  224. package/build/esm/dev/utils/isBinding.js +1 -4
  225. package/build/esm/dev/utils/isBinding.js.map +1 -1
  226. package/build/esm/dev/utils/rpcPropagation.js +13 -0
  227. package/build/esm/dev/utils/rpcPropagation.js.map +1 -0
  228. package/build/esm/dev/utils/traceLinks.js +1 -1
  229. package/build/esm/dev/vendor/stacktrace.js +2 -1
  230. package/build/esm/dev/vendor/stacktrace.js.map +1 -1
  231. package/build/esm/dev/vite/autoInstrument.js +2 -1
  232. package/build/esm/dev/vite/autoInstrument.js.map +1 -1
  233. package/build/esm/dev/vite/index.js.map +1 -1
  234. package/build/esm/dev/vite/transform.js +30 -5
  235. package/build/esm/dev/vite/transform.js.map +1 -1
  236. package/build/esm/dev/vite/wranglerConfig.js +21 -2
  237. package/build/esm/dev/vite/wranglerConfig.js.map +1 -1
  238. package/build/esm/dev/withSentry.js.map +1 -1
  239. package/build/esm/dev/workflows.js +48 -36
  240. package/build/esm/dev/workflows.js.map +1 -1
  241. package/build/esm/dev/wrapMethodWithSentry.js +53 -17
  242. package/build/esm/dev/wrapMethodWithSentry.js.map +1 -1
  243. package/build/esm/dev/wrapRequestHandlerWithInit.js +132 -0
  244. package/build/esm/dev/wrapRequestHandlerWithInit.js.map +1 -0
  245. package/build/esm/prod/baseSdk.js +21 -9
  246. package/build/esm/prod/baseSdk.js.map +1 -1
  247. package/build/esm/prod/client.js +118 -25
  248. package/build/esm/prod/client.js.map +1 -1
  249. package/build/esm/prod/clientCache.js +12 -0
  250. package/build/esm/prod/clientCache.js.map +1 -0
  251. package/build/esm/prod/defineCloudflareOptions.js.map +1 -1
  252. package/build/esm/prod/durableobject.js +5 -63
  253. package/build/esm/prod/durableobject.js.map +1 -1
  254. package/build/esm/prod/flush.js +6 -4
  255. package/build/esm/prod/flush.js.map +1 -1
  256. package/build/esm/prod/index.js +4 -4
  257. package/build/esm/prod/instrumentations/agents/instrumentAgentCallableRpc.js +4 -2
  258. package/build/esm/prod/instrumentations/agents/instrumentAgentCallableRpc.js.map +1 -1
  259. package/build/esm/prod/instrumentations/instrumentDurableObjectHandlers.js +121 -0
  260. package/build/esm/prod/instrumentations/instrumentDurableObjectHandlers.js.map +1 -0
  261. package/build/esm/prod/instrumentations/instrumentDurableObjectNamespace.js +4 -4
  262. package/build/esm/prod/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
  263. package/build/esm/prod/instrumentations/instrumentDurableObjectStorage.js +3 -1
  264. package/build/esm/prod/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
  265. package/build/esm/prod/instrumentations/instrumentDurableObjectSyncKvStorage.js +3 -1
  266. package/build/esm/prod/instrumentations/instrumentDurableObjectSyncKvStorage.js.map +1 -1
  267. package/build/esm/prod/instrumentations/instrumentSqlStorage.js +5 -2
  268. package/build/esm/prod/instrumentations/instrumentSqlStorage.js.map +1 -1
  269. package/build/esm/prod/instrumentations/instrumentWorkerEntrypoint.js +9 -16
  270. package/build/esm/prod/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
  271. package/build/esm/prod/instrumentations/worker/instrumentD1.js +11 -4
  272. package/build/esm/prod/instrumentations/worker/instrumentD1.js.map +1 -1
  273. package/build/esm/prod/instrumentations/worker/instrumentEmail.js +7 -5
  274. package/build/esm/prod/instrumentations/worker/instrumentEmail.js.map +1 -1
  275. package/build/esm/prod/instrumentations/worker/instrumentEnv.js +6 -13
  276. package/build/esm/prod/instrumentations/worker/instrumentEnv.js.map +1 -1
  277. package/build/esm/prod/instrumentations/worker/instrumentFetch.js +1 -1
  278. package/build/esm/prod/instrumentations/worker/instrumentFetch.js.map +1 -1
  279. package/build/esm/prod/instrumentations/worker/instrumentQueue.js +7 -5
  280. package/build/esm/prod/instrumentations/worker/instrumentQueue.js.map +1 -1
  281. package/build/esm/prod/instrumentations/worker/instrumentQueueProducer.js +4 -3
  282. package/build/esm/prod/instrumentations/worker/instrumentQueueProducer.js.map +1 -1
  283. package/build/esm/prod/instrumentations/worker/instrumentR2.js +22 -19
  284. package/build/esm/prod/instrumentations/worker/instrumentR2.js.map +1 -1
  285. package/build/esm/prod/instrumentations/worker/instrumentScheduled.js +7 -5
  286. package/build/esm/prod/instrumentations/worker/instrumentScheduled.js.map +1 -1
  287. package/build/esm/prod/instrumentations/worker/instrumentTail.js +2 -0
  288. package/build/esm/prod/instrumentations/worker/instrumentTail.js.map +1 -1
  289. package/build/esm/prod/integrations/fetch.js +2 -12
  290. package/build/esm/prod/integrations/fetch.js.map +1 -1
  291. package/build/esm/prod/opentelemetry/tracer.js +2 -40
  292. package/build/esm/prod/opentelemetry/tracer.js.map +1 -1
  293. package/build/esm/prod/package.json +1 -1
  294. package/build/esm/prod/pages-plugin.js +1 -1
  295. package/build/esm/prod/pages-plugin.js.map +1 -1
  296. package/build/esm/prod/request.js +2 -122
  297. package/build/esm/prod/request.js.map +1 -1
  298. package/build/esm/prod/sdk.js +11 -7
  299. package/build/esm/prod/sdk.js.map +1 -1
  300. package/build/esm/prod/transport.js +1 -1
  301. package/build/esm/prod/transport.js.map +1 -1
  302. package/build/esm/prod/utils/invocationContext.js +37 -0
  303. package/build/esm/prod/utils/invocationContext.js.map +1 -0
  304. package/build/esm/prod/utils/invocationScope.js +7 -2
  305. package/build/esm/prod/utils/invocationScope.js.map +1 -1
  306. package/build/esm/prod/utils/isBinding.js +1 -4
  307. package/build/esm/prod/utils/isBinding.js.map +1 -1
  308. package/build/esm/prod/utils/rpcPropagation.js +13 -0
  309. package/build/esm/prod/utils/rpcPropagation.js.map +1 -0
  310. package/build/esm/prod/utils/traceLinks.js +1 -1
  311. package/build/esm/prod/vendor/stacktrace.js +2 -1
  312. package/build/esm/prod/vendor/stacktrace.js.map +1 -1
  313. package/build/esm/prod/vite/autoInstrument.js +2 -1
  314. package/build/esm/prod/vite/autoInstrument.js.map +1 -1
  315. package/build/esm/prod/vite/index.js.map +1 -1
  316. package/build/esm/prod/vite/transform.js +30 -5
  317. package/build/esm/prod/vite/transform.js.map +1 -1
  318. package/build/esm/prod/vite/wranglerConfig.js +21 -2
  319. package/build/esm/prod/vite/wranglerConfig.js.map +1 -1
  320. package/build/esm/prod/withSentry.js.map +1 -1
  321. package/build/esm/prod/workflows.js +48 -36
  322. package/build/esm/prod/workflows.js.map +1 -1
  323. package/build/esm/prod/wrapMethodWithSentry.js +53 -17
  324. package/build/esm/prod/wrapMethodWithSentry.js.map +1 -1
  325. package/build/esm/prod/wrapRequestHandlerWithInit.js +132 -0
  326. package/build/esm/prod/wrapRequestHandlerWithInit.js.map +1 -0
  327. package/build/types/baseSdk.d.ts +8 -0
  328. package/build/types/baseSdk.d.ts.map +1 -1
  329. package/build/types/client.d.ts +91 -18
  330. package/build/types/client.d.ts.map +1 -1
  331. package/build/types/clientCache.d.ts +8 -0
  332. package/build/types/clientCache.d.ts.map +1 -0
  333. package/build/types/defineCloudflareOptions.d.ts +3 -2
  334. package/build/types/defineCloudflareOptions.d.ts.map +1 -1
  335. package/build/types/durableobject.d.ts +5 -7
  336. package/build/types/durableobject.d.ts.map +1 -1
  337. package/build/types/flush.d.ts +2 -0
  338. package/build/types/flush.d.ts.map +1 -1
  339. package/build/types/index.d.ts +4 -4
  340. package/build/types/index.d.ts.map +1 -1
  341. package/build/types/instrumentations/agents/instrumentAgentCallableRpc.d.ts.map +1 -1
  342. package/build/types/instrumentations/instrumentDurableObjectHandlers.d.ts +28 -0
  343. package/build/types/instrumentations/instrumentDurableObjectHandlers.d.ts.map +1 -0
  344. package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts +2 -1
  345. package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts.map +1 -1
  346. package/build/types/instrumentations/instrumentDurableObjectStorage.d.ts.map +1 -1
  347. package/build/types/instrumentations/instrumentDurableObjectSyncKvStorage.d.ts.map +1 -1
  348. package/build/types/instrumentations/instrumentSqlStorage.d.ts.map +1 -1
  349. package/build/types/instrumentations/instrumentWorkerEntrypoint.d.ts +2 -3
  350. package/build/types/instrumentations/instrumentWorkerEntrypoint.d.ts.map +1 -1
  351. package/build/types/instrumentations/worker/instrumentD1.d.ts.map +1 -1
  352. package/build/types/instrumentations/worker/instrumentEmail.d.ts.map +1 -1
  353. package/build/types/instrumentations/worker/instrumentEnv.d.ts +0 -1
  354. package/build/types/instrumentations/worker/instrumentEnv.d.ts.map +1 -1
  355. package/build/types/instrumentations/worker/instrumentQueue.d.ts.map +1 -1
  356. package/build/types/instrumentations/worker/instrumentQueueProducer.d.ts.map +1 -1
  357. package/build/types/instrumentations/worker/instrumentR2.d.ts.map +1 -1
  358. package/build/types/instrumentations/worker/instrumentScheduled.d.ts.map +1 -1
  359. package/build/types/instrumentations/worker/instrumentTail.d.ts.map +1 -1
  360. package/build/types/integrations/fetch.d.ts.map +1 -1
  361. package/build/types/opentelemetry/tracer.d.ts.map +1 -1
  362. package/build/types/pages-plugin.d.ts +3 -1
  363. package/build/types/pages-plugin.d.ts.map +1 -1
  364. package/build/types/request.d.ts +5 -31
  365. package/build/types/request.d.ts.map +1 -1
  366. package/build/types/sdk.d.ts +13 -4
  367. package/build/types/sdk.d.ts.map +1 -1
  368. package/build/types/transport.d.ts.map +1 -1
  369. package/build/types/types.d.ts +28 -0
  370. package/build/types/types.d.ts.map +1 -1
  371. package/build/types/utils/invocationContext.d.ts +58 -0
  372. package/build/types/utils/invocationContext.d.ts.map +1 -0
  373. package/build/types/utils/invocationScope.d.ts +2 -1
  374. package/build/types/utils/invocationScope.d.ts.map +1 -1
  375. package/build/types/utils/isBinding.d.ts +1 -9
  376. package/build/types/utils/isBinding.d.ts.map +1 -1
  377. package/build/types/utils/rpcPropagation.d.ts +10 -0
  378. package/build/types/utils/rpcPropagation.d.ts.map +1 -0
  379. package/build/types/vendor/stacktrace.d.ts.map +1 -1
  380. package/build/types/vite/autoInstrument.d.ts.map +1 -1
  381. package/build/types/vite/index.d.ts +4 -0
  382. package/build/types/vite/index.d.ts.map +1 -1
  383. package/build/types/vite/transform.d.ts +3 -0
  384. package/build/types/vite/transform.d.ts.map +1 -1
  385. package/build/types/vite/wranglerConfig.d.ts +13 -0
  386. package/build/types/vite/wranglerConfig.d.ts.map +1 -1
  387. package/build/types/withSentry.d.ts +2 -3
  388. package/build/types/withSentry.d.ts.map +1 -1
  389. package/build/types/workflows.d.ts +3 -3
  390. package/build/types/workflows.d.ts.map +1 -1
  391. package/build/types/wrapMethodWithSentry.d.ts +6 -1
  392. package/build/types/wrapMethodWithSentry.d.ts.map +1 -1
  393. package/build/types/wrapRequestHandlerWithInit.d.ts +31 -0
  394. package/build/types/wrapRequestHandlerWithInit.d.ts.map +1 -0
  395. package/package.json +6 -4
  396. package/build/cjs/dev/instrumentations/worker/instrumentRateLimit.js +0 -29
  397. package/build/cjs/dev/instrumentations/worker/instrumentRateLimit.js.map +0 -1
  398. package/build/cjs/dev/integrations/tracing/vercelai.js +0 -18
  399. package/build/cjs/dev/integrations/tracing/vercelai.js.map +0 -1
  400. package/build/cjs/prod/instrumentations/worker/instrumentRateLimit.js +0 -29
  401. package/build/cjs/prod/instrumentations/worker/instrumentRateLimit.js.map +0 -1
  402. package/build/cjs/prod/integrations/tracing/vercelai.js +0 -18
  403. package/build/cjs/prod/integrations/tracing/vercelai.js.map +0 -1
  404. package/build/esm/dev/instrumentations/worker/instrumentRateLimit.js +0 -27
  405. package/build/esm/dev/instrumentations/worker/instrumentRateLimit.js.map +0 -1
  406. package/build/esm/dev/integrations/tracing/vercelai.js +0 -16
  407. package/build/esm/dev/integrations/tracing/vercelai.js.map +0 -1
  408. package/build/esm/prod/instrumentations/worker/instrumentRateLimit.js +0 -27
  409. package/build/esm/prod/instrumentations/worker/instrumentRateLimit.js.map +0 -1
  410. package/build/esm/prod/integrations/tracing/vercelai.js +0 -16
  411. package/build/esm/prod/integrations/tracing/vercelai.js.map +0 -1
  412. package/build/types/instrumentations/worker/instrumentRateLimit.d.ts +0 -6
  413. package/build/types/instrumentations/worker/instrumentRateLimit.d.ts.map +0 -1
  414. package/build/types/integrations/tracing/vercelai.d.ts +0 -39
  415. package/build/types/integrations/tracing/vercelai.d.ts.map +0 -1
@@ -1,10 +1,11 @@
1
- import { isThenable, SEMANTIC_ATTRIBUTE_SENTRY_OP, continueTrace, startNewTrace, captureException, startSpan, isObjectLike, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
1
+ import { isThenable, SEMANTIC_ATTRIBUTE_SENTRY_OP, continueTrace, startNewTrace, isObjectLike, captureException, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
2
2
  import { getOriginalWaitUntil, flushAndDispose } from './flush.js';
3
3
  import { ensureInstrumented } from './instrument.js';
4
4
  import { init } from './sdk.js';
5
+ import { getInvocationState, getInvocationWaitUntil } from './utils/invocationContext.js';
5
6
  import { withInvocationIsolationScope } from './utils/invocationScope.js';
6
7
  import { extractRpcMeta } from './utils/rpcMeta.js';
7
- import { getStoredSpanContext, buildSpanLinks, storeSpanContext } from './utils/traceLinks.js';
8
+ import { storeSpanContext, getStoredSpanContext, buildSpanLinks } from './utils/traceLinks.js';
8
9
 
9
10
  function resolveOriginalStorage(context, thisArg) {
10
11
  if (isObjectLike(thisArg) && "ctx" in thisArg) {
@@ -31,9 +32,11 @@ function wrapMethodWithSentry(wrapperOptions, handler, callback, noMark) {
31
32
  args = extracted.args;
32
33
  rpcMeta = extracted.rpcMeta;
33
34
  }
35
+ const spanName = typeof wrapperOptions.spanName === "function" ? wrapperOptions.spanName(rpcMeta) : wrapperOptions.spanName;
34
36
  const wrappedFunction = (scope) => {
35
37
  const context = wrapperOptions.context;
36
- const waitUntil = context ? getOriginalWaitUntil(context)?.bind(context) : void 0;
38
+ const invocationState = getInvocationState();
39
+ const waitUntil = invocationState ? getInvocationWaitUntil(invocationState) : context ? getOriginalWaitUntil(context)?.bind(context) : void 0;
37
40
  const storage = resolveOriginalStorage(context, thisArg);
38
41
  let scopeClient = scope.getClient();
39
42
  if (startNewTrace$1 || !scopeClient?.getTransport()) {
@@ -45,7 +48,7 @@ function wrapMethodWithSentry(wrapperOptions, handler, callback, noMark) {
45
48
  scopeClient = client;
46
49
  }
47
50
  const clientToDispose = scopeClient;
48
- const methodName = wrapperOptions.spanName || "unknown";
51
+ const methodName = spanName || "unknown";
49
52
  const teardown = async () => {
50
53
  if (startNewTrace$1 && storage) {
51
54
  storeSpanContext(storage, methodName);
@@ -56,17 +59,23 @@ function wrapMethodWithSentry(wrapperOptions, handler, callback, noMark) {
56
59
  waitUntil?.(teardown());
57
60
  return res;
58
61
  };
59
- const onRejected = (e) => {
62
+ const captureAndRethrow = (e) => {
60
63
  captureException(e, {
61
64
  mechanism: {
62
65
  type: origin,
63
66
  handled: false
64
67
  }
65
68
  });
66
- waitUntil?.(teardown());
67
69
  throw e;
68
70
  };
69
- if (!wrapperOptions.spanName) {
71
+ const onRejected = (e) => {
72
+ try {
73
+ return captureAndRethrow(e);
74
+ } finally {
75
+ waitUntil?.(teardown());
76
+ }
77
+ };
78
+ if (!spanName) {
70
79
  try {
71
80
  if (callback) {
72
81
  callback(...args);
@@ -101,27 +110,54 @@ function wrapMethodWithSentry(wrapperOptions, handler, callback, noMark) {
101
110
  try {
102
111
  const result = Reflect.apply(target, thisArg, args);
103
112
  if (isThenable(result)) {
104
- return result.then(onFulfilled, onRejected);
105
- } else {
106
- return onFulfilled(result);
113
+ return result.then(void 0, captureAndRethrow);
107
114
  }
115
+ return result;
108
116
  } catch (e) {
109
- return onRejected(e);
117
+ return captureAndRethrow(e);
110
118
  }
111
119
  });
112
120
  };
121
+ const runWithTeardown = (run) => {
122
+ let out;
123
+ try {
124
+ out = run();
125
+ } catch (e) {
126
+ waitUntil?.(teardown());
127
+ throw e;
128
+ }
129
+ if (isThenable(out)) {
130
+ return out.then(
131
+ (res) => {
132
+ waitUntil?.(teardown());
133
+ return res;
134
+ },
135
+ (e) => {
136
+ waitUntil?.(teardown());
137
+ throw e;
138
+ }
139
+ );
140
+ }
141
+ waitUntil?.(teardown());
142
+ return out;
143
+ };
113
144
  if (rpcMeta) {
114
- return continueTrace(
115
- { sentryTrace: rpcMeta["sentry-trace"] || "", baggage: rpcMeta.baggage || "" },
116
- executeSpan
145
+ return runWithTeardown(
146
+ () => continueTrace(
147
+ { sentryTrace: rpcMeta["sentry-trace"] || "", baggage: rpcMeta.baggage || "" },
148
+ executeSpan
149
+ )
117
150
  );
118
151
  }
119
152
  if (startNewTrace$1) {
120
- return startNewTrace(() => executeSpan());
153
+ return runWithTeardown(() => startNewTrace(() => executeSpan()));
121
154
  }
122
- return executeSpan();
155
+ return runWithTeardown(executeSpan);
123
156
  };
124
- return withInvocationIsolationScope(wrappedFunction);
157
+ return withInvocationIsolationScope(
158
+ wrappedFunction,
159
+ wrapperOptions.context
160
+ );
125
161
  }
126
162
  }),
127
163
  noMark
@@ -1 +1 @@
1
- {"version":3,"file":"wrapMethodWithSentry.js","sources":["../../../src/wrapMethodWithSentry.ts"],"sourcesContent":["import type { DurableObjectStorage } from '@cloudflare/workers-types';\nimport type { SerializedTraceData } from '@sentry/core';\nimport {\n isObjectLike,\n captureException,\n continueTrace,\n isThenable,\n type Scope,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startNewTrace as startNewTraceCore,\n startSpan,\n} from '@sentry/core';\nimport type { CloudflareOptions } from './client';\nimport type { ExecutionContextCompat } from './executionContext';\nimport { flushAndDispose, getOriginalWaitUntil } from './flush';\nimport { ensureInstrumented } from './instrument';\nimport { init } from './sdk';\nimport { withInvocationIsolationScope } from './utils/invocationScope';\nimport { extractRpcMeta } from './utils/rpcMeta';\nimport { buildSpanLinks, getStoredSpanContext, storeSpanContext } from './utils/traceLinks';\n\n/** Extended DurableObjectState with originalStorage exposed by instrumentContext */\nexport interface InstrumentedDurableObjectState extends DurableObjectState {\n originalStorage?: DurableObjectStorage;\n}\n\n/**\n * Resolves uninstrumented DO storage for the current invocation.\n * Prefer `thisArg.ctx` (the live Durable Object instance) over the context captured at\n * construction time to avoid cross-DO I/O errors in the same isolate.\n */\nfunction resolveOriginalStorage(\n context: ExecutionContext | InstrumentedDurableObjectState | undefined,\n thisArg: unknown,\n): DurableObjectStorage | undefined {\n if (isObjectLike(thisArg) && 'ctx' in thisArg) {\n const doCtx = (thisArg as { ctx: InstrumentedDurableObjectState }).ctx;\n if (doCtx?.originalStorage) {\n return doCtx.originalStorage;\n }\n }\n\n if (context && 'originalStorage' in context && context.originalStorage) {\n return context.originalStorage;\n }\n\n return undefined;\n}\n\ntype MethodWrapperOptions = {\n spanName?: string;\n spanOp?: string;\n options: CloudflareOptions;\n context: ExecutionContext | InstrumentedDurableObjectState;\n /**\n * If true, starts a fresh trace instead of inheriting from a parent trace.\n * Useful for scheduled/independent invocations like alarms.\n *\n * If true, it also stores the current span context and links to the previous invocation's span.\n * Uses Durable Object storage to persist the link. The link is set asynchronously via `span.addLinks()`\n * in a `waitUntil` to avoid blocking.\n *\n * @default false\n */\n startNewTrace?: boolean;\n /**\n * The trace origin identifying which instrumentation created the span, e.g. `auto.faas.cloudflare.durable_object`.\n * Used both as the span's `sentry.origin` attribute and as the `mechanism.type` for captured exceptions.\n */\n origin: string;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type UncheckedMethod = (...args: any[]) => any;\ntype OriginalMethod = UncheckedMethod;\n\n/**\n * Wraps a method with Sentry error tracking and optional tracing.\n * Supports starting new traces and linking to previous invocations via Durable Object storage.\n *\n * @param wrapperOptions - The options for the wrapper.\n * @param handler - The method to wrap.\n * @param callback - The callback to call.\n * @param noMark - Whether to mark the method as instrumented.\n * @returns The wrapped method.\n */\nexport function wrapMethodWithSentry<T extends OriginalMethod>(\n wrapperOptions: MethodWrapperOptions,\n handler: T,\n callback?: (...args: Parameters<T>) => void,\n noMark?: true,\n): T {\n return ensureInstrumented(\n handler,\n original =>\n new Proxy(original, {\n apply(target, thisArg, rawArgs: Parameters<T>) {\n const { startNewTrace, origin } = wrapperOptions;\n\n // For RPC methods, extract Sentry trace context from the trailing argument.\n // The caller side (instrumentDurableObjectStub / JSRPC proxy) appends it;\n // we strip it here so the user's method never sees it.\n let args = rawArgs;\n let rpcMeta: SerializedTraceData | undefined;\n\n if (wrapperOptions.spanOp === 'rpc') {\n const extracted = extractRpcMeta(rawArgs);\n args = extracted.args;\n rpcMeta = extracted.rpcMeta;\n }\n\n const wrappedFunction = (scope: Scope): unknown | Promise<unknown> => {\n // In certain situations, the passed context can become undefined.\n // For example, for Astro while prerendering pages at build time.\n // see: https://github.com/getsentry/sentry-javascript/issues/13217\n const context: typeof wrapperOptions.context | undefined = wrapperOptions.context;\n\n // see: https://github.com/getsentry/sentry-javascript/issues/22328\n const waitUntil = context\n ? getOriginalWaitUntil(context as ExecutionContextCompat)?.bind(context)\n : undefined;\n const storage = resolveOriginalStorage(context, thisArg);\n\n let scopeClient = scope.getClient();\n // Check if client exists AND is still usable (transport not disposed)\n // This handles the case where a previous handler disposed the client\n // but the scope still holds a reference to it (e.g., alarm handlers in Durable Objects)\n // For startNewTrace, always create a fresh client\n if (startNewTrace || !scopeClient?.getTransport()) {\n const client = init({\n ...wrapperOptions.options,\n ctx: context as unknown as ExecutionContext | undefined,\n });\n scope.setClient(client);\n scopeClient = client;\n }\n\n const clientToDispose = scopeClient;\n const methodName = wrapperOptions.spanName || 'unknown';\n\n const teardown = async (): Promise<void> => {\n if (startNewTrace && storage) {\n storeSpanContext(storage, methodName);\n }\n await flushAndDispose(clientToDispose);\n };\n\n const onFulfilled = (res: unknown) => {\n waitUntil?.(teardown());\n return res;\n };\n\n const onRejected = (e: unknown) => {\n captureException(e, {\n mechanism: {\n type: origin,\n handled: false,\n },\n });\n waitUntil?.(teardown());\n throw e;\n };\n\n if (!wrapperOptions.spanName) {\n try {\n if (callback) {\n callback(...args);\n }\n\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(onFulfilled, onRejected);\n } else {\n return onFulfilled(result);\n }\n } catch (e) {\n return onRejected(e);\n }\n }\n\n const attributes = wrapperOptions.spanOp\n ? {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: wrapperOptions.spanOp,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin,\n }\n : {};\n\n const executeSpan = (): unknown => {\n return startSpan({ name: methodName, attributes }, span => {\n if (startNewTrace && storage) {\n const storedContext = getStoredSpanContext(storage, methodName);\n\n if (storedContext) {\n span.addLinks(buildSpanLinks(storedContext));\n // TODO: Remove this once EAP can store span links. We currently only set this attribute so that we\n // can obtain the previous trace information from the EAP store. Long-term, EAP will handle\n // span links and then we should remove this again. Also throwing in a TODO(v11), to remind us\n // to check this at v11 time :)\n const sampledFlag = storedContext.sampled ? '1' : '0';\n span.setAttribute(\n 'sentry.previous_trace',\n `${storedContext.traceId}-${storedContext.spanId}-${sampledFlag}`,\n );\n }\n }\n\n try {\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(onFulfilled, onRejected);\n } else {\n return onFulfilled(result);\n }\n } catch (e) {\n return onRejected(e);\n }\n });\n };\n\n if (rpcMeta) {\n return continueTrace(\n { sentryTrace: rpcMeta['sentry-trace'] || '', baggage: rpcMeta.baggage || '' },\n executeSpan,\n );\n }\n\n if (startNewTrace) {\n return startNewTraceCore(() => executeSpan());\n }\n\n return executeSpan();\n };\n\n return withInvocationIsolationScope(wrappedFunction);\n },\n }),\n noMark,\n );\n}\n"],"names":["startNewTrace","startNewTraceCore"],"mappings":";;;;;;;;AAgCA,SAAS,sBAAA,CACP,SACA,OAAA,EACkC;AAClC,EAAA,IAAI,YAAA,CAAa,OAAO,CAAA,IAAK,KAAA,IAAS,OAAA,EAAS;AAC7C,IAAA,MAAM,QAAS,OAAA,CAAoD,GAAA;AACnE,IAAA,IAAI,OAAO,eAAA,EAAiB;AAC1B,MAAA,OAAO,KAAA,CAAM,eAAA;AAAA,IACf;AAAA,EACF;AAEA,EAAA,IAAI,OAAA,IAAW,iBAAA,IAAqB,OAAA,IAAW,OAAA,CAAQ,eAAA,EAAiB;AACtE,IAAA,OAAO,OAAA,CAAQ,eAAA;AAAA,EACjB;AAEA,EAAA,OAAO,MAAA;AACT;AAuCO,SAAS,oBAAA,CACd,cAAA,EACA,OAAA,EACA,QAAA,EACA,MAAA,EACG;AACH,EAAA,OAAO,kBAAA;AAAA,IACL,OAAA;AAAA,IACA,CAAA,QAAA,KACE,IAAI,KAAA,CAAM,QAAA,EAAU;AAAA,MAClB,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAS,OAAA,EAAwB;AAC7C,QAAA,MAAM,iBAAEA,eAAA,EAAe,MAAA,EAAO,GAAI,cAAA;AAKlC,QAAA,IAAI,IAAA,GAAO,OAAA;AACX,QAAA,IAAI,OAAA;AAEJ,QAAA,IAAI,cAAA,CAAe,WAAW,KAAA,EAAO;AACnC,UAAA,MAAM,SAAA,GAAY,eAAe,OAAO,CAAA;AACxC,UAAA,IAAA,GAAO,SAAA,CAAU,IAAA;AACjB,UAAA,OAAA,GAAU,SAAA,CAAU,OAAA;AAAA,QACtB;AAEA,QAAA,MAAM,eAAA,GAAkB,CAAC,KAAA,KAA6C;AAIpE,UAAA,MAAM,UAAqD,cAAA,CAAe,OAAA;AAG1E,UAAA,MAAM,YAAY,OAAA,GACd,oBAAA,CAAqB,OAAiC,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,GACrE,MAAA;AACJ,UAAA,MAAM,OAAA,GAAU,sBAAA,CAAuB,OAAA,EAAS,OAAO,CAAA;AAEvD,UAAA,IAAI,WAAA,GAAc,MAAM,SAAA,EAAU;AAKlC,UAAA,IAAIA,eAAA,IAAiB,CAAC,WAAA,EAAa,YAAA,EAAa,EAAG;AACjD,YAAA,MAAM,SAAS,IAAA,CAAK;AAAA,cAClB,GAAG,cAAA,CAAe,OAAA;AAAA,cAClB,GAAA,EAAK;AAAA,aACN,CAAA;AACD,YAAA,KAAA,CAAM,UAAU,MAAM,CAAA;AACtB,YAAA,WAAA,GAAc,MAAA;AAAA,UAChB;AAEA,UAAA,MAAM,eAAA,GAAkB,WAAA;AACxB,UAAA,MAAM,UAAA,GAAa,eAAe,QAAA,IAAY,SAAA;AAE9C,UAAA,MAAM,WAAW,YAA2B;AAC1C,YAAA,IAAIA,mBAAiB,OAAA,EAAS;AAC5B,cAAA,gBAAA,CAAiB,SAAS,UAAU,CAAA;AAAA,YACtC;AACA,YAAA,MAAM,gBAAgB,eAAe,CAAA;AAAA,UACvC,CAAA;AAEA,UAAA,MAAM,WAAA,GAAc,CAAC,GAAA,KAAiB;AACpC,YAAA,SAAA,GAAY,UAAU,CAAA;AACtB,YAAA,OAAO,GAAA;AAAA,UACT,CAAA;AAEA,UAAA,MAAM,UAAA,GAAa,CAAC,CAAA,KAAe;AACjC,YAAA,gBAAA,CAAiB,CAAA,EAAG;AAAA,cAClB,SAAA,EAAW;AAAA,gBACT,IAAA,EAAM,MAAA;AAAA,gBACN,OAAA,EAAS;AAAA;AACX,aACD,CAAA;AACD,YAAA,SAAA,GAAY,UAAU,CAAA;AACtB,YAAA,MAAM,CAAA;AAAA,UACR,CAAA;AAEA,UAAA,IAAI,CAAC,eAAe,QAAA,EAAU;AAC5B,YAAA,IAAI;AACF,cAAA,IAAI,QAAA,EAAU;AACZ,gBAAA,QAAA,CAAS,GAAG,IAAI,CAAA;AAAA,cAClB;AAEA,cAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ,SAAS,IAAI,CAAA;AAElD,cAAA,IAAI,UAAA,CAAW,MAAM,CAAA,EAAG;AACtB,gBAAA,OAAO,MAAA,CAAO,IAAA,CAAK,WAAA,EAAa,UAAU,CAAA;AAAA,cAC5C,CAAA,MAAO;AACL,gBAAA,OAAO,YAAY,MAAM,CAAA;AAAA,cAC3B;AAAA,YACF,SAAS,CAAA,EAAG;AACV,cAAA,OAAO,WAAW,CAAC,CAAA;AAAA,YACrB;AAAA,UACF;AAEA,UAAA,MAAM,UAAA,GAAa,eAAe,MAAA,GAC9B;AAAA,YACE,CAAC,4BAA4B,GAAG,cAAA,CAAe,MAAA;AAAA,YAC/C,CAAC,gCAAgC,GAAG;AAAA,cAEtC,EAAC;AAEL,UAAA,MAAM,cAAc,MAAe;AACjC,YAAA,OAAO,UAAU,EAAE,IAAA,EAAM,UAAA,EAAY,UAAA,IAAc,CAAA,IAAA,KAAQ;AACzD,cAAA,IAAIA,mBAAiB,OAAA,EAAS;AAC5B,gBAAA,MAAM,aAAA,GAAgB,oBAAA,CAAqB,OAAA,EAAS,UAAU,CAAA;AAE9D,gBAAA,IAAI,aAAA,EAAe;AACjB,kBAAA,IAAA,CAAK,QAAA,CAAS,cAAA,CAAe,aAAa,CAAC,CAAA;AAK3C,kBAAA,MAAM,WAAA,GAAc,aAAA,CAAc,OAAA,GAAU,GAAA,GAAM,GAAA;AAClD,kBAAA,IAAA,CAAK,YAAA;AAAA,oBACH,uBAAA;AAAA,oBACA,GAAG,aAAA,CAAc,OAAO,IAAI,aAAA,CAAc,MAAM,IAAI,WAAW,CAAA;AAAA,mBACjE;AAAA,gBACF;AAAA,cACF;AAEA,cAAA,IAAI;AACF,gBAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ,SAAS,IAAI,CAAA;AAElD,gBAAA,IAAI,UAAA,CAAW,MAAM,CAAA,EAAG;AACtB,kBAAA,OAAO,MAAA,CAAO,IAAA,CAAK,WAAA,EAAa,UAAU,CAAA;AAAA,gBAC5C,CAAA,MAAO;AACL,kBAAA,OAAO,YAAY,MAAM,CAAA;AAAA,gBAC3B;AAAA,cACF,SAAS,CAAA,EAAG;AACV,gBAAA,OAAO,WAAW,CAAC,CAAA;AAAA,cACrB;AAAA,YACF,CAAC,CAAA;AAAA,UACH,CAAA;AAEA,UAAA,IAAI,OAAA,EAAS;AACX,YAAA,OAAO,aAAA;AAAA,cACL,EAAE,aAAa,OAAA,CAAQ,cAAc,KAAK,EAAA,EAAI,OAAA,EAAS,OAAA,CAAQ,OAAA,IAAW,EAAA,EAAG;AAAA,cAC7E;AAAA,aACF;AAAA,UACF;AAEA,UAAA,IAAIA,eAAA,EAAe;AACjB,YAAA,OAAOC,aAAA,CAAkB,MAAM,WAAA,EAAa,CAAA;AAAA,UAC9C;AAEA,UAAA,OAAO,WAAA,EAAY;AAAA,QACrB,CAAA;AAEA,QAAA,OAAO,6BAA6B,eAAe,CAAA;AAAA,MACrD;AAAA,KACD,CAAA;AAAA,IACH;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"wrapMethodWithSentry.js","sources":["../../../src/wrapMethodWithSentry.ts"],"sourcesContent":["import type { DurableObjectStorage } from '@cloudflare/workers-types';\nimport type { SerializedTraceData } from '@sentry/core';\nimport {\n isObjectLike,\n captureException,\n continueTrace,\n isThenable,\n type Scope,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startNewTrace as startNewTraceCore,\n startSpan,\n} from '@sentry/core';\nimport type { CloudflareOptions } from './client';\nimport type { ExecutionContextCompat } from './executionContext';\nimport { flushAndDispose, getOriginalWaitUntil } from './flush';\nimport { ensureInstrumented } from './instrument';\nimport { init } from './sdk';\nimport { getInvocationState, getInvocationWaitUntil } from './utils/invocationContext';\nimport { withInvocationIsolationScope } from './utils/invocationScope';\nimport { extractRpcMeta } from './utils/rpcMeta';\nimport { buildSpanLinks, getStoredSpanContext, storeSpanContext } from './utils/traceLinks';\n\n/** Extended DurableObjectState with originalStorage exposed by instrumentContext */\nexport interface InstrumentedDurableObjectState extends DurableObjectState {\n originalStorage?: DurableObjectStorage;\n}\n\n/**\n * Resolves uninstrumented DO storage for the current invocation.\n * Prefer `thisArg.ctx` (the live Durable Object instance) over the context captured at\n * construction time to avoid cross-DO I/O errors in the same isolate.\n */\nfunction resolveOriginalStorage(\n context: ExecutionContext | InstrumentedDurableObjectState | undefined,\n thisArg: unknown,\n): DurableObjectStorage | undefined {\n if (isObjectLike(thisArg) && 'ctx' in thisArg) {\n const doCtx = (thisArg as { ctx: InstrumentedDurableObjectState }).ctx;\n if (doCtx?.originalStorage) {\n return doCtx.originalStorage;\n }\n }\n\n if (context && 'originalStorage' in context && context.originalStorage) {\n return context.originalStorage;\n }\n\n return undefined;\n}\n\ntype MethodWrapperOptions = {\n /**\n * The span name, or a resolver called with the RPC metadata of the current call.\n * Returning `undefined` skips the span and only captures errors.\n */\n spanName?: string | ((rpcMeta: SerializedTraceData | undefined) => string | undefined);\n spanOp?: string;\n options: CloudflareOptions;\n context: ExecutionContext | InstrumentedDurableObjectState;\n /**\n * If true, starts a fresh trace instead of inheriting from a parent trace.\n * Useful for scheduled/independent invocations like alarms.\n *\n * If true, it also stores the current span context and links to the previous invocation's span.\n * Uses Durable Object storage to persist the link. The link is set asynchronously via `span.addLinks()`\n * in a `waitUntil` to avoid blocking.\n *\n * @default false\n */\n startNewTrace?: boolean;\n /**\n * The trace origin identifying which instrumentation created the span, e.g. `auto.faas.cloudflare.durable_object`.\n * Used both as the span's `sentry.origin` attribute and as the `mechanism.type` for captured exceptions.\n */\n origin: string;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type UncheckedMethod = (...args: any[]) => any;\ntype OriginalMethod = UncheckedMethod;\n\n/**\n * Wraps a method with Sentry error tracking and optional tracing.\n * Supports starting new traces and linking to previous invocations via Durable Object storage.\n *\n * @param wrapperOptions - The options for the wrapper.\n * @param handler - The method to wrap.\n * @param callback - The callback to call.\n * @param noMark - Whether to mark the method as instrumented.\n * @returns The wrapped method.\n */\nexport function wrapMethodWithSentry<T extends OriginalMethod>(\n wrapperOptions: MethodWrapperOptions,\n handler: T,\n callback?: (...args: Parameters<T>) => void,\n noMark?: true,\n): T {\n return ensureInstrumented(\n handler,\n original =>\n new Proxy(original, {\n apply(target, thisArg, rawArgs: Parameters<T>) {\n const { startNewTrace, origin } = wrapperOptions;\n\n // For RPC methods, extract Sentry trace context from the trailing argument.\n // The caller side (instrumentDurableObjectStub / JSRPC proxy) appends it;\n // we strip it here so the user's method never sees it.\n let args = rawArgs;\n let rpcMeta: SerializedTraceData | undefined;\n\n if (wrapperOptions.spanOp === 'rpc') {\n const extracted = extractRpcMeta(rawArgs);\n args = extracted.args;\n rpcMeta = extracted.rpcMeta;\n }\n\n const spanName =\n typeof wrapperOptions.spanName === 'function' ? wrapperOptions.spanName(rpcMeta) : wrapperOptions.spanName;\n\n const wrappedFunction = (scope: Scope): unknown | Promise<unknown> => {\n // In certain situations, the passed context can become undefined.\n // For example, for Astro while prerendering pages at build time.\n // see: https://github.com/getsentry/sentry-javascript/issues/13217\n const context: typeof wrapperOptions.context | undefined = wrapperOptions.context;\n\n // see: https://github.com/getsentry/sentry-javascript/issues/22328\n // Resolved once per invocation and cached on its state: reading `ctx.waitUntil`\n // on a native context is a runtime getter call.\n const invocationState = getInvocationState();\n const waitUntil = invocationState\n ? getInvocationWaitUntil(invocationState)\n : context\n ? getOriginalWaitUntil(context as ExecutionContextCompat)?.bind(context)\n : undefined;\n const storage = resolveOriginalStorage(context, thisArg);\n\n let scopeClient = scope.getClient();\n // Re-init when the scope has no usable client (a previous handler disposed it, e.g.\n // DO alarm handlers) or for `startNewTrace`, so the client points at this\n // invocation's context. With `cacheClient: true` `init()` returns the isolate's\n // cached client and only creates (and caches) a fresh one when nothing is cached yet;\n // `cacheClient: false` creates one per invocation.\n if (startNewTrace || !scopeClient?.getTransport()) {\n const client = init({\n ...wrapperOptions.options,\n ctx: context as unknown as ExecutionContext | undefined,\n });\n scope.setClient(client);\n scopeClient = client;\n }\n\n const clientToDispose = scopeClient;\n const methodName = spanName || 'unknown';\n\n const teardown = async (): Promise<void> => {\n if (startNewTrace && storage) {\n storeSpanContext(storage, methodName);\n }\n await flushAndDispose(clientToDispose);\n };\n\n const onFulfilled = (res: unknown) => {\n waitUntil?.(teardown());\n return res;\n };\n\n const captureAndRethrow = (e: unknown): never => {\n captureException(e, {\n mechanism: {\n type: origin,\n handled: false,\n },\n });\n throw e;\n };\n\n const onRejected = (e: unknown) => {\n try {\n return captureAndRethrow(e);\n } finally {\n waitUntil?.(teardown());\n }\n };\n\n if (!spanName) {\n try {\n if (callback) {\n callback(...args);\n }\n\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(onFulfilled, onRejected);\n } else {\n return onFulfilled(result);\n }\n } catch (e) {\n return onRejected(e);\n }\n }\n\n const attributes = wrapperOptions.spanOp\n ? {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: wrapperOptions.spanOp,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin,\n }\n : {};\n\n const executeSpan = (): unknown => {\n return startSpan({ name: methodName, attributes }, span => {\n if (startNewTrace && storage) {\n const storedContext = getStoredSpanContext(storage, methodName);\n\n if (storedContext) {\n span.addLinks(buildSpanLinks(storedContext));\n // TODO: Remove this once EAP can store span links. We currently only set this attribute so that we\n // can obtain the previous trace information from the EAP store. Long-term, EAP will handle\n // span links and then we should remove this again. Also throwing in a TODO(v11), to remind us\n // to check this at v11 time :)\n const sampledFlag = storedContext.sampled ? '1' : '0';\n span.setAttribute(\n 'sentry.previous_trace',\n `${storedContext.traceId}-${storedContext.spanId}-${sampledFlag}`,\n );\n }\n }\n\n try {\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(undefined, captureAndRethrow);\n }\n return result;\n } catch (e) {\n return captureAndRethrow(e);\n }\n });\n };\n\n // The boundary flush (teardown) must run after the method span has ended, so the\n // span is in the buffer when that flush drains it. Running it inside the span\n // callback (before `startSpan` ends the span) would leave the span for the eager\n // path and cost a second flush per invocation.\n const runWithTeardown = (run: () => unknown): unknown => {\n let out: unknown;\n try {\n out = run();\n } catch (e) {\n // Synchronous throw: `startSpan` already ended the span and rethrew.\n waitUntil?.(teardown());\n throw e;\n }\n if (isThenable(out)) {\n return out.then(\n res => {\n waitUntil?.(teardown());\n return res;\n },\n e => {\n waitUntil?.(teardown());\n throw e;\n },\n );\n }\n waitUntil?.(teardown());\n return out;\n };\n\n if (rpcMeta) {\n return runWithTeardown(() =>\n continueTrace(\n { sentryTrace: rpcMeta['sentry-trace'] || '', baggage: rpcMeta.baggage || '' },\n executeSpan,\n ),\n );\n }\n\n if (startNewTrace) {\n return runWithTeardown(() => startNewTraceCore(() => executeSpan()));\n }\n\n return runWithTeardown(executeSpan);\n };\n\n return withInvocationIsolationScope(\n wrappedFunction,\n wrapperOptions.context as ExecutionContextCompat | undefined,\n );\n },\n }),\n noMark,\n );\n}\n"],"names":["startNewTrace","startNewTraceCore"],"mappings":"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"}
@@ -0,0 +1,132 @@
1
+ import { SENTRY_SEGMENT_NAME_SOURCE, SENTRY_OP, NETWORK_PROTOCOL_NAME, NETWORK_PROTOCOL_VERSION } from '@sentry/conventions/attributes';
2
+ import { HTTP_SERVER } from '@sentry/conventions/op';
3
+ import { parseStringToURLObject, getHttpSpanDetailsFromUrlObject, hasSpanStreamingEnabled, HTTP_SPAN_NAME_FALLBACK, httpHeadersToSpanAttributes, winterCGHeadersToDict, captureException, continueTrace, startSpanManual, setHttpStatus } from '@sentry/core';
4
+ import { captureIncomingRequestBody } from './integrations/httpServer.js';
5
+ import { getOriginalWaitUntil, flushAndDispose } from './flush.js';
6
+ import { addCloudResourceContext, addRequest, addCultureContext } from './scope-utils.js';
7
+ import { getInvocationState, getInvocationWaitUntil } from './utils/invocationContext.js';
8
+ import { withInvocationIsolationScope } from './utils/invocationScope.js';
9
+ import { classifyResponseStreaming } from './utils/streaming.js';
10
+
11
+ function getRequestErrorMechanismType(context) {
12
+ return context && "storage" in context ? "auto.faas.cloudflare.durable_object" : "auto.http.cloudflare";
13
+ }
14
+ function wrapRequestHandlerWithInit(wrapperOptions, handler, initSdk) {
15
+ return withInvocationIsolationScope(async (isolationScope) => {
16
+ const { options, request, captureErrors = true } = wrapperOptions;
17
+ const context = wrapperOptions.context;
18
+ const invocationState = getInvocationState();
19
+ const waitUntil = invocationState ? getInvocationWaitUntil(invocationState) : context ? getOriginalWaitUntil(context).bind(context) : void 0;
20
+ const errorMechanismType = getRequestErrorMechanismType(context);
21
+ const client = initSdk({ ...options, ctx: context });
22
+ isolationScope.setClient(client);
23
+ const urlObject = parseStringToURLObject(request.url);
24
+ const [rawName, attributes] = getHttpSpanDetailsFromUrlObject(
25
+ urlObject,
26
+ "server",
27
+ "auto.http.cloudflare",
28
+ request,
29
+ void 0,
30
+ client
31
+ );
32
+ const name = attributes[SENTRY_SEGMENT_NAME_SOURCE] === "route" || !client || !hasSpanStreamingEnabled(client) ? rawName : request.method?.toUpperCase() || HTTP_SPAN_NAME_FALLBACK;
33
+ const contentLength = request.headers.get("content-length");
34
+ if (contentLength) {
35
+ attributes["http.request.body.size"] = parseInt(contentLength, 10);
36
+ }
37
+ const userAgentHeader = request.headers.get("user-agent");
38
+ if (userAgentHeader) {
39
+ attributes["user_agent.original"] = userAgentHeader;
40
+ }
41
+ if (client) {
42
+ Object.assign(
43
+ attributes,
44
+ httpHeadersToSpanAttributes(winterCGHeadersToDict(request.headers), client.getDataCollectionOptions())
45
+ );
46
+ }
47
+ attributes[SENTRY_OP] = HTTP_SERVER;
48
+ addCloudResourceContext(isolationScope);
49
+ addRequest(isolationScope, request);
50
+ if (request.cf) {
51
+ addCultureContext(isolationScope, request.cf);
52
+ if (typeof request.cf.httpProtocol === "string") {
53
+ const [protocolName, protocolVersion] = request.cf.httpProtocol.toLowerCase().split("/");
54
+ attributes[NETWORK_PROTOCOL_NAME] = protocolName;
55
+ attributes[NETWORK_PROTOCOL_VERSION] = protocolVersion;
56
+ }
57
+ }
58
+ if (request.method === "OPTIONS" || request.method === "HEAD") {
59
+ try {
60
+ return await handler();
61
+ } catch (e) {
62
+ if (captureErrors) {
63
+ captureException(e, { mechanism: { handled: false, type: errorMechanismType } });
64
+ }
65
+ throw e;
66
+ } finally {
67
+ waitUntil?.(flushAndDispose(client));
68
+ }
69
+ }
70
+ if (client) {
71
+ await captureIncomingRequestBody(client, request);
72
+ }
73
+ return continueTrace(
74
+ { sentryTrace: request.headers.get("sentry-trace") || "", baggage: request.headers.get("baggage") },
75
+ () => {
76
+ return startSpanManual({ name, attributes }, async (span) => {
77
+ let res;
78
+ try {
79
+ res = await handler();
80
+ setHttpStatus(span, res.status);
81
+ } catch (e) {
82
+ span.end();
83
+ if (captureErrors) {
84
+ captureException(e, { mechanism: { handled: false, type: errorMechanismType } });
85
+ }
86
+ waitUntil?.(flushAndDispose(client));
87
+ throw e;
88
+ }
89
+ const classification = classifyResponseStreaming(res);
90
+ if (classification.isStreaming && res.body) {
91
+ try {
92
+ let ended = false;
93
+ const endSpanOnce = () => {
94
+ if (ended) return;
95
+ ended = true;
96
+ span.end();
97
+ waitUntil?.(flushAndDispose(client));
98
+ };
99
+ const transform = new TransformStream({
100
+ flush() {
101
+ endSpanOnce();
102
+ },
103
+ cancel() {
104
+ endSpanOnce();
105
+ }
106
+ });
107
+ return new Response(res.body.pipeThrough(transform), {
108
+ status: res.status,
109
+ statusText: res.statusText,
110
+ headers: res.headers
111
+ });
112
+ } catch {
113
+ span.end();
114
+ waitUntil?.(flushAndDispose(client));
115
+ return res;
116
+ }
117
+ }
118
+ span.end();
119
+ if (res.status === 101) {
120
+ waitUntil?.(client?.flush(2e3));
121
+ } else {
122
+ waitUntil?.(flushAndDispose(client));
123
+ }
124
+ return res;
125
+ });
126
+ }
127
+ );
128
+ }, wrapperOptions.context);
129
+ }
130
+
131
+ export { wrapRequestHandlerWithInit };
132
+ //# sourceMappingURL=wrapRequestHandlerWithInit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrapRequestHandlerWithInit.js","sources":["../../../src/wrapRequestHandlerWithInit.ts"],"sourcesContent":["import type { CfProperties, IncomingRequestCfProperties } from '@cloudflare/workers-types';\nimport {\n NETWORK_PROTOCOL_NAME,\n NETWORK_PROTOCOL_VERSION,\n SENTRY_OP,\n SENTRY_SEGMENT_NAME_SOURCE,\n} from '@sentry/conventions/attributes';\nimport { HTTP_SERVER } from '@sentry/conventions/op';\nimport {\n captureException,\n continueTrace,\n getHttpSpanDetailsFromUrlObject,\n hasSpanStreamingEnabled,\n httpHeadersToSpanAttributes,\n HTTP_SPAN_NAME_FALLBACK,\n parseStringToURLObject,\n setHttpStatus,\n startSpanManual,\n winterCGHeadersToDict,\n} from '@sentry/core';\nimport { captureIncomingRequestBody } from './integrations/httpServer';\nimport type { CloudflareClient, CloudflareOptions } from './client';\nimport type { ExecutionContextCompat } from './executionContext';\nimport { flushAndDispose, getOriginalWaitUntil } from './flush';\nimport { addCloudResourceContext, addCultureContext, addRequest } from './scope-utils';\nimport { getInvocationState, getInvocationWaitUntil } from './utils/invocationContext';\nimport { withInvocationIsolationScope } from './utils/invocationScope';\nimport { classifyResponseStreaming } from './utils/streaming';\n\nfunction getRequestErrorMechanismType(context: ExecutionContextCompat | undefined): string {\n // Durable Object fetch handlers use DO state as context (see instrumentDurableObjectWithSentry)\n return context && 'storage' in context ? 'auto.faas.cloudflare.durable_object' : 'auto.http.cloudflare';\n}\n\nexport interface RequestHandlerWrapperOptions {\n options: CloudflareOptions;\n request: Request<unknown, IncomingRequestCfProperties<unknown> | CfProperties<unknown>>;\n context: ExecutionContextCompat | undefined;\n /**\n * If true, errors will be captured, rethrown and sent to Sentry.\n * Otherwise, errors are rethrown but not captured.\n *\n * You most likely don't want to set this to `false`, if you use `wrapRequestHandler` directly.\n * This is primarily meant as an escape hatch for higher-level SDKs relying on additional error\n * capturing mechanisms where this wrapper captures errors too early or too generally.\n *\n * @default true\n */\n captureErrors?: boolean;\n}\n\ntype InitSdk = (options: CloudflareOptions) => CloudflareClient | undefined;\n\n/**\n * Same as {@link wrapRequestHandler}, but with the SDK initialization injected.\n *\n * Wrappers that are only reachable from the main entry point — where `nodejs_compat` is a\n * requirement anyway — pass `init` from `sdk.ts` to get the full default integrations.\n *\n * @internal\n */\nexport function wrapRequestHandlerWithInit(\n wrapperOptions: RequestHandlerWrapperOptions,\n handler: (...args: unknown[]) => Response | Promise<Response>,\n initSdk: InitSdk,\n): Promise<Response> {\n return withInvocationIsolationScope(async isolationScope => {\n const { options, request, captureErrors = true } = wrapperOptions;\n const context = wrapperOptions.context;\n\n // The un-instrumented waitUntil, so flushAndDispose cannot deadlock on the flush\n // lock's own wrapper. Resolved once per invocation and cached on its state; reading\n // `ctx.waitUntil` on a native context is a runtime getter call.\n const invocationState = getInvocationState();\n const waitUntil = invocationState\n ? getInvocationWaitUntil(invocationState)\n : context\n ? getOriginalWaitUntil(context).bind(context)\n : undefined;\n const errorMechanismType = getRequestErrorMechanismType(context);\n\n const client = initSdk({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n const urlObject = parseStringToURLObject(request.url);\n const [rawName, attributes] = getHttpSpanDetailsFromUrlObject(\n urlObject,\n 'server',\n 'auto.http.cloudflare',\n request,\n undefined,\n client,\n );\n // With span streaming, span names have to be low cardinality, so we can't fall back to the URL.\n // A `route` source means the name already is (e.g. the `/` path), so it is kept as-is.\n const name =\n attributes[SENTRY_SEGMENT_NAME_SOURCE] === 'route' || !client || !hasSpanStreamingEnabled(client)\n ? rawName\n : request.method?.toUpperCase() || HTTP_SPAN_NAME_FALLBACK;\n\n const contentLength = request.headers.get('content-length');\n if (contentLength) {\n attributes['http.request.body.size'] = parseInt(contentLength, 10);\n }\n\n const userAgentHeader = request.headers.get('user-agent');\n if (userAgentHeader) {\n attributes['user_agent.original'] = userAgentHeader;\n }\n\n if (client) {\n Object.assign(\n attributes,\n httpHeadersToSpanAttributes(winterCGHeadersToDict(request.headers), client.getDataCollectionOptions()),\n );\n }\n\n attributes[SENTRY_OP] = HTTP_SERVER;\n\n addCloudResourceContext(isolationScope);\n addRequest(isolationScope, request);\n if (request.cf) {\n addCultureContext(isolationScope, request.cf);\n\n if (typeof request.cf.httpProtocol === 'string') {\n const [protocolName, protocolVersion] = request.cf.httpProtocol.toLowerCase().split('/');\n attributes[NETWORK_PROTOCOL_NAME] = protocolName;\n attributes[NETWORK_PROTOCOL_VERSION] = protocolVersion;\n }\n }\n\n // Do not capture spans for OPTIONS and HEAD requests\n if (request.method === 'OPTIONS' || request.method === 'HEAD') {\n try {\n return await handler();\n } catch (e) {\n if (captureErrors) {\n captureException(e, { mechanism: { handled: false, type: errorMechanismType } });\n }\n throw e;\n } finally {\n waitUntil?.(flushAndDispose(client));\n }\n }\n\n if (client) {\n await captureIncomingRequestBody(client, request);\n }\n\n return continueTrace(\n { sentryTrace: request.headers.get('sentry-trace') || '', baggage: request.headers.get('baggage') },\n () => {\n // Note: This span will not have a duration unless I/O happens in the handler. This is\n // because of how the cloudflare workers runtime works.\n // See: https://developers.cloudflare.com/workers/runtime-apis/performance/\n\n // Use startSpanManual to control when span ends (needed for streaming responses)\n return startSpanManual({ name, attributes }, async span => {\n let res: Response;\n\n try {\n res = await handler();\n setHttpStatus(span, res.status);\n\n // After the handler runs, the span name might have been updated by nested instrumentation\n // (e.g., Remix parameterizing routes). The span should already have the correct name\n // from that instrumentation, so we don't need to do anything here.\n } catch (e) {\n span.end();\n if (captureErrors) {\n captureException(e, { mechanism: { handled: false, type: errorMechanismType } });\n }\n waitUntil?.(flushAndDispose(client));\n throw e;\n }\n\n // Classify response to detect actual streaming\n const classification = classifyResponseStreaming(res);\n\n if (classification.isStreaming && res.body) {\n try {\n let ended = false;\n\n const endSpanOnce = (): void => {\n if (ended) return;\n\n ended = true;\n span.end();\n waitUntil?.(flushAndDispose(client));\n };\n\n const transform = new TransformStream({\n flush() {\n // Source stream completed normally.\n endSpanOnce();\n },\n cancel() {\n // Client disconnected (or downstream cancelled). The `cancel`\n // is being called while the response is still considered\n // active, so this is a safe place to end the span.\n endSpanOnce();\n },\n });\n\n return new Response(res.body.pipeThrough(transform), {\n status: res.status,\n statusText: res.statusText,\n headers: res.headers,\n });\n } catch {\n span.end();\n waitUntil?.(flushAndDispose(client));\n return res;\n }\n }\n\n // Non-streaming response - end span immediately and return original\n span.end();\n\n // Don't dispose for protocol upgrades (101 Switching Protocols) - the connection stays alive.\n // This includes WebSocket upgrades where webSocketMessage/webSocketClose handlers\n // will still be called and may need the client to capture errors.\n if (res.status === 101) {\n waitUntil?.(client?.flush(2000));\n } else {\n waitUntil?.(flushAndDispose(client));\n }\n return res;\n });\n },\n );\n }, wrapperOptions.context);\n}\n"],"names":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
- import { dedupeIntegration, eventFiltersIntegration, functionToStringIntegration, conversationIdIntegration, linkedErrorsIntegration, requestDataIntegration, consoleIntegration, GLOBAL_OBJ, getIntegrationsToSetup, stackParserFromStackParserOptions, initAndBind } from '@sentry/core';
1
+ import { dedupeIntegration, eventFiltersIntegration, functionToStringIntegration, conversationIdIntegration, linkedErrorsIntegration, requestDataIntegration, consoleIntegration, GLOBAL_OBJ, debug, getCurrentScope, setCurrentClient, getIntegrationsToSetup, stackParserFromStackParserOptions, initAndBind } from '@sentry/core';
2
2
  import { CloudflareClient } from './client.js';
3
3
  import { makeFlushLock } from './flush.js';
4
+ import { getCachedClient, cacheClient } from './clientCache.js';
5
+ import { DEBUG_BUILD } from './debug-build.js';
4
6
  import { fetchIntegration } from './integrations/fetch.js';
5
7
  import { httpServerIntegration } from './integrations/httpServer.js';
6
- import { setupOpenTelemetryTracer } from './opentelemetry/tracer.js';
7
8
  import { makeCloudflareTransport } from './transport.js';
8
9
  import { defaultStackParser } from './vendor/stacktrace.js';
9
10
 
@@ -34,25 +35,36 @@ function getBaseDefaultIntegrations(options) {
34
35
  ];
35
36
  }
36
37
  function initWithDefaultIntegrations(options, getDefaultIntegrationsImpl) {
38
+ const cached = getCachedClient();
39
+ const cacheEnabled = options.cacheClient !== false;
40
+ if (cacheEnabled && cached) {
41
+ if (DEBUG_BUILD && cached.getOptions().dsn !== options.dsn) {
42
+ debug.warn(
43
+ "[Sentry] init() was called with a different DSN than the cached client of this isolate; the cached client keeps its DSN. Pass `cacheClient: false` for per-invocation options."
44
+ );
45
+ }
46
+ getCurrentScope().update(options.initialScope);
47
+ setCurrentClient(cached);
48
+ return cached;
49
+ }
37
50
  if (options.defaultIntegrations === void 0) {
38
51
  options.defaultIntegrations = getDefaultIntegrationsImpl(options);
39
52
  }
40
- const flushLock = options.ctx ? makeFlushLock(options.ctx) : void 0;
53
+ const invocationContext = options.ctx;
54
+ const flushLock = !cacheEnabled && invocationContext ? makeFlushLock(invocationContext) : void 0;
41
55
  delete options.ctx;
42
56
  const clientOptions = {
43
57
  ...options,
58
+ cacheClient: cacheEnabled,
44
59
  stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),
45
60
  integrations: getIntegrationsToSetup(options),
46
61
  transport: options.transport || makeCloudflareTransport,
47
- // Like most Node-based SDKs, Cloudflare defaults to running without a Sentry OpenTelemetry tracer
48
- // provider. Scope isolation is handled by the entrypoint wrappers' AsyncLocalStorage strategy.
49
- enableOpenTelemetrySetup: options.enableOpenTelemetrySetup ?? false,
50
62
  flushLock
51
63
  };
52
- if (clientOptions.enableOpenTelemetrySetup) {
53
- setupOpenTelemetryTracer();
54
- }
55
64
  const client = initAndBind(CloudflareClient, clientOptions);
65
+ if (cacheEnabled && client) {
66
+ cacheClient(client);
67
+ }
56
68
  client.on("orchestrion.module-injected", (moduleName) => {
57
69
  const factory = GLOBAL_OBJ.__SENTRY_ORCHESTRION__?.integrations?.get(moduleName);
58
70
  if (factory) {
@@ -1 +1 @@
1
- {"version":3,"file":"baseSdk.js","sources":["../../../src/baseSdk.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport {\n consoleIntegration,\n conversationIdIntegration,\n dedupeIntegration,\n eventFiltersIntegration,\n functionToStringIntegration,\n getIntegrationsToSetup,\n GLOBAL_OBJ,\n initAndBind,\n linkedErrorsIntegration,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport type { CloudflareClientOptions, CloudflareOptions } from './client';\nimport { CloudflareClient } from './client';\nimport { makeFlushLock } from './flush';\nimport { fetchIntegration } from './integrations/fetch';\nimport { httpServerIntegration } from './integrations/httpServer';\nimport { INTEGRATION_NAME as SPOTLIGHT_INTEGRATION_NAME, spotlightIntegration } from './integrations/spotlight';\nimport { setupOpenTelemetryTracer } from './opentelemetry/tracer';\nimport { makeCloudflareTransport } from './transport';\nimport { defaultStackParser } from './vendor/stacktrace';\n\n/**\n * Instantiate the channel-subscriber factories the `@sentry/cloudflare/vite`\n * plugin registered on the global marker. The plugin splices a small snippet\n * into each instrumented module that `.set`s its factory here (keyed by module\n * name), so the marker holds one factory per package actually bundled.\n *\n * The marker is read directly instead of importing the factories, so a worker\n * built without the plugin — where the channels never fire — ships none of this\n * code.\n * TODO(v11): Use `@sentry/server-utils/orchestrion` once we move to `nodejs_compat` by default.\n */\nfunction getRegisteredChannelIntegrations(): Integration[] {\n const registered = GLOBAL_OBJ.__SENTRY_ORCHESTRION__?.integrations;\n\n return registered ? [...registered.values()].map(factory => factory()) : [];\n}\n\n/**\n * Get the default integrations that run on any Workers-compatible runtime, i.e. without the\n * `nodejs_compat` compatibility flag.\n *\n * `getDefaultIntegrations` in `sdk.ts` extends this set with the integrations that do depend on\n * Node.js APIs. Keeping the two apart is what allows `wrapRequestHandler` to stay usable on runtimes\n * that cannot enable `nodejs_compat`, such as Shopify Oxygen.\n */\nexport function getBaseDefaultIntegrations(options: CloudflareOptions): Integration[] {\n return [\n // The Dedupe integration should not be used in workflows because we want to\n // capture all step failures, even if they are the same error.\n ...(options.enableDedupe === false ? [] : [dedupeIntegration()]),\n eventFiltersIntegration(),\n functionToStringIntegration(),\n conversationIdIntegration(),\n linkedErrorsIntegration(),\n fetchIntegration(),\n httpServerIntegration(),\n requestDataIntegration(),\n consoleIntegration(),\n // The orchestrion diagnostics-channel subscribers (mysql, pg, …). The\n // `@sentry/cloudflare/vite` plugin injects the channels at build time and,\n // next to each, a snippet that registers the matching subscriber factory on\n // the global marker. Read from there instead of importing them so bundles\n // built without the plugin — where the channels would never fire — don't\n // ship the code.\n ...getRegisteredChannelIntegrations(),\n ];\n}\n\n/**\n * Initializes the Cloudflare SDK with the passed default integrations.\n *\n * The default integrations are injected rather than imported so that this module stays free of\n * Node.js-only code. `request.ts` — which backs both `wrapRequestHandler` and the\n * `@sentry/cloudflare/request` entry point, and therefore has to work on runtimes without the\n * `nodejs_compat` compatibility flag — creates its client from here instead of from `sdk.ts`.\n */\nexport function initWithDefaultIntegrations(\n options: CloudflareOptions,\n getDefaultIntegrationsImpl: (options: CloudflareOptions) => Integration[],\n): CloudflareClient | undefined {\n if (options.defaultIntegrations === undefined) {\n options.defaultIntegrations = getDefaultIntegrationsImpl(options);\n }\n\n const flushLock = options.ctx ? makeFlushLock(options.ctx) : undefined;\n delete options.ctx;\n\n const clientOptions: CloudflareClientOptions = {\n ...options,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n integrations: getIntegrationsToSetup(options),\n transport: options.transport || makeCloudflareTransport,\n // Like most Node-based SDKs, Cloudflare defaults to running without a Sentry OpenTelemetry tracer\n // provider. Scope isolation is handled by the entrypoint wrappers' AsyncLocalStorage strategy.\n enableOpenTelemetrySetup: options.enableOpenTelemetrySetup ?? false,\n flushLock,\n };\n\n /*! rollup-include-development-only */\n if (options.spotlight && !clientOptions.integrations.some(({ name }) => name === SPOTLIGHT_INTEGRATION_NAME)) {\n clientOptions.integrations.push(\n spotlightIntegration({\n sidecarUrl: typeof options.spotlight === 'string' ? options.spotlight : undefined,\n }),\n );\n }\n /*! rollup-include-development-only-end */\n\n // Opt-in only: when `enableOpenTelemetrySetup` is `true`, set up a custom trace provider so spans\n // emitted via `@opentelemetry/api` are captured by Sentry. See the option's docs for the caveats.\n if (clientOptions.enableOpenTelemetrySetup) {\n setupOpenTelemetryTracer();\n }\n\n const client = initAndBind(CloudflareClient, clientOptions) as CloudflareClient;\n\n // An instrumented module that first evaluates AFTER this init (e.g. a driver\n // lazily required on first use) stores its subscriber factory on the global\n // marker too late for the default-integrations snapshot above. Its injected\n // snippet emits this event right after storing the factory, so install the\n // integration on the live client here. `addIntegration` dedupes by\n // integration name, so already-installed integrations are no-ops.\n client.on('orchestrion.module-injected', moduleName => {\n const factory = GLOBAL_OBJ.__SENTRY_ORCHESTRION__?.integrations?.get(moduleName);\n if (factory) {\n client.addIntegration(factory());\n }\n });\n\n return client;\n}\n\n/**\n * Initializes the Cloudflare SDK with only the default integrations from\n * {@link getBaseDefaultIntegrations}, i.e. those that work without the `nodejs_compat`\n * compatibility flag.\n */\nexport function initBaseSdk(options: CloudflareOptions): CloudflareClient | undefined {\n return initWithDefaultIntegrations(options, getBaseDefaultIntegrations);\n}\n"],"names":[],"mappings":";;;;;;;;;AAmCA,SAAS,gCAAA,GAAkD;AACzD,EAAA,MAAM,UAAA,GAAa,WAAW,sBAAA,EAAwB,YAAA;AAEtD,EAAA,OAAO,UAAA,GAAa,CAAC,GAAG,UAAA,CAAW,MAAA,EAAQ,CAAA,CAAE,GAAA,CAAI,CAAA,OAAA,KAAW,OAAA,EAAS,CAAA,GAAI,EAAC;AAC5E;AAUO,SAAS,2BAA2B,OAAA,EAA2C;AACpF,EAAA,OAAO;AAAA;AAAA;AAAA,IAGL,GAAI,QAAQ,YAAA,KAAiB,KAAA,GAAQ,EAAC,GAAI,CAAC,mBAAmB,CAAA;AAAA,IAC9D,uBAAA,EAAwB;AAAA,IACxB,2BAAA,EAA4B;AAAA,IAC5B,yBAAA,EAA0B;AAAA,IAC1B,uBAAA,EAAwB;AAAA,IACxB,gBAAA,EAAiB;AAAA,IACjB,qBAAA,EAAsB;AAAA,IACtB,sBAAA,EAAuB;AAAA,IACvB,kBAAA,EAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOnB,GAAG,gCAAA;AAAiC,GACtC;AACF;AAUO,SAAS,2BAAA,CACd,SACA,0BAAA,EAC8B;AAC9B,EAAA,IAAI,OAAA,CAAQ,wBAAwB,MAAA,EAAW;AAC7C,IAAA,OAAA,CAAQ,mBAAA,GAAsB,2BAA2B,OAAO,CAAA;AAAA,EAClE;AAEA,EAAA,MAAM,YAAY,OAAA,CAAQ,GAAA,GAAM,aAAA,CAAc,OAAA,CAAQ,GAAG,CAAA,GAAI,MAAA;AAC7D,EAAA,OAAO,OAAA,CAAQ,GAAA;AAEf,EAAA,MAAM,aAAA,GAAyC;AAAA,IAC7C,GAAG,OAAA;AAAA,IACH,WAAA,EAAa,iCAAA,CAAkC,OAAA,CAAQ,WAAA,IAAe,kBAAkB,CAAA;AAAA,IACxF,YAAA,EAAc,uBAAuB,OAAO,CAAA;AAAA,IAC5C,SAAA,EAAW,QAAQ,SAAA,IAAa,uBAAA;AAAA;AAAA;AAAA,IAGhC,wBAAA,EAA0B,QAAQ,wBAAA,IAA4B,KAAA;AAAA,IAC9D;AAAA,GACF;AAIA,EAAA,IAAI,cAAc,wBAAA,EAA0B;AAC1C,IAAA,wBAAA,EAAyB;AAAA,EAC3B;AAEA,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,gBAAA,EAAkB,aAAa,CAAA;AAQ1D,EAAA,MAAA,CAAO,EAAA,CAAG,+BAA+B,CAAA,UAAA,KAAc;AACrD,IAAA,MAAM,OAAA,GAAU,UAAA,CAAW,sBAAA,EAAwB,YAAA,EAAc,IAAI,UAAU,CAAA;AAC/E,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAA,CAAO,cAAA,CAAe,SAAS,CAAA;AAAA,IACjC;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,YAAY,OAAA,EAA0D;AACpF,EAAA,OAAO,2BAAA,CAA4B,SAAS,0BAA0B,CAAA;AACxE;;;;"}
1
+ {"version":3,"file":"baseSdk.js","sources":["../../../src/baseSdk.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { debug, getCurrentScope, setCurrentClient } from '@sentry/core';\nimport {\n consoleIntegration,\n conversationIdIntegration,\n dedupeIntegration,\n eventFiltersIntegration,\n functionToStringIntegration,\n getIntegrationsToSetup,\n GLOBAL_OBJ,\n initAndBind,\n linkedErrorsIntegration,\n requestDataIntegration,\n stackParserFromStackParserOptions,\n} from '@sentry/core';\nimport type { CloudflareClientOptions, CloudflareOptions } from './client';\nimport { CloudflareClient } from './client';\nimport { makeFlushLock } from './flush';\nimport { cacheClient, getCachedClient } from './clientCache';\nimport { DEBUG_BUILD } from './debug-build';\nimport { fetchIntegration } from './integrations/fetch';\nimport { httpServerIntegration } from './integrations/httpServer';\nimport { INTEGRATION_NAME as SPOTLIGHT_INTEGRATION_NAME, spotlightIntegration } from './integrations/spotlight';\nimport { makeCloudflareTransport } from './transport';\nimport { defaultStackParser } from './vendor/stacktrace';\n\n/**\n * Instantiate the channel-subscriber factories the `@sentry/cloudflare/vite`\n * plugin registered on the global marker. The plugin splices a small snippet\n * into each instrumented module that `.set`s its factory here (keyed by module\n * name), so the marker holds one factory per package actually bundled.\n *\n * The marker is read directly instead of importing the factories, so a worker\n * built without the plugin — where the channels never fire — ships none of this\n * code.\n */\nfunction getRegisteredChannelIntegrations(): Integration[] {\n const registered = GLOBAL_OBJ.__SENTRY_ORCHESTRION__?.integrations;\n\n return registered ? [...registered.values()].map(factory => factory()) : [];\n}\n\n/**\n * Get the default integrations that run on any Workers-compatible runtime, i.e. without the\n * `nodejs_compat` compatibility flag.\n *\n * `getDefaultIntegrations` in `sdk.ts` extends this set with the integrations that do depend on\n * Node.js APIs. Keeping the two apart is what allows `wrapRequestHandler` to stay usable on runtimes\n * that cannot enable `nodejs_compat`, such as Shopify Oxygen.\n */\nexport function getBaseDefaultIntegrations(options: CloudflareOptions): Integration[] {\n return [\n // The Dedupe integration should not be used in workflows because we want to\n // capture all step failures, even if they are the same error.\n ...(options.enableDedupe === false ? [] : [dedupeIntegration()]),\n eventFiltersIntegration(),\n functionToStringIntegration(),\n conversationIdIntegration(),\n linkedErrorsIntegration(),\n fetchIntegration(),\n httpServerIntegration(),\n requestDataIntegration(),\n consoleIntegration(),\n // The orchestrion diagnostics-channel subscribers (mysql, pg, …). The\n // `@sentry/cloudflare/vite` plugin injects the channels at build time and,\n // next to each, a snippet that registers the matching subscriber factory on\n // the global marker. Read from there instead of importing them so bundles\n // built without the plugin — where the channels would never fire — don't\n // ship the code.\n ...getRegisteredChannelIntegrations(),\n ];\n}\n\n/**\n * Initializes the Cloudflare SDK with the passed default integrations.\n *\n * The default integrations are injected rather than imported so that this module stays free of\n * Node.js-only code. `request.ts` — which backs both `wrapRequestHandler` and the\n * `@sentry/cloudflare/request` entry point, and therefore has to work on runtimes without the\n * `nodejs_compat` compatibility flag — creates its client from here instead of from `sdk.ts`.\n *\n * The client is cached and reused across invocations within the same isolate,\n * unless `cacheClient: false` is passed. This avoids the\n * per-invocation cost of constructing a new client, and it is what makes\n * Durable Object telemetry reliable: a per-invocation client is disposed at\n * the end of the handler, and in a Durable Object there is no `waitUntil`\n * boundary that reliably extends execution, so spans/events that end after\n * disposal would otherwise be lost.\n */\nexport function initWithDefaultIntegrations(\n options: CloudflareOptions,\n getDefaultIntegrationsImpl: (options: CloudflareOptions) => Integration[],\n): CloudflareClient | undefined {\n const cached = getCachedClient();\n const cacheEnabled = options.cacheClient !== false;\n\n if (cacheEnabled && cached) {\n if (DEBUG_BUILD && cached.getOptions().dsn !== options.dsn) {\n debug.warn(\n '[Sentry] init() was called with a different DSN than the cached client of this isolate; the cached client keeps its DSN. Pass `cacheClient: false` for per-invocation options.',\n );\n }\n getCurrentScope().update(options.initialScope);\n setCurrentClient(cached);\n return cached;\n }\n\n if (options.defaultIntegrations === undefined) {\n options.defaultIntegrations = getDefaultIntegrationsImpl(options);\n }\n\n // A cached client outlives any single invocation, so binding it to one\n // invocation's flush lock would make later flushes wait on that invocation's\n // waitUntil work forever. Eager delivery replaces the flush lock's purpose.\n const invocationContext = options.ctx;\n const flushLock = !cacheEnabled && invocationContext ? makeFlushLock(invocationContext) : undefined;\n delete options.ctx;\n\n const clientOptions: CloudflareClientOptions = {\n ...options,\n cacheClient: cacheEnabled,\n stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser),\n integrations: getIntegrationsToSetup(options),\n transport: options.transport || makeCloudflareTransport,\n flushLock,\n };\n\n /*! rollup-include-development-only */\n if (options.spotlight && !clientOptions.integrations.some(({ name }) => name === SPOTLIGHT_INTEGRATION_NAME)) {\n clientOptions.integrations.push(\n spotlightIntegration({\n sidecarUrl: typeof options.spotlight === 'string' ? options.spotlight : undefined,\n }),\n );\n }\n /*! rollup-include-development-only-end */\n\n const client = initAndBind(CloudflareClient, clientOptions) as CloudflareClient;\n\n if (cacheEnabled && client) {\n cacheClient(client);\n }\n\n // An instrumented module that first evaluates AFTER this init (e.g. a driver\n // lazily required on first use) stores its subscriber factory on the global\n // marker too late for the default-integrations snapshot above. Its injected\n // snippet emits this event right after storing the factory, so install the\n // integration on the live client here. `addIntegration` dedupes by\n // integration name, so already-installed integrations are no-ops.\n client.on('orchestrion.module-injected', moduleName => {\n const factory = GLOBAL_OBJ.__SENTRY_ORCHESTRION__?.integrations?.get(moduleName);\n if (factory) {\n client.addIntegration(factory());\n }\n });\n\n return client;\n}\n\n/**\n * Initializes the Cloudflare SDK with only the default integrations from\n * {@link getBaseDefaultIntegrations}, i.e. those that work without the `nodejs_compat`\n * compatibility flag.\n */\nexport function initBaseSdk(options: CloudflareOptions): CloudflareClient | undefined {\n return initWithDefaultIntegrations(options, getBaseDefaultIntegrations);\n}\n"],"names":[],"mappings":";;;;;;;;;;AAoCA,SAAS,gCAAA,GAAkD;AACzD,EAAA,MAAM,UAAA,GAAa,WAAW,sBAAA,EAAwB,YAAA;AAEtD,EAAA,OAAO,UAAA,GAAa,CAAC,GAAG,UAAA,CAAW,MAAA,EAAQ,CAAA,CAAE,GAAA,CAAI,CAAA,OAAA,KAAW,OAAA,EAAS,CAAA,GAAI,EAAC;AAC5E;AAUO,SAAS,2BAA2B,OAAA,EAA2C;AACpF,EAAA,OAAO;AAAA;AAAA;AAAA,IAGL,GAAI,QAAQ,YAAA,KAAiB,KAAA,GAAQ,EAAC,GAAI,CAAC,mBAAmB,CAAA;AAAA,IAC9D,uBAAA,EAAwB;AAAA,IACxB,2BAAA,EAA4B;AAAA,IAC5B,yBAAA,EAA0B;AAAA,IAC1B,uBAAA,EAAwB;AAAA,IACxB,gBAAA,EAAiB;AAAA,IACjB,qBAAA,EAAsB;AAAA,IACtB,sBAAA,EAAuB;AAAA,IACvB,kBAAA,EAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOnB,GAAG,gCAAA;AAAiC,GACtC;AACF;AAkBO,SAAS,2BAAA,CACd,SACA,0BAAA,EAC8B;AAC9B,EAAA,MAAM,SAAS,eAAA,EAAgB;AAC/B,EAAA,MAAM,YAAA,GAAe,QAAQ,WAAA,KAAgB,KAAA;AAE7C,EAAA,IAAI,gBAAgB,MAAA,EAAQ;AAC1B,IAAA,IAAI,eAAe,MAAA,CAAO,UAAA,EAAW,CAAE,GAAA,KAAQ,QAAQ,GAAA,EAAK;AAC1D,MAAA,KAAA,CAAM,IAAA;AAAA,QACJ;AAAA,OACF;AAAA,IACF;AACA,IAAA,eAAA,EAAgB,CAAE,MAAA,CAAO,OAAA,CAAQ,YAAY,CAAA;AAC7C,IAAA,gBAAA,CAAiB,MAAM,CAAA;AACvB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI,OAAA,CAAQ,wBAAwB,MAAA,EAAW;AAC7C,IAAA,OAAA,CAAQ,mBAAA,GAAsB,2BAA2B,OAAO,CAAA;AAAA,EAClE;AAKA,EAAA,MAAM,oBAAoB,OAAA,CAAQ,GAAA;AAClC,EAAA,MAAM,YAAY,CAAC,YAAA,IAAgB,iBAAA,GAAoB,aAAA,CAAc,iBAAiB,CAAA,GAAI,MAAA;AAC1F,EAAA,OAAO,OAAA,CAAQ,GAAA;AAEf,EAAA,MAAM,aAAA,GAAyC;AAAA,IAC7C,GAAG,OAAA;AAAA,IACH,WAAA,EAAa,YAAA;AAAA,IACb,WAAA,EAAa,iCAAA,CAAkC,OAAA,CAAQ,WAAA,IAAe,kBAAkB,CAAA;AAAA,IACxF,YAAA,EAAc,uBAAuB,OAAO,CAAA;AAAA,IAC5C,SAAA,EAAW,QAAQ,SAAA,IAAa,uBAAA;AAAA,IAChC;AAAA,GACF;AAEA,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,gBAAA,EAAkB,aAAa,CAAA;AAE1D,EAAA,IAAI,gBAAgB,MAAA,EAAQ;AAC1B,IAAA,WAAA,CAAY,MAAM,CAAA;AAAA,EACpB;AAQA,EAAA,MAAA,CAAO,EAAA,CAAG,+BAA+B,CAAA,UAAA,KAAc;AACrD,IAAA,MAAM,OAAA,GAAU,UAAA,CAAW,sBAAA,EAAwB,YAAA,EAAc,IAAI,UAAU,CAAA;AAC/E,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAA,CAAO,cAAA,CAAe,SAAS,CAAA;AAAA,IACjC;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,YAAY,OAAA,EAA0D;AACpF,EAAA,OAAO,2BAAA,CAA4B,SAAS,0BAA0B,CAAA;AACxE;;;;"}
@@ -1,5 +1,7 @@
1
- import { ServerRuntimeClient, applySdkMetadata, debug, spanIsSampled, _INTERNAL_clearAiProviderSkips } from '@sentry/core';
1
+ import { applySdkMetadata, debug, spanIsSampled, _INTERNAL_clearAiProviderSkips, _INTERNAL_flushLogsBuffer, _INTERNAL_flushMetricsBuffer } from '@sentry/core';
2
+ import { ServerRuntimeClient } from '@sentry/core/server';
2
3
  import { DEBUG_BUILD } from './debug-build.js';
4
+ import { getInvocationState, getInvocationWaitUntil } from './utils/invocationContext.js';
3
5
 
4
6
  class CloudflareClient extends ServerRuntimeClient {
5
7
  /**
@@ -24,30 +26,36 @@ class CloudflareClient extends ServerRuntimeClient {
24
26
  this._resolveSpanCompletion = null;
25
27
  this._unsubscribeSpanStart = null;
26
28
  this._unsubscribeSpanEnd = null;
29
+ // True while a boundary `flush()` is draining; envelopes created by that drain ride it
30
+ // and must not each start their own eager transport flush.
31
+ this._inBoundaryFlush = false;
27
32
  this._flushLock = flushLock;
28
- this._unsubscribeSpanStart = this.on("spanStart", (span) => {
29
- const spanId = span.spanContext().spanId;
30
- DEBUG_BUILD && debug.log("[CloudflareClient] Span started:", spanId);
31
- if (!spanIsSampled(span)) {
32
- return;
33
- }
34
- this._pendingSpans.add(spanId);
35
- if (!this._spanCompletionPromise) {
36
- this._spanCompletionPromise = new Promise((resolve) => {
37
- this._resolveSpanCompletion = resolve;
38
- });
39
- }
40
- });
41
- this._unsubscribeSpanEnd = this.on("spanEnd", (span) => {
42
- const spanId = span.spanContext().spanId;
43
- DEBUG_BUILD && debug.log("[CloudflareClient] Span ended:", spanId);
44
- this._pendingSpans.delete(spanId);
45
- if (this._pendingSpans.size === 0 && this._resolveSpanCompletion) {
46
- DEBUG_BUILD && debug.log("[CloudflareClient] All spans completed, resolving promise");
47
- this._resolveSpanCompletion();
48
- this._resetSpanCompletionPromise();
49
- }
50
- });
33
+ this.isCachedClient = options.cacheClient === true;
34
+ if (!this.isCachedClient) {
35
+ this._unsubscribeSpanStart = this.on("spanStart", (span) => {
36
+ const spanId = span.spanContext().spanId;
37
+ DEBUG_BUILD && debug.log("[CloudflareClient] Span started:", spanId);
38
+ if (!spanIsSampled(span)) {
39
+ return;
40
+ }
41
+ this._pendingSpans.add(spanId);
42
+ if (!this._spanCompletionPromise) {
43
+ this._spanCompletionPromise = new Promise((resolve) => {
44
+ this._resolveSpanCompletion = resolve;
45
+ });
46
+ }
47
+ });
48
+ this._unsubscribeSpanEnd = this.on("spanEnd", (span) => {
49
+ const spanId = span.spanContext().spanId;
50
+ DEBUG_BUILD && debug.log("[CloudflareClient] Span ended:", spanId);
51
+ this._pendingSpans.delete(spanId);
52
+ if (this._pendingSpans.size === 0 && this._resolveSpanCompletion) {
53
+ DEBUG_BUILD && debug.log("[CloudflareClient] All spans completed, preparing to flush");
54
+ this._resolveSpanCompletion();
55
+ this._resetSpanCompletionPromise();
56
+ }
57
+ });
58
+ }
51
59
  }
52
60
  /**
53
61
  * Flushes pending operations and ensures all data is processed.
@@ -76,7 +84,12 @@ class CloudflareClient extends ServerRuntimeClient {
76
84
  ]);
77
85
  await spanCompletionRace;
78
86
  }
79
- return super.flush(timeout);
87
+ this._inBoundaryFlush = true;
88
+ try {
89
+ return await super.flush(timeout);
90
+ } finally {
91
+ this._inBoundaryFlush = false;
92
+ }
80
93
  }
81
94
  /**
82
95
  * Disposes of the client and releases all resources.
@@ -105,6 +118,16 @@ class CloudflareClient extends ServerRuntimeClient {
105
118
  _setupIntegrations() {
106
119
  _INTERNAL_clearAiProviderSkips();
107
120
  super._setupIntegrations();
121
+ if (this.isCachedClient) {
122
+ this.on("flush", () => {
123
+ const invocationState = getInvocationState();
124
+ if (invocationState) {
125
+ invocationState.flushPointReached = true;
126
+ }
127
+ });
128
+ this._setupEagerEnvelopeDelivery();
129
+ this._setupEagerBufferDelivery();
130
+ }
108
131
  }
109
132
  /**
110
133
  * Resets the span completion promise and resolve function.
@@ -114,6 +137,76 @@ class CloudflareClient extends ServerRuntimeClient {
114
137
  this._spanCompletionPromise = null;
115
138
  this._resolveSpanCompletion = null;
116
139
  }
140
+ /**
141
+ * Drains the transport after an envelope has been accepted past the invocation's
142
+ * flush point. The transport queues request producers until `flush()`; before the
143
+ * flush point the boundary `flush()` drains everything, but envelopes created after
144
+ * it (post-response `waitUntil` work, detached continuations) have no later flush to
145
+ * ride. The drain is registered with the invocation's `waitUntil` to keep the fetch
146
+ * alive; outside any instrumented invocation it always runs.
147
+ */
148
+ _setupEagerEnvelopeDelivery() {
149
+ this.on("afterEnvelope", () => {
150
+ const transport = this.getTransport();
151
+ const invocationState = getInvocationState();
152
+ if (!transport || this._inBoundaryFlush || invocationState && !invocationState.flushPointReached) {
153
+ return;
154
+ }
155
+ this._registerWithInvocationWaitUntil(transport.flush(2e3));
156
+ });
157
+ }
158
+ /**
159
+ * Turns spans, logs and metrics captured past the invocation's flush point into
160
+ * envelopes. Before the flush point the boundary `flush()` drains their buffers; after
161
+ * it (or outside any instrumented invocation) nothing else would: the log/metric idle
162
+ * timer is disabled for this runtime (`_flushInterval: 0`) and the span buffer's own 5s
163
+ * timer fires outside any invocation, where the runtime suspends the send. Each capture
164
+ * drains only its own bucket (the ended span's trace, the log buffer, the metric
165
+ * buffer), so a fan-out of concurrent traces stays one envelope per trace. RPC method
166
+ * spans never reach this path: `wrapMethodWithSentry` runs the boundary flush after the
167
+ * method span has ended, so only work past that (e.g. detached continuations) lands here.
168
+ */
169
+ _setupEagerBufferDelivery() {
170
+ this.on("afterSpanEnd", (span) => {
171
+ const traceId = span.spanContext().traceId;
172
+ this._eagerDrain(() => this.emit("flushTraceSpans", traceId));
173
+ });
174
+ this.on("afterCaptureLog", () => this._eagerDrain(() => _INTERNAL_flushLogsBuffer(this)));
175
+ this.on("afterCaptureMetric", () => this._eagerDrain(() => _INTERNAL_flushMetricsBuffer(this)));
176
+ }
177
+ /**
178
+ * Runs `drain` unless the owning invocation has not reached its flush point yet
179
+ * (before it the boundary `flush()` delivers the buffers).
180
+ */
181
+ _eagerDrain(drain) {
182
+ const invocationState = getInvocationState();
183
+ if (invocationState && !invocationState.flushPointReached) {
184
+ return;
185
+ }
186
+ drain();
187
+ }
188
+ /**
189
+ * Attaches a promise to the `waitUntil` of the invocation that owns the current
190
+ * async context, so the runtime keeps the send alive after the response is returned.
191
+ * Outside any instrumented invocation (or where the context has no `waitUntil`,
192
+ * e.g. Astro prerendering) the send is fire-and-forget.
193
+ */
194
+ _registerWithInvocationWaitUntil(promise) {
195
+ const invocationState = getInvocationState();
196
+ const waitUntil = invocationState && getInvocationWaitUntil(invocationState);
197
+ if (!waitUntil) {
198
+ return;
199
+ }
200
+ try {
201
+ waitUntil(
202
+ Promise.resolve(promise).then(
203
+ () => void 0,
204
+ () => void 0
205
+ )
206
+ );
207
+ } catch {
208
+ }
209
+ }
117
210
  }
118
211
 
119
212
  export { CloudflareClient };