@sentry/cloudflare 10.42.0 → 10.44.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 (69) hide show
  1. package/build/cjs/index.js +3 -2
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/cjs/instrumentations/instrumentDurableObjectStorage.js +7 -2
  4. package/build/cjs/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
  5. package/build/cjs/instrumentations/worker/instrumentEmail.js +80 -0
  6. package/build/cjs/instrumentations/worker/instrumentEmail.js.map +1 -0
  7. package/build/cjs/instrumentations/worker/instrumentFetch.js +36 -0
  8. package/build/cjs/instrumentations/worker/instrumentFetch.js.map +1 -0
  9. package/build/cjs/instrumentations/worker/instrumentQueue.js +85 -0
  10. package/build/cjs/instrumentations/worker/instrumentQueue.js.map +1 -0
  11. package/build/cjs/instrumentations/worker/instrumentScheduled.js +82 -0
  12. package/build/cjs/instrumentations/worker/instrumentScheduled.js.map +1 -0
  13. package/build/cjs/instrumentations/worker/instrumentTail.js +63 -0
  14. package/build/cjs/instrumentations/worker/instrumentTail.js.map +1 -0
  15. package/build/cjs/request.js +1 -1
  16. package/build/cjs/request.js.map +1 -1
  17. package/build/cjs/withSentry.js +66 -0
  18. package/build/cjs/withSentry.js.map +1 -0
  19. package/build/cjs/wrapMethodWithSentry.js +7 -3
  20. package/build/cjs/wrapMethodWithSentry.js.map +1 -1
  21. package/build/esm/index.js +2 -2
  22. package/build/esm/instrumentations/instrumentDurableObjectStorage.js +7 -2
  23. package/build/esm/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
  24. package/build/esm/instrumentations/worker/instrumentEmail.js +78 -0
  25. package/build/esm/instrumentations/worker/instrumentEmail.js.map +1 -0
  26. package/build/esm/instrumentations/worker/instrumentFetch.js +34 -0
  27. package/build/esm/instrumentations/worker/instrumentFetch.js.map +1 -0
  28. package/build/esm/instrumentations/worker/instrumentQueue.js +83 -0
  29. package/build/esm/instrumentations/worker/instrumentQueue.js.map +1 -0
  30. package/build/esm/instrumentations/worker/instrumentScheduled.js +80 -0
  31. package/build/esm/instrumentations/worker/instrumentScheduled.js.map +1 -0
  32. package/build/esm/instrumentations/worker/instrumentTail.js +61 -0
  33. package/build/esm/instrumentations/worker/instrumentTail.js.map +1 -0
  34. package/build/esm/package.json +1 -1
  35. package/build/esm/request.js +1 -1
  36. package/build/esm/request.js.map +1 -1
  37. package/build/esm/withSentry.js +64 -0
  38. package/build/esm/withSentry.js.map +1 -0
  39. package/build/esm/wrapMethodWithSentry.js +7 -3
  40. package/build/esm/wrapMethodWithSentry.js.map +1 -1
  41. package/build/types/index.d.ts +2 -2
  42. package/build/types/index.d.ts.map +1 -1
  43. package/build/types/instrumentations/instrumentDurableObjectStorage.d.ts.map +1 -1
  44. package/build/types/instrumentations/worker/instrumentEmail.d.ts +7 -0
  45. package/build/types/instrumentations/worker/instrumentEmail.d.ts.map +1 -0
  46. package/build/types/instrumentations/worker/instrumentFetch.d.ts +7 -0
  47. package/build/types/instrumentations/worker/instrumentFetch.d.ts.map +1 -0
  48. package/build/types/instrumentations/worker/instrumentQueue.d.ts +7 -0
  49. package/build/types/instrumentations/worker/instrumentQueue.d.ts.map +1 -0
  50. package/build/types/instrumentations/worker/instrumentScheduled.d.ts +7 -0
  51. package/build/types/instrumentations/worker/instrumentScheduled.d.ts.map +1 -0
  52. package/build/types/instrumentations/worker/instrumentTail.d.ts +7 -0
  53. package/build/types/instrumentations/worker/instrumentTail.d.ts.map +1 -0
  54. package/build/types/{handler.d.ts → withSentry.d.ts} +1 -1
  55. package/build/types/withSentry.d.ts.map +1 -0
  56. package/build/types/wrapMethodWithSentry.d.ts.map +1 -1
  57. package/build/types-ts3.8/index.d.ts +2 -2
  58. package/build/types-ts3.8/instrumentations/worker/instrumentEmail.d.ts +7 -0
  59. package/build/types-ts3.8/instrumentations/worker/instrumentFetch.d.ts +7 -0
  60. package/build/types-ts3.8/instrumentations/worker/instrumentQueue.d.ts +7 -0
  61. package/build/types-ts3.8/instrumentations/worker/instrumentScheduled.d.ts +7 -0
  62. package/build/types-ts3.8/instrumentations/worker/instrumentTail.d.ts +7 -0
  63. package/build/types-ts3.8/{handler.d.ts → withSentry.d.ts} +1 -1
  64. package/package.json +4 -4
  65. package/build/cjs/handler.js +0 -251
  66. package/build/cjs/handler.js.map +0 -1
  67. package/build/esm/handler.js +0 -249
  68. package/build/esm/handler.js.map +0 -1
  69. package/build/types/handler.d.ts.map +0 -1
@@ -44,13 +44,17 @@ function wrapMethodWithSentry(
44
44
 
45
45
  const waitUntil = context?.waitUntil?.bind?.(context);
46
46
 
47
- const currentClient = scope.getClient();
48
- if (!currentClient) {
47
+ let currentClient = scope.getClient();
48
+ // Check if client exists AND is still usable (transport not disposed)
49
+ // This handles the case where a previous handler disposed the client
50
+ // but the scope still holds a reference to it (e.g., alarm handlers in Durable Objects)
51
+ if (!currentClient?.getTransport()) {
49
52
  const client = sdk.init({ ...wrapperOptions.options, ctx: context });
50
53
  scope.setClient(client);
54
+ currentClient = client;
51
55
  }
52
56
 
53
- const clientToDispose = currentClient || scope.getClient();
57
+ const clientToDispose = currentClient;
54
58
 
55
59
  if (!wrapperOptions.spanName) {
56
60
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"wrapMethodWithSentry.js","sources":["../../src/wrapMethodWithSentry.ts"],"sourcesContent":["import type { DurableObjectStorage } from '@cloudflare/workers-types';\nimport {\n captureException,\n getClient,\n isThenable,\n type Scope,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startSpan,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from './client';\nimport { flushAndDispose } from './flush';\nimport { isInstrumented, markAsInstrumented } from './instrument';\nimport { init } from './sdk';\n\n/** Extended DurableObjectState with originalStorage exposed by instrumentContext */\ninterface InstrumentedDurableObjectState extends DurableObjectState {\n originalStorage?: DurableObjectStorage;\n}\n\ntype MethodWrapperOptions = {\n spanName?: string;\n spanOp?: string;\n options: CloudflareOptions;\n context: ExecutionContext | DurableObjectState;\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 tracing.\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 if (isInstrumented(handler)) {\n return handler;\n }\n\n if (!noMark) {\n markAsInstrumented(handler);\n }\n\n return new Proxy(handler, {\n apply(target, thisArg, args: Parameters<T>) {\n const currentClient = getClient();\n // if a client is already set, use withScope, otherwise use withIsolationScope\n const sentryWithScope = currentClient ? withScope : withIsolationScope;\n\n const wrappedFunction = (scope: Scope): 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 = wrapperOptions.context as InstrumentedDurableObjectState | undefined;\n\n const waitUntil = context?.waitUntil?.bind?.(context);\n\n const currentClient = scope.getClient();\n if (!currentClient) {\n const client = init({ ...wrapperOptions.options, ctx: context as unknown as ExecutionContext | undefined });\n scope.setClient(client);\n }\n\n const clientToDispose = currentClient || scope.getClient();\n\n if (!wrapperOptions.spanName) {\n try {\n if (callback) {\n callback(...args);\n }\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(\n (res: unknown) => {\n waitUntil?.(flushAndDispose(clientToDispose));\n return res;\n },\n (e: unknown) => {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(flushAndDispose(clientToDispose));\n throw e;\n },\n );\n } else {\n waitUntil?.(flushAndDispose(clientToDispose));\n return result;\n }\n } catch (e) {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(flushAndDispose(clientToDispose));\n throw e;\n }\n }\n\n const attributes = wrapperOptions.spanOp\n ? {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: wrapperOptions.spanOp,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.durable_object',\n }\n : {};\n\n return startSpan({ name: wrapperOptions.spanName, attributes }, () => {\n try {\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(\n (res: unknown) => {\n waitUntil?.(flushAndDispose(clientToDispose));\n return res;\n },\n (e: unknown) => {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(flushAndDispose(clientToDispose));\n throw e;\n },\n );\n } else {\n waitUntil?.(flushAndDispose(clientToDispose));\n return result;\n }\n } catch (e) {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(flushAndDispose(clientToDispose));\n throw e;\n }\n });\n };\n\n return sentryWithScope(wrappedFunction);\n },\n });\n}\n"],"names":["isInstrumented","markAsInstrumented","getClient","withScope","withIsolationScope","init","isThenable","flushAndDispose","captureException","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","startSpan"],"mappings":"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"}
1
+ {"version":3,"file":"wrapMethodWithSentry.js","sources":["../../src/wrapMethodWithSentry.ts"],"sourcesContent":["import type { DurableObjectStorage } from '@cloudflare/workers-types';\nimport {\n captureException,\n getClient,\n isThenable,\n type Scope,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startSpan,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from './client';\nimport { flushAndDispose } from './flush';\nimport { isInstrumented, markAsInstrumented } from './instrument';\nimport { init } from './sdk';\n\n/** Extended DurableObjectState with originalStorage exposed by instrumentContext */\ninterface InstrumentedDurableObjectState extends DurableObjectState {\n originalStorage?: DurableObjectStorage;\n}\n\ntype MethodWrapperOptions = {\n spanName?: string;\n spanOp?: string;\n options: CloudflareOptions;\n context: ExecutionContext | DurableObjectState;\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 tracing.\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 if (isInstrumented(handler)) {\n return handler;\n }\n\n if (!noMark) {\n markAsInstrumented(handler);\n }\n\n return new Proxy(handler, {\n apply(target, thisArg, args: Parameters<T>) {\n const currentClient = getClient();\n // if a client is already set, use withScope, otherwise use withIsolationScope\n const sentryWithScope = currentClient ? withScope : withIsolationScope;\n\n const wrappedFunction = (scope: Scope): 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 = wrapperOptions.context as InstrumentedDurableObjectState | undefined;\n\n const waitUntil = context?.waitUntil?.bind?.(context);\n\n let currentClient = 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 if (!currentClient?.getTransport()) {\n const client = init({ ...wrapperOptions.options, ctx: context as unknown as ExecutionContext | undefined });\n scope.setClient(client);\n currentClient = client;\n }\n\n const clientToDispose = currentClient;\n\n if (!wrapperOptions.spanName) {\n try {\n if (callback) {\n callback(...args);\n }\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(\n (res: unknown) => {\n waitUntil?.(flushAndDispose(clientToDispose));\n return res;\n },\n (e: unknown) => {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(flushAndDispose(clientToDispose));\n throw e;\n },\n );\n } else {\n waitUntil?.(flushAndDispose(clientToDispose));\n return result;\n }\n } catch (e) {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(flushAndDispose(clientToDispose));\n throw e;\n }\n }\n\n const attributes = wrapperOptions.spanOp\n ? {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: wrapperOptions.spanOp,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.durable_object',\n }\n : {};\n\n return startSpan({ name: wrapperOptions.spanName, attributes }, () => {\n try {\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(\n (res: unknown) => {\n waitUntil?.(flushAndDispose(clientToDispose));\n return res;\n },\n (e: unknown) => {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(flushAndDispose(clientToDispose));\n throw e;\n },\n );\n } else {\n waitUntil?.(flushAndDispose(clientToDispose));\n return result;\n }\n } catch (e) {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(flushAndDispose(clientToDispose));\n throw e;\n }\n });\n };\n\n return sentryWithScope(wrappedFunction);\n },\n });\n}\n"],"names":["isInstrumented","markAsInstrumented","getClient","withScope","withIsolationScope","init","isThenable","flushAndDispose","captureException","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","startSpan"],"mappings":";;;;;;;AAiBA;;AAgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,oBAAoB;AACpC,EAAE,cAAc;AAChB,EAAE,OAAO;AACT,EAAE,QAAQ;AACV,EAAE,MAAM;AACR,EAAK;AACL,EAAE,IAAIA,yBAAc,CAAC,OAAO,CAAC,EAAE;AAC/B,IAAI,OAAO,OAAO;AAClB,EAAE;;AAEF,EAAE,IAAI,CAAC,MAAM,EAAE;AACf,IAAIC,6BAAkB,CAAC,OAAO,CAAC;AAC/B,EAAE;;AAEF,EAAE,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE;AAC5B,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAiB;AAChD,MAAM,MAAM,aAAA,GAAgBC,cAAS,EAAE;AACvC;AACA,MAAM,MAAM,eAAA,GAAkB,gBAAgBC,cAAA,GAAYC,uBAAkB;;AAE5E,MAAM,MAAM,eAAA,GAAkB,CAAC,KAAK,KAAqB;AACzD;AACA;AACA;AACA,QAAQ,MAAM,OAAA,GAAU,cAAc,CAAC,OAAA;;AAEvC,QAAQ,MAAM,SAAA,GAAY,OAAO,EAAE,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC;;AAE7D,QAAQ,IAAI,aAAA,GAAgB,KAAK,CAAC,SAAS,EAAE;AAC7C;AACA;AACA;AACA,QAAQ,IAAI,CAAC,aAAa,EAAE,YAAY,EAAE,EAAE;AAC5C,UAAU,MAAM,MAAA,GAASC,QAAI,CAAC,EAAE,GAAG,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,OAAA,GAAoD,CAAC;AACrH,UAAU,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC;AACjC,UAAU,aAAA,GAAgB,MAAM;AAChC,QAAQ;;AAER,QAAQ,MAAM,eAAA,GAAkB,aAAa;;AAE7C,QAAQ,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE;AACtC,UAAU,IAAI;AACd,YAAY,IAAI,QAAQ,EAAE;AAC1B,cAAc,QAAQ,CAAC,GAAG,IAAI,CAAC;AAC/B,YAAY;AACZ,YAAY,MAAM,MAAA,GAAS,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;;AAE/D,YAAY,IAAIC,eAAU,CAAC,MAAM,CAAC,EAAE;AACpC,cAAc,OAAO,MAAM,CAAC,IAAI;AAChC,gBAAgB,CAAC,GAAG,KAAc;AAClC,kBAAkB,SAAS,GAAGC,qBAAe,CAAC,eAAe,CAAC,CAAC;AAC/D,kBAAkB,OAAO,GAAG;AAC5B,gBAAgB,CAAC;AACjB,gBAAgB,CAAC,CAAC,KAAc;AAChC,kBAAkBC,qBAAgB,CAAC,CAAC,EAAE;AACtC,oBAAoB,SAAS,EAAE;AAC/B,sBAAsB,IAAI,EAAE,qCAAqC;AACjE,sBAAsB,OAAO,EAAE,KAAK;AACpC,qBAAqB;AACrB,mBAAmB,CAAC;AACpB,kBAAkB,SAAS,GAAGD,qBAAe,CAAC,eAAe,CAAC,CAAC;AAC/D,kBAAkB,MAAM,CAAC;AACzB,gBAAgB,CAAC;AACjB,eAAe;AACf,YAAY,OAAO;AACnB,cAAc,SAAS,GAAGA,qBAAe,CAAC,eAAe,CAAC,CAAC;AAC3D,cAAc,OAAO,MAAM;AAC3B,YAAY;AACZ,UAAU,CAAA,CAAE,OAAO,CAAC,EAAE;AACtB,YAAYC,qBAAgB,CAAC,CAAC,EAAE;AAChC,cAAc,SAAS,EAAE;AACzB,gBAAgB,IAAI,EAAE,qCAAqC;AAC3D,gBAAgB,OAAO,EAAE,KAAK;AAC9B,eAAe;AACf,aAAa,CAAC;AACd,YAAY,SAAS,GAAGD,qBAAe,CAAC,eAAe,CAAC,CAAC;AACzD,YAAY,MAAM,CAAC;AACnB,UAAU;AACV,QAAQ;;AAER,QAAQ,MAAM,UAAA,GAAa,cAAc,CAAC;AAC1C,YAAY;AACZ,cAAc,CAACE,iCAA4B,GAAG,cAAc,CAAC,MAAM;AACnE,cAAc,CAACC,qCAAgC,GAAG,qCAAqC;AACvF;AACA,YAAY,EAAE;;AAEd,QAAQ,OAAOC,cAAS,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,QAAQ,EAAE,UAAA,EAAY,EAAE,MAAM;AAC9E,UAAU,IAAI;AACd,YAAY,MAAM,MAAA,GAAS,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;;AAE/D,YAAY,IAAIL,eAAU,CAAC,MAAM,CAAC,EAAE;AACpC,cAAc,OAAO,MAAM,CAAC,IAAI;AAChC,gBAAgB,CAAC,GAAG,KAAc;AAClC,kBAAkB,SAAS,GAAGC,qBAAe,CAAC,eAAe,CAAC,CAAC;AAC/D,kBAAkB,OAAO,GAAG;AAC5B,gBAAgB,CAAC;AACjB,gBAAgB,CAAC,CAAC,KAAc;AAChC,kBAAkBC,qBAAgB,CAAC,CAAC,EAAE;AACtC,oBAAoB,SAAS,EAAE;AAC/B,sBAAsB,IAAI,EAAE,qCAAqC;AACjE,sBAAsB,OAAO,EAAE,KAAK;AACpC,qBAAqB;AACrB,mBAAmB,CAAC;AACpB,kBAAkB,SAAS,GAAGD,qBAAe,CAAC,eAAe,CAAC,CAAC;AAC/D,kBAAkB,MAAM,CAAC;AACzB,gBAAgB,CAAC;AACjB,eAAe;AACf,YAAY,OAAO;AACnB,cAAc,SAAS,GAAGA,qBAAe,CAAC,eAAe,CAAC,CAAC;AAC3D,cAAc,OAAO,MAAM;AAC3B,YAAY;AACZ,UAAU,CAAA,CAAE,OAAO,CAAC,EAAE;AACtB,YAAYC,qBAAgB,CAAC,CAAC,EAAE;AAChC,cAAc,SAAS,EAAE;AACzB,gBAAgB,IAAI,EAAE,qCAAqC;AAC3D,gBAAgB,OAAO,EAAE,KAAK;AAC9B,eAAe;AACf,aAAa,CAAC;AACd,YAAY,SAAS,GAAGD,qBAAe,CAAC,eAAe,CAAC,CAAC;AACzD,YAAY,MAAM,CAAC;AACnB,UAAU;AACV,QAAQ,CAAC,CAAC;AACV,MAAM,CAAC;;AAEP,MAAM,OAAO,eAAe,CAAC,eAAe,CAAC;AAC7C,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;;;"}
@@ -1,5 +1,5 @@
1
- export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, captureCheckIn, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, close, consoleIntegration, consoleLoggingIntegration, continueTrace, createConsolaReporter, createLangChainCallbackHandler, createTransport, dedupeIntegration, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, getTraceMetaTags, growthbookIntegration, inboundFiltersIntegration, instrumentAnthropicAiClient, instrumentGoogleGenAIClient, instrumentLangGraph, instrumentOpenAiClient, instrumentPostgresJsSql, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, linkedErrorsIntegration, logger, metrics, moduleMetadataIntegration, requestDataIntegration, rewriteFramesIntegration, setContext, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSpan, startSpanManual, supabaseIntegration, suppressTracing, trpcMiddleware, updateSpanName, withActiveSpan, withIsolationScope, withMonitor, withScope, wrapMcpServerWithSentry, zodErrorsIntegration } from '@sentry/core';
2
- export { withSentry } from './handler.js';
1
+ export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, captureCheckIn, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, close, consoleIntegration, consoleLoggingIntegration, continueTrace, createConsolaReporter, createLangChainCallbackHandler, createTransport, dedupeIntegration, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, getTraceMetaTags, growthbookIntegration, inboundFiltersIntegration, instrumentAnthropicAiClient, instrumentGoogleGenAIClient, instrumentLangGraph, instrumentOpenAiClient, instrumentPostgresJsSql, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, linkedErrorsIntegration, logger, metrics, moduleMetadataIntegration, requestDataIntegration, rewriteFramesIntegration, setContext, setConversationId, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSpan, startSpanManual, supabaseIntegration, suppressTracing, trpcMiddleware, updateSpanName, withActiveSpan, withIsolationScope, withMonitor, withScope, wrapMcpServerWithSentry, zodErrorsIntegration } from '@sentry/core';
2
+ export { withSentry } from './withSentry.js';
3
3
  export { instrumentDurableObjectWithSentry } from './durableobject.js';
4
4
  export { sentryPagesPlugin } from './pages-plugin.js';
5
5
  export { wrapRequestHandler } from './request.js';
@@ -13,8 +13,13 @@ const STORAGE_METHODS_TO_INSTRUMENT = ['get', 'put', 'delete', 'list'] ;
13
13
  */
14
14
  function instrumentDurableObjectStorage(storage) {
15
15
  return new Proxy(storage, {
16
- get(target, prop, receiver) {
17
- const original = Reflect.get(target, prop, receiver);
16
+ get(target, prop, _receiver) {
17
+ // Use `target` as the receiver instead of the proxy (`_receiver`).
18
+ // Native workerd getters (e.g., `storage.sql`) validate `this` via
19
+ // internal slots. Passing the proxy as receiver breaks that check,
20
+ // causing "Illegal invocation: function called with incorrect `this`
21
+ // reference" errors.
22
+ const original = Reflect.get(target, prop, target);
18
23
 
19
24
  if (typeof original !== 'function') {
20
25
  return original;
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentDurableObjectStorage.js","sources":["../../../src/instrumentations/instrumentDurableObjectStorage.ts"],"sourcesContent":["import type { DurableObjectStorage } from '@cloudflare/workers-types';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan } from '@sentry/core';\n\nconst STORAGE_METHODS_TO_INSTRUMENT = ['get', 'put', 'delete', 'list'] as const;\n\ntype StorageMethod = (typeof STORAGE_METHODS_TO_INSTRUMENT)[number];\n\n/**\n * Instruments DurableObjectStorage methods with Sentry spans.\n *\n * Wraps the following async methods:\n * - get, put, delete, list (KV API)\n *\n * @param storage - The DurableObjectStorage instance to instrument\n * @returns An instrumented DurableObjectStorage instance\n */\nexport function instrumentDurableObjectStorage(storage: DurableObjectStorage): DurableObjectStorage {\n return new Proxy(storage, {\n get(target, prop, receiver) {\n const original = Reflect.get(target, prop, receiver);\n\n if (typeof original !== 'function') {\n return original;\n }\n\n const methodName = prop as string;\n if (!STORAGE_METHODS_TO_INSTRUMENT.includes(methodName as StorageMethod)) {\n return (original as (...args: unknown[]) => unknown).bind(target);\n }\n\n return function (this: unknown, ...args: unknown[]) {\n return startSpan(\n {\n // Use underscore naming to match Cloudflare's native instrumentation (e.g., \"durable_object_storage_get\")\n name: `durable_object_storage_${methodName}`,\n op: 'db',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.cloudflare.durable_object',\n 'db.system.name': 'cloudflare.durable_object.storage',\n 'db.operation.name': methodName,\n },\n },\n () => {\n return (original as (...args: unknown[]) => unknown).apply(target, args);\n },\n );\n };\n },\n });\n}\n"],"names":[],"mappings":";;AAGA,MAAM,6BAAA,GAAgC,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAA;;AAIrE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,8BAA8B,CAAC,OAAO,EAA8C;AACpG,EAAE,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE;AAC5B,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE;AAChC,MAAM,MAAM,QAAA,GAAW,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC;;AAE1D,MAAM,IAAI,OAAO,QAAA,KAAa,UAAU,EAAE;AAC1C,QAAQ,OAAO,QAAQ;AACvB,MAAM;;AAEN,MAAM,MAAM,UAAA,GAAa,IAAA;AACzB,MAAM,IAAI,CAAC,6BAA6B,CAAC,QAAQ,CAAC,UAAA,EAA4B,EAAE;AAChF,QAAQ,OAAO,CAAC,QAAA,GAA6C,IAAI,CAAC,MAAM,CAAC;AACzE,MAAM;;AAEN,MAAM,OAAO,WAAyB,GAAG,IAAI,EAAa;AAC1D,QAAQ,OAAO,SAAS;AACxB,UAAU;AACV;AACA,YAAY,IAAI,EAAE,CAAC,uBAAuB,EAAE,UAAU,CAAC,CAAA;AACA,YAAA,EAAA,EAAA,IAAA;AACA,YAAA,UAAA,EAAA;AACA,cAAA,CAAA,gCAAA,GAAA,mCAAA;AACA,cAAA,gBAAA,EAAA,mCAAA;AACA,cAAA,mBAAA,EAAA,UAAA;AACA,aAAA;AACA,WAAA;AACA,UAAA,MAAA;AACA,YAAA,OAAA,CAAA,QAAA,GAAA,KAAA,CAAA,MAAA,EAAA,IAAA,CAAA;AACA,UAAA,CAAA;AACA,SAAA;AACA,MAAA,CAAA;AACA,IAAA,CAAA;AACA,GAAA,CAAA;AACA;;;;"}
1
+ {"version":3,"file":"instrumentDurableObjectStorage.js","sources":["../../../src/instrumentations/instrumentDurableObjectStorage.ts"],"sourcesContent":["import type { DurableObjectStorage } from '@cloudflare/workers-types';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan } from '@sentry/core';\n\nconst STORAGE_METHODS_TO_INSTRUMENT = ['get', 'put', 'delete', 'list'] as const;\n\ntype StorageMethod = (typeof STORAGE_METHODS_TO_INSTRUMENT)[number];\n\n/**\n * Instruments DurableObjectStorage methods with Sentry spans.\n *\n * Wraps the following async methods:\n * - get, put, delete, list (KV API)\n *\n * @param storage - The DurableObjectStorage instance to instrument\n * @returns An instrumented DurableObjectStorage instance\n */\nexport function instrumentDurableObjectStorage(storage: DurableObjectStorage): DurableObjectStorage {\n return new Proxy(storage, {\n get(target, prop, _receiver) {\n // Use `target` as the receiver instead of the proxy (`_receiver`).\n // Native workerd getters (e.g., `storage.sql`) validate `this` via\n // internal slots. Passing the proxy as receiver breaks that check,\n // causing \"Illegal invocation: function called with incorrect `this`\n // reference\" errors.\n const original = Reflect.get(target, prop, target);\n\n if (typeof original !== 'function') {\n return original;\n }\n\n const methodName = prop as string;\n if (!STORAGE_METHODS_TO_INSTRUMENT.includes(methodName as StorageMethod)) {\n return (original as (...args: unknown[]) => unknown).bind(target);\n }\n\n return function (this: unknown, ...args: unknown[]) {\n return startSpan(\n {\n // Use underscore naming to match Cloudflare's native instrumentation (e.g., \"durable_object_storage_get\")\n name: `durable_object_storage_${methodName}`,\n op: 'db',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.cloudflare.durable_object',\n 'db.system.name': 'cloudflare.durable_object.storage',\n 'db.operation.name': methodName,\n },\n },\n () => {\n return (original as (...args: unknown[]) => unknown).apply(target, args);\n },\n );\n };\n },\n });\n}\n"],"names":[],"mappings":";;AAGA,MAAM,6BAAA,GAAgC,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAA;;AAIrE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,8BAA8B,CAAC,OAAO,EAA8C;AACpG,EAAE,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE;AAC5B,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;AACjC;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,QAAA,GAAW,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;;AAExD,MAAM,IAAI,OAAO,QAAA,KAAa,UAAU,EAAE;AAC1C,QAAQ,OAAO,QAAQ;AACvB,MAAM;;AAEN,MAAM,MAAM,UAAA,GAAa,IAAA;AACzB,MAAM,IAAI,CAAC,6BAA6B,CAAC,QAAQ,CAAC,UAAA,EAA4B,EAAE;AAChF,QAAQ,OAAO,CAAC,QAAA,GAA6C,IAAI,CAAC,MAAM,CAAC;AACzE,MAAM;;AAEN,MAAM,OAAO,WAAyB,GAAG,IAAI,EAAa;AAC1D,QAAQ,OAAO,SAAS;AACxB,UAAU;AACV;AACA,YAAY,IAAI,EAAE,CAAC,uBAAuB,EAAE,UAAU,CAAC,CAAA;AACA,YAAA,EAAA,EAAA,IAAA;AACA,YAAA,UAAA,EAAA;AACA,cAAA,CAAA,gCAAA,GAAA,mCAAA;AACA,cAAA,gBAAA,EAAA,mCAAA;AACA,cAAA,mBAAA,EAAA,UAAA;AACA,aAAA;AACA,WAAA;AACA,UAAA,MAAA;AACA,YAAA,OAAA,CAAA,QAAA,GAAA,KAAA,CAAA,MAAA,EAAA,IAAA,CAAA;AACA,UAAA,CAAA;AACA,SAAA;AACA,MAAA,CAAA;AACA,IAAA,CAAA;AACA,GAAA,CAAA;AACA;;;;"}
@@ -0,0 +1,78 @@
1
+ import { withIsolationScope, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, captureException } from '@sentry/core';
2
+ import { flushAndDispose } from '../../flush.js';
3
+ import { isInstrumented, markAsInstrumented } from '../../instrument.js';
4
+ import { getFinalOptions } from '../../options.js';
5
+ import { addCloudResourceContext } from '../../scope-utils.js';
6
+ import { init } from '../../sdk.js';
7
+ import { instrumentContext } from '../../utils/instrumentContext.js';
8
+
9
+ /**
10
+ * Core email handler logic - wraps execution with Sentry instrumentation.
11
+ */
12
+ function wrapEmailHandler(
13
+ emailMessage,
14
+ options,
15
+ context,
16
+ fn,
17
+ ) {
18
+ return withIsolationScope(isolationScope => {
19
+ const waitUntil = context.waitUntil.bind(context);
20
+
21
+ const client = init({ ...options, ctx: context });
22
+ isolationScope.setClient(client);
23
+
24
+ addCloudResourceContext(isolationScope);
25
+
26
+ return startSpan(
27
+ {
28
+ op: 'faas.email',
29
+ name: `Handle Email ${emailMessage.to}`,
30
+ attributes: {
31
+ 'faas.trigger': 'email',
32
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.email',
33
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',
34
+ },
35
+ },
36
+ async () => {
37
+ try {
38
+ return await fn();
39
+ } catch (e) {
40
+ captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.email' } });
41
+ throw e;
42
+ } finally {
43
+ waitUntil(flushAndDispose(client));
44
+ }
45
+ },
46
+ );
47
+ });
48
+ }
49
+
50
+ /**
51
+ * Instruments an email handler for ExportedHandler (env/ctx come from args).
52
+ */
53
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
+ function instrumentExportedHandlerEmail(
55
+ handler,
56
+ optionsCallback,
57
+ ) {
58
+ if (!('email' in handler) || typeof handler.email !== 'function' || isInstrumented(handler.email)) {
59
+ return;
60
+ }
61
+
62
+ handler.email = new Proxy(handler.email, {
63
+ apply(target, thisArg, args) {
64
+ const [emailMessage, env, ctx] = args;
65
+ const context = instrumentContext(ctx);
66
+ args[2] = context;
67
+
68
+ const options = getFinalOptions(optionsCallback(env), env);
69
+
70
+ return wrapEmailHandler(emailMessage, options, context, () => target.apply(thisArg, args));
71
+ },
72
+ });
73
+
74
+ markAsInstrumented(handler.email);
75
+ }
76
+
77
+ export { instrumentExportedHandlerEmail };
78
+ //# sourceMappingURL=instrumentEmail.js.map
@@ -0,0 +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":[],"mappings":";;;;;;;;AAgBA;AACA;AACA;AACA,SAAS,gBAAgB;AACzB,EAAE,YAAY;AACd,EAAE,OAAO;AACT,EAAE,OAAO;AACT,EAAE,EAAE;AACJ,EAAW;AACX,EAAE,OAAO,kBAAkB,CAAC,cAAA,IAAkB;AAC9C,IAAI,MAAM,SAAA,GAAY,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;;AAErD,IAAI,MAAM,MAAA,GAAS,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,OAAA,EAAS,CAAC;AACrD,IAAI,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC;;AAEpC,IAAI,uBAAuB,CAAC,cAAc,CAAC;;AAE3C,IAAI,OAAO,SAAS;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,CAAA,gCAAA,GAAA,4BAAA;AACA,UAAA,CAAA,gCAAA,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,UAAA,gBAAA,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,CAAA,eAAA,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,IAAA,cAAA,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,GAAA,iBAAA,CAAA,GAAA,CAAA;AACA,MAAA,IAAA,CAAA,CAAA,CAAA,GAAA,OAAA;;AAEA,MAAA,MAAA,OAAA,GAAA,eAAA,CAAA,eAAA,CAAA,GAAA,CAAA,EAAA,GAAA,CAAA;;AAEA,MAAA,OAAA,gBAAA,CAAA,YAAA,EAAA,OAAA,EAAA,OAAA,EAAA,MAAA,MAAA,CAAA,KAAA,CAAA,OAAA,EAAA,IAAA,CAAA,CAAA;AACA,IAAA,CAAA;AACA,GAAA,CAAA;;AAEA,EAAA,kBAAA,CAAA,OAAA,CAAA,KAAA,CAAA;AACA;;;;"}
@@ -0,0 +1,34 @@
1
+ import { isInstrumented, markAsInstrumented } from '../../instrument.js';
2
+ import { getFinalOptions } from '../../options.js';
3
+ import { wrapRequestHandler } from '../../request.js';
4
+ import { instrumentContext } from '../../utils/instrumentContext.js';
5
+
6
+ /**
7
+ * Instruments a fetch handler for ExportedHandler (env/ctx come from args).
8
+ */
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ function instrumentExportedHandlerFetch(
11
+ handler,
12
+ optionsCallback,
13
+ ) {
14
+ if (!('fetch' in handler) || typeof handler.fetch !== 'function' || isInstrumented(handler.fetch)) {
15
+ return;
16
+ }
17
+
18
+ handler.fetch = new Proxy(handler.fetch, {
19
+ apply(target, thisArg, args) {
20
+ const [request, env, ctx] = args;
21
+ const context = instrumentContext(ctx);
22
+ args[2] = context;
23
+
24
+ const options = getFinalOptions(optionsCallback(env), env);
25
+
26
+ return wrapRequestHandler({ options, request, context }, () => target.apply(thisArg, args));
27
+ },
28
+ });
29
+
30
+ markAsInstrumented(handler.fetch);
31
+ }
32
+
33
+ export { instrumentExportedHandlerFetch };
34
+ //# sourceMappingURL=instrumentFetch.js.map
@@ -0,0 +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":[],"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,cAAc,cAAc,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,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAA,GAAI,IAAI;AACtC,MAAM,MAAM,OAAA,GAAU,iBAAiB,CAAC,GAAG,CAAC;AAC5C,MAAM,IAAI,CAAC,CAAC,CAAA,GAAI,OAAO;;AAEvB,MAAM,MAAM,OAAA,GAAU,eAAe,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;;AAEhE,MAAM,OAAO,kBAAkB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAA,EAAS,EAAE,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACjG,IAAI,CAAC;AACL,GAAG,CAAC;;AAEJ,EAAE,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC;AACnC;;;;"}
@@ -0,0 +1,83 @@
1
+ import { withIsolationScope, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, captureException } from '@sentry/core';
2
+ import { flushAndDispose } from '../../flush.js';
3
+ import { isInstrumented, markAsInstrumented } from '../../instrument.js';
4
+ import { getFinalOptions } from '../../options.js';
5
+ import { addCloudResourceContext } from '../../scope-utils.js';
6
+ import { init } from '../../sdk.js';
7
+ import { instrumentContext } from '../../utils/instrumentContext.js';
8
+
9
+ /**
10
+ * Core queue handler logic - wraps execution with Sentry instrumentation.
11
+ */
12
+ function wrapQueueHandler(
13
+ batch,
14
+ options,
15
+ context,
16
+ fn,
17
+ ) {
18
+ return withIsolationScope(isolationScope => {
19
+ const waitUntil = context.waitUntil.bind(context);
20
+
21
+ const client = init({ ...options, ctx: context });
22
+ isolationScope.setClient(client);
23
+
24
+ addCloudResourceContext(isolationScope);
25
+
26
+ return startSpan(
27
+ {
28
+ op: 'faas.queue',
29
+ name: `process ${batch.queue}`,
30
+ attributes: {
31
+ 'faas.trigger': 'pubsub',
32
+ 'messaging.destination.name': batch.queue,
33
+ 'messaging.system': 'cloudflare',
34
+ 'messaging.batch.message_count': batch.messages.length,
35
+ 'messaging.message.retry.count': batch.messages.reduce((acc, message) => acc + message.attempts - 1, 0),
36
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'queue.process',
37
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.queue',
38
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',
39
+ },
40
+ },
41
+ async () => {
42
+ try {
43
+ return await fn();
44
+ } catch (e) {
45
+ captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.queue' } });
46
+ throw e;
47
+ } finally {
48
+ waitUntil(flushAndDispose(client));
49
+ }
50
+ },
51
+ );
52
+ });
53
+ }
54
+
55
+ /**
56
+ * Instruments a queue handler for ExportedHandler (env/ctx come from args).
57
+ */
58
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
+ function instrumentExportedHandlerQueue(
60
+ handler,
61
+ optionsCallback,
62
+ ) {
63
+ if (!('queue' in handler) || typeof handler.queue !== 'function' || isInstrumented(handler.queue)) {
64
+ return;
65
+ }
66
+
67
+ handler.queue = new Proxy(handler.queue, {
68
+ apply(target, thisArg, args) {
69
+ const [batch, env, ctx] = args;
70
+ const context = instrumentContext(ctx);
71
+ args[2] = context;
72
+
73
+ const options = getFinalOptions(optionsCallback(env), env);
74
+
75
+ return wrapQueueHandler(batch, options, context, () => target.apply(thisArg, args));
76
+ },
77
+ });
78
+
79
+ markAsInstrumented(handler.queue);
80
+ }
81
+
82
+ export { instrumentExportedHandlerQueue };
83
+ //# sourceMappingURL=instrumentQueue.js.map
@@ -0,0 +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":[],"mappings":";;;;;;;;AAiBA;AACA;AACA;AACA,SAAS,gBAAgB;AACzB,EAAE,KAAK;AACP,EAAE,OAAO;AACT,EAAE,OAAO;AACT,EAAE,EAAE;AACJ,EAAW;AACX,EAAE,OAAO,kBAAkB,CAAC,cAAA,IAAkB;AAC9C,IAAI,MAAM,SAAA,GAAY,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;;AAErD,IAAI,MAAM,MAAA,GAAS,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,OAAA,EAAS,CAAC;AACrD,IAAI,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC;;AAEpC,IAAI,uBAAuB,CAAC,cAAc,CAAC;;AAE3C,IAAI,OAAO,SAAS;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,CAAA,4BAAA,GAAA,eAAA;AACA,UAAA,CAAA,gCAAA,GAAA,4BAAA;AACA,UAAA,CAAA,gCAAA,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,UAAA,gBAAA,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,CAAA,eAAA,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,IAAA,cAAA,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,GAAA,iBAAA,CAAA,GAAA,CAAA;AACA,MAAA,IAAA,CAAA,CAAA,CAAA,GAAA,OAAA;;AAEA,MAAA,MAAA,OAAA,GAAA,eAAA,CAAA,eAAA,CAAA,GAAA,CAAA,EAAA,GAAA,CAAA;;AAEA,MAAA,OAAA,gBAAA,CAAA,KAAA,EAAA,OAAA,EAAA,OAAA,EAAA,MAAA,MAAA,CAAA,KAAA,CAAA,OAAA,EAAA,IAAA,CAAA,CAAA;AACA,IAAA,CAAA;AACA,GAAA,CAAA;;AAEA,EAAA,kBAAA,CAAA,OAAA,CAAA,KAAA,CAAA;AACA;;;;"}
@@ -0,0 +1,80 @@
1
+ import { withIsolationScope, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, captureException } from '@sentry/core';
2
+ import { flushAndDispose } from '../../flush.js';
3
+ import { isInstrumented, markAsInstrumented } from '../../instrument.js';
4
+ import { getFinalOptions } from '../../options.js';
5
+ import { addCloudResourceContext } from '../../scope-utils.js';
6
+ import { init } from '../../sdk.js';
7
+ import { instrumentContext } from '../../utils/instrumentContext.js';
8
+
9
+ /**
10
+ * Core scheduled handler logic - wraps execution with Sentry instrumentation.
11
+ */
12
+ function wrapScheduledHandler(
13
+ controller,
14
+ options,
15
+ context,
16
+ fn,
17
+ ) {
18
+ return withIsolationScope(isolationScope => {
19
+ const waitUntil = context.waitUntil.bind(context);
20
+
21
+ const client = init({ ...options, ctx: context });
22
+ isolationScope.setClient(client);
23
+
24
+ addCloudResourceContext(isolationScope);
25
+
26
+ return startSpan(
27
+ {
28
+ op: 'faas.cron',
29
+ name: `Scheduled Cron ${controller.cron}`,
30
+ attributes: {
31
+ 'faas.cron': controller.cron,
32
+ 'faas.time': new Date(controller.scheduledTime).toISOString(),
33
+ 'faas.trigger': 'timer',
34
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.scheduled',
35
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',
36
+ },
37
+ },
38
+ async () => {
39
+ try {
40
+ return await fn();
41
+ } catch (e) {
42
+ captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.scheduled' } });
43
+ throw e;
44
+ } finally {
45
+ waitUntil(flushAndDispose(client));
46
+ }
47
+ },
48
+ );
49
+ });
50
+ }
51
+
52
+ /**
53
+ * Instruments a scheduled handler for ExportedHandler (env/ctx come from args).
54
+ */
55
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
+ function instrumentExportedHandlerScheduled(
57
+ handler,
58
+ optionsCallback,
59
+ ) {
60
+ if (!('scheduled' in handler) || typeof handler.scheduled !== 'function' || isInstrumented(handler.scheduled)) {
61
+ return;
62
+ }
63
+
64
+ handler.scheduled = new Proxy(handler.scheduled, {
65
+ apply(target, thisArg, args) {
66
+ const [controller, env, ctx] = args;
67
+ const context = instrumentContext(ctx);
68
+ args[2] = context;
69
+
70
+ const options = getFinalOptions(optionsCallback(env), env);
71
+
72
+ return wrapScheduledHandler(controller, options, context, () => target.apply(thisArg, args));
73
+ },
74
+ });
75
+
76
+ markAsInstrumented(handler.scheduled);
77
+ }
78
+
79
+ export { instrumentExportedHandlerScheduled };
80
+ //# sourceMappingURL=instrumentScheduled.js.map
@@ -0,0 +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":[],"mappings":";;;;;;;;AAgBA;AACA;AACA;AACA,SAAS,oBAAoB;AAC7B,EAAE,UAAU;AACZ,EAAE,OAAO;AACT,EAAE,OAAO;AACT,EAAE,EAAE;AACJ,EAAW;AACX,EAAE,OAAO,kBAAkB,CAAC,cAAA,IAAkB;AAC9C,IAAI,MAAM,SAAA,GAAY,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;;AAErD,IAAI,MAAM,MAAA,GAAS,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,OAAA,EAAS,CAAC;AACrD,IAAI,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC;;AAEpC,IAAI,uBAAuB,CAAC,cAAc,CAAC;;AAE3C,IAAI,OAAO,SAAS;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,CAAA,gCAAA,GAAA,gCAAA;AACA,UAAA,CAAA,gCAAA,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,UAAA,gBAAA,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,CAAA,eAAA,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,IAAA,cAAA,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,GAAA,iBAAA,CAAA,GAAA,CAAA;AACA,MAAA,IAAA,CAAA,CAAA,CAAA,GAAA,OAAA;;AAEA,MAAA,MAAA,OAAA,GAAA,eAAA,CAAA,eAAA,CAAA,GAAA,CAAA,EAAA,GAAA,CAAA;;AAEA,MAAA,OAAA,oBAAA,CAAA,UAAA,EAAA,OAAA,EAAA,OAAA,EAAA,MAAA,MAAA,CAAA,KAAA,CAAA,OAAA,EAAA,IAAA,CAAA,CAAA;AACA,IAAA,CAAA;AACA,GAAA,CAAA;;AAEA,EAAA,kBAAA,CAAA,OAAA,CAAA,SAAA,CAAA;AACA;;;;"}
@@ -0,0 +1,61 @@
1
+ import { withIsolationScope, captureException } from '@sentry/core';
2
+ import { flushAndDispose } from '../../flush.js';
3
+ import { isInstrumented, markAsInstrumented } from '../../instrument.js';
4
+ import { getFinalOptions } from '../../options.js';
5
+ import { addCloudResourceContext } from '../../scope-utils.js';
6
+ import { init } from '../../sdk.js';
7
+ import { instrumentContext } from '../../utils/instrumentContext.js';
8
+
9
+ /**
10
+ * Core tail handler logic - wraps execution with Sentry instrumentation.
11
+ * Note: tail handlers don't create spans, just error capture.
12
+ */
13
+ function wrapTailHandler(options, context, fn) {
14
+ return withIsolationScope(async isolationScope => {
15
+ const waitUntil = context.waitUntil.bind(context);
16
+
17
+ const client = init({ ...options, ctx: context });
18
+ isolationScope.setClient(client);
19
+
20
+ addCloudResourceContext(isolationScope);
21
+
22
+ try {
23
+ return await fn();
24
+ } catch (e) {
25
+ captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.tail' } });
26
+ throw e;
27
+ } finally {
28
+ waitUntil(flushAndDispose(client));
29
+ }
30
+ });
31
+ }
32
+
33
+ /**
34
+ * Instruments a tail handler for ExportedHandler (env/ctx come from args).
35
+ */
36
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
+ function instrumentExportedHandlerTail(
38
+ handler,
39
+ optionsCallback,
40
+ ) {
41
+ if (!('tail' in handler) || typeof handler.tail !== 'function' || isInstrumented(handler.tail)) {
42
+ return;
43
+ }
44
+
45
+ handler.tail = new Proxy(handler.tail, {
46
+ apply(target, thisArg, args) {
47
+ const [, env, ctx] = args;
48
+ const context = instrumentContext(ctx);
49
+ args[2] = context;
50
+
51
+ const options = getFinalOptions(optionsCallback(env), env);
52
+
53
+ return wrapTailHandler(options, context, () => target.apply(thisArg, args));
54
+ },
55
+ });
56
+
57
+ markAsInstrumented(handler.tail);
58
+ }
59
+
60
+ export { instrumentExportedHandlerTail };
61
+ //# sourceMappingURL=instrumentTail.js.map
@@ -0,0 +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":[],"mappings":";;;;;;;;AAUA;AACA;AACA;AACA;AACA,SAAS,eAAe,CAAC,OAAO,EAAqB,OAAO,EAAoB,EAAE,EAA0B;AAC5G,EAAE,OAAO,kBAAkB,CAAC,MAAM,kBAAkB;AACpD,IAAI,MAAM,SAAA,GAAY,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;;AAErD,IAAI,MAAM,MAAA,GAAS,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE,OAAA,EAAS,CAAC;AACrD,IAAI,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC;;AAEpC,IAAI,uBAAuB,CAAC,cAAc,CAAC;;AAE3C,IAAI,IAAI;AACR,MAAM,OAAO,MAAM,EAAE,EAAE;AACvB,IAAI,CAAA,CAAE,OAAO,CAAC,EAAE;AAChB,MAAM,gBAAgB,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,CAAC,eAAe,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,cAAc,cAAc,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,GAAU,iBAAiB,CAAC,GAAG,CAAC;AAC5C,MAAM,IAAI,CAAC,CAAC,CAAA,GAAI,OAAO;;AAEvB,MAAM,MAAM,OAAA,GAAU,eAAe,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;;AAEhE,MAAM,OAAO,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AACjF,IAAI,CAAC;AACL,GAAG,CAAC;;AAEJ,EAAE,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC;AAClC;;;;"}
@@ -1 +1 @@
1
- {"type":"module","version":"10.42.0","sideEffects":false}
1
+ {"type":"module","version":"10.44.0","sideEffects":false}
@@ -131,7 +131,7 @@ function wrapRequestHandler(
131
131
  statusText: res.statusText,
132
132
  headers: res.headers,
133
133
  });
134
- } catch (e) {
134
+ } catch (_e) {
135
135
  // tee() failed (e.g stream already locked) - fall back to non-streaming handling
136
136
  span.end();
137
137
  waitUntil?.(flushAndDispose(client));
@@ -1 +1 @@
1
- {"version":3,"file":"request.js","sources":["../../src/request.ts"],"sourcesContent":["import type { ExecutionContext, IncomingRequestCfProperties } from '@cloudflare/workers-types';\nimport {\n captureException,\n continueTrace,\n getClient,\n getHttpSpanDetailsFromUrlObject,\n httpHeadersToSpanAttributes,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n setHttpStatus,\n startSpanManual,\n winterCGHeadersToDict,\n withIsolationScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from './client';\nimport { flushAndDispose } from './flush';\nimport { addCloudResourceContext, addCultureContext, addRequest } from './scope-utils';\nimport { init } from './sdk';\nimport { classifyResponseStreaming } from './utils/streaming';\n\ninterface RequestHandlerWrapperOptions {\n options: CloudflareOptions;\n request: Request<unknown, IncomingRequestCfProperties<unknown>>;\n context: ExecutionContext;\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\n/**\n * Wraps a cloudflare request handler in Sentry instrumentation\n */\nexport function wrapRequestHandler(\n wrapperOptions: RequestHandlerWrapperOptions,\n handler: (...args: unknown[]) => Response | Promise<Response>,\n): Promise<Response> {\n return withIsolationScope(async isolationScope => {\n const { options, request, captureErrors = true } = wrapperOptions;\n\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 = wrapperOptions.context as ExecutionContext | undefined;\n\n const waitUntil = context?.waitUntil?.bind?.(context);\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n const urlObject = parseStringToURLObject(request.url);\n const [name, attributes] = getHttpSpanDetailsFromUrlObject(urlObject, 'server', 'auto.http.cloudflare', request);\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 Object.assign(\n attributes,\n httpHeadersToSpanAttributes(\n winterCGHeadersToDict(request.headers),\n getClient()?.getOptions().sendDefaultPii ?? false,\n ),\n );\n\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] = 'http.server';\n\n addCloudResourceContext(isolationScope);\n addRequest(isolationScope, request);\n if (request.cf) {\n addCultureContext(isolationScope, request.cf);\n attributes['network.protocol.name'] = request.cf.httpProtocol;\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: 'auto.http.cloudflare' } });\n }\n throw e;\n } finally {\n waitUntil?.(flushAndDispose(client));\n }\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: 'auto.http.cloudflare' } });\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 // Streaming response detected - monitor consumption to keep span alive\n try {\n const [clientStream, monitorStream] = res.body.tee();\n\n // Monitor stream consumption and end span when complete\n const streamMonitor = (async () => {\n const reader = monitorStream.getReader();\n\n try {\n let done = false;\n while (!done) {\n const result = await reader.read();\n done = result.done;\n }\n } catch {\n // Stream error or cancellation - will end span in finally\n } finally {\n reader.releaseLock();\n span.end();\n waitUntil?.(flushAndDispose(client));\n }\n })();\n\n // Keep worker alive until stream monitoring completes (otherwise span won't end)\n waitUntil?.(streamMonitor);\n\n // Return response with client stream\n return new Response(clientStream, {\n status: res.status,\n statusText: res.statusText,\n headers: res.headers,\n });\n } catch (e) {\n // tee() failed (e.g stream already locked) - fall back to non-streaming handling\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 });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"request.js","sources":["../../src/request.ts"],"sourcesContent":["import type { ExecutionContext, IncomingRequestCfProperties } from '@cloudflare/workers-types';\nimport {\n captureException,\n continueTrace,\n getClient,\n getHttpSpanDetailsFromUrlObject,\n httpHeadersToSpanAttributes,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n setHttpStatus,\n startSpanManual,\n winterCGHeadersToDict,\n withIsolationScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from './client';\nimport { flushAndDispose } from './flush';\nimport { addCloudResourceContext, addCultureContext, addRequest } from './scope-utils';\nimport { init } from './sdk';\nimport { classifyResponseStreaming } from './utils/streaming';\n\ninterface RequestHandlerWrapperOptions {\n options: CloudflareOptions;\n request: Request<unknown, IncomingRequestCfProperties<unknown>>;\n context: ExecutionContext;\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\n/**\n * Wraps a cloudflare request handler in Sentry instrumentation\n */\nexport function wrapRequestHandler(\n wrapperOptions: RequestHandlerWrapperOptions,\n handler: (...args: unknown[]) => Response | Promise<Response>,\n): Promise<Response> {\n return withIsolationScope(async isolationScope => {\n const { options, request, captureErrors = true } = wrapperOptions;\n\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 = wrapperOptions.context as ExecutionContext | undefined;\n\n const waitUntil = context?.waitUntil?.bind?.(context);\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n const urlObject = parseStringToURLObject(request.url);\n const [name, attributes] = getHttpSpanDetailsFromUrlObject(urlObject, 'server', 'auto.http.cloudflare', request);\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 Object.assign(\n attributes,\n httpHeadersToSpanAttributes(\n winterCGHeadersToDict(request.headers),\n getClient()?.getOptions().sendDefaultPii ?? false,\n ),\n );\n\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] = 'http.server';\n\n addCloudResourceContext(isolationScope);\n addRequest(isolationScope, request);\n if (request.cf) {\n addCultureContext(isolationScope, request.cf);\n attributes['network.protocol.name'] = request.cf.httpProtocol;\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: 'auto.http.cloudflare' } });\n }\n throw e;\n } finally {\n waitUntil?.(flushAndDispose(client));\n }\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: 'auto.http.cloudflare' } });\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 // Streaming response detected - monitor consumption to keep span alive\n try {\n const [clientStream, monitorStream] = res.body.tee();\n\n // Monitor stream consumption and end span when complete\n const streamMonitor = (async () => {\n const reader = monitorStream.getReader();\n\n try {\n let done = false;\n while (!done) {\n const result = await reader.read();\n done = result.done;\n }\n } catch {\n // Stream error or cancellation - will end span in finally\n } finally {\n reader.releaseLock();\n span.end();\n waitUntil?.(flushAndDispose(client));\n }\n })();\n\n // Keep worker alive until stream monitoring completes (otherwise span won't end)\n waitUntil?.(streamMonitor);\n\n // Return response with client stream\n return new Response(clientStream, {\n status: res.status,\n statusText: res.statusText,\n headers: res.headers,\n });\n } catch (_e) {\n // tee() failed (e.g stream already locked) - fall back to non-streaming handling\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 });\n}\n"],"names":[],"mappings":"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"}