@sentry/cloudflare 10.47.0 → 10.49.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 (171) hide show
  1. package/build/cjs/client.js.map +1 -1
  2. package/build/cjs/durableobject.js +42 -16
  3. package/build/cjs/durableobject.js.map +1 -1
  4. package/build/cjs/index.js +3 -0
  5. package/build/cjs/index.js.map +1 -1
  6. package/build/cjs/instrument.js +72 -8
  7. package/build/cjs/instrument.js.map +1 -1
  8. package/build/cjs/instrumentations/instrumentDurableObjectNamespace.js +56 -0
  9. package/build/cjs/instrumentations/instrumentDurableObjectNamespace.js.map +1 -0
  10. package/build/cjs/instrumentations/instrumentDurableObjectStorage.js +38 -3
  11. package/build/cjs/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
  12. package/build/cjs/instrumentations/instrumentWorkerEntrypoint.js +101 -0
  13. package/build/cjs/instrumentations/instrumentWorkerEntrypoint.js.map +1 -0
  14. package/build/cjs/instrumentations/worker/instrumentEmail.js +16 -13
  15. package/build/cjs/instrumentations/worker/instrumentEmail.js.map +1 -1
  16. package/build/cjs/instrumentations/worker/instrumentEnv.js +83 -0
  17. package/build/cjs/instrumentations/worker/instrumentEnv.js.map +1 -0
  18. package/build/cjs/instrumentations/worker/instrumentFetch.js +36 -10
  19. package/build/cjs/instrumentations/worker/instrumentFetch.js.map +1 -1
  20. package/build/cjs/instrumentations/worker/instrumentFetcher.js +38 -0
  21. package/build/cjs/instrumentations/worker/instrumentFetcher.js.map +1 -0
  22. package/build/cjs/instrumentations/worker/instrumentQueue.js +36 -10
  23. package/build/cjs/instrumentations/worker/instrumentQueue.js.map +1 -1
  24. package/build/cjs/instrumentations/worker/instrumentScheduled.js +36 -13
  25. package/build/cjs/instrumentations/worker/instrumentScheduled.js.map +1 -1
  26. package/build/cjs/instrumentations/worker/instrumentTail.js +34 -10
  27. package/build/cjs/instrumentations/worker/instrumentTail.js.map +1 -1
  28. package/build/cjs/integrations/tracing/vercelai.js +2 -1
  29. package/build/cjs/integrations/tracing/vercelai.js.map +1 -1
  30. package/build/cjs/request.js +5 -6
  31. package/build/cjs/request.js.map +1 -1
  32. package/build/cjs/scope-utils.js.map +1 -1
  33. package/build/cjs/sdk.js +6 -1
  34. package/build/cjs/sdk.js.map +1 -1
  35. package/build/cjs/utils/instrumentContext.js +2 -1
  36. package/build/cjs/utils/instrumentContext.js.map +1 -1
  37. package/build/cjs/utils/isBinding.js +32 -0
  38. package/build/cjs/utils/isBinding.js.map +1 -0
  39. package/build/cjs/utils/isCloudflareClass.js +29 -0
  40. package/build/cjs/utils/isCloudflareClass.js.map +1 -0
  41. package/build/cjs/utils/rpcOptions.js +84 -0
  42. package/build/cjs/utils/rpcOptions.js.map +1 -0
  43. package/build/cjs/utils/traceLinks.js +78 -0
  44. package/build/cjs/utils/traceLinks.js.map +1 -0
  45. package/build/cjs/withSentry.js +31 -20
  46. package/build/cjs/withSentry.js.map +1 -1
  47. package/build/cjs/workflows.js +3 -2
  48. package/build/cjs/workflows.js.map +1 -1
  49. package/build/cjs/wrapMethodWithSentry.js +157 -112
  50. package/build/cjs/wrapMethodWithSentry.js.map +1 -1
  51. package/build/esm/client.js.map +1 -1
  52. package/build/esm/durableobject.js +43 -17
  53. package/build/esm/durableobject.js.map +1 -1
  54. package/build/esm/index.js +1 -1
  55. package/build/esm/instrument.js +71 -8
  56. package/build/esm/instrument.js.map +1 -1
  57. package/build/esm/instrumentations/instrumentDurableObjectNamespace.js +54 -0
  58. package/build/esm/instrumentations/instrumentDurableObjectNamespace.js.map +1 -0
  59. package/build/esm/instrumentations/instrumentDurableObjectStorage.js +39 -4
  60. package/build/esm/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
  61. package/build/esm/instrumentations/instrumentWorkerEntrypoint.js +99 -0
  62. package/build/esm/instrumentations/instrumentWorkerEntrypoint.js.map +1 -0
  63. package/build/esm/instrumentations/worker/instrumentEmail.js +17 -14
  64. package/build/esm/instrumentations/worker/instrumentEmail.js.map +1 -1
  65. package/build/esm/instrumentations/worker/instrumentEnv.js +81 -0
  66. package/build/esm/instrumentations/worker/instrumentEnv.js.map +1 -0
  67. package/build/esm/instrumentations/worker/instrumentFetch.js +37 -12
  68. package/build/esm/instrumentations/worker/instrumentFetch.js.map +1 -1
  69. package/build/esm/instrumentations/worker/instrumentFetcher.js +36 -0
  70. package/build/esm/instrumentations/worker/instrumentFetcher.js.map +1 -0
  71. package/build/esm/instrumentations/worker/instrumentQueue.js +37 -12
  72. package/build/esm/instrumentations/worker/instrumentQueue.js.map +1 -1
  73. package/build/esm/instrumentations/worker/instrumentScheduled.js +37 -15
  74. package/build/esm/instrumentations/worker/instrumentScheduled.js.map +1 -1
  75. package/build/esm/instrumentations/worker/instrumentTail.js +35 -12
  76. package/build/esm/instrumentations/worker/instrumentTail.js.map +1 -1
  77. package/build/esm/integrations/tracing/vercelai.js +2 -1
  78. package/build/esm/integrations/tracing/vercelai.js.map +1 -1
  79. package/build/esm/package.json +1 -1
  80. package/build/esm/request.js +5 -6
  81. package/build/esm/request.js.map +1 -1
  82. package/build/esm/scope-utils.js.map +1 -1
  83. package/build/esm/sdk.js +7 -2
  84. package/build/esm/sdk.js.map +1 -1
  85. package/build/esm/utils/instrumentContext.js +2 -1
  86. package/build/esm/utils/instrumentContext.js.map +1 -1
  87. package/build/esm/utils/isBinding.js +29 -0
  88. package/build/esm/utils/isBinding.js.map +1 -0
  89. package/build/esm/utils/isCloudflareClass.js +27 -0
  90. package/build/esm/utils/isCloudflareClass.js.map +1 -0
  91. package/build/esm/utils/rpcOptions.js +81 -0
  92. package/build/esm/utils/rpcOptions.js.map +1 -0
  93. package/build/esm/utils/traceLinks.js +73 -0
  94. package/build/esm/utils/traceLinks.js.map +1 -0
  95. package/build/esm/withSentry.js +32 -21
  96. package/build/esm/withSentry.js.map +1 -1
  97. package/build/esm/workflows.js +3 -2
  98. package/build/esm/workflows.js.map +1 -1
  99. package/build/esm/wrapMethodWithSentry.js +159 -114
  100. package/build/esm/wrapMethodWithSentry.js.map +1 -1
  101. package/build/types/client.d.ts +39 -10
  102. package/build/types/client.d.ts.map +1 -1
  103. package/build/types/durableobject.d.ts.map +1 -1
  104. package/build/types/index.d.ts +1 -1
  105. package/build/types/index.d.ts.map +1 -1
  106. package/build/types/instrument.d.ts +15 -4
  107. package/build/types/instrument.d.ts.map +1 -1
  108. package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts +12 -0
  109. package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts.map +1 -0
  110. package/build/types/instrumentations/instrumentDurableObjectStorage.d.ts +8 -1
  111. package/build/types/instrumentations/instrumentDurableObjectStorage.d.ts.map +1 -1
  112. package/build/types/instrumentations/instrumentWorkerEntrypoint.d.ts +42 -0
  113. package/build/types/instrumentations/instrumentWorkerEntrypoint.d.ts.map +1 -0
  114. package/build/types/instrumentations/worker/instrumentEmail.d.ts +2 -1
  115. package/build/types/instrumentations/worker/instrumentEmail.d.ts.map +1 -1
  116. package/build/types/instrumentations/worker/instrumentEnv.d.ts +16 -0
  117. package/build/types/instrumentations/worker/instrumentEnv.d.ts.map +1 -0
  118. package/build/types/instrumentations/worker/instrumentFetch.d.ts +6 -1
  119. package/build/types/instrumentations/worker/instrumentFetch.d.ts.map +1 -1
  120. package/build/types/instrumentations/worker/instrumentFetcher.d.ts +10 -0
  121. package/build/types/instrumentations/worker/instrumentFetcher.d.ts.map +1 -0
  122. package/build/types/instrumentations/worker/instrumentQueue.d.ts +6 -1
  123. package/build/types/instrumentations/worker/instrumentQueue.d.ts.map +1 -1
  124. package/build/types/instrumentations/worker/instrumentScheduled.d.ts +6 -1
  125. package/build/types/instrumentations/worker/instrumentScheduled.d.ts.map +1 -1
  126. package/build/types/instrumentations/worker/instrumentTail.d.ts +6 -1
  127. package/build/types/instrumentations/worker/instrumentTail.d.ts.map +1 -1
  128. package/build/types/integrations/tracing/vercelai.d.ts +9 -1
  129. package/build/types/integrations/tracing/vercelai.d.ts.map +1 -1
  130. package/build/types/request.d.ts +3 -3
  131. package/build/types/request.d.ts.map +1 -1
  132. package/build/types/scope-utils.d.ts +2 -2
  133. package/build/types/scope-utils.d.ts.map +1 -1
  134. package/build/types/sdk.d.ts.map +1 -1
  135. package/build/types/utils/instrumentContext.d.ts.map +1 -1
  136. package/build/types/utils/isBinding.d.ts +49 -0
  137. package/build/types/utils/isBinding.d.ts.map +1 -0
  138. package/build/types/utils/isCloudflareClass.d.ts +30 -0
  139. package/build/types/utils/isCloudflareClass.d.ts.map +1 -0
  140. package/build/types/utils/rpcOptions.d.ts +24 -0
  141. package/build/types/utils/rpcOptions.d.ts.map +1 -0
  142. package/build/types/utils/traceLinks.d.ts +27 -0
  143. package/build/types/utils/traceLinks.d.ts.map +1 -0
  144. package/build/types/withSentry.d.ts +3 -2
  145. package/build/types/withSentry.d.ts.map +1 -1
  146. package/build/types/workflows.d.ts.map +1 -1
  147. package/build/types/wrapMethodWithSentry.d.ts +19 -2
  148. package/build/types/wrapMethodWithSentry.d.ts.map +1 -1
  149. package/build/types-ts3.8/client.d.ts +39 -10
  150. package/build/types-ts3.8/index.d.ts +1 -1
  151. package/build/types-ts3.8/instrument.d.ts +15 -4
  152. package/build/types-ts3.8/instrumentations/instrumentDurableObjectNamespace.d.ts +12 -0
  153. package/build/types-ts3.8/instrumentations/instrumentDurableObjectStorage.d.ts +8 -1
  154. package/build/types-ts3.8/instrumentations/instrumentWorkerEntrypoint.d.ts +42 -0
  155. package/build/types-ts3.8/instrumentations/worker/instrumentEmail.d.ts +2 -1
  156. package/build/types-ts3.8/instrumentations/worker/instrumentEnv.d.ts +16 -0
  157. package/build/types-ts3.8/instrumentations/worker/instrumentFetch.d.ts +6 -1
  158. package/build/types-ts3.8/instrumentations/worker/instrumentFetcher.d.ts +10 -0
  159. package/build/types-ts3.8/instrumentations/worker/instrumentQueue.d.ts +6 -1
  160. package/build/types-ts3.8/instrumentations/worker/instrumentScheduled.d.ts +6 -1
  161. package/build/types-ts3.8/instrumentations/worker/instrumentTail.d.ts +6 -1
  162. package/build/types-ts3.8/integrations/tracing/vercelai.d.ts +9 -1
  163. package/build/types-ts3.8/request.d.ts +3 -3
  164. package/build/types-ts3.8/scope-utils.d.ts +2 -2
  165. package/build/types-ts3.8/utils/isBinding.d.ts +49 -0
  166. package/build/types-ts3.8/utils/isCloudflareClass.d.ts +30 -0
  167. package/build/types-ts3.8/utils/rpcOptions.d.ts +24 -0
  168. package/build/types-ts3.8/utils/traceLinks.d.ts +27 -0
  169. package/build/types-ts3.8/withSentry.d.ts +3 -2
  170. package/build/types-ts3.8/wrapMethodWithSentry.d.ts +19 -2
  171. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumentWorkerEntrypoint.js","sources":["../../../src/instrumentations/instrumentWorkerEntrypoint.ts"],"sourcesContent":["import { setAsyncLocalStorageAsyncContextStrategy } from '../async';\nimport type { env as cloudflareEnv, WorkerEntrypoint } from 'cloudflare:workers';\nimport type { CloudflareOptions } from '../client';\nimport { instrumentWorkerEntrypointFetch } from './worker/instrumentFetch';\nimport { instrumentWorkerEntrypointQueue } from './worker/instrumentQueue';\nimport { instrumentWorkerEntrypointScheduled } from './worker/instrumentScheduled';\nimport { instrumentWorkerEntrypointTail } from './worker/instrumentTail';\nimport { getFinalOptions } from '../options';\nimport { instrumentContext } from '../utils/instrumentContext';\n\nexport type WorkerEntrypointConstructor<Env = typeof cloudflareEnv, Props = {}> = new (\n ctx: ExecutionContext,\n env: typeof cloudflareEnv,\n) => InstanceType<typeof WorkerEntrypoint<Env, Props>>;\n\n/**\n * Instruments a WorkerEntrypoint class to capture errors and performance data.\n *\n * Instruments the following methods (same as `withSentry` for ExportedHandler):\n * - fetch (HTTP requests)\n * - scheduled (cron triggers)\n * - queue (queue consumers)\n * - email (email handlers)\n * - tail (tail workers)\n *\n * as well as any other public RPC methods on the WorkerEntrypoint instance.\n *\n * @param optionsCallback Function that returns the options for the SDK initialization.\n * @param WorkerEntrypointClass The WorkerEntrypoint class to instrument.\n * @returns The instrumented WorkerEntrypoint class.\n *\n * @example\n * ```ts\n * class MyWorkerBase extends WorkerEntrypoint<Env> {\n * async fetch(request: Request): Promise<Response> {\n * return new Response('Hello World!');\n * }\n *\n * async myRpcMethod(arg: string): Promise<string> {\n * return `Hello ${arg}!`;\n * }\n * }\n *\n * export default instrumentWorkerEntrypoint(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * }),\n * MyWorkerBase,\n * );\n * ```\n */\nexport function instrumentWorkerEntrypoint<T extends WorkerEntrypointConstructor>(\n optionsCallback: (env: typeof cloudflareEnv) => CloudflareOptions | undefined,\n WorkerEntrypointClass: T,\n): T {\n // Set up AsyncLocalStorage strategy ONCE at instrumentation time, not per-request\n // This is critical - calling this per-request would create a new AsyncLocalStorage\n // each time, breaking scope isolation for concurrent requests\n setAsyncLocalStorageAsyncContextStrategy();\n\n return new Proxy(WorkerEntrypointClass, {\n construct(target, [ctx, env]) {\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n const obj = new target(context, env);\n\n // Override this.ctx to ensure the instrumented context is used\n // This is necessary because the base WorkerEntrypoint class sets this.ctx\n // from the constructor parameter, but we want users accessing this.ctx\n // to get the instrumented version\n if ('ctx' in obj) {\n Object.defineProperty(obj, 'ctx', {\n value: context,\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n\n Object.defineProperty(obj, '__SENTRY_CONTEXT__', {\n value: context,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n\n Object.defineProperty(obj, '__SENTRY_OPTIONS__', {\n value: options,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n\n instrumentWorkerEntrypointFetch(obj, options, context);\n instrumentWorkerEntrypointScheduled(obj, options, context);\n instrumentWorkerEntrypointQueue(obj, options, context);\n instrumentWorkerEntrypointTail(obj, options, context);\n\n return obj;\n },\n });\n}\n"],"names":["setAsyncLocalStorageAsyncContextStrategy","instrumentContext","options","getFinalOptions","instrumentWorkerEntrypointFetch","instrumentWorkerEntrypointScheduled","instrumentWorkerEntrypointQueue","instrumentWorkerEntrypointTail"],"mappings":";;;;;;;;;;AAeA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,0BAA0B;AAC1C,EAAE,eAAe;AACjB,EAAE,qBAAqB;AACvB,EAAK;AACL;AACA;AACA;AACA,EAAEA,8CAAwC,EAAE;;AAE5C,EAAE,OAAO,IAAI,KAAK,CAAC,qBAAqB,EAAE;AAC1C,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE;AAClC,MAAM,MAAM,OAAA,GAAUC,mCAAiB,CAAC,GAAG,CAAC;AAC5C,MAAM,MAAMC,SAAA,GAAUC,uBAAe,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;AAChE,MAAM,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC;;AAE1C;AACA;AACA;AACA;AACA,MAAM,IAAI,KAAA,IAAS,GAAG,EAAE;AACxB,QAAQ,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE;AAC1C,UAAU,KAAK,EAAE,OAAO;AACxB,UAAU,QAAQ,EAAE,IAAI;AACxB,UAAU,UAAU,EAAE,IAAI;AAC1B,UAAU,YAAY,EAAE,IAAI;AAC5B,SAAS,CAAC;AACV,MAAM;;AAEN,MAAM,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,oBAAoB,EAAE;AACvD,QAAQ,KAAK,EAAE,OAAO;AACtB,QAAQ,UAAU,EAAE,KAAK;AACzB,QAAQ,QAAQ,EAAE,KAAK;AACvB,QAAQ,YAAY,EAAE,KAAK;AAC3B,OAAO,CAAC;;AAER,MAAM,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,oBAAoB,EAAE;AACvD,QAAQ,KAAK,EAAED,SAAO;AACtB,QAAQ,UAAU,EAAE,KAAK;AACzB,QAAQ,QAAQ,EAAE,KAAK;AACvB,QAAQ,YAAY,EAAE,KAAK;AAC3B,OAAO,CAAC;;AAER,MAAME,+CAA+B,CAAC,GAAG,EAAEF,SAAO,EAAE,OAAO,CAAC;AAC5D,MAAMG,uDAAmC,CAAC,GAAG,EAAEH,SAAO,EAAE,OAAO,CAAC;AAChE,MAAMI,+CAA+B,CAAC,GAAG,EAAEJ,SAAO,EAAE,OAAO,CAAC;AAC5D,MAAMK,6CAA8B,CAAC,GAAG,EAAEL,SAAO,EAAE,OAAO,CAAC;;AAE3D,MAAM,OAAO,GAAG;AAChB,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;;;"}
@@ -7,6 +7,7 @@ const options = require('../../options.js');
7
7
  const scopeUtils = require('../../scope-utils.js');
8
8
  const sdk = require('../../sdk.js');
9
9
  const instrumentContext = require('../../utils/instrumentContext.js');
10
+ const instrumentEnv = require('./instrumentEnv.js');
10
11
 
11
12
  /**
12
13
  * Core email handler logic - wraps execution with Sentry instrumentation.
@@ -57,23 +58,25 @@ function instrumentExportedHandlerEmail(
57
58
  handler,
58
59
  optionsCallback,
59
60
  ) {
60
- if (!('email' in handler) || typeof handler.email !== 'function' || instrument.isInstrumented(handler.email)) {
61
+ if (!('email' in handler) || typeof handler.email !== 'function') {
61
62
  return;
62
63
  }
63
64
 
64
- handler.email = new Proxy(handler.email, {
65
- apply(target, thisArg, args) {
66
- const [emailMessage, env, ctx] = args;
67
- const context = instrumentContext.instrumentContext(ctx);
68
- args[2] = context;
65
+ handler.email = instrument.ensureInstrumented(
66
+ handler.email,
67
+ original =>
68
+ new Proxy(original, {
69
+ apply(target, thisArg, args) {
70
+ const [emailMessage, env, ctx] = args;
71
+ const context = instrumentContext.instrumentContext(ctx);
72
+ const options$1 = options.getFinalOptions(optionsCallback(env), env);
73
+ args[1] = instrumentEnv.instrumentEnv(env, options$1);
74
+ args[2] = context;
69
75
 
70
- const options$1 = options.getFinalOptions(optionsCallback(env), env);
71
-
72
- return wrapEmailHandler(emailMessage, options$1, context, () => target.apply(thisArg, args));
73
- },
74
- });
75
-
76
- instrument.markAsInstrumented(handler.email);
76
+ return wrapEmailHandler(emailMessage, options$1, context, () => target.apply(thisArg, args));
77
+ },
78
+ }),
79
+ );
77
80
  }
78
81
 
79
82
  exports.instrumentExportedHandlerEmail = instrumentExportedHandlerEmail;
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentEmail.js","sources":["../../../../src/instrumentations/worker/instrumentEmail.ts"],"sourcesContent":["import type { EmailMessage, ExportedHandler } from '@cloudflare/workers-types';\nimport {\n captureException,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n startSpan,\n withIsolationScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport { flushAndDispose } from '../../flush';\nimport { isInstrumented, markAsInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { addCloudResourceContext } from '../../scope-utils';\nimport { init } from '../../sdk';\nimport { instrumentContext } from '../../utils/instrumentContext';\n\n/**\n * Core email handler logic - wraps execution with Sentry instrumentation.\n */\nfunction wrapEmailHandler(\n emailMessage: EmailMessage,\n options: CloudflareOptions,\n context: ExecutionContext,\n fn: () => unknown,\n): unknown {\n return withIsolationScope(isolationScope => {\n const waitUntil = context.waitUntil.bind(context);\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return startSpan(\n {\n op: 'faas.email',\n name: `Handle Email ${emailMessage.to}`,\n attributes: {\n 'faas.trigger': 'email',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.email',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',\n },\n },\n async () => {\n try {\n return await fn();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.email' } });\n throw e;\n } finally {\n waitUntil(flushAndDispose(client));\n }\n },\n );\n });\n}\n\n/**\n * Instruments an email handler for ExportedHandler (env/ctx come from args).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function instrumentExportedHandlerEmail<T extends ExportedHandler<any, any, any>>(\n handler: T,\n optionsCallback: (env: Parameters<NonNullable<T['email']>>[1]) => CloudflareOptions | undefined,\n): void {\n if (!('email' in handler) || typeof handler.email !== 'function' || isInstrumented(handler.email)) {\n return;\n }\n\n handler.email = new Proxy(handler.email, {\n apply(target, thisArg, args: Parameters<NonNullable<T['email']>>) {\n const [emailMessage, env, ctx] = args;\n const context = instrumentContext(ctx);\n args[2] = context;\n\n const options = getFinalOptions(optionsCallback(env), env);\n\n return wrapEmailHandler(emailMessage, options, context, () => target.apply(thisArg, args));\n },\n });\n\n markAsInstrumented(handler.email);\n}\n"],"names":["withIsolationScope","init","addCloudResourceContext","startSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","captureException","flushAndDispose","isInstrumented","instrumentContext","options","getFinalOptions","markAsInstrumented"],"mappings":";;;;;;;;;;AAgBA;AACA;AACA;AACA,SAAS,gBAAgB;AACzB,EAAE,YAAY;AACd,EAAE,OAAO;AACT,EAAE,OAAO;AACT,EAAE,EAAE;AACJ,EAAW;AACX,EAAE,OAAOA,uBAAkB,CAAC,cAAA,IAAkB;AAC9C,IAAI,MAAM,SAAA,GAAY,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;;AAErD,IAAI,MAAM,MAAA,GAASC,QAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,OAAA,EAAS,CAAC;AACrD,IAAI,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC;;AAEpC,IAAIC,kCAAuB,CAAC,cAAc,CAAC;;AAE3C,IAAI,OAAOC,cAAS;AACpB,MAAM;AACN,QAAQ,EAAE,EAAE,YAAY;AACxB,QAAQ,IAAI,EAAE,CAAC,aAAa,EAAE,YAAY,CAAC,EAAE,CAAC,CAAA;AACA,QAAA,UAAA,EAAA;AACA,UAAA,cAAA,EAAA,OAAA;AACA,UAAA,CAAAC,qCAAA,GAAA,4BAAA;AACA,UAAA,CAAAC,qCAAA,GAAA,MAAA;AACA,SAAA;AACA,OAAA;AACA,MAAA,YAAA;AACA,QAAA,IAAA;AACA,UAAA,OAAA,MAAA,EAAA,EAAA;AACA,QAAA,CAAA,CAAA,OAAA,CAAA,EAAA;AACA,UAAAC,qBAAA,CAAA,CAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,KAAA,EAAA,IAAA,EAAA,4BAAA,EAAA,EAAA,CAAA;AACA,UAAA,MAAA,CAAA;AACA,QAAA,CAAA,SAAA;AACA,UAAA,SAAA,CAAAC,qBAAA,CAAA,MAAA,CAAA,CAAA;AACA,QAAA;AACA,MAAA,CAAA;AACA,KAAA;AACA,EAAA,CAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA;AACA,SAAA,8BAAA;AACA,EAAA,OAAA;AACA,EAAA,eAAA;AACA,EAAA;AACA,EAAA,IAAA,EAAA,OAAA,IAAA,OAAA,CAAA,IAAA,OAAA,OAAA,CAAA,KAAA,KAAA,UAAA,IAAAC,yBAAA,CAAA,OAAA,CAAA,KAAA,CAAA,EAAA;AACA,IAAA;AACA,EAAA;;AAEA,EAAA,OAAA,CAAA,KAAA,GAAA,IAAA,KAAA,CAAA,OAAA,CAAA,KAAA,EAAA;AACA,IAAA,KAAA,CAAA,MAAA,EAAA,OAAA,EAAA,IAAA,EAAA;AACA,MAAA,MAAA,CAAA,YAAA,EAAA,GAAA,EAAA,GAAA,CAAA,GAAA,IAAA;AACA,MAAA,MAAA,OAAA,GAAAC,mCAAA,CAAA,GAAA,CAAA;AACA,MAAA,IAAA,CAAA,CAAA,CAAA,GAAA,OAAA;;AAEA,MAAA,MAAAC,SAAA,GAAAC,uBAAA,CAAA,eAAA,CAAA,GAAA,CAAA,EAAA,GAAA,CAAA;;AAEA,MAAA,OAAA,gBAAA,CAAA,YAAA,EAAAD,SAAA,EAAA,OAAA,EAAA,MAAA,MAAA,CAAA,KAAA,CAAA,OAAA,EAAA,IAAA,CAAA,CAAA;AACA,IAAA,CAAA;AACA,GAAA,CAAA;;AAEA,EAAAE,6BAAA,CAAA,OAAA,CAAA,KAAA,CAAA;AACA;;;;"}
1
+ {"version":3,"file":"instrumentEmail.js","sources":["../../../../src/instrumentations/worker/instrumentEmail.ts"],"sourcesContent":["import type { EmailMessage, ExportedHandler } from '@cloudflare/workers-types';\nimport type { env as cloudflareEnv } from 'cloudflare:workers';\nimport {\n captureException,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n startSpan,\n withIsolationScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport { flushAndDispose } from '../../flush';\nimport { ensureInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { addCloudResourceContext } from '../../scope-utils';\nimport { init } from '../../sdk';\nimport { instrumentContext } from '../../utils/instrumentContext';\nimport { instrumentEnv } from './instrumentEnv';\n\n/**\n * Core email handler logic - wraps execution with Sentry instrumentation.\n */\nfunction wrapEmailHandler(\n emailMessage: EmailMessage,\n options: CloudflareOptions,\n context: ExecutionContext,\n fn: () => unknown,\n): unknown {\n return withIsolationScope(isolationScope => {\n const waitUntil = context.waitUntil.bind(context);\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return startSpan(\n {\n op: 'faas.email',\n name: `Handle Email ${emailMessage.to}`,\n attributes: {\n 'faas.trigger': 'email',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.email',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',\n },\n },\n async () => {\n try {\n return await fn();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.email' } });\n throw e;\n } finally {\n waitUntil(flushAndDispose(client));\n }\n },\n );\n });\n}\n\n/**\n * Instruments an email handler for ExportedHandler (env/ctx come from args).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function instrumentExportedHandlerEmail<T extends ExportedHandler<any, any, any>>(\n handler: T,\n optionsCallback: (env: typeof cloudflareEnv) => CloudflareOptions | undefined,\n): void {\n if (!('email' in handler) || typeof handler.email !== 'function') {\n return;\n }\n\n handler.email = ensureInstrumented(\n handler.email,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args: Parameters<NonNullable<T['email']>>) {\n const [emailMessage, env, ctx] = args;\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n args[1] = instrumentEnv(env, options);\n args[2] = context;\n\n return wrapEmailHandler(emailMessage, options, context, () => target.apply(thisArg, args));\n },\n }),\n );\n}\n"],"names":["withIsolationScope","init","addCloudResourceContext","startSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","captureException","flushAndDispose","ensureInstrumented","instrumentContext","options","getFinalOptions","instrumentEnv"],"mappings":";;;;;;;;;;;AAkBA;AACA;AACA;AACA,SAAS,gBAAgB;AACzB,EAAE,YAAY;AACd,EAAE,OAAO;AACT,EAAE,OAAO;AACT,EAAE,EAAE;AACJ,EAAW;AACX,EAAE,OAAOA,uBAAkB,CAAC,cAAA,IAAkB;AAC9C,IAAI,MAAM,SAAA,GAAY,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;;AAErD,IAAI,MAAM,MAAA,GAASC,QAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,OAAA,EAAS,CAAC;AACrD,IAAI,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC;;AAEpC,IAAIC,kCAAuB,CAAC,cAAc,CAAC;;AAE3C,IAAI,OAAOC,cAAS;AACpB,MAAM;AACN,QAAQ,EAAE,EAAE,YAAY;AACxB,QAAQ,IAAI,EAAE,CAAC,aAAa,EAAE,YAAY,CAAC,EAAE,CAAC,CAAA;AACA,QAAA,UAAA,EAAA;AACA,UAAA,cAAA,EAAA,OAAA;AACA,UAAA,CAAAC,qCAAA,GAAA,4BAAA;AACA,UAAA,CAAAC,qCAAA,GAAA,MAAA;AACA,SAAA;AACA,OAAA;AACA,MAAA,YAAA;AACA,QAAA,IAAA;AACA,UAAA,OAAA,MAAA,EAAA,EAAA;AACA,QAAA,CAAA,CAAA,OAAA,CAAA,EAAA;AACA,UAAAC,qBAAA,CAAA,CAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,KAAA,EAAA,IAAA,EAAA,4BAAA,EAAA,EAAA,CAAA;AACA,UAAA,MAAA,CAAA;AACA,QAAA,CAAA,SAAA;AACA,UAAA,SAAA,CAAAC,qBAAA,CAAA,MAAA,CAAA,CAAA;AACA,QAAA;AACA,MAAA,CAAA;AACA,KAAA;AACA,EAAA,CAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA;AACA,SAAA,8BAAA;AACA,EAAA,OAAA;AACA,EAAA,eAAA;AACA,EAAA;AACA,EAAA,IAAA,EAAA,OAAA,IAAA,OAAA,CAAA,IAAA,OAAA,OAAA,CAAA,KAAA,KAAA,UAAA,EAAA;AACA,IAAA;AACA,EAAA;;AAEA,EAAA,OAAA,CAAA,KAAA,GAAAC,6BAAA;AACA,IAAA,OAAA,CAAA,KAAA;AACA,IAAA,QAAA;AACA,MAAA,IAAA,KAAA,CAAA,QAAA,EAAA;AACA,QAAA,KAAA,CAAA,MAAA,EAAA,OAAA,EAAA,IAAA,EAAA;AACA,UAAA,MAAA,CAAA,YAAA,EAAA,GAAA,EAAA,GAAA,CAAA,GAAA,IAAA;AACA,UAAA,MAAA,OAAA,GAAAC,mCAAA,CAAA,GAAA,CAAA;AACA,UAAA,MAAAC,SAAA,GAAAC,uBAAA,CAAA,eAAA,CAAA,GAAA,CAAA,EAAA,GAAA,CAAA;AACA,UAAA,IAAA,CAAA,CAAA,CAAA,GAAAC,2BAAA,CAAA,GAAA,EAAAF,SAAA,CAAA;AACA,UAAA,IAAA,CAAA,CAAA,CAAA,GAAA,OAAA;;AAEA,UAAA,OAAA,gBAAA,CAAA,YAAA,EAAAA,SAAA,EAAA,OAAA,EAAA,MAAA,MAAA,CAAA,KAAA,CAAA,OAAA,EAAA,IAAA,CAAA,CAAA;AACA,QAAA,CAAA;AACA,OAAA,CAAA;AACA,GAAA;AACA;;;;"}
@@ -0,0 +1,83 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const isBinding = require('../../utils/isBinding.js');
4
+ const rpcOptions = require('../../utils/rpcOptions.js');
5
+ const instrumentDurableObjectNamespace = require('../instrumentDurableObjectNamespace.js');
6
+ const instrumentFetcher = require('./instrumentFetcher.js');
7
+
8
+ function isProxyable(item) {
9
+ return item !== null && (typeof item === 'object' || typeof item === 'function');
10
+ }
11
+
12
+ const instrumentedBindings = new WeakMap();
13
+
14
+ /**
15
+ * Wraps the Cloudflare `env` object in a Proxy that detects binding types
16
+ * on property access and returns instrumented versions.
17
+ *
18
+ * Currently detects:
19
+ * - DurableObjectNamespace (via `idFromName` duck-typing)
20
+ * - Service bindings / JSRPC proxies (wraps `fetch` for trace propagation)
21
+ *
22
+ * Extensible for future binding types (KV, D1, Queue, etc.).
23
+ *
24
+ * @param env - The Cloudflare env object to instrument
25
+ * @param options - Optional CloudflareOptions to control RPC trace propagation
26
+ */
27
+ function instrumentEnv(env, options) {
28
+ if (!env || typeof env !== 'object') {
29
+ return env;
30
+ }
31
+
32
+ const rpcPropagation = options ? rpcOptions.getEffectiveRpcPropagation(options) : false;
33
+
34
+ // As of now only trace propagation is used for the instrumentEnv
35
+ // so this is an optimization to avoid wrapping the env in a proxy if trace propagation is disabled
36
+ if (!rpcPropagation) {
37
+ return env;
38
+ }
39
+
40
+ return new Proxy(env, {
41
+ get(target, prop, receiver) {
42
+ const item = Reflect.get(target, prop, receiver);
43
+
44
+ if (!isProxyable(item)) {
45
+ return item;
46
+ }
47
+
48
+ const cached = instrumentedBindings.get(item);
49
+
50
+ if (cached) {
51
+ return cached;
52
+ }
53
+
54
+ if (isBinding.isDurableObjectNamespace(item)) {
55
+ const instrumented = instrumentDurableObjectNamespace.instrumentDurableObjectNamespace(item);
56
+ instrumentedBindings.set(item, instrumented);
57
+ return instrumented;
58
+ }
59
+
60
+ if (isBinding.isJSRPC(item)) {
61
+ const instrumented = new Proxy(item, {
62
+ get(target, p, rcv) {
63
+ const value = Reflect.get(target, p, rcv);
64
+
65
+ if (p === 'fetch' && typeof value === 'function') {
66
+ return instrumentFetcher.instrumentFetcher(value.bind(target));
67
+ }
68
+
69
+ return value;
70
+ },
71
+ });
72
+
73
+ instrumentedBindings.set(item, instrumented);
74
+ return instrumented;
75
+ }
76
+
77
+ return item;
78
+ },
79
+ });
80
+ }
81
+
82
+ exports.instrumentEnv = instrumentEnv;
83
+ //# sourceMappingURL=instrumentEnv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumentEnv.js","sources":["../../../../src/instrumentations/worker/instrumentEnv.ts"],"sourcesContent":["import type { CloudflareOptions } from '../../client';\nimport { isDurableObjectNamespace, isJSRPC } from '../../utils/isBinding';\nimport { getEffectiveRpcPropagation } from '../../utils/rpcOptions';\nimport { instrumentDurableObjectNamespace } from '../instrumentDurableObjectNamespace';\nimport { instrumentFetcher } from './instrumentFetcher';\n\nfunction isProxyable(item: unknown): item is object {\n return item !== null && (typeof item === 'object' || typeof item === 'function');\n}\n\nconst instrumentedBindings = new WeakMap<object, unknown>();\n\n/**\n * Wraps the Cloudflare `env` object in a Proxy that detects binding types\n * on property access and returns instrumented versions.\n *\n * Currently detects:\n * - DurableObjectNamespace (via `idFromName` duck-typing)\n * - Service bindings / JSRPC proxies (wraps `fetch` for trace propagation)\n *\n * Extensible for future binding types (KV, D1, Queue, etc.).\n *\n * @param env - The Cloudflare env object to instrument\n * @param options - Optional CloudflareOptions to control RPC trace propagation\n */\nexport function instrumentEnv<Env extends Record<string, unknown>>(env: Env, options?: CloudflareOptions): Env {\n if (!env || typeof env !== 'object') {\n return env;\n }\n\n const rpcPropagation = options ? getEffectiveRpcPropagation(options) : false;\n\n // As of now only trace propagation is used for the instrumentEnv\n // so this is an optimization to avoid wrapping the env in a proxy if trace propagation is disabled\n if (!rpcPropagation) {\n return env;\n }\n\n return new Proxy(env, {\n get(target, prop, receiver) {\n const item = Reflect.get(target, prop, receiver);\n\n if (!isProxyable(item)) {\n return item;\n }\n\n const cached = instrumentedBindings.get(item);\n\n if (cached) {\n return cached;\n }\n\n if (isDurableObjectNamespace(item)) {\n const instrumented = instrumentDurableObjectNamespace(item);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n if (isJSRPC(item)) {\n const instrumented = new Proxy(item, {\n get(target, p, rcv) {\n const value = Reflect.get(target, p, rcv);\n\n if (p === 'fetch' && typeof value === 'function') {\n return instrumentFetcher(value.bind(target));\n }\n\n return value;\n },\n });\n\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n return item;\n },\n });\n}\n"],"names":["getEffectiveRpcPropagation","isDurableObjectNamespace","instrumentDurableObjectNamespace","isJSRPC","instrumentFetcher"],"mappings":";;;;;;;AAMA,SAAS,WAAW,CAAC,IAAI,EAA2B;AACpD,EAAE,OAAO,IAAA,KAAS,IAAA,KAAS,OAAO,IAAA,KAAS,YAAY,OAAO,IAAA,KAAS,UAAU,CAAC;AAClF;;AAEA,MAAM,oBAAA,GAAuB,IAAI,OAAO,EAAmB;;AAE3D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,aAAa,CAAsC,GAAG,EAAO,OAAO,EAA2B;AAC/G,EAAE,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAQ,EAAE;AACvC,IAAI,OAAO,GAAG;AACd,EAAE;;AAEF,EAAE,MAAM,cAAA,GAAiB,OAAA,GAAUA,qCAA0B,CAAC,OAAO,CAAA,GAAI,KAAK;;AAE9E;AACA;AACA,EAAE,IAAI,CAAC,cAAc,EAAE;AACvB,IAAI,OAAO,GAAG;AACd,EAAE;;AAEF,EAAE,OAAO,IAAI,KAAK,CAAC,GAAG,EAAE;AACxB,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE;AAChC,MAAM,MAAM,IAAA,GAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC;;AAEtD,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE;AAC9B,QAAQ,OAAO,IAAI;AACnB,MAAM;;AAEN,MAAM,MAAM,SAAS,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC;;AAEnD,MAAM,IAAI,MAAM,EAAE;AAClB,QAAQ,OAAO,MAAM;AACrB,MAAM;;AAEN,MAAM,IAAIC,kCAAwB,CAAC,IAAI,CAAC,EAAE;AAC1C,QAAQ,MAAM,YAAA,GAAeC,iEAAgC,CAAC,IAAI,CAAC;AACnE,QAAQ,oBAAoB,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC;AACpD,QAAQ,OAAO,YAAY;AAC3B,MAAM;;AAEN,MAAM,IAAIC,iBAAO,CAAC,IAAI,CAAC,EAAE;AACzB,QAAQ,MAAM,YAAA,GAAe,IAAI,KAAK,CAAC,IAAI,EAAE;AAC7C,UAAU,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE;AAC9B,YAAY,MAAM,KAAA,GAAQ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC;;AAErD,YAAY,IAAI,CAAA,KAAM,OAAA,IAAW,OAAO,KAAA,KAAU,UAAU,EAAE;AAC9D,cAAc,OAAOC,mCAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC1D,YAAY;;AAEZ,YAAY,OAAO,KAAK;AACxB,UAAU,CAAC;AACX,SAAS,CAAC;;AAEV,QAAQ,oBAAoB,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC;AACpD,QAAQ,OAAO,YAAY;AAC3B,MAAM;;AAEN,MAAM,OAAO,IAAI;AACjB,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;;;"}
@@ -4,6 +4,7 @@ const instrument = require('../../instrument.js');
4
4
  const options = require('../../options.js');
5
5
  const request = require('../../request.js');
6
6
  const instrumentContext = require('../../utils/instrumentContext.js');
7
+ const instrumentEnv = require('./instrumentEnv.js');
7
8
 
8
9
  /**
9
10
  * Instruments a fetch handler for ExportedHandler (env/ctx come from args).
@@ -13,24 +14,49 @@ function instrumentExportedHandlerFetch(
13
14
  handler,
14
15
  optionsCallback,
15
16
  ) {
16
- if (!('fetch' in handler) || typeof handler.fetch !== 'function' || instrument.isInstrumented(handler.fetch)) {
17
+ if (!('fetch' in handler) || typeof handler.fetch !== 'function') {
17
18
  return;
18
19
  }
19
20
 
20
- handler.fetch = new Proxy(handler.fetch, {
21
- apply(target, thisArg, args) {
22
- const [request$1, env, ctx] = args;
23
- const context = instrumentContext.instrumentContext(ctx);
24
- args[2] = context;
21
+ handler.fetch = instrument.ensureInstrumented(
22
+ handler.fetch,
23
+ original =>
24
+ new Proxy(original, {
25
+ apply(target, thisArg, args) {
26
+ const [request$1, env, ctx] = args;
27
+ const context = instrumentContext.instrumentContext(ctx);
28
+ const options$1 = options.getFinalOptions(optionsCallback(env), env);
29
+ args[1] = instrumentEnv.instrumentEnv(env, options$1);
30
+ args[2] = context;
25
31
 
26
- const options$1 = options.getFinalOptions(optionsCallback(env), env);
32
+ return request.wrapRequestHandler({ options: options$1, request: request$1, context }, () => target.apply(thisArg, args));
33
+ },
34
+ }),
35
+ );
36
+ }
27
37
 
28
- return request.wrapRequestHandler({ options: options$1, request: request$1, context }, () => target.apply(thisArg, args));
38
+ /**
39
+ * Instruments a fetch method for WorkerEntrypoint (options/context already available).
40
+ */
41
+ function instrumentWorkerEntrypointFetch(
42
+ instance,
43
+ options,
44
+ context,
45
+ ) {
46
+ if (!instance.fetch) {
47
+ return;
48
+ }
49
+
50
+ const original = instance.fetch.bind(instance);
51
+ instance.fetch = new Proxy(original, {
52
+ apply(target, thisArg, args) {
53
+ const [request$1] = args;
54
+
55
+ return request.wrapRequestHandler({ options, request: request$1, context }, () => Reflect.apply(target, thisArg, args));
29
56
  },
30
57
  });
31
-
32
- instrument.markAsInstrumented(handler.fetch);
33
58
  }
34
59
 
35
60
  exports.instrumentExportedHandlerFetch = instrumentExportedHandlerFetch;
61
+ exports.instrumentWorkerEntrypointFetch = instrumentWorkerEntrypointFetch;
36
62
  //# sourceMappingURL=instrumentFetch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentFetch.js","sources":["../../../../src/instrumentations/worker/instrumentFetch.ts"],"sourcesContent":["import type { ExportedHandler } from '@cloudflare/workers-types';\nimport type { CloudflareOptions } from '../../client';\nimport { isInstrumented, markAsInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { wrapRequestHandler } from '../../request';\nimport { instrumentContext } from '../../utils/instrumentContext';\n\n/**\n * Instruments a fetch handler for ExportedHandler (env/ctx come from args).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function instrumentExportedHandlerFetch<T extends ExportedHandler<any, any, any>>(\n handler: T,\n optionsCallback: (env: Parameters<NonNullable<T['fetch']>>[1]) => CloudflareOptions | undefined,\n): void {\n if (!('fetch' in handler) || typeof handler.fetch !== 'function' || isInstrumented(handler.fetch)) {\n return;\n }\n\n handler.fetch = new Proxy(handler.fetch, {\n apply(target, thisArg, args: Parameters<NonNullable<T['fetch']>>) {\n const [request, env, ctx] = args;\n const context = instrumentContext(ctx);\n args[2] = context;\n\n const options = getFinalOptions(optionsCallback(env), env);\n\n return wrapRequestHandler({ options, request, context }, () => target.apply(thisArg, args));\n },\n });\n\n markAsInstrumented(handler.fetch);\n}\n"],"names":["isInstrumented","request","instrumentContext","options","getFinalOptions","wrapRequestHandler","markAsInstrumented"],"mappings":";;;;;;;AAOA;AACA;AACA;AACA;AACO,SAAS,8BAA8B;AAC9C,EAAE,OAAO;AACT,EAAE,eAAe;AACjB,EAAQ;AACR,EAAE,IAAI,EAAE,WAAW,OAAO,CAAA,IAAK,OAAO,OAAO,CAAC,KAAA,KAAU,cAAcA,yBAAc,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACrG,IAAI;AACJ,EAAE;;AAEF,EAAE,OAAO,CAAC,KAAA,GAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE;AAC3C,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAuC;AACtE,MAAM,MAAM,CAACC,SAAO,EAAE,GAAG,EAAE,GAAG,CAAA,GAAI,IAAI;AACtC,MAAM,MAAM,OAAA,GAAUC,mCAAiB,CAAC,GAAG,CAAC;AAC5C,MAAM,IAAI,CAAC,CAAC,CAAA,GAAI,OAAO;;AAEvB,MAAM,MAAMC,SAAA,GAAUC,uBAAe,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;;AAEhE,MAAM,OAAOC,0BAAkB,CAAC,WAAEF,SAAO,WAAEF,SAAO,EAAE,OAAA,EAAS,EAAE,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACjG,IAAI,CAAC;AACL,GAAG,CAAC;;AAEJ,EAAEK,6BAAkB,CAAC,OAAO,CAAC,KAAK,CAAC;AACnC;;;;"}
1
+ {"version":3,"file":"instrumentFetch.js","sources":["../../../../src/instrumentations/worker/instrumentFetch.ts"],"sourcesContent":["import type { ExportedHandler } from '@cloudflare/workers-types';\nimport type { env as cloudflareEnv, WorkerEntrypoint } from 'cloudflare:workers';\nimport type { CloudflareOptions } from '../../client';\nimport { ensureInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { wrapRequestHandler } from '../../request';\nimport { instrumentContext } from '../../utils/instrumentContext';\nimport { instrumentEnv } from './instrumentEnv';\n\n/**\n * Instruments a fetch handler for ExportedHandler (env/ctx come from args).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function instrumentExportedHandlerFetch<T extends ExportedHandler<any, any, any>>(\n handler: T,\n optionsCallback: (env: typeof cloudflareEnv) => CloudflareOptions | undefined,\n): void {\n if (!('fetch' in handler) || typeof handler.fetch !== 'function') {\n return;\n }\n\n handler.fetch = ensureInstrumented(\n handler.fetch,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args: Parameters<NonNullable<T['fetch']>>) {\n const [request, env, ctx] = args;\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n args[1] = instrumentEnv(env, options);\n args[2] = context;\n\n return wrapRequestHandler({ options, request, context }, () => target.apply(thisArg, args));\n },\n }),\n );\n}\n\n/**\n * Instruments a fetch method for WorkerEntrypoint (options/context already available).\n */\nexport function instrumentWorkerEntrypointFetch<T extends WorkerEntrypoint>(\n instance: T,\n options: CloudflareOptions,\n context: ExecutionContext,\n): void {\n if (!instance.fetch) {\n return;\n }\n\n const original = instance.fetch.bind(instance);\n instance.fetch = new Proxy(original, {\n apply(target, thisArg, args: [Request]) {\n const [request] = args;\n\n return wrapRequestHandler({ options, request, context }, () => Reflect.apply(target, thisArg, args));\n },\n });\n}\n"],"names":["ensureInstrumented","request","instrumentContext","options","getFinalOptions","instrumentEnv","wrapRequestHandler"],"mappings":";;;;;;;;AASA;AACA;AACA;AACA;AACO,SAAS,8BAA8B;AAC9C,EAAE,OAAO;AACT,EAAE,eAAe;AACjB,EAAQ;AACR,EAAE,IAAI,EAAE,WAAW,OAAO,CAAA,IAAK,OAAO,OAAO,CAAC,KAAA,KAAU,UAAU,EAAE;AACpE,IAAI;AACJ,EAAE;;AAEF,EAAE,OAAO,CAAC,KAAA,GAAQA,6BAAkB;AACpC,IAAI,OAAO,CAAC,KAAK;AACjB,IAAI,QAAA;AACJ,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE;AAC1B,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAuC;AAC1E,UAAU,MAAM,CAACC,SAAO,EAAE,GAAG,EAAE,GAAG,CAAA,GAAI,IAAI;AAC1C,UAAU,MAAM,OAAA,GAAUC,mCAAiB,CAAC,GAAG,CAAC;AAChD,UAAU,MAAMC,SAAA,GAAUC,uBAAe,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;AACpE,UAAU,IAAI,CAAC,CAAC,CAAA,GAAIC,2BAAa,CAAC,GAAG,EAAEF,SAAO,CAAC;AAC/C,UAAU,IAAI,CAAC,CAAC,CAAA,GAAI,OAAO;;AAE3B,UAAU,OAAOG,0BAAkB,CAAC,WAAEH,SAAO,WAAEF,SAAO,EAAE,OAAA,EAAS,EAAE,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACrG,QAAQ,CAAC;AACT,OAAO,CAAC;AACR,GAAG;AACH;;AAEA;AACA;AACA;AACO,SAAS,+BAA+B;AAC/C,EAAE,QAAQ;AACV,EAAE,OAAO;AACT,EAAE,OAAO;AACT,EAAQ;AACR,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE;AACvB,IAAI;AACJ,EAAE;;AAEF,EAAE,MAAM,QAAA,GAAW,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;AAChD,EAAE,QAAQ,CAAC,KAAA,GAAQ,IAAI,KAAK,CAAC,QAAQ,EAAE;AACvC,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAa;AAC5C,MAAM,MAAM,CAACA,SAAO,CAAA,GAAI,IAAI;;AAE5B,MAAM,OAAOK,0BAAkB,CAAC,EAAE,OAAO,WAAEL,SAAO,EAAE,OAAA,EAAS,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AAC1G,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;;;;"}
@@ -0,0 +1,38 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+
5
+ /**
6
+ * Wraps a fetch-like function to create a span and propagate trace headers
7
+ * (`sentry-trace` and `baggage`) on the outgoing request.
8
+ *
9
+ * Useful for instrumenting Cloudflare bindings that expose a `fetch` method
10
+ * (e.g. Durable Object stubs, Service bindings).
11
+ */
12
+ function instrumentFetcher(fetchFn) {
13
+ return function (input, init) {
14
+ const headers = core._INTERNAL_getTracingHeadersForFetchRequest(input, { headers: init?.headers });
15
+
16
+ if (input instanceof Request && init === undefined) {
17
+ if (!headers) {
18
+ return fetchFn(input);
19
+ }
20
+
21
+ // Newly created headers already include the previous headers from the original request
22
+ // so we can clone the request and pass in all headers.
23
+ const requestWithTracing = new Request(input, { headers: headers });
24
+
25
+ return fetchFn(requestWithTracing);
26
+ }
27
+
28
+ const mergedInit = {
29
+ ...init,
30
+ ...(headers ? { headers } : {}),
31
+ } ;
32
+
33
+ return fetchFn(input, mergedInit);
34
+ };
35
+ }
36
+
37
+ exports.instrumentFetcher = instrumentFetcher;
38
+ //# sourceMappingURL=instrumentFetcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumentFetcher.js","sources":["../../../../src/instrumentations/worker/instrumentFetcher.ts"],"sourcesContent":["import type { Fetcher } from '@cloudflare/workers-types';\nimport { _INTERNAL_getTracingHeadersForFetchRequest } from '@sentry/core';\n\n/**\n * Wraps a fetch-like function to create a span and propagate trace headers\n * (`sentry-trace` and `baggage`) on the outgoing request.\n *\n * Useful for instrumenting Cloudflare bindings that expose a `fetch` method\n * (e.g. Durable Object stubs, Service bindings).\n */\nexport function instrumentFetcher(fetchFn: Fetcher['fetch']): Fetcher['fetch'] {\n return function (input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n const headers = _INTERNAL_getTracingHeadersForFetchRequest(input, { headers: init?.headers });\n\n if (input instanceof Request && init === undefined) {\n if (!headers) {\n return fetchFn(input);\n }\n\n // Newly created headers already include the previous headers from the original request\n // so we can clone the request and pass in all headers.\n const requestWithTracing = new Request(input, { headers: headers as HeadersInit });\n\n return fetchFn(requestWithTracing);\n }\n\n const mergedInit = {\n ...init,\n ...(headers ? { headers } : {}),\n } as NonNullable<Parameters<Fetcher['fetch']>[1]>;\n\n return fetchFn(input, mergedInit);\n };\n}\n"],"names":["_INTERNAL_getTracingHeadersForFetchRequest"],"mappings":";;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,iBAAiB,CAAC,OAAO,EAAsC;AAC/E,EAAE,OAAO,UAAU,KAAK,EAAqB,IAAI,EAAmC;AACpF,IAAI,MAAM,OAAA,GAAUA,+CAA0C,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAA,EAAS,CAAC;;AAEjG,IAAI,IAAI,KAAA,YAAiB,WAAW,IAAA,KAAS,SAAS,EAAE;AACxD,MAAM,IAAI,CAAC,OAAO,EAAE;AACpB,QAAQ,OAAO,OAAO,CAAC,KAAK,CAAC;AAC7B,MAAM;;AAEN;AACA;AACA,MAAM,MAAM,kBAAA,GAAqB,IAAI,OAAO,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,OAAA,GAAwB,CAAC;;AAExF,MAAM,OAAO,OAAO,CAAC,kBAAkB,CAAC;AACxC,IAAI;;AAEJ,IAAI,MAAM,aAAa;AACvB,MAAM,GAAG,IAAI;AACb,MAAM,IAAI,OAAA,GAAU,EAAE,SAAQ,GAAI,EAAE,CAAC;AACrC,KAAI;;AAEJ,IAAI,OAAO,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC;AACrC,EAAE,CAAC;AACH;;;;"}
@@ -7,6 +7,7 @@ const options = require('../../options.js');
7
7
  const scopeUtils = require('../../scope-utils.js');
8
8
  const sdk = require('../../sdk.js');
9
9
  const instrumentContext = require('../../utils/instrumentContext.js');
10
+ const instrumentEnv = require('./instrumentEnv.js');
10
11
 
11
12
  /**
12
13
  * Core queue handler logic - wraps execution with Sentry instrumentation.
@@ -62,24 +63,49 @@ function instrumentExportedHandlerQueue(
62
63
  handler,
63
64
  optionsCallback,
64
65
  ) {
65
- if (!('queue' in handler) || typeof handler.queue !== 'function' || instrument.isInstrumented(handler.queue)) {
66
+ if (!('queue' in handler) || typeof handler.queue !== 'function') {
66
67
  return;
67
68
  }
68
69
 
69
- handler.queue = new Proxy(handler.queue, {
70
- apply(target, thisArg, args) {
71
- const [batch, env, ctx] = args;
72
- const context = instrumentContext.instrumentContext(ctx);
73
- args[2] = context;
70
+ handler.queue = instrument.ensureInstrumented(
71
+ handler.queue,
72
+ original =>
73
+ new Proxy(original, {
74
+ apply(target, thisArg, args) {
75
+ const [batch, env, ctx] = args;
76
+ const context = instrumentContext.instrumentContext(ctx);
77
+ const options$1 = options.getFinalOptions(optionsCallback(env), env);
78
+ args[1] = instrumentEnv.instrumentEnv(env, options$1);
79
+ args[2] = context;
80
+
81
+ return wrapQueueHandler(batch, options$1, context, () => target.apply(thisArg, args));
82
+ },
83
+ }),
84
+ );
85
+ }
86
+
87
+ /**
88
+ * Instruments a queue method for WorkerEntrypoint (options/context already available).
89
+ */
90
+ function instrumentWorkerEntrypointQueue(
91
+ instance,
92
+ options,
93
+ context,
94
+ ) {
95
+ if (!instance.queue) {
96
+ return;
97
+ }
74
98
 
75
- const options$1 = options.getFinalOptions(optionsCallback(env), env);
99
+ const original = instance.queue.bind(instance);
100
+ instance.queue = new Proxy(original, {
101
+ apply(target, thisArg, args) {
102
+ const [batch] = args;
76
103
 
77
- return wrapQueueHandler(batch, options$1, context, () => target.apply(thisArg, args));
104
+ return wrapQueueHandler(batch, options, context, () => Reflect.apply(target, thisArg, args));
78
105
  },
79
106
  });
80
-
81
- instrument.markAsInstrumented(handler.queue);
82
107
  }
83
108
 
84
109
  exports.instrumentExportedHandlerQueue = instrumentExportedHandlerQueue;
110
+ exports.instrumentWorkerEntrypointQueue = instrumentWorkerEntrypointQueue;
85
111
  //# sourceMappingURL=instrumentQueue.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentQueue.js","sources":["../../../../src/instrumentations/worker/instrumentQueue.ts"],"sourcesContent":["import type { ExportedHandler, MessageBatch } from '@cloudflare/workers-types';\nimport {\n captureException,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n startSpan,\n withIsolationScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport { flushAndDispose } from '../../flush';\nimport { isInstrumented, markAsInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { addCloudResourceContext } from '../../scope-utils';\nimport { init } from '../../sdk';\nimport { instrumentContext } from '../../utils/instrumentContext';\n\n/**\n * Core queue handler logic - wraps execution with Sentry instrumentation.\n */\nfunction wrapQueueHandler(\n batch: MessageBatch,\n options: CloudflareOptions,\n context: ExecutionContext,\n fn: () => unknown,\n): unknown {\n return withIsolationScope(isolationScope => {\n const waitUntil = context.waitUntil.bind(context);\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return startSpan(\n {\n op: 'faas.queue',\n name: `process ${batch.queue}`,\n attributes: {\n 'faas.trigger': 'pubsub',\n 'messaging.destination.name': batch.queue,\n 'messaging.system': 'cloudflare',\n 'messaging.batch.message_count': batch.messages.length,\n 'messaging.message.retry.count': batch.messages.reduce((acc, message) => acc + message.attempts - 1, 0),\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'queue.process',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.queue',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',\n },\n },\n async () => {\n try {\n return await fn();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.queue' } });\n throw e;\n } finally {\n waitUntil(flushAndDispose(client));\n }\n },\n );\n });\n}\n\n/**\n * Instruments a queue handler for ExportedHandler (env/ctx come from args).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function instrumentExportedHandlerQueue<T extends ExportedHandler<any, any, any>>(\n handler: T,\n optionsCallback: (env: Parameters<NonNullable<T['queue']>>[1]) => CloudflareOptions | undefined,\n): void {\n if (!('queue' in handler) || typeof handler.queue !== 'function' || isInstrumented(handler.queue)) {\n return;\n }\n\n handler.queue = new Proxy(handler.queue, {\n apply(target, thisArg, args: Parameters<NonNullable<T['queue']>>) {\n const [batch, env, ctx] = args;\n const context = instrumentContext(ctx);\n args[2] = context;\n\n const options = getFinalOptions(optionsCallback(env), env);\n\n return wrapQueueHandler(batch, options, context, () => target.apply(thisArg, args));\n },\n });\n\n markAsInstrumented(handler.queue);\n}\n"],"names":["withIsolationScope","init","addCloudResourceContext","startSpan","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","captureException","flushAndDispose","isInstrumented","instrumentContext","options","getFinalOptions","markAsInstrumented"],"mappings":";;;;;;;;;;AAiBA;AACA;AACA;AACA,SAAS,gBAAgB;AACzB,EAAE,KAAK;AACP,EAAE,OAAO;AACT,EAAE,OAAO;AACT,EAAE,EAAE;AACJ,EAAW;AACX,EAAE,OAAOA,uBAAkB,CAAC,cAAA,IAAkB;AAC9C,IAAI,MAAM,SAAA,GAAY,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;;AAErD,IAAI,MAAM,MAAA,GAASC,QAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,OAAA,EAAS,CAAC;AACrD,IAAI,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC;;AAEpC,IAAIC,kCAAuB,CAAC,cAAc,CAAC;;AAE3C,IAAI,OAAOC,cAAS;AACpB,MAAM;AACN,QAAQ,EAAE,EAAE,YAAY;AACxB,QAAQ,IAAI,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;AACA,QAAA,UAAA,EAAA;AACA,UAAA,cAAA,EAAA,QAAA;AACA,UAAA,4BAAA,EAAA,KAAA,CAAA,KAAA;AACA,UAAA,kBAAA,EAAA,YAAA;AACA,UAAA,+BAAA,EAAA,KAAA,CAAA,QAAA,CAAA,MAAA;AACA,UAAA,+BAAA,EAAA,KAAA,CAAA,QAAA,CAAA,MAAA,CAAA,CAAA,GAAA,EAAA,OAAA,KAAA,GAAA,GAAA,OAAA,CAAA,QAAA,GAAA,CAAA,EAAA,CAAA,CAAA;AACA,UAAA,CAAAC,iCAAA,GAAA,eAAA;AACA,UAAA,CAAAC,qCAAA,GAAA,4BAAA;AACA,UAAA,CAAAC,qCAAA,GAAA,MAAA;AACA,SAAA;AACA,OAAA;AACA,MAAA,YAAA;AACA,QAAA,IAAA;AACA,UAAA,OAAA,MAAA,EAAA,EAAA;AACA,QAAA,CAAA,CAAA,OAAA,CAAA,EAAA;AACA,UAAAC,qBAAA,CAAA,CAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,KAAA,EAAA,IAAA,EAAA,4BAAA,EAAA,EAAA,CAAA;AACA,UAAA,MAAA,CAAA;AACA,QAAA,CAAA,SAAA;AACA,UAAA,SAAA,CAAAC,qBAAA,CAAA,MAAA,CAAA,CAAA;AACA,QAAA;AACA,MAAA,CAAA;AACA,KAAA;AACA,EAAA,CAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA;AACA,SAAA,8BAAA;AACA,EAAA,OAAA;AACA,EAAA,eAAA;AACA,EAAA;AACA,EAAA,IAAA,EAAA,OAAA,IAAA,OAAA,CAAA,IAAA,OAAA,OAAA,CAAA,KAAA,KAAA,UAAA,IAAAC,yBAAA,CAAA,OAAA,CAAA,KAAA,CAAA,EAAA;AACA,IAAA;AACA,EAAA;;AAEA,EAAA,OAAA,CAAA,KAAA,GAAA,IAAA,KAAA,CAAA,OAAA,CAAA,KAAA,EAAA;AACA,IAAA,KAAA,CAAA,MAAA,EAAA,OAAA,EAAA,IAAA,EAAA;AACA,MAAA,MAAA,CAAA,KAAA,EAAA,GAAA,EAAA,GAAA,CAAA,GAAA,IAAA;AACA,MAAA,MAAA,OAAA,GAAAC,mCAAA,CAAA,GAAA,CAAA;AACA,MAAA,IAAA,CAAA,CAAA,CAAA,GAAA,OAAA;;AAEA,MAAA,MAAAC,SAAA,GAAAC,uBAAA,CAAA,eAAA,CAAA,GAAA,CAAA,EAAA,GAAA,CAAA;;AAEA,MAAA,OAAA,gBAAA,CAAA,KAAA,EAAAD,SAAA,EAAA,OAAA,EAAA,MAAA,MAAA,CAAA,KAAA,CAAA,OAAA,EAAA,IAAA,CAAA,CAAA;AACA,IAAA,CAAA;AACA,GAAA,CAAA;;AAEA,EAAAE,6BAAA,CAAA,OAAA,CAAA,KAAA,CAAA;AACA;;;;"}
1
+ {"version":3,"file":"instrumentQueue.js","sources":["../../../../src/instrumentations/worker/instrumentQueue.ts"],"sourcesContent":["import type { ExportedHandler, MessageBatch } from '@cloudflare/workers-types';\nimport type { env as cloudflareEnv, WorkerEntrypoint } from 'cloudflare:workers';\nimport {\n captureException,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n startSpan,\n withIsolationScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport { flushAndDispose } from '../../flush';\nimport { ensureInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { addCloudResourceContext } from '../../scope-utils';\nimport { init } from '../../sdk';\nimport { instrumentContext } from '../../utils/instrumentContext';\nimport { instrumentEnv } from './instrumentEnv';\n\n/**\n * Core queue handler logic - wraps execution with Sentry instrumentation.\n */\nfunction wrapQueueHandler(\n batch: MessageBatch,\n options: CloudflareOptions,\n context: ExecutionContext,\n fn: () => unknown,\n): unknown {\n return withIsolationScope(isolationScope => {\n const waitUntil = context.waitUntil.bind(context);\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return startSpan(\n {\n op: 'faas.queue',\n name: `process ${batch.queue}`,\n attributes: {\n 'faas.trigger': 'pubsub',\n 'messaging.destination.name': batch.queue,\n 'messaging.system': 'cloudflare',\n 'messaging.batch.message_count': batch.messages.length,\n 'messaging.message.retry.count': batch.messages.reduce((acc, message) => acc + message.attempts - 1, 0),\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'queue.process',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.queue',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',\n },\n },\n async () => {\n try {\n return await fn();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.queue' } });\n throw e;\n } finally {\n waitUntil(flushAndDispose(client));\n }\n },\n );\n });\n}\n\n/**\n * Instruments a queue handler for ExportedHandler (env/ctx come from args).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function instrumentExportedHandlerQueue<T extends ExportedHandler<any, any, any>>(\n handler: T,\n optionsCallback: (env: typeof cloudflareEnv) => CloudflareOptions | undefined,\n): void {\n if (!('queue' in handler) || typeof handler.queue !== 'function') {\n return;\n }\n\n handler.queue = ensureInstrumented(\n handler.queue,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args: Parameters<NonNullable<T['queue']>>) {\n const [batch, env, ctx] = args;\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n args[1] = instrumentEnv(env, options);\n args[2] = context;\n\n return wrapQueueHandler(batch, options, context, () => target.apply(thisArg, args));\n },\n }),\n );\n}\n\n/**\n * Instruments a queue method for WorkerEntrypoint (options/context already available).\n */\nexport function instrumentWorkerEntrypointQueue<T extends WorkerEntrypoint>(\n instance: T,\n options: CloudflareOptions,\n context: ExecutionContext,\n): void {\n if (!instance.queue) {\n return;\n }\n\n const original = instance.queue.bind(instance);\n instance.queue = new Proxy(original, {\n apply(target, thisArg, args: [MessageBatch]) {\n const [batch] = args;\n\n return wrapQueueHandler(batch, options, context, () => Reflect.apply(target, thisArg, args));\n },\n });\n}\n"],"names":["withIsolationScope","init","addCloudResourceContext","startSpan","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","captureException","flushAndDispose","ensureInstrumented","instrumentContext","options","getFinalOptions","instrumentEnv"],"mappings":"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"}
@@ -7,10 +7,8 @@ const options = require('../../options.js');
7
7
  const scopeUtils = require('../../scope-utils.js');
8
8
  const sdk = require('../../sdk.js');
9
9
  const instrumentContext = require('../../utils/instrumentContext.js');
10
+ const instrumentEnv = require('./instrumentEnv.js');
10
11
 
11
- /**
12
- * Core scheduled handler logic - wraps execution with Sentry instrumentation.
13
- */
14
12
  function wrapScheduledHandler(
15
13
  controller,
16
14
  options,
@@ -59,24 +57,49 @@ function instrumentExportedHandlerScheduled(
59
57
  handler,
60
58
  optionsCallback,
61
59
  ) {
62
- if (!('scheduled' in handler) || typeof handler.scheduled !== 'function' || instrument.isInstrumented(handler.scheduled)) {
60
+ if (!('scheduled' in handler) || typeof handler.scheduled !== 'function') {
63
61
  return;
64
62
  }
65
63
 
66
- handler.scheduled = new Proxy(handler.scheduled, {
67
- apply(target, thisArg, args) {
68
- const [controller, env, ctx] = args;
69
- const context = instrumentContext.instrumentContext(ctx);
70
- args[2] = context;
64
+ handler.scheduled = instrument.ensureInstrumented(
65
+ handler.scheduled,
66
+ original =>
67
+ new Proxy(original, {
68
+ apply(target, thisArg, args) {
69
+ const [controller, env, ctx] = args;
70
+ const context = instrumentContext.instrumentContext(ctx);
71
+ const options$1 = options.getFinalOptions(optionsCallback(env), env);
72
+ args[1] = instrumentEnv.instrumentEnv(env, options$1);
73
+ args[2] = context;
74
+
75
+ return wrapScheduledHandler(controller, options$1, context, () => target.apply(thisArg, args));
76
+ },
77
+ }),
78
+ );
79
+ }
80
+
81
+ /**
82
+ * Instruments a scheduled method for WorkerEntrypoint (options/context already available).
83
+ */
84
+ function instrumentWorkerEntrypointScheduled(
85
+ instance,
86
+ options,
87
+ context,
88
+ ) {
89
+ if (!instance.scheduled) {
90
+ return;
91
+ }
71
92
 
72
- const options$1 = options.getFinalOptions(optionsCallback(env), env);
93
+ const original = instance.scheduled.bind(instance);
94
+ instance.scheduled = new Proxy(original, {
95
+ apply(target, thisArg, args) {
96
+ const [controller] = args;
73
97
 
74
- return wrapScheduledHandler(controller, options$1, context, () => target.apply(thisArg, args));
98
+ return wrapScheduledHandler(controller, options, context, () => Reflect.apply(target, thisArg, args));
75
99
  },
76
100
  });
77
-
78
- instrument.markAsInstrumented(handler.scheduled);
79
101
  }
80
102
 
81
103
  exports.instrumentExportedHandlerScheduled = instrumentExportedHandlerScheduled;
104
+ exports.instrumentWorkerEntrypointScheduled = instrumentWorkerEntrypointScheduled;
82
105
  //# sourceMappingURL=instrumentScheduled.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentScheduled.js","sources":["../../../../src/instrumentations/worker/instrumentScheduled.ts"],"sourcesContent":["import type { ExportedHandler, ScheduledController } from '@cloudflare/workers-types';\nimport {\n captureException,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n startSpan,\n withIsolationScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport { flushAndDispose } from '../../flush';\nimport { isInstrumented, markAsInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { addCloudResourceContext } from '../../scope-utils';\nimport { init } from '../../sdk';\nimport { instrumentContext } from '../../utils/instrumentContext';\n\n/**\n * Core scheduled handler logic - wraps execution with Sentry instrumentation.\n */\nfunction wrapScheduledHandler(\n controller: ScheduledController,\n options: CloudflareOptions,\n context: ExecutionContext,\n fn: () => unknown,\n): unknown {\n return withIsolationScope(isolationScope => {\n const waitUntil = context.waitUntil.bind(context);\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return startSpan(\n {\n op: 'faas.cron',\n name: `Scheduled Cron ${controller.cron}`,\n attributes: {\n 'faas.cron': controller.cron,\n 'faas.time': new Date(controller.scheduledTime).toISOString(),\n 'faas.trigger': 'timer',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.scheduled',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',\n },\n },\n async () => {\n try {\n return await fn();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.scheduled' } });\n throw e;\n } finally {\n waitUntil(flushAndDispose(client));\n }\n },\n );\n });\n}\n\n/**\n * Instruments a scheduled handler for ExportedHandler (env/ctx come from args).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function instrumentExportedHandlerScheduled<T extends ExportedHandler<any, any, any>>(\n handler: T,\n optionsCallback: (env: Parameters<NonNullable<T['scheduled']>>[1]) => CloudflareOptions | undefined,\n): void {\n if (!('scheduled' in handler) || typeof handler.scheduled !== 'function' || isInstrumented(handler.scheduled)) {\n return;\n }\n\n handler.scheduled = new Proxy(handler.scheduled, {\n apply(target, thisArg, args: Parameters<NonNullable<T['scheduled']>>) {\n const [controller, env, ctx] = args;\n const context = instrumentContext(ctx);\n args[2] = context;\n\n const options = getFinalOptions(optionsCallback(env), env);\n\n return wrapScheduledHandler(controller, options, context, () => target.apply(thisArg, args));\n },\n });\n\n markAsInstrumented(handler.scheduled);\n}\n"],"names":["withIsolationScope","init","addCloudResourceContext","startSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","captureException","flushAndDispose","isInstrumented","instrumentContext","options","getFinalOptions","markAsInstrumented"],"mappings":";;;;;;;;;;AAgBA;AACA;AACA;AACA,SAAS,oBAAoB;AAC7B,EAAE,UAAU;AACZ,EAAE,OAAO;AACT,EAAE,OAAO;AACT,EAAE,EAAE;AACJ,EAAW;AACX,EAAE,OAAOA,uBAAkB,CAAC,cAAA,IAAkB;AAC9C,IAAI,MAAM,SAAA,GAAY,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;;AAErD,IAAI,MAAM,MAAA,GAASC,QAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,OAAA,EAAS,CAAC;AACrD,IAAI,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC;;AAEpC,IAAIC,kCAAuB,CAAC,cAAc,CAAC;;AAE3C,IAAI,OAAOC,cAAS;AACpB,MAAM;AACN,QAAQ,EAAE,EAAE,WAAW;AACvB,QAAQ,IAAI,EAAE,CAAC,eAAe,EAAE,UAAU,CAAC,IAAI,CAAC,CAAA;AACA,QAAA,UAAA,EAAA;AACA,UAAA,WAAA,EAAA,UAAA,CAAA,IAAA;AACA,UAAA,WAAA,EAAA,IAAA,IAAA,CAAA,UAAA,CAAA,aAAA,CAAA,CAAA,WAAA,EAAA;AACA,UAAA,cAAA,EAAA,OAAA;AACA,UAAA,CAAAC,qCAAA,GAAA,gCAAA;AACA,UAAA,CAAAC,qCAAA,GAAA,MAAA;AACA,SAAA;AACA,OAAA;AACA,MAAA,YAAA;AACA,QAAA,IAAA;AACA,UAAA,OAAA,MAAA,EAAA,EAAA;AACA,QAAA,CAAA,CAAA,OAAA,CAAA,EAAA;AACA,UAAAC,qBAAA,CAAA,CAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,KAAA,EAAA,IAAA,EAAA,gCAAA,EAAA,EAAA,CAAA;AACA,UAAA,MAAA,CAAA;AACA,QAAA,CAAA,SAAA;AACA,UAAA,SAAA,CAAAC,qBAAA,CAAA,MAAA,CAAA,CAAA;AACA,QAAA;AACA,MAAA,CAAA;AACA,KAAA;AACA,EAAA,CAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA;AACA,SAAA,kCAAA;AACA,EAAA,OAAA;AACA,EAAA,eAAA;AACA,EAAA;AACA,EAAA,IAAA,EAAA,WAAA,IAAA,OAAA,CAAA,IAAA,OAAA,OAAA,CAAA,SAAA,KAAA,UAAA,IAAAC,yBAAA,CAAA,OAAA,CAAA,SAAA,CAAA,EAAA;AACA,IAAA;AACA,EAAA;;AAEA,EAAA,OAAA,CAAA,SAAA,GAAA,IAAA,KAAA,CAAA,OAAA,CAAA,SAAA,EAAA;AACA,IAAA,KAAA,CAAA,MAAA,EAAA,OAAA,EAAA,IAAA,EAAA;AACA,MAAA,MAAA,CAAA,UAAA,EAAA,GAAA,EAAA,GAAA,CAAA,GAAA,IAAA;AACA,MAAA,MAAA,OAAA,GAAAC,mCAAA,CAAA,GAAA,CAAA;AACA,MAAA,IAAA,CAAA,CAAA,CAAA,GAAA,OAAA;;AAEA,MAAA,MAAAC,SAAA,GAAAC,uBAAA,CAAA,eAAA,CAAA,GAAA,CAAA,EAAA,GAAA,CAAA;;AAEA,MAAA,OAAA,oBAAA,CAAA,UAAA,EAAAD,SAAA,EAAA,OAAA,EAAA,MAAA,MAAA,CAAA,KAAA,CAAA,OAAA,EAAA,IAAA,CAAA,CAAA;AACA,IAAA,CAAA;AACA,GAAA,CAAA;;AAEA,EAAAE,6BAAA,CAAA,OAAA,CAAA,SAAA,CAAA;AACA;;;;"}
1
+ {"version":3,"file":"instrumentScheduled.js","sources":["../../../../src/instrumentations/worker/instrumentScheduled.ts"],"sourcesContent":["import type { ExportedHandler, ScheduledController } from '@cloudflare/workers-types';\nimport type { env as cloudflareEnv, WorkerEntrypoint } from 'cloudflare:workers';\nimport {\n captureException,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n startSpan,\n withIsolationScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport { flushAndDispose } from '../../flush';\nimport { ensureInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { addCloudResourceContext } from '../../scope-utils';\nimport { init } from '../../sdk';\nimport { instrumentContext } from '../../utils/instrumentContext';\nimport { instrumentEnv } from './instrumentEnv';\n\nfunction wrapScheduledHandler(\n controller: ScheduledController,\n options: CloudflareOptions,\n context: ExecutionContext,\n fn: () => unknown,\n): unknown {\n return withIsolationScope(isolationScope => {\n const waitUntil = context.waitUntil.bind(context);\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return startSpan(\n {\n op: 'faas.cron',\n name: `Scheduled Cron ${controller.cron}`,\n attributes: {\n 'faas.cron': controller.cron,\n 'faas.time': new Date(controller.scheduledTime).toISOString(),\n 'faas.trigger': 'timer',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.scheduled',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',\n },\n },\n async () => {\n try {\n return await fn();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.scheduled' } });\n throw e;\n } finally {\n waitUntil(flushAndDispose(client));\n }\n },\n );\n });\n}\n\n/**\n * Instruments a scheduled handler for ExportedHandler (env/ctx come from args).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function instrumentExportedHandlerScheduled<T extends ExportedHandler<any, any, any>>(\n handler: T,\n optionsCallback: (env: typeof cloudflareEnv) => CloudflareOptions | undefined,\n): void {\n if (!('scheduled' in handler) || typeof handler.scheduled !== 'function') {\n return;\n }\n\n handler.scheduled = ensureInstrumented(\n handler.scheduled,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args: Parameters<NonNullable<T['scheduled']>>) {\n const [controller, env, ctx] = args;\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n args[1] = instrumentEnv(env, options);\n args[2] = context;\n\n return wrapScheduledHandler(controller, options, context, () => target.apply(thisArg, args));\n },\n }),\n );\n}\n\n/**\n * Instruments a scheduled method for WorkerEntrypoint (options/context already available).\n */\nexport function instrumentWorkerEntrypointScheduled<T extends WorkerEntrypoint>(\n instance: T,\n options: CloudflareOptions,\n context: ExecutionContext,\n): void {\n if (!instance.scheduled) {\n return;\n }\n\n const original = instance.scheduled.bind(instance);\n instance.scheduled = new Proxy(original, {\n apply(target, thisArg, args: [ScheduledController]) {\n const [controller] = args;\n\n return wrapScheduledHandler(controller, options, context, () => Reflect.apply(target, thisArg, args));\n },\n });\n}\n"],"names":["withIsolationScope","init","addCloudResourceContext","startSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","captureException","flushAndDispose","ensureInstrumented","instrumentContext","options","getFinalOptions","instrumentEnv"],"mappings":"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"}
@@ -7,6 +7,7 @@ const options = require('../../options.js');
7
7
  const scopeUtils = require('../../scope-utils.js');
8
8
  const sdk = require('../../sdk.js');
9
9
  const instrumentContext = require('../../utils/instrumentContext.js');
10
+ const instrumentEnv = require('./instrumentEnv.js');
10
11
 
11
12
  /**
12
13
  * Core tail handler logic - wraps execution with Sentry instrumentation.
@@ -40,24 +41,47 @@ function instrumentExportedHandlerTail(
40
41
  handler,
41
42
  optionsCallback,
42
43
  ) {
43
- if (!('tail' in handler) || typeof handler.tail !== 'function' || instrument.isInstrumented(handler.tail)) {
44
+ if (!('tail' in handler) || typeof handler.tail !== 'function') {
44
45
  return;
45
46
  }
46
47
 
47
- handler.tail = new Proxy(handler.tail, {
48
- apply(target, thisArg, args) {
49
- const [, env, ctx] = args;
50
- const context = instrumentContext.instrumentContext(ctx);
51
- args[2] = context;
48
+ handler.tail = instrument.ensureInstrumented(
49
+ handler.tail,
50
+ original =>
51
+ new Proxy(original, {
52
+ apply(target, thisArg, args) {
53
+ const [, env, ctx] = args;
54
+ const context = instrumentContext.instrumentContext(ctx);
55
+ const options$1 = options.getFinalOptions(optionsCallback(env), env);
56
+ args[1] = instrumentEnv.instrumentEnv(env, options$1);
57
+ args[2] = context;
58
+
59
+ return wrapTailHandler(options$1, context, () => target.apply(thisArg, args));
60
+ },
61
+ }),
62
+ );
63
+ }
52
64
 
53
- const options$1 = options.getFinalOptions(optionsCallback(env), env);
65
+ /**
66
+ * Instruments a tail method for WorkerEntrypoint (options/context already available).
67
+ */
68
+ function instrumentWorkerEntrypointTail(
69
+ instance,
70
+ options,
71
+ context,
72
+ ) {
73
+ if (!instance.tail) {
74
+ return;
75
+ }
54
76
 
55
- return wrapTailHandler(options$1, context, () => target.apply(thisArg, args));
77
+ const original = instance.tail.bind(instance);
78
+ instance.tail = new Proxy(original, {
79
+ apply(target, thisArg, args) {
80
+ return wrapTailHandler(options, context, () => Reflect.apply(target, thisArg, args));
56
81
  },
57
82
  });
58
-
59
- instrument.markAsInstrumented(handler.tail);
60
83
  }
61
84
 
62
85
  exports.instrumentExportedHandlerTail = instrumentExportedHandlerTail;
86
+ exports.instrumentWorkerEntrypointTail = instrumentWorkerEntrypointTail;
63
87
  //# sourceMappingURL=instrumentTail.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentTail.js","sources":["../../../../src/instrumentations/worker/instrumentTail.ts"],"sourcesContent":["import type { ExportedHandler } from '@cloudflare/workers-types';\nimport { captureException, withIsolationScope } from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport { flushAndDispose } from '../../flush';\nimport { isInstrumented, markAsInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { addCloudResourceContext } from '../../scope-utils';\nimport { init } from '../../sdk';\nimport { instrumentContext } from '../../utils/instrumentContext';\n\n/**\n * Core tail handler logic - wraps execution with Sentry instrumentation.\n * Note: tail handlers don't create spans, just error capture.\n */\nfunction wrapTailHandler(options: CloudflareOptions, context: ExecutionContext, fn: () => unknown): unknown {\n return withIsolationScope(async isolationScope => {\n const waitUntil = context.waitUntil.bind(context);\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n try {\n return await fn();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.tail' } });\n throw e;\n } finally {\n waitUntil(flushAndDispose(client));\n }\n });\n}\n\n/**\n * Instruments a tail handler for ExportedHandler (env/ctx come from args).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function instrumentExportedHandlerTail<T extends ExportedHandler<any, any, any>>(\n handler: T,\n optionsCallback: (env: Parameters<NonNullable<T['tail']>>[1]) => CloudflareOptions | undefined,\n): void {\n if (!('tail' in handler) || typeof handler.tail !== 'function' || isInstrumented(handler.tail)) {\n return;\n }\n\n handler.tail = new Proxy(handler.tail, {\n apply(target, thisArg, args: Parameters<NonNullable<T['tail']>>) {\n const [, env, ctx] = args;\n const context = instrumentContext(ctx);\n args[2] = context;\n\n const options = getFinalOptions(optionsCallback(env), env);\n\n return wrapTailHandler(options, context, () => target.apply(thisArg, args));\n },\n });\n\n markAsInstrumented(handler.tail);\n}\n"],"names":["withIsolationScope","init","addCloudResourceContext","captureException","flushAndDispose","isInstrumented","instrumentContext","options","getFinalOptions","markAsInstrumented"],"mappings":";;;;;;;;;;AAUA;AACA;AACA;AACA;AACA,SAAS,eAAe,CAAC,OAAO,EAAqB,OAAO,EAAoB,EAAE,EAA0B;AAC5G,EAAE,OAAOA,uBAAkB,CAAC,MAAM,kBAAkB;AACpD,IAAI,MAAM,SAAA,GAAY,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;;AAErD,IAAI,MAAM,MAAA,GAASC,QAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,OAAA,EAAS,CAAC;AACrD,IAAI,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC;;AAEpC,IAAIC,kCAAuB,CAAC,cAAc,CAAC;;AAE3C,IAAI,IAAI;AACR,MAAM,OAAO,MAAM,EAAE,EAAE;AACvB,IAAI,CAAA,CAAE,OAAO,CAAC,EAAE;AAChB,MAAMC,qBAAgB,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,2BAAA,EAA4B,EAAG,CAAC;AAC/F,MAAM,MAAM,CAAC;AACb,IAAI,UAAU;AACd,MAAM,SAAS,CAACC,qBAAe,CAAC,MAAM,CAAC,CAAC;AACxC,IAAI;AACJ,EAAE,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACO,SAAS,6BAA6B;AAC7C,EAAE,OAAO;AACT,EAAE,eAAe;AACjB,EAAQ;AACR,EAAE,IAAI,EAAE,UAAU,OAAO,CAAA,IAAK,OAAO,OAAO,CAAC,IAAA,KAAS,cAAcC,yBAAc,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;AAClG,IAAI;AACJ,EAAE;;AAEF,EAAE,OAAO,CAAC,IAAA,GAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE;AACzC,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAsC;AACrE,MAAM,MAAM,GAAG,GAAG,EAAE,GAAG,CAAA,GAAI,IAAI;AAC/B,MAAM,MAAM,OAAA,GAAUC,mCAAiB,CAAC,GAAG,CAAC;AAC5C,MAAM,IAAI,CAAC,CAAC,CAAA,GAAI,OAAO;;AAEvB,MAAM,MAAMC,SAAA,GAAUC,uBAAe,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;;AAEhE,MAAM,OAAO,eAAe,CAACD,SAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACjF,IAAI,CAAC;AACL,GAAG,CAAC;;AAEJ,EAAEE,6BAAkB,CAAC,OAAO,CAAC,IAAI,CAAC;AAClC;;;;"}
1
+ {"version":3,"file":"instrumentTail.js","sources":["../../../../src/instrumentations/worker/instrumentTail.ts"],"sourcesContent":["import type { ExportedHandler, TraceItem } from '@cloudflare/workers-types';\nimport type { env as cloudflareEnv, WorkerEntrypoint } from 'cloudflare:workers';\nimport { captureException, withIsolationScope } from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport { flushAndDispose } from '../../flush';\nimport { ensureInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { addCloudResourceContext } from '../../scope-utils';\nimport { init } from '../../sdk';\nimport { instrumentContext } from '../../utils/instrumentContext';\nimport { instrumentEnv } from './instrumentEnv';\n\n/**\n * Core tail handler logic - wraps execution with Sentry instrumentation.\n * Note: tail handlers don't create spans, just error capture.\n */\nfunction wrapTailHandler(options: CloudflareOptions, context: ExecutionContext, fn: () => unknown): unknown {\n return withIsolationScope(async isolationScope => {\n const waitUntil = context.waitUntil.bind(context);\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n try {\n return await fn();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.tail' } });\n throw e;\n } finally {\n waitUntil(flushAndDispose(client));\n }\n });\n}\n\n/**\n * Instruments a tail handler for ExportedHandler (env/ctx come from args).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function instrumentExportedHandlerTail<T extends ExportedHandler<any, any, any>>(\n handler: T,\n optionsCallback: (env: typeof cloudflareEnv) => CloudflareOptions | undefined,\n): void {\n if (!('tail' in handler) || typeof handler.tail !== 'function') {\n return;\n }\n\n handler.tail = ensureInstrumented(\n handler.tail,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args: Parameters<NonNullable<T['tail']>>) {\n const [, env, ctx] = args;\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n args[1] = instrumentEnv(env, options);\n args[2] = context;\n\n return wrapTailHandler(options, context, () => target.apply(thisArg, args));\n },\n }),\n );\n}\n\n/**\n * Instruments a tail method for WorkerEntrypoint (options/context already available).\n */\nexport function instrumentWorkerEntrypointTail<T extends WorkerEntrypoint>(\n instance: T,\n options: CloudflareOptions,\n context: ExecutionContext,\n): void {\n if (!instance.tail) {\n return;\n }\n\n const original = instance.tail.bind(instance);\n instance.tail = new Proxy(original, {\n apply(target, thisArg, args: [TraceItem[]]) {\n return wrapTailHandler(options, context, () => Reflect.apply(target, thisArg, args));\n },\n });\n}\n"],"names":["withIsolationScope","init","addCloudResourceContext","captureException","flushAndDispose","ensureInstrumented","instrumentContext","options","getFinalOptions","instrumentEnv"],"mappings":";;;;;;;;;;;AAYA;AACA;AACA;AACA;AACA,SAAS,eAAe,CAAC,OAAO,EAAqB,OAAO,EAAoB,EAAE,EAA0B;AAC5G,EAAE,OAAOA,uBAAkB,CAAC,MAAM,kBAAkB;AACpD,IAAI,MAAM,SAAA,GAAY,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;;AAErD,IAAI,MAAM,MAAA,GAASC,QAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,OAAA,EAAS,CAAC;AACrD,IAAI,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC;;AAEpC,IAAIC,kCAAuB,CAAC,cAAc,CAAC;;AAE3C,IAAI,IAAI;AACR,MAAM,OAAO,MAAM,EAAE,EAAE;AACvB,IAAI,CAAA,CAAE,OAAO,CAAC,EAAE;AAChB,MAAMC,qBAAgB,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,2BAAA,EAA4B,EAAG,CAAC;AAC/F,MAAM,MAAM,CAAC;AACb,IAAI,UAAU;AACd,MAAM,SAAS,CAACC,qBAAe,CAAC,MAAM,CAAC,CAAC;AACxC,IAAI;AACJ,EAAE,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACO,SAAS,6BAA6B;AAC7C,EAAE,OAAO;AACT,EAAE,eAAe;AACjB,EAAQ;AACR,EAAE,IAAI,EAAE,UAAU,OAAO,CAAA,IAAK,OAAO,OAAO,CAAC,IAAA,KAAS,UAAU,EAAE;AAClE,IAAI;AACJ,EAAE;;AAEF,EAAE,OAAO,CAAC,IAAA,GAAOC,6BAAkB;AACnC,IAAI,OAAO,CAAC,IAAI;AAChB,IAAI,QAAA;AACJ,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE;AAC1B,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAsC;AACzE,UAAU,MAAM,GAAG,GAAG,EAAE,GAAG,CAAA,GAAI,IAAI;AACnC,UAAU,MAAM,OAAA,GAAUC,mCAAiB,CAAC,GAAG,CAAC;AAChD,UAAU,MAAMC,SAAA,GAAUC,uBAAe,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;AACpE,UAAU,IAAI,CAAC,CAAC,CAAA,GAAIC,2BAAa,CAAC,GAAG,EAAEF,SAAO,CAAC;AAC/C,UAAU,IAAI,CAAC,CAAC,CAAA,GAAI,OAAO;;AAE3B,UAAU,OAAO,eAAe,CAACA,SAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACrF,QAAQ,CAAC;AACT,OAAO,CAAC;AACR,GAAG;AACH;;AAEA;AACA;AACA;AACO,SAAS,8BAA8B;AAC9C,EAAE,QAAQ;AACV,EAAE,OAAO;AACT,EAAE,OAAO;AACT,EAAQ;AACR,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE;AACtB,IAAI;AACJ,EAAE;;AAEF,EAAE,MAAM,QAAA,GAAW,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;AAC/C,EAAE,QAAQ,CAAC,IAAA,GAAO,IAAI,KAAK,CAAC,QAAQ,EAAE;AACtC,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAiB;AAChD,MAAM,OAAO,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AAC1F,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;;;;"}