@sentry/cloudflare 10.48.0 → 10.50.0-alpha.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 (121) hide show
  1. package/build/cjs/client.js.map +1 -1
  2. package/build/cjs/durableobject.js +13 -5
  3. package/build/cjs/durableobject.js.map +1 -1
  4. package/build/cjs/index.js +1 -0
  5. package/build/cjs/index.js.map +1 -1
  6. package/build/cjs/instrumentations/instrumentDurableObjectNamespace.js +56 -0
  7. package/build/cjs/instrumentations/instrumentDurableObjectNamespace.js.map +1 -0
  8. package/build/cjs/instrumentations/instrumentDurableObjectStorage.js +38 -3
  9. package/build/cjs/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
  10. package/build/cjs/instrumentations/worker/instrumentEmail.js +3 -2
  11. package/build/cjs/instrumentations/worker/instrumentEmail.js.map +1 -1
  12. package/build/cjs/instrumentations/worker/instrumentEnv.js +83 -0
  13. package/build/cjs/instrumentations/worker/instrumentEnv.js.map +1 -0
  14. package/build/cjs/instrumentations/worker/instrumentFetch.js +3 -2
  15. package/build/cjs/instrumentations/worker/instrumentFetch.js.map +1 -1
  16. package/build/cjs/instrumentations/worker/instrumentFetcher.js +38 -0
  17. package/build/cjs/instrumentations/worker/instrumentFetcher.js.map +1 -0
  18. package/build/cjs/instrumentations/worker/instrumentQueue.js +3 -2
  19. package/build/cjs/instrumentations/worker/instrumentQueue.js.map +1 -1
  20. package/build/cjs/instrumentations/worker/instrumentScheduled.js +3 -2
  21. package/build/cjs/instrumentations/worker/instrumentScheduled.js.map +1 -1
  22. package/build/cjs/instrumentations/worker/instrumentTail.js +3 -2
  23. package/build/cjs/instrumentations/worker/instrumentTail.js.map +1 -1
  24. package/build/cjs/integrations/tracing/vercelai.js +2 -1
  25. package/build/cjs/integrations/tracing/vercelai.js.map +1 -1
  26. package/build/cjs/sdk.js +6 -1
  27. package/build/cjs/sdk.js.map +1 -1
  28. package/build/cjs/utils/instrumentContext.js +2 -1
  29. package/build/cjs/utils/instrumentContext.js.map +1 -1
  30. package/build/cjs/utils/isBinding.js +32 -0
  31. package/build/cjs/utils/isBinding.js.map +1 -0
  32. package/build/cjs/utils/rpcOptions.js +84 -0
  33. package/build/cjs/utils/rpcOptions.js.map +1 -0
  34. package/build/cjs/utils/traceLinks.js +78 -0
  35. package/build/cjs/utils/traceLinks.js.map +1 -0
  36. package/build/cjs/workflows.js +3 -2
  37. package/build/cjs/workflows.js.map +1 -1
  38. package/build/cjs/wrapMethodWithSentry.js +90 -45
  39. package/build/cjs/wrapMethodWithSentry.js.map +1 -1
  40. package/build/esm/client.js.map +1 -1
  41. package/build/esm/durableobject.js +13 -5
  42. package/build/esm/durableobject.js.map +1 -1
  43. package/build/esm/index.js +1 -1
  44. package/build/esm/instrumentations/instrumentDurableObjectNamespace.js +54 -0
  45. package/build/esm/instrumentations/instrumentDurableObjectNamespace.js.map +1 -0
  46. package/build/esm/instrumentations/instrumentDurableObjectStorage.js +39 -4
  47. package/build/esm/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
  48. package/build/esm/instrumentations/worker/instrumentEmail.js +3 -2
  49. package/build/esm/instrumentations/worker/instrumentEmail.js.map +1 -1
  50. package/build/esm/instrumentations/worker/instrumentEnv.js +81 -0
  51. package/build/esm/instrumentations/worker/instrumentEnv.js.map +1 -0
  52. package/build/esm/instrumentations/worker/instrumentFetch.js +3 -2
  53. package/build/esm/instrumentations/worker/instrumentFetch.js.map +1 -1
  54. package/build/esm/instrumentations/worker/instrumentFetcher.js +36 -0
  55. package/build/esm/instrumentations/worker/instrumentFetcher.js.map +1 -0
  56. package/build/esm/instrumentations/worker/instrumentQueue.js +3 -2
  57. package/build/esm/instrumentations/worker/instrumentQueue.js.map +1 -1
  58. package/build/esm/instrumentations/worker/instrumentScheduled.js +3 -2
  59. package/build/esm/instrumentations/worker/instrumentScheduled.js.map +1 -1
  60. package/build/esm/instrumentations/worker/instrumentTail.js +3 -2
  61. package/build/esm/instrumentations/worker/instrumentTail.js.map +1 -1
  62. package/build/esm/integrations/tracing/vercelai.js +2 -1
  63. package/build/esm/integrations/tracing/vercelai.js.map +1 -1
  64. package/build/esm/package.json +1 -1
  65. package/build/esm/sdk.js +7 -2
  66. package/build/esm/sdk.js.map +1 -1
  67. package/build/esm/utils/instrumentContext.js +2 -1
  68. package/build/esm/utils/instrumentContext.js.map +1 -1
  69. package/build/esm/utils/isBinding.js +29 -0
  70. package/build/esm/utils/isBinding.js.map +1 -0
  71. package/build/esm/utils/rpcOptions.js +81 -0
  72. package/build/esm/utils/rpcOptions.js.map +1 -0
  73. package/build/esm/utils/traceLinks.js +73 -0
  74. package/build/esm/utils/traceLinks.js.map +1 -0
  75. package/build/esm/workflows.js +3 -2
  76. package/build/esm/workflows.js.map +1 -1
  77. package/build/esm/wrapMethodWithSentry.js +91 -46
  78. package/build/esm/wrapMethodWithSentry.js.map +1 -1
  79. package/build/types/client.d.ts +39 -10
  80. package/build/types/client.d.ts.map +1 -1
  81. package/build/types/durableobject.d.ts.map +1 -1
  82. package/build/types/index.d.ts +1 -1
  83. package/build/types/index.d.ts.map +1 -1
  84. package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts +12 -0
  85. package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts.map +1 -0
  86. package/build/types/instrumentations/instrumentDurableObjectStorage.d.ts +8 -1
  87. package/build/types/instrumentations/instrumentDurableObjectStorage.d.ts.map +1 -1
  88. package/build/types/instrumentations/worker/instrumentEmail.d.ts.map +1 -1
  89. package/build/types/instrumentations/worker/instrumentEnv.d.ts +16 -0
  90. package/build/types/instrumentations/worker/instrumentEnv.d.ts.map +1 -0
  91. package/build/types/instrumentations/worker/instrumentFetch.d.ts.map +1 -1
  92. package/build/types/instrumentations/worker/instrumentFetcher.d.ts +10 -0
  93. package/build/types/instrumentations/worker/instrumentFetcher.d.ts.map +1 -0
  94. package/build/types/instrumentations/worker/instrumentQueue.d.ts.map +1 -1
  95. package/build/types/instrumentations/worker/instrumentScheduled.d.ts.map +1 -1
  96. package/build/types/instrumentations/worker/instrumentTail.d.ts.map +1 -1
  97. package/build/types/integrations/tracing/vercelai.d.ts +9 -1
  98. package/build/types/integrations/tracing/vercelai.d.ts.map +1 -1
  99. package/build/types/sdk.d.ts.map +1 -1
  100. package/build/types/utils/instrumentContext.d.ts.map +1 -1
  101. package/build/types/utils/isBinding.d.ts +49 -0
  102. package/build/types/utils/isBinding.d.ts.map +1 -0
  103. package/build/types/utils/rpcOptions.d.ts +24 -0
  104. package/build/types/utils/rpcOptions.d.ts.map +1 -0
  105. package/build/types/utils/traceLinks.d.ts +27 -0
  106. package/build/types/utils/traceLinks.d.ts.map +1 -0
  107. package/build/types/workflows.d.ts.map +1 -1
  108. package/build/types/wrapMethodWithSentry.d.ts +19 -2
  109. package/build/types/wrapMethodWithSentry.d.ts.map +1 -1
  110. package/build/types-ts3.8/client.d.ts +39 -10
  111. package/build/types-ts3.8/index.d.ts +1 -1
  112. package/build/types-ts3.8/instrumentations/instrumentDurableObjectNamespace.d.ts +12 -0
  113. package/build/types-ts3.8/instrumentations/instrumentDurableObjectStorage.d.ts +8 -1
  114. package/build/types-ts3.8/instrumentations/worker/instrumentEnv.d.ts +16 -0
  115. package/build/types-ts3.8/instrumentations/worker/instrumentFetcher.d.ts +10 -0
  116. package/build/types-ts3.8/integrations/tracing/vercelai.d.ts +9 -1
  117. package/build/types-ts3.8/utils/isBinding.d.ts +49 -0
  118. package/build/types-ts3.8/utils/rpcOptions.d.ts +24 -0
  119. package/build/types-ts3.8/utils/traceLinks.d.ts +27 -0
  120. package/build/types-ts3.8/wrapMethodWithSentry.d.ts +19 -2
  121. package/package.json +2 -2
@@ -0,0 +1,81 @@
1
+ import { debug } from '@sentry/core';
2
+ import { DEBUG_BUILD } from '../debug-build.js';
3
+
4
+ /**
5
+ * Gets the effective RPC propagation setting, handling deprecation of `instrumentPrototypeMethods`.
6
+ *
7
+ * Priority:
8
+ * 1. If `enableRpcTracePropagation` is set, use it (ignore `instrumentPrototypeMethods`)
9
+ * 2. If only `instrumentPrototypeMethods` is set, use it with deprecation warning (converted to boolean)
10
+ * 3. If neither is set, return `false`
11
+ *
12
+ * @returns The effective setting for RPC trace propagation
13
+ */
14
+ function getEffectiveRpcPropagation(options) {
15
+ const { enableRpcTracePropagation, instrumentPrototypeMethods } = options;
16
+
17
+ // If the new option is explicitly set, use it
18
+ if (enableRpcTracePropagation !== undefined) {
19
+ if (instrumentPrototypeMethods !== undefined) {
20
+ DEBUG_BUILD &&
21
+ debug.warn(
22
+ '[Sentry] Both `enableRpcTracePropagation` and `instrumentPrototypeMethods` are set. ' +
23
+ 'Using `enableRpcTracePropagation` and ignoring `instrumentPrototypeMethods`.',
24
+ );
25
+ }
26
+ return enableRpcTracePropagation;
27
+ }
28
+
29
+ // Fall back to deprecated option with warning
30
+ if (instrumentPrototypeMethods !== undefined) {
31
+ DEBUG_BUILD &&
32
+ debug.warn(
33
+ '[Sentry] `instrumentPrototypeMethods` is deprecated and will be removed in a future major version. ' +
34
+ 'Please use `enableRpcTracePropagation` instead.',
35
+ );
36
+ // instrumentPrototypeMethods can be boolean or string[], convert to boolean
37
+ return (
38
+ instrumentPrototypeMethods === true ||
39
+ (Array.isArray(instrumentPrototypeMethods) && instrumentPrototypeMethods.length > 0)
40
+ );
41
+ }
42
+
43
+ return false;
44
+ }
45
+
46
+ /**
47
+ * Gets the method filter for prototype method instrumentation.
48
+ *
49
+ * Returns:
50
+ * - `null` if no instrumentation should occur
51
+ * - `true` if all methods should be instrumented
52
+ * - `string[]` if only specific methods should be instrumented (deprecated behavior)
53
+ *
54
+ * @returns The method filter or null if no instrumentation
55
+ */
56
+ function getPrototypeMethodFilter(options) {
57
+ const { enableRpcTracePropagation, instrumentPrototypeMethods } = options;
58
+
59
+ // If the new option is explicitly set, use it (boolean only, no filtering)
60
+ if (enableRpcTracePropagation !== undefined) {
61
+ return !!enableRpcTracePropagation;
62
+ }
63
+
64
+ // Fall back to deprecated option - preserve array filtering behavior
65
+ if (instrumentPrototypeMethods !== undefined) {
66
+ if (instrumentPrototypeMethods === true) {
67
+ return true;
68
+ }
69
+
70
+ if (Array.isArray(instrumentPrototypeMethods) && instrumentPrototypeMethods.length > 0) {
71
+ return instrumentPrototypeMethods;
72
+ }
73
+
74
+ return false;
75
+ }
76
+
77
+ return false;
78
+ }
79
+
80
+ export { getEffectiveRpcPropagation, getPrototypeMethodFilter };
81
+ //# sourceMappingURL=rpcOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpcOptions.js","sources":["../../../src/utils/rpcOptions.ts"],"sourcesContent":["import { debug } from '@sentry/core';\nimport type { CloudflareOptions } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\n\n/**\n * Gets the effective RPC propagation setting, handling deprecation of `instrumentPrototypeMethods`.\n *\n * Priority:\n * 1. If `enableRpcTracePropagation` is set, use it (ignore `instrumentPrototypeMethods`)\n * 2. If only `instrumentPrototypeMethods` is set, use it with deprecation warning (converted to boolean)\n * 3. If neither is set, return `false`\n *\n * @returns The effective setting for RPC trace propagation\n */\nexport function getEffectiveRpcPropagation(options: CloudflareOptions): boolean {\n const { enableRpcTracePropagation, instrumentPrototypeMethods } = options;\n\n // If the new option is explicitly set, use it\n if (enableRpcTracePropagation !== undefined) {\n if (instrumentPrototypeMethods !== undefined) {\n DEBUG_BUILD &&\n debug.warn(\n '[Sentry] Both `enableRpcTracePropagation` and `instrumentPrototypeMethods` are set. ' +\n 'Using `enableRpcTracePropagation` and ignoring `instrumentPrototypeMethods`.',\n );\n }\n return enableRpcTracePropagation;\n }\n\n // Fall back to deprecated option with warning\n if (instrumentPrototypeMethods !== undefined) {\n DEBUG_BUILD &&\n debug.warn(\n '[Sentry] `instrumentPrototypeMethods` is deprecated and will be removed in a future major version. ' +\n 'Please use `enableRpcTracePropagation` instead.',\n );\n // instrumentPrototypeMethods can be boolean or string[], convert to boolean\n return (\n instrumentPrototypeMethods === true ||\n (Array.isArray(instrumentPrototypeMethods) && instrumentPrototypeMethods.length > 0)\n );\n }\n\n return false;\n}\n\n/**\n * Gets the method filter for prototype method instrumentation.\n *\n * Returns:\n * - `null` if no instrumentation should occur\n * - `true` if all methods should be instrumented\n * - `string[]` if only specific methods should be instrumented (deprecated behavior)\n *\n * @returns The method filter or null if no instrumentation\n */\nexport function getPrototypeMethodFilter(options: CloudflareOptions): boolean | string[] {\n const { enableRpcTracePropagation, instrumentPrototypeMethods } = options;\n\n // If the new option is explicitly set, use it (boolean only, no filtering)\n if (enableRpcTracePropagation !== undefined) {\n return !!enableRpcTracePropagation;\n }\n\n // Fall back to deprecated option - preserve array filtering behavior\n if (instrumentPrototypeMethods !== undefined) {\n if (instrumentPrototypeMethods === true) {\n return true;\n }\n\n if (Array.isArray(instrumentPrototypeMethods) && instrumentPrototypeMethods.length > 0) {\n return instrumentPrototypeMethods;\n }\n\n return false;\n }\n\n return false;\n}\n"],"names":[],"mappings":";;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,0BAA0B,CAAC,OAAO,EAA8B;AAChF,EAAE,MAAM,EAAE,yBAAyB,EAAE,0BAAA,EAA2B,GAAI,OAAO;;AAE3E;AACA,EAAE,IAAI,yBAAA,KAA8B,SAAS,EAAE;AAC/C,IAAI,IAAI,0BAAA,KAA+B,SAAS,EAAE;AAClD,MAAM,WAAA;AACN,QAAQ,KAAK,CAAC,IAAI;AAClB,UAAU,sFAAA;AACV,YAAY,8EAA8E;AAC1F,SAAS;AACT,IAAI;AACJ,IAAI,OAAO,yBAAyB;AACpC,EAAE;;AAEF;AACA,EAAE,IAAI,0BAAA,KAA+B,SAAS,EAAE;AAChD,IAAI,WAAA;AACJ,MAAM,KAAK,CAAC,IAAI;AAChB,QAAQ,qGAAA;AACR,UAAU,iDAAiD;AAC3D,OAAO;AACP;AACA,IAAI;AACJ,MAAM,0BAAA,KAA+B,IAAA;AACrC,OAAO,KAAK,CAAC,OAAO,CAAC,0BAA0B,CAAA,IAAK,0BAA0B,CAAC,MAAA,GAAS,CAAC;AACzF;AACA,EAAE;;AAEF,EAAE,OAAO,KAAK;AACd;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,wBAAwB,CAAC,OAAO,EAAyC;AACzF,EAAE,MAAM,EAAE,yBAAyB,EAAE,0BAAA,EAA2B,GAAI,OAAO;;AAE3E;AACA,EAAE,IAAI,yBAAA,KAA8B,SAAS,EAAE;AAC/C,IAAI,OAAO,CAAC,CAAC,yBAAyB;AACtC,EAAE;;AAEF;AACA,EAAE,IAAI,0BAAA,KAA+B,SAAS,EAAE;AAChD,IAAI,IAAI,0BAAA,KAA+B,IAAI,EAAE;AAC7C,MAAM,OAAO,IAAI;AACjB,IAAI;;AAEJ,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,0BAA0B,CAAA,IAAK,0BAA0B,CAAC,MAAA,GAAS,CAAC,EAAE;AAC5F,MAAM,OAAO,0BAA0B;AACvC,IAAI;;AAEJ,IAAI,OAAO,KAAK;AAChB,EAAE;;AAEF,EAAE,OAAO,KAAK;AACd;;;;"}
@@ -0,0 +1,73 @@
1
+ import { TraceFlags } from '@opentelemetry/api';
2
+ import { getActiveSpan, spanIsSampled, debug, SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE } from '@sentry/core';
3
+ import { DEBUG_BUILD } from '../debug-build.js';
4
+
5
+ /** Storage key prefix for the span context that links consecutive method invocations */
6
+ const SENTRY_TRACE_LINK_KEY_PREFIX = '__SENTRY_TRACE_LINK__';
7
+
8
+ /** Stored span context for creating span links */
9
+
10
+ /**
11
+ * Gets the storage key for a specific method's trace link.
12
+ */
13
+ function getTraceLinkKey(methodName) {
14
+ return `${SENTRY_TRACE_LINK_KEY_PREFIX}${methodName}`;
15
+ }
16
+
17
+ /**
18
+ * Stores the current span context in Durable Object storage for trace linking.
19
+ * Uses the original uninstrumented storage to avoid creating spans for internal operations.
20
+ * Errors are silently ignored to prevent internal storage failures from propagating to user code.
21
+ */
22
+ async function storeSpanContext(originalStorage, methodName) {
23
+ try {
24
+ const activeSpan = getActiveSpan();
25
+ if (activeSpan) {
26
+ const spanContext = activeSpan.spanContext();
27
+ const storedContext = {
28
+ traceId: spanContext.traceId,
29
+ spanId: spanContext.spanId,
30
+ sampled: spanIsSampled(activeSpan),
31
+ };
32
+ await originalStorage.put(getTraceLinkKey(methodName), storedContext);
33
+ }
34
+ } catch (error) {
35
+ // Silently ignore storage errors to prevent internal failures from affecting user code
36
+ DEBUG_BUILD && debug.log(`[CloudflareClient] Error storing span context for method ${methodName}`, error);
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Retrieves a stored span context from Durable Object storage.
42
+ */
43
+ async function getStoredSpanContext(
44
+ originalStorage,
45
+ methodName,
46
+ ) {
47
+ try {
48
+ return await originalStorage.get(getTraceLinkKey(methodName));
49
+ } catch {
50
+ return undefined;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Builds span links from a stored span context.
56
+ */
57
+ function buildSpanLinks(storedContext) {
58
+ return [
59
+ {
60
+ context: {
61
+ traceId: storedContext.traceId,
62
+ spanId: storedContext.spanId,
63
+ traceFlags: storedContext.sampled ? TraceFlags.SAMPLED : TraceFlags.NONE,
64
+ },
65
+ attributes: {
66
+ [SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE]: 'previous_trace',
67
+ },
68
+ },
69
+ ];
70
+ }
71
+
72
+ export { buildSpanLinks, getStoredSpanContext, getTraceLinkKey, storeSpanContext };
73
+ //# sourceMappingURL=traceLinks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traceLinks.js","sources":["../../../src/utils/traceLinks.ts"],"sourcesContent":["import type { DurableObjectStorage } from '@cloudflare/workers-types';\nimport { TraceFlags } from '@opentelemetry/api';\nimport type { SpanLink } from '@sentry/core';\nimport { debug, getActiveSpan, SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE, spanIsSampled } from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\n\n/** Storage key prefix for the span context that links consecutive method invocations */\nconst SENTRY_TRACE_LINK_KEY_PREFIX = '__SENTRY_TRACE_LINK__';\n\n/** Stored span context for creating span links */\nexport interface StoredSpanContext {\n traceId: string;\n spanId: string;\n sampled: boolean;\n}\n\n/**\n * Gets the storage key for a specific method's trace link.\n */\nexport function getTraceLinkKey(methodName: string): string {\n return `${SENTRY_TRACE_LINK_KEY_PREFIX}${methodName}`;\n}\n\n/**\n * Stores the current span context in Durable Object storage for trace linking.\n * Uses the original uninstrumented storage to avoid creating spans for internal operations.\n * Errors are silently ignored to prevent internal storage failures from propagating to user code.\n */\nexport async function storeSpanContext(originalStorage: DurableObjectStorage, methodName: string): Promise<void> {\n try {\n const activeSpan = getActiveSpan();\n if (activeSpan) {\n const spanContext = activeSpan.spanContext();\n const storedContext: StoredSpanContext = {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n sampled: spanIsSampled(activeSpan),\n };\n await originalStorage.put(getTraceLinkKey(methodName), storedContext);\n }\n } catch (error) {\n // Silently ignore storage errors to prevent internal failures from affecting user code\n DEBUG_BUILD && debug.log(`[CloudflareClient] Error storing span context for method ${methodName}`, error);\n }\n}\n\n/**\n * Retrieves a stored span context from Durable Object storage.\n */\nexport async function getStoredSpanContext(\n originalStorage: DurableObjectStorage,\n methodName: string,\n): Promise<StoredSpanContext | undefined> {\n try {\n return await originalStorage.get<StoredSpanContext>(getTraceLinkKey(methodName));\n } catch {\n return undefined;\n }\n}\n\n/**\n * Builds span links from a stored span context.\n */\nexport function buildSpanLinks(storedContext: StoredSpanContext): SpanLink[] {\n return [\n {\n context: {\n traceId: storedContext.traceId,\n spanId: storedContext.spanId,\n traceFlags: storedContext.sampled ? TraceFlags.SAMPLED : TraceFlags.NONE,\n },\n attributes: {\n [SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE]: 'previous_trace',\n },\n },\n ];\n}\n"],"names":[],"mappings":";;;;AAMA;AACA,MAAM,4BAAA,GAA+B,uBAAuB;;AAE5D;;AAOA;AACA;AACA;AACO,SAAS,eAAe,CAAC,UAAU,EAAkB;AAC5D,EAAE,OAAO,CAAC,EAAA,4BAAA,CAAA,EAAA,UAAA,CAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,eAAA,gBAAA,CAAA,eAAA,EAAA,UAAA,EAAA;AACA,EAAA,IAAA;AACA,IAAA,MAAA,UAAA,GAAA,aAAA,EAAA;AACA,IAAA,IAAA,UAAA,EAAA;AACA,MAAA,MAAA,WAAA,GAAA,UAAA,CAAA,WAAA,EAAA;AACA,MAAA,MAAA,aAAA,GAAA;AACA,QAAA,OAAA,EAAA,WAAA,CAAA,OAAA;AACA,QAAA,MAAA,EAAA,WAAA,CAAA,MAAA;AACA,QAAA,OAAA,EAAA,aAAA,CAAA,UAAA,CAAA;AACA,OAAA;AACA,MAAA,MAAA,eAAA,CAAA,GAAA,CAAA,eAAA,CAAA,UAAA,CAAA,EAAA,aAAA,CAAA;AACA,IAAA;AACA,EAAA,CAAA,CAAA,OAAA,KAAA,EAAA;AACA;AACA,IAAA,WAAA,IAAA,KAAA,CAAA,GAAA,CAAA,CAAA,yDAAA,EAAA,UAAA,CAAA,CAAA,EAAA,KAAA,CAAA;AACA,EAAA;AACA;;AAEA;AACA;AACA;AACA,eAAA,oBAAA;AACA,EAAA,eAAA;AACA,EAAA,UAAA;AACA,EAAA;AACA,EAAA,IAAA;AACA,IAAA,OAAA,MAAA,eAAA,CAAA,GAAA,CAAA,eAAA,CAAA,UAAA,CAAA,CAAA;AACA,EAAA,CAAA,CAAA,MAAA;AACA,IAAA,OAAA,SAAA;AACA,EAAA;AACA;;AAEA;AACA;AACA;AACA,SAAA,cAAA,CAAA,aAAA,EAAA;AACA,EAAA,OAAA;AACA,IAAA;AACA,MAAA,OAAA,EAAA;AACA,QAAA,OAAA,EAAA,aAAA,CAAA,OAAA;AACA,QAAA,MAAA,EAAA,aAAA,CAAA,MAAA;AACA,QAAA,UAAA,EAAA,aAAA,CAAA,OAAA,GAAA,UAAA,CAAA,OAAA,GAAA,UAAA,CAAA,IAAA;AACA,OAAA;AACA,MAAA,UAAA,EAAA;AACA,QAAA,CAAA,iCAAA,GAAA,gBAAA;AACA,OAAA;AACA,KAAA;AACA,GAAA;AACA;;;;"}
@@ -1,6 +1,7 @@
1
1
  import { withIsolationScope, withScope, getCurrentScope, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, captureException, flush } from '@sentry/core';
2
2
  import { setAsyncLocalStorageAsyncContextStrategy } from './async.js';
3
3
  import { flushAndDispose } from './flush.js';
4
+ import { instrumentEnv } from './instrumentations/worker/instrumentEnv.js';
4
5
  import { addCloudResourceContext } from './scope-utils.js';
5
6
  import { init } from './sdk.js';
6
7
  import { instrumentContext } from './utils/instrumentContext.js';
@@ -131,9 +132,9 @@ function instrumentWorkflowWithSentry
131
132
  construct(target, args, newTarget) {
132
133
  const [ctx, env] = args;
133
134
  const context = instrumentContext(ctx);
134
- args[0] = context;
135
-
136
135
  const options = optionsCallback(env);
136
+ args[0] = context;
137
+ args[1] = instrumentEnv(env , options) ;
137
138
  const instance = Reflect.construct(target, args, newTarget) ;
138
139
  return new Proxy(instance, {
139
140
  get(obj, prop, receiver) {
@@ -1 +1 @@
1
- {"version":3,"file":"workflows.js","sources":["../../src/workflows.ts"],"sourcesContent":["import type { PropagationContext } from '@sentry/core';\nimport {\n captureException,\n flush,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n startSpan,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport type {\n WorkflowEntrypoint,\n WorkflowEvent,\n WorkflowSleepDuration,\n WorkflowStep,\n WorkflowStepConfig,\n WorkflowStepEvent,\n WorkflowTimeoutDuration,\n} from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from './async';\nimport type { CloudflareOptions } from './client';\nimport { flushAndDispose } from './flush';\nimport { addCloudResourceContext } from './scope-utils';\nimport { init } from './sdk';\nimport { instrumentContext } from './utils/instrumentContext';\n\nconst UUID_REGEX = /^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$/i;\n\n/**\n * Hashes a string to a UUID using SHA-1.\n */\nexport async function deterministicTraceIdFromInstanceId(instanceId: string): Promise<string> {\n const buf = await crypto.subtle.digest('SHA-1', new TextEncoder().encode(instanceId));\n return (\n Array.from(new Uint8Array(buf))\n // We only need the first 16 bytes for the 32 characters\n .slice(0, 16)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n );\n}\n\nasync function propagationContextFromInstanceId(instanceId: string): Promise<PropagationContext> {\n const traceId = UUID_REGEX.test(instanceId)\n ? instanceId.replace(/-/g, '')\n : await deterministicTraceIdFromInstanceId(instanceId);\n\n // Derive sampleRand from last 4 characters of the random UUID\n //\n // We cannot store any state between workflow steps, so we derive the\n // sampleRand from the traceId itself. This ensures that the sampling is\n // consistent across all steps in the same workflow instance.\n const sampleRand = parseInt(traceId.slice(-4), 16) / 0xffff;\n\n return {\n traceId,\n sampleRand,\n };\n}\n\nclass WrappedWorkflowStep implements WorkflowStep {\n public constructor(\n private _instanceId: string,\n private _ctx: ExecutionContext,\n private _options: CloudflareOptions,\n private _step: WorkflowStep,\n ) {}\n\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n callback: (...args: unknown[]) => Promise<T>,\n ): Promise<T>;\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n config: WorkflowStepConfig,\n callback: (...args: unknown[]) => Promise<T>,\n ): Promise<T>;\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n configOrCallback: WorkflowStepConfig | (() => Promise<T>),\n maybeCallback?: (...args: unknown[]) => Promise<T>,\n ): Promise<T> {\n // Capture the current scope, so parent span (e.g., a startSpan surrounding step.do) is preserved\n const scopeForStep = getCurrentScope();\n\n const userCallback = (maybeCallback || configOrCallback) as (...args: unknown[]) => Promise<T>;\n const config = typeof configOrCallback === 'function' ? undefined : configOrCallback;\n\n const instrumentedCallback = async (...args: unknown[]): Promise<T> => {\n return startSpan(\n {\n op: 'function.step.do',\n name,\n scope: scopeForStep,\n attributes: {\n 'cloudflare.workflow.timeout': config?.timeout,\n 'cloudflare.workflow.retries.backoff': config?.retries?.backoff,\n 'cloudflare.workflow.retries.delay': config?.retries?.delay,\n 'cloudflare.workflow.retries.limit': config?.retries?.limit,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.workflow',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',\n },\n },\n async span => {\n try {\n const result = await userCallback(...args);\n span.setStatus({ code: 1 });\n return result;\n } catch (error) {\n captureException(error, { mechanism: { handled: true, type: 'auto.faas.cloudflare.workflow' } });\n throw error;\n } finally {\n this._ctx.waitUntil(flush(2000));\n }\n },\n );\n };\n\n return config ? this._step.do(name, config, instrumentedCallback) : this._step.do(name, instrumentedCallback);\n }\n\n public async sleep(name: string, duration: WorkflowSleepDuration): Promise<void> {\n return this._step.sleep(name, duration);\n }\n\n public async sleepUntil(name: string, timestamp: Date | number): Promise<void> {\n return this._step.sleepUntil(name, timestamp);\n }\n\n public async waitForEvent<T extends Rpc.Serializable<T>>(\n name: string,\n options: { type: string; timeout?: WorkflowTimeoutDuration | number },\n ): Promise<WorkflowStepEvent<T>> {\n return this._step.waitForEvent<T>(name, options);\n }\n}\n\n/**\n * Instruments a Cloudflare Workflow class with Sentry.\n *\n * @example\n * ```typescript\n * const InstrumentedWorkflow = instrumentWorkflowWithSentry(\n * (env) => ({ dsn: env.SENTRY_DSN }),\n * MyWorkflowClass\n * );\n *\n * export default InstrumentedWorkflow;\n * ```\n *\n * @param optionsCallback - Function that returns Sentry options to initialize Sentry\n * @param WorkflowClass - The workflow class to instrument\n * @returns Instrumented workflow class with the same interface\n */\nexport function instrumentWorkflowWithSentry<\n E, // Environment type\n P, // Payload type\n T extends WorkflowEntrypoint<E, P>, // WorkflowEntrypoint type\n C extends new (ctx: ExecutionContext, env: E) => T, // Constructor type of the WorkflowEntrypoint class\n>(optionsCallback: (env: E) => CloudflareOptions, WorkFlowClass: C): C {\n return new Proxy(WorkFlowClass, {\n construct(target: C, args: [ctx: ExecutionContext, env: E], newTarget) {\n const [ctx, env] = args;\n const context = instrumentContext(ctx);\n args[0] = context;\n\n const options = optionsCallback(env);\n const instance = Reflect.construct(target, args, newTarget) as T;\n return new Proxy(instance, {\n get(obj, prop, receiver) {\n if (prop === 'run') {\n return async function (event: WorkflowEvent<P>, step: WorkflowStep): Promise<unknown> {\n setAsyncLocalStorageAsyncContextStrategy();\n\n return withIsolationScope(async isolationScope => {\n const client = init({ ...options, enableDedupe: false });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return withScope(async scope => {\n const propagationContext = await propagationContextFromInstanceId(event.instanceId);\n scope.setPropagationContext(propagationContext);\n\n try {\n return await obj.run.call(\n obj,\n event,\n new WrappedWorkflowStep(event.instanceId, context, options, step),\n );\n } finally {\n context.waitUntil(flushAndDispose(client));\n }\n });\n });\n };\n }\n return Reflect.get(obj, prop, receiver);\n },\n });\n },\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workflows.js","sources":["../../src/workflows.ts"],"sourcesContent":["import type { PropagationContext } from '@sentry/core';\nimport {\n captureException,\n flush,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n startSpan,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport type {\n WorkflowEntrypoint,\n WorkflowEvent,\n WorkflowSleepDuration,\n WorkflowStep,\n WorkflowStepConfig,\n WorkflowStepEvent,\n WorkflowTimeoutDuration,\n} from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from './async';\nimport type { CloudflareOptions } from './client';\nimport { flushAndDispose } from './flush';\nimport { instrumentEnv } from './instrumentations/worker/instrumentEnv';\nimport { addCloudResourceContext } from './scope-utils';\nimport { init } from './sdk';\nimport { instrumentContext } from './utils/instrumentContext';\n\nconst UUID_REGEX = /^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$/i;\n\n/**\n * Hashes a string to a UUID using SHA-1.\n */\nexport async function deterministicTraceIdFromInstanceId(instanceId: string): Promise<string> {\n const buf = await crypto.subtle.digest('SHA-1', new TextEncoder().encode(instanceId));\n return (\n Array.from(new Uint8Array(buf))\n // We only need the first 16 bytes for the 32 characters\n .slice(0, 16)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n );\n}\n\nasync function propagationContextFromInstanceId(instanceId: string): Promise<PropagationContext> {\n const traceId = UUID_REGEX.test(instanceId)\n ? instanceId.replace(/-/g, '')\n : await deterministicTraceIdFromInstanceId(instanceId);\n\n // Derive sampleRand from last 4 characters of the random UUID\n //\n // We cannot store any state between workflow steps, so we derive the\n // sampleRand from the traceId itself. This ensures that the sampling is\n // consistent across all steps in the same workflow instance.\n const sampleRand = parseInt(traceId.slice(-4), 16) / 0xffff;\n\n return {\n traceId,\n sampleRand,\n };\n}\n\nclass WrappedWorkflowStep implements WorkflowStep {\n public constructor(\n private _instanceId: string,\n private _ctx: ExecutionContext,\n private _options: CloudflareOptions,\n private _step: WorkflowStep,\n ) {}\n\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n callback: (...args: unknown[]) => Promise<T>,\n ): Promise<T>;\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n config: WorkflowStepConfig,\n callback: (...args: unknown[]) => Promise<T>,\n ): Promise<T>;\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n configOrCallback: WorkflowStepConfig | (() => Promise<T>),\n maybeCallback?: (...args: unknown[]) => Promise<T>,\n ): Promise<T> {\n // Capture the current scope, so parent span (e.g., a startSpan surrounding step.do) is preserved\n const scopeForStep = getCurrentScope();\n\n const userCallback = (maybeCallback || configOrCallback) as (...args: unknown[]) => Promise<T>;\n const config = typeof configOrCallback === 'function' ? undefined : configOrCallback;\n\n const instrumentedCallback = async (...args: unknown[]): Promise<T> => {\n return startSpan(\n {\n op: 'function.step.do',\n name,\n scope: scopeForStep,\n attributes: {\n 'cloudflare.workflow.timeout': config?.timeout,\n 'cloudflare.workflow.retries.backoff': config?.retries?.backoff,\n 'cloudflare.workflow.retries.delay': config?.retries?.delay,\n 'cloudflare.workflow.retries.limit': config?.retries?.limit,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.workflow',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'task',\n },\n },\n async span => {\n try {\n const result = await userCallback(...args);\n span.setStatus({ code: 1 });\n return result;\n } catch (error) {\n captureException(error, { mechanism: { handled: true, type: 'auto.faas.cloudflare.workflow' } });\n throw error;\n } finally {\n this._ctx.waitUntil(flush(2000));\n }\n },\n );\n };\n\n return config ? this._step.do(name, config, instrumentedCallback) : this._step.do(name, instrumentedCallback);\n }\n\n public async sleep(name: string, duration: WorkflowSleepDuration): Promise<void> {\n return this._step.sleep(name, duration);\n }\n\n public async sleepUntil(name: string, timestamp: Date | number): Promise<void> {\n return this._step.sleepUntil(name, timestamp);\n }\n\n public async waitForEvent<T extends Rpc.Serializable<T>>(\n name: string,\n options: { type: string; timeout?: WorkflowTimeoutDuration | number },\n ): Promise<WorkflowStepEvent<T>> {\n return this._step.waitForEvent<T>(name, options);\n }\n}\n\n/**\n * Instruments a Cloudflare Workflow class with Sentry.\n *\n * @example\n * ```typescript\n * const InstrumentedWorkflow = instrumentWorkflowWithSentry(\n * (env) => ({ dsn: env.SENTRY_DSN }),\n * MyWorkflowClass\n * );\n *\n * export default InstrumentedWorkflow;\n * ```\n *\n * @param optionsCallback - Function that returns Sentry options to initialize Sentry\n * @param WorkflowClass - The workflow class to instrument\n * @returns Instrumented workflow class with the same interface\n */\nexport function instrumentWorkflowWithSentry<\n E, // Environment type\n P, // Payload type\n T extends WorkflowEntrypoint<E, P>, // WorkflowEntrypoint type\n C extends new (ctx: ExecutionContext, env: E) => T, // Constructor type of the WorkflowEntrypoint class\n>(optionsCallback: (env: E) => CloudflareOptions, WorkFlowClass: C): C {\n return new Proxy(WorkFlowClass, {\n construct(target: C, args: [ctx: ExecutionContext, env: E], newTarget) {\n const [ctx, env] = args;\n const context = instrumentContext(ctx);\n const options = optionsCallback(env);\n args[0] = context;\n args[1] = instrumentEnv(env as Record<string, unknown>, options) as E;\n const instance = Reflect.construct(target, args, newTarget) as T;\n return new Proxy(instance, {\n get(obj, prop, receiver) {\n if (prop === 'run') {\n return async function (event: WorkflowEvent<P>, step: WorkflowStep): Promise<unknown> {\n setAsyncLocalStorageAsyncContextStrategy();\n\n return withIsolationScope(async isolationScope => {\n const client = init({ ...options, enableDedupe: false });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return withScope(async scope => {\n const propagationContext = await propagationContextFromInstanceId(event.instanceId);\n scope.setPropagationContext(propagationContext);\n\n try {\n return await obj.run.call(\n obj,\n event,\n new WrappedWorkflowStep(event.instanceId, context, options, step),\n );\n } finally {\n context.waitUntil(flushAndDispose(client));\n }\n });\n });\n };\n }\n return Reflect.get(obj, prop, receiver);\n },\n });\n },\n });\n}\n"],"names":[],"mappings":"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"}
@@ -1,12 +1,14 @@
1
- import { getClient, withScope, withIsolationScope, isThenable, captureException, SEMANTIC_ATTRIBUTE_SENTRY_OP, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
1
+ import { getClient, withIsolationScope, withScope, isThenable, captureException, SEMANTIC_ATTRIBUTE_SENTRY_OP, startNewTrace, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
2
2
  import { flushAndDispose } from './flush.js';
3
3
  import { ensureInstrumented } from './instrument.js';
4
4
  import { init } from './sdk.js';
5
+ import { storeSpanContext, getStoredSpanContext, buildSpanLinks } from './utils/traceLinks.js';
5
6
 
6
7
  /** Extended DurableObjectState with originalStorage exposed by instrumentContext */
7
8
 
8
9
  /**
9
- * Wraps a method with Sentry tracing.
10
+ * Wraps a method with Sentry error tracking and optional tracing.
11
+ * Supports starting new traces and linking to previous invocations via Durable Object storage.
10
12
  *
11
13
  * @param wrapperOptions - The options for the wrapper.
12
14
  * @param handler - The method to wrap.
@@ -25,44 +27,58 @@ function wrapMethodWithSentry(
25
27
  original =>
26
28
  new Proxy(original, {
27
29
  apply(target, thisArg, args) {
30
+ const { startNewTrace: startNewTrace$1 } = wrapperOptions;
31
+
32
+ // For startNewTrace, always use withIsolationScope to ensure a fresh scope
33
+ // Otherwise, use existing client's scope or isolation scope
28
34
  const currentClient = getClient();
29
- // if a client is already set, use withScope, otherwise use withIsolationScope
30
- const sentryWithScope = currentClient ? withScope : withIsolationScope;
35
+ const sentryWithScope = startNewTrace$1 ? withIsolationScope : currentClient ? withScope : withIsolationScope;
31
36
 
32
37
  const wrappedFunction = (scope) => {
33
38
  // In certain situations, the passed context can become undefined.
34
39
  // For example, for Astro while prerendering pages at build time.
35
40
  // see: https://github.com/getsentry/sentry-javascript/issues/13217
36
- const context = wrapperOptions.context ;
41
+ const context = wrapperOptions.context;
37
42
 
38
43
  const waitUntil = context?.waitUntil?.bind?.(context);
44
+ const storage = context && 'originalStorage' in context ? context.originalStorage : undefined;
39
45
 
40
- let currentClient = scope.getClient();
46
+ let scopeClient = scope.getClient();
41
47
  // Check if client exists AND is still usable (transport not disposed)
42
48
  // This handles the case where a previous handler disposed the client
43
49
  // but the scope still holds a reference to it (e.g., alarm handlers in Durable Objects)
44
- if (!currentClient?.getTransport()) {
50
+ // For startNewTrace, always create a fresh client
51
+ if (startNewTrace$1 || !scopeClient?.getTransport()) {
45
52
  const client = init({
46
53
  ...wrapperOptions.options,
47
54
  ctx: context ,
48
55
  });
49
56
  scope.setClient(client);
50
- currentClient = client;
57
+ scopeClient = client;
51
58
  }
52
59
 
53
- const clientToDispose = currentClient;
60
+ const clientToDispose = scopeClient;
61
+ const methodName = wrapperOptions.spanName || 'unknown';
62
+
63
+ const teardown = async () => {
64
+ if (startNewTrace$1 && storage) {
65
+ await storeSpanContext(storage, methodName);
66
+ }
67
+ await flushAndDispose(clientToDispose);
68
+ };
54
69
 
55
70
  if (!wrapperOptions.spanName) {
56
71
  try {
57
72
  if (callback) {
58
73
  callback(...args);
59
74
  }
75
+
60
76
  const result = Reflect.apply(target, thisArg, args);
61
77
 
62
78
  if (isThenable(result)) {
63
79
  return result.then(
64
80
  (res) => {
65
- waitUntil?.(flushAndDispose(clientToDispose));
81
+ waitUntil?.(teardown());
66
82
  return res;
67
83
  },
68
84
  (e) => {
@@ -72,12 +88,12 @@ function wrapMethodWithSentry(
72
88
  handled: false,
73
89
  },
74
90
  });
75
- waitUntil?.(flushAndDispose(clientToDispose));
91
+ waitUntil?.(teardown());
76
92
  throw e;
77
93
  },
78
94
  );
79
95
  } else {
80
- waitUntil?.(flushAndDispose(clientToDispose));
96
+ waitUntil?.(teardown());
81
97
  return result;
82
98
  }
83
99
  } catch (e) {
@@ -87,7 +103,7 @@ function wrapMethodWithSentry(
87
103
  handled: false,
88
104
  },
89
105
  });
90
- waitUntil?.(flushAndDispose(clientToDispose));
106
+ waitUntil?.(teardown());
91
107
  throw e;
92
108
  }
93
109
  }
@@ -99,42 +115,71 @@ function wrapMethodWithSentry(
99
115
  }
100
116
  : {};
101
117
 
102
- return startSpan({ name: wrapperOptions.spanName, attributes }, () => {
103
- try {
104
- const result = Reflect.apply(target, thisArg, args);
118
+ const executeSpan = () => {
119
+ return startSpan({ name: methodName, attributes }, span => {
120
+ // When linking to previous trace, fetch the stored context and add links asynchronously
121
+ // This avoids blocking the response while fetching from storage
122
+ if (startNewTrace$1 && storage) {
123
+ waitUntil?.(
124
+ getStoredSpanContext(storage, methodName).then(storedContext => {
125
+ if (storedContext) {
126
+ span.addLinks(buildSpanLinks(storedContext));
127
+ // TODO: Remove this once EAP can store span links. We currently only set this attribute so that we
128
+ // can obtain the previous trace information from the EAP store. Long-term, EAP will handle
129
+ // span links and then we should remove this again. Also throwing in a TODO(v11), to remind us
130
+ // to check this at v11 time :)
131
+ const sampledFlag = storedContext.sampled ? '1' : '0';
132
+ span.setAttribute(
133
+ 'sentry.previous_trace',
134
+ `${storedContext.traceId}-${storedContext.spanId}-${sampledFlag}`,
135
+ );
136
+ }
137
+ }),
138
+ );
139
+ }
105
140
 
106
- if (isThenable(result)) {
107
- return result.then(
108
- (res) => {
109
- waitUntil?.(flushAndDispose(clientToDispose));
110
- return res;
111
- },
112
- (e) => {
113
- captureException(e, {
114
- mechanism: {
115
- type: 'auto.faas.cloudflare.durable_object',
116
- handled: false,
117
- },
118
- });
119
- waitUntil?.(flushAndDispose(clientToDispose));
120
- throw e;
141
+ try {
142
+ const result = Reflect.apply(target, thisArg, args);
143
+
144
+ if (isThenable(result)) {
145
+ return result.then(
146
+ (res) => {
147
+ waitUntil?.(teardown());
148
+ return res;
149
+ },
150
+ (e) => {
151
+ captureException(e, {
152
+ mechanism: {
153
+ type: 'auto.faas.cloudflare.durable_object',
154
+ handled: false,
155
+ },
156
+ });
157
+ waitUntil?.(teardown());
158
+ throw e;
159
+ },
160
+ );
161
+ } else {
162
+ waitUntil?.(teardown());
163
+ return result;
164
+ }
165
+ } catch (e) {
166
+ captureException(e, {
167
+ mechanism: {
168
+ type: 'auto.faas.cloudflare.durable_object',
169
+ handled: false,
121
170
  },
122
- );
123
- } else {
124
- waitUntil?.(flushAndDispose(clientToDispose));
125
- return result;
171
+ });
172
+ waitUntil?.(teardown());
173
+ throw e;
126
174
  }
127
- } catch (e) {
128
- captureException(e, {
129
- mechanism: {
130
- type: 'auto.faas.cloudflare.durable_object',
131
- handled: false,
132
- },
133
- });
134
- waitUntil?.(flushAndDispose(clientToDispose));
135
- throw e;
136
- }
137
- });
175
+ });
176
+ };
177
+
178
+ if (startNewTrace$1) {
179
+ return startNewTrace(() => executeSpan());
180
+ }
181
+
182
+ return executeSpan();
138
183
  };
139
184
 
140
185
  return sentryWithScope(wrappedFunction);
@@ -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 { ensureInstrumented } 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 return ensureInstrumented(\n handler,\n original =>\n new Proxy(original, {\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({\n ...wrapperOptions.options,\n ctx: context as unknown as ExecutionContext | undefined,\n });\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 noMark,\n );\n}\n"],"names":[],"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 startNewTrace as startNewTraceCore,\n startSpan,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from './client';\nimport { flushAndDispose } from './flush';\nimport { ensureInstrumented } from './instrument';\nimport { init } from './sdk';\nimport { buildSpanLinks, getStoredSpanContext, storeSpanContext } from './utils/traceLinks';\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 | InstrumentedDurableObjectState;\n /**\n * If true, starts a fresh trace instead of inheriting from a parent trace.\n * Useful for scheduled/independent invocations like alarms.\n *\n * If true, it also stores the current span context and links to the previous invocation's span.\n * Uses Durable Object storage to persist the link. The link is set asynchronously via `span.addLinks()`\n * in a `waitUntil` to avoid blocking.\n *\n * @default false\n */\n startNewTrace?: boolean;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type UncheckedMethod = (...args: any[]) => any;\ntype OriginalMethod = UncheckedMethod;\n\n/**\n * Wraps a method with Sentry error tracking and optional tracing.\n * Supports starting new traces and linking to previous invocations via Durable Object storage.\n *\n * @param wrapperOptions - The options for the wrapper.\n * @param handler - The method to wrap.\n * @param callback - The callback to call.\n * @param noMark - Whether to mark the method as instrumented.\n * @returns The wrapped method.\n */\nexport function wrapMethodWithSentry<T extends OriginalMethod>(\n wrapperOptions: MethodWrapperOptions,\n handler: T,\n callback?: (...args: Parameters<T>) => void,\n noMark?: true,\n): T {\n return ensureInstrumented(\n handler,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args: Parameters<T>) {\n const { startNewTrace } = wrapperOptions;\n\n // For startNewTrace, always use withIsolationScope to ensure a fresh scope\n // Otherwise, use existing client's scope or isolation scope\n const currentClient = getClient();\n const sentryWithScope = startNewTrace ? withIsolationScope : currentClient ? withScope : withIsolationScope;\n\n const wrappedFunction = (scope: Scope): unknown | Promise<unknown> => {\n // In certain situations, the passed context can become undefined.\n // For example, for Astro while prerendering pages at build time.\n // see: https://github.com/getsentry/sentry-javascript/issues/13217\n const context: typeof wrapperOptions.context | undefined = wrapperOptions.context;\n\n const waitUntil = context?.waitUntil?.bind?.(context);\n const storage = context && 'originalStorage' in context ? context.originalStorage : undefined;\n\n let scopeClient = scope.getClient();\n // Check if client exists AND is still usable (transport not disposed)\n // This handles the case where a previous handler disposed the client\n // but the scope still holds a reference to it (e.g., alarm handlers in Durable Objects)\n // For startNewTrace, always create a fresh client\n if (startNewTrace || !scopeClient?.getTransport()) {\n const client = init({\n ...wrapperOptions.options,\n ctx: context as unknown as ExecutionContext | undefined,\n });\n scope.setClient(client);\n scopeClient = client;\n }\n\n const clientToDispose = scopeClient;\n const methodName = wrapperOptions.spanName || 'unknown';\n\n const teardown = async (): Promise<void> => {\n if (startNewTrace && storage) {\n await storeSpanContext(storage, methodName);\n }\n await flushAndDispose(clientToDispose);\n };\n\n if (!wrapperOptions.spanName) {\n try {\n if (callback) {\n callback(...args);\n }\n\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(\n (res: unknown) => {\n waitUntil?.(teardown());\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?.(teardown());\n throw e;\n },\n );\n } else {\n waitUntil?.(teardown());\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?.(teardown());\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 const executeSpan = (): unknown => {\n return startSpan({ name: methodName, attributes }, span => {\n // When linking to previous trace, fetch the stored context and add links asynchronously\n // This avoids blocking the response while fetching from storage\n if (startNewTrace && storage) {\n waitUntil?.(\n getStoredSpanContext(storage, methodName).then(storedContext => {\n if (storedContext) {\n span.addLinks(buildSpanLinks(storedContext));\n // TODO: Remove this once EAP can store span links. We currently only set this attribute so that we\n // can obtain the previous trace information from the EAP store. Long-term, EAP will handle\n // span links and then we should remove this again. Also throwing in a TODO(v11), to remind us\n // to check this at v11 time :)\n const sampledFlag = storedContext.sampled ? '1' : '0';\n span.setAttribute(\n 'sentry.previous_trace',\n `${storedContext.traceId}-${storedContext.spanId}-${sampledFlag}`,\n );\n }\n }),\n );\n }\n\n try {\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(\n (res: unknown) => {\n waitUntil?.(teardown());\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?.(teardown());\n throw e;\n },\n );\n } else {\n waitUntil?.(teardown());\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?.(teardown());\n throw e;\n }\n });\n };\n\n if (startNewTrace) {\n return startNewTraceCore(() => executeSpan());\n }\n\n return executeSpan();\n };\n\n return sentryWithScope(wrappedFunction);\n },\n }),\n noMark,\n );\n}\n"],"names":["startNewTrace","startNewTraceCore"],"mappings":"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"}
@@ -65,26 +65,55 @@ interface BaseCloudflareOptions {
65
65
  */
66
66
  skipOpenTelemetrySetup?: boolean;
67
67
  /**
68
- * Enable instrumentation of prototype methods for DurableObjects.
68
+ * Enable trace propagation for RPC calls between Workers, Durable Objects, and Service Bindings.
69
69
  *
70
- * When `true`, the SDK will wrap all methods on the DurableObject prototype chain
71
- * to automatically create spans and capture errors for RPC method calls.
70
+ * When enabled, trace context (sentry-trace + baggage) is propagated across:
71
+ * - `stub.fetch()` calls to Durable Objects (via HTTP headers)
72
+ * - Service binding `fetch()` calls (via HTTP headers)
73
+ * - RPC method calls to Durable Objects (via trailing argument)
72
74
  *
73
- * When an array of strings is provided, only the specified method names will be instrumented.
75
+ * When enabled on the **receiver side** (DurableObject), the SDK will also:
76
+ * - Extract and continue traces from incoming RPC calls
77
+ * - Create spans for each RPC method invocation
78
+ * - Capture errors thrown by RPC methods
74
79
  *
75
- * This feature adds runtime overhead as it wraps methods at the prototype level.
76
- * Only enable this if you need automatic instrumentation of prototype methods.
80
+ * **Important:** This option should be enabled on **both sides** for full trace propagation.
77
81
  *
78
82
  * @default false
79
83
  * @example
80
84
  * ```ts
81
- * // Instrument all prototype methods
82
- * instrumentPrototypeMethods: true
85
+ * // Worker side (caller)
86
+ * export default Sentry.withSentry(
87
+ * (env) => ({
88
+ * dsn: env.SENTRY_DSN,
89
+ * enableRpcTracePropagation: true,
90
+ * }),
91
+ * handler,
92
+ * );
83
93
  *
84
- * // Instrument only specific methods
85
- * instrumentPrototypeMethods: ['myMethod', 'anotherMethod']
94
+ * // Durable Object side (receiver)
95
+ * export const MyDO = Sentry.instrumentDurableObjectWithSentry(
96
+ * (env) => ({
97
+ * dsn: env.SENTRY_DSN,
98
+ * enableRpcTracePropagation: true,
99
+ * }),
100
+ * MyDOBase,
101
+ * );
86
102
  * ```
87
103
  */
104
+ enableRpcTracePropagation?: boolean;
105
+ /**
106
+ * @deprecated Use `enableRpcTracePropagation` instead. This option will be removed in a future major version.
107
+ *
108
+ * Enable instrumentation of prototype methods for DurableObjects.
109
+ *
110
+ * When `true`, the SDK will wrap all methods on the DurableObject prototype chain
111
+ * to automatically create spans and capture errors for RPC method calls.
112
+ *
113
+ * When an array of strings is provided, only the specified method names will be instrumented.
114
+ *
115
+ * @default false
116
+ */
88
117
  instrumentPrototypeMethods?: boolean | string[];
89
118
  }
90
119
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAA8B,MAAM,cAAc,CAAC;AACvF,OAAO,EAA2B,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAE9D;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,mBAAmB;IACvD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0C;IACrE,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,sBAAsB,CAA8B;IAC5D,OAAO,CAAC,sBAAsB,CAA6B;IAE3D,OAAO,CAAC,qBAAqB,CAA6B;IAC1D,OAAO,CAAC,mBAAmB,CAA6B;IAExD;;;OAGG;gBACgB,OAAO,EAAE,uBAAuB;IA2CnD;;;;;;;;OAQG;IACU,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA2BtD;;;;;;;;OAQG;IACa,OAAO,IAAI,IAAI;IAkB/B;;OAEG;IACH,OAAO,CAAC,2BAA2B;CAKpC;AAED,UAAU,qBAAqB;IAC7B;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;;;;;;;OAUG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,0BAA0B,CAAC,EAAE,OAAO,GAAG,MAAM,EAAE,CAAC;CACjD;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,OAAO,CAAC,0BAA0B,CAAC,EAAE,qBAAqB;IACnG,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAwB,SAAQ,aAAa,CAAC,0BAA0B,CAAC,EAAE,qBAAqB;IAC/G,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;CAC9C"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAA8B,MAAM,cAAc,CAAC;AACvF,OAAO,EAA2B,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAE9D;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,mBAAmB;IACvD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0C;IACrE,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,sBAAsB,CAA8B;IAC5D,OAAO,CAAC,sBAAsB,CAA6B;IAE3D,OAAO,CAAC,qBAAqB,CAA6B;IAC1D,OAAO,CAAC,mBAAmB,CAA6B;IAExD;;;OAGG;gBACgB,OAAO,EAAE,uBAAuB;IA2CnD;;;;;;;;OAQG;IACU,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA2BtD;;;;;;;;OAQG;IACa,OAAO,IAAI,IAAI;IAkB/B;;OAEG;IACH,OAAO,CAAC,2BAA2B;CAKpC;AAED,UAAU,qBAAqB;IAC7B;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;;;;;;;OAUG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoCG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IAEpC;;;;;;;;;;;OAWG;IACH,0BAA0B,CAAC,EAAE,OAAO,GAAG,MAAM,EAAE,CAAC;CACjD;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,OAAO,CAAC,0BAA0B,CAAC,EAAE,qBAAqB;IACnG,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAwB,SAAQ,aAAa,CAAC,0BAA0B,CAAC,EAAE,qBAAqB;IAC/G,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;CAC9C"}
@@ -1 +1 @@
1
- {"version":3,"file":"durableobject.d.ts","sourceRoot":"","sources":["../../src/durableobject.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAQlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,iCAAiC,CAC/C,CAAC,EACD,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,EAC1B,CAAC,SAAS,KAAK,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EACtD,eAAe,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,iBAAiB,EAAE,kBAAkB,EAAE,CAAC,GAAG,CAAC,CA2G1E"}
1
+ {"version":3,"file":"durableobject.d.ts","sourceRoot":"","sources":["../../src/durableobject.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAUlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,iCAAiC,CAC/C,CAAC,EACD,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,EAC1B,CAAC,SAAS,KAAK,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EACtD,eAAe,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,iBAAiB,EAAE,kBAAkB,EAAE,CAAC,GAAG,CAAC,CAiH1E"}
@@ -1,6 +1,6 @@
1
1
  export type { Breadcrumb, BreadcrumbHint, PolymorphicRequest, RequestEventData, SdkInfo, Event, EventHint, ErrorEvent, Exception, FeatureFlagsIntegration, Session, SeverityLevel, Span, StackFrame, Stacktrace, Thread, User, Metric, ExclusiveEventHintOrCaptureContext, CaptureContext, } from '@sentry/core';
2
2
  export type { CloudflareOptions } from './client';
3
- export { addEventProcessor, addBreadcrumb, addIntegration, captureException, captureEvent, captureMessage, captureFeedback, close, createTransport, lastEventId, flush, getClient, isInitialized, isEnabled, getCurrentScope, getGlobalScope, getIsolationScope, setCurrentClient, Scope, SDK_VERSION, setContext, setExtra, setExtras, setTag, setTags, setUser, setConversationId, getSpanStatusFromHttpCode, setHttpStatus, withScope, withIsolationScope, captureCheckIn, withMonitor, setMeasurement, getActiveSpan, getRootSpan, getTraceData, getTraceMetaTags, startSpan, startInactiveSpan, startSpanManual, startNewTrace, suppressTracing, withActiveSpan, getSpanDescendants, continueTrace, functionToStringIntegration, inboundFiltersIntegration, instrumentOpenAiClient, instrumentGoogleGenAIClient, instrumentAnthropicAiClient, eventFiltersIntegration, linkedErrorsIntegration, requestDataIntegration, extraErrorDataIntegration, dedupeIntegration, rewriteFramesIntegration, captureConsoleIntegration, moduleMetadataIntegration, supabaseIntegration, instrumentSupabaseClient, instrumentPostgresJsSql, zodErrorsIntegration, consoleIntegration, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, trpcMiddleware, spanToJSON, spanToTraceHeader, spanToBaggageHeader, updateSpanName, wrapMcpServerWithSentry, consoleLoggingIntegration, createConsolaReporter, createLangChainCallbackHandler, instrumentLangChainEmbeddings, featureFlagsIntegration, growthbookIntegration, logger, metrics, withStreamedSpan, instrumentLangGraph, } from '@sentry/core';
3
+ export { addEventProcessor, addBreadcrumb, addIntegration, captureException, captureEvent, captureMessage, captureFeedback, close, createTransport, lastEventId, flush, getClient, isInitialized, isEnabled, getCurrentScope, getGlobalScope, getIsolationScope, setCurrentClient, Scope, SDK_VERSION, setContext, setExtra, setExtras, setTag, setTags, setUser, setConversationId, getSpanStatusFromHttpCode, setHttpStatus, withScope, withIsolationScope, captureCheckIn, withMonitor, setMeasurement, getActiveSpan, getRootSpan, getTraceData, getTraceMetaTags, startSpan, startInactiveSpan, startSpanManual, startNewTrace, suppressTracing, withActiveSpan, getSpanDescendants, continueTrace, functionToStringIntegration, inboundFiltersIntegration, instrumentOpenAiClient, instrumentGoogleGenAIClient, instrumentAnthropicAiClient, eventFiltersIntegration, linkedErrorsIntegration, requestDataIntegration, extraErrorDataIntegration, dedupeIntegration, rewriteFramesIntegration, captureConsoleIntegration, moduleMetadataIntegration, supabaseIntegration, instrumentSupabaseClient, instrumentPostgresJsSql, zodErrorsIntegration, consoleIntegration, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, trpcMiddleware, spanToJSON, spanToTraceHeader, spanToBaggageHeader, updateSpanName, wrapMcpServerWithSentry, consoleLoggingIntegration, createConsolaReporter, createLangChainCallbackHandler, instrumentLangChainEmbeddings, featureFlagsIntegration, growthbookIntegration, logger, metrics, withStreamedSpan, spanStreamingIntegration, instrumentLangGraph, } from '@sentry/core';
4
4
  export { withSentry } from './withSentry';
5
5
  export { instrumentDurableObjectWithSentry } from './durableobject';
6
6
  export { sentryPagesPlugin } from './pages-plugin';