@sentry/cloudflare 10.50.0-alpha.0 → 10.51.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 (51) hide show
  1. package/build/cjs/durableobject.js +68 -130
  2. package/build/cjs/durableobject.js.map +1 -1
  3. package/build/cjs/index.js +1 -0
  4. package/build/cjs/index.js.map +1 -1
  5. package/build/cjs/instrumentations/instrumentDurableObjectNamespace.js +14 -4
  6. package/build/cjs/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
  7. package/build/cjs/instrumentations/worker/instrumentEnv.js +8 -3
  8. package/build/cjs/instrumentations/worker/instrumentEnv.js.map +1 -1
  9. package/build/cjs/request.js +25 -29
  10. package/build/cjs/request.js.map +1 -1
  11. package/build/cjs/utils/rpcMeta.js +60 -0
  12. package/build/cjs/utils/rpcMeta.js.map +1 -0
  13. package/build/cjs/utils/rpcOptions.js +1 -36
  14. package/build/cjs/utils/rpcOptions.js.map +1 -1
  15. package/build/cjs/wrapMethodWithSentry.js +21 -1
  16. package/build/cjs/wrapMethodWithSentry.js.map +1 -1
  17. package/build/esm/durableobject.js +70 -132
  18. package/build/esm/durableobject.js.map +1 -1
  19. package/build/esm/index.js +1 -1
  20. package/build/esm/instrumentations/instrumentDurableObjectNamespace.js +14 -5
  21. package/build/esm/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
  22. package/build/esm/instrumentations/worker/instrumentEnv.js +9 -4
  23. package/build/esm/instrumentations/worker/instrumentEnv.js.map +1 -1
  24. package/build/esm/package.json +1 -1
  25. package/build/esm/request.js +25 -29
  26. package/build/esm/request.js.map +1 -1
  27. package/build/esm/utils/rpcMeta.js +57 -0
  28. package/build/esm/utils/rpcMeta.js.map +1 -0
  29. package/build/esm/utils/rpcOptions.js +2 -36
  30. package/build/esm/utils/rpcOptions.js.map +1 -1
  31. package/build/esm/wrapMethodWithSentry.js +22 -2
  32. package/build/esm/wrapMethodWithSentry.js.map +1 -1
  33. package/build/types/durableobject.d.ts +2 -2
  34. package/build/types/durableobject.d.ts.map +1 -1
  35. package/build/types/index.d.ts +1 -1
  36. package/build/types/index.d.ts.map +1 -1
  37. package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts +1 -0
  38. package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts.map +1 -1
  39. package/build/types/instrumentations/worker/instrumentEnv.d.ts.map +1 -1
  40. package/build/types/request.d.ts.map +1 -1
  41. package/build/types/utils/rpcMeta.d.ts +15 -0
  42. package/build/types/utils/rpcMeta.d.ts.map +1 -0
  43. package/build/types/utils/rpcOptions.d.ts +1 -12
  44. package/build/types/utils/rpcOptions.d.ts.map +1 -1
  45. package/build/types/wrapMethodWithSentry.d.ts.map +1 -1
  46. package/build/types-ts3.8/durableobject.d.ts +2 -2
  47. package/build/types-ts3.8/index.d.ts +1 -1
  48. package/build/types-ts3.8/instrumentations/instrumentDurableObjectNamespace.d.ts +1 -0
  49. package/build/types-ts3.8/utils/rpcMeta.d.ts +15 -0
  50. package/build/types-ts3.8/utils/rpcOptions.d.ts +1 -12
  51. package/package.json +2 -2
@@ -12,17 +12,26 @@ const wrapMethodWithSentry = require('./wrapMethodWithSentry.js');
12
12
 
13
13
  /* eslint-disable @typescript-eslint/unbound-method */
14
14
 
15
+ const BUILT_IN_DO_METHODS = new Set([
16
+ 'constructor',
17
+ 'fetch',
18
+ 'alarm',
19
+ 'webSocketError',
20
+ 'webSocketClose',
21
+ 'webSocketMessage',
22
+ ]);
23
+
15
24
  /**
16
25
  * Instruments a Durable Object class to capture errors and performance data.
17
26
  *
18
- * Instruments the following methods:
27
+ * Instruments the following methods by default:
19
28
  * - fetch
20
29
  * - alarm
21
30
  * - webSocketMessage
22
31
  * - webSocketClose
23
32
  * - webSocketError
24
33
  *
25
- * as well as any other public RPC methods on the Durable Object instance.
34
+ * To instrument RPC methods (prototype methods), enable the `enableRpcTracePropagation` option.
26
35
  *
27
36
  * @param optionsCallback Function that returns the options for the SDK initialization.
28
37
  * @param DurableObjectClass The Durable Object class to instrument.
@@ -114,140 +123,69 @@ function instrumentDurableObjectWithSentry
114
123
  );
115
124
  }
116
125
 
117
- for (const method of Object.getOwnPropertyNames(obj)) {
118
- if (
119
- method === 'fetch' ||
120
- method === 'alarm' ||
121
- method === 'webSocketError' ||
122
- method === 'webSocketClose' ||
123
- method === 'webSocketMessage'
124
- ) {
125
- continue;
126
- }
127
-
128
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
129
- const value = (obj )[method] ;
130
- if (typeof value === 'function') {
131
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
132
- (obj )[method] = wrapMethodWithSentry.wrapMethodWithSentry(
133
- { options: options$1, context, spanName: method, spanOp: 'rpc' },
134
- value ,
135
- );
136
- }
137
- }
138
-
139
- // Store context and options on the instance for prototype methods to access
140
- Object.defineProperty(obj, '__SENTRY_CONTEXT__', {
141
- value: context,
142
- enumerable: false,
143
- writable: false,
144
- configurable: false,
145
- });
146
-
147
- Object.defineProperty(obj, '__SENTRY_OPTIONS__', {
148
- value: options$1,
149
- enumerable: false,
150
- writable: false,
151
- configurable: false,
152
- });
153
-
154
- const methodFilter = rpcOptions.getPrototypeMethodFilter(options$1);
126
+ // Get effective RPC propagation setting (handles deprecation of instrumentPrototypeMethods)
127
+ const rpcPropagation = rpcOptions.getEffectiveRpcPropagation(options$1);
155
128
 
156
- if (methodFilter) {
157
- instrumentPrototype(target, methodFilter);
129
+ // Skip RPC instrumentation if not enabled
130
+ if (!rpcPropagation) {
131
+ return obj;
158
132
  }
159
133
 
160
- return obj;
161
- },
162
- });
163
- }
164
-
165
- function instrumentPrototype(target, methodsToInstrument) {
166
- const proto = target.prototype;
167
-
168
- // Get all methods from the prototype chain
169
- const methodNames = new Set();
170
- let current = proto;
171
-
172
- while (current && current !== Object.prototype) {
173
- Object.getOwnPropertyNames(current).forEach(name => {
174
- if (name !== 'constructor' && typeof (current )[name] === 'function') {
175
- methodNames.add(name);
176
- }
177
- });
178
- current = Object.getPrototypeOf(current);
179
- }
180
-
181
- // Create a set for efficient lookups when methodsToInstrument is an array
182
- const methodsToInstrumentSet = Array.isArray(methodsToInstrument) ? new Set(methodsToInstrument) : null;
183
-
184
- // Instrument each method on the prototype
185
- methodNames.forEach(methodName => {
186
- const originalMethod = (proto )[methodName];
187
-
188
- if (!originalMethod) {
189
- return;
190
- }
191
-
192
- const existingInstrumented = instrument.getInstrumented(originalMethod);
193
- if (existingInstrumented) {
194
- Object.defineProperty(proto, methodName, {
195
- value: existingInstrumented,
196
- enumerable: false,
197
- writable: true,
198
- configurable: true,
199
- });
200
- return;
201
- }
202
-
203
- // If methodsToInstrument is an array, only instrument methods in that set
204
- if (methodsToInstrumentSet && !methodsToInstrumentSet.has(methodName)) {
205
- return;
206
- }
207
-
208
- // Create a wrapper that gets context/options from the instance at runtime
209
- const wrappedMethod = function ( ...args) {
210
- const thisWithSentry = this
211
-
212
- ;
213
- const instanceContext = thisWithSentry.__SENTRY_CONTEXT__;
214
- const instanceOptions = thisWithSentry.__SENTRY_OPTIONS__;
134
+ // If `instrumentPrototypeMethods` was passed as an array (deprecated),
135
+ // only the listed method names should be instrumented.
136
+ const instrumentPrototypeMethods = Array.isArray(options$1.instrumentPrototypeMethods)
137
+ ? options$1.instrumentPrototypeMethods
138
+ : undefined;
139
+ const allowSet = instrumentPrototypeMethods ? new Set(instrumentPrototypeMethods) : null;
140
+
141
+ // Return a Proxy that lazily wraps prototype methods on access.
142
+ // This avoids iterating the prototype chain at construction time —
143
+ // we only check if a property is an RPC method when it's accessed.
144
+ const rpcMethodCache = new Map();
145
+
146
+ return new Proxy(obj, {
147
+ get(proxyTarget, prop, receiver) {
148
+ const value = Reflect.get(proxyTarget, prop, receiver);
149
+
150
+ if (typeof prop !== 'string' || BUILT_IN_DO_METHODS.has(prop)) {
151
+ return value;
152
+ }
153
+
154
+ const cached = rpcMethodCache.get(prop);
155
+
156
+ if (cached) {
157
+ return cached;
158
+ }
159
+
160
+ if (
161
+ typeof value !== 'function' ||
162
+ Object.prototype.hasOwnProperty.call(proxyTarget, prop) ||
163
+ (allowSet && !allowSet.has(prop)) ||
164
+ // Exclude inherited Object.prototype methods (toString, valueOf, etc.)
165
+ // These are not RPC methods and should not create spans
166
+ prop in Object.prototype
167
+ ) {
168
+ return value;
169
+ }
170
+
171
+ // Bind the method to the original object to ensure private fields work correctly.
172
+ // When called via the Proxy, `this` would be the Proxy, but private fields require
173
+ // the original object. Bound functions ignore the thisArg passed via Reflect.apply.
174
+ const boundValue = (value ).bind(proxyTarget);
175
+
176
+ const wrapped = wrapMethodWithSentry.wrapMethodWithSentry(
177
+ { options: options$1, context, spanName: prop, spanOp: 'rpc' },
178
+ boundValue,
179
+ undefined,
180
+ true,
181
+ );
215
182
 
216
- if (!instanceOptions) {
217
- // Fallback to original method if no Sentry data found
218
- return (originalMethod ).apply(this, args);
219
- }
183
+ rpcMethodCache.set(prop, wrapped);
220
184
 
221
- // Use the existing wrapper but with instance-specific context/options
222
- const wrapper = wrapMethodWithSentry.wrapMethodWithSentry(
223
- {
224
- options: instanceOptions,
225
- context: instanceContext,
226
- spanName: methodName,
227
- spanOp: 'rpc',
185
+ return wrapped;
228
186
  },
229
- originalMethod ,
230
- undefined,
231
- true, // noMark = true since we'll mark the prototype method
232
- );
233
-
234
- return wrapper.apply(this, args);
235
- };
236
-
237
- // Only mark wrappedMethod as instrumented (not originalMethod → wrappedMethod).
238
- // originalMethod must stay unmapped because wrappedMethod calls
239
- // wrapMethodWithSentry(options, originalMethod) on each invocation to create
240
- // a per-instance proxy. If originalMethod mapped to wrappedMethod, that call
241
- // would return wrappedMethod itself, causing infinite recursion.
242
- instrument.markAsInstrumented(wrappedMethod);
243
-
244
- // Replace the prototype method
245
- Object.defineProperty(proto, methodName, {
246
- value: wrappedMethod,
247
- enumerable: false,
248
- writable: true,
249
- configurable: true,
250
- });
187
+ });
188
+ },
251
189
  });
252
190
  }
253
191
 
@@ -1 +1 @@
1
- {"version":3,"file":"durableobject.js","sources":["../../src/durableobject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport { captureException } from '@sentry/core';\nimport type { DurableObject } from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from './async';\nimport type { CloudflareOptions } from './client';\nimport { ensureInstrumented, getInstrumented, markAsInstrumented } from './instrument';\nimport { instrumentEnv } from './instrumentations/worker/instrumentEnv';\nimport { getFinalOptions } from './options';\nimport { wrapRequestHandler } from './request';\nimport { instrumentContext } from './utils/instrumentContext';\nimport { getPrototypeMethodFilter } from './utils/rpcOptions';\nimport type { UncheckedMethod } from './wrapMethodWithSentry';\nimport { wrapMethodWithSentry } from './wrapMethodWithSentry';\n\n/**\n * Instruments a Durable Object class to capture errors and performance data.\n *\n * Instruments the following methods:\n * - fetch\n * - alarm\n * - webSocketMessage\n * - webSocketClose\n * - webSocketError\n *\n * as well as any other public RPC methods on the Durable Object instance.\n *\n * @param optionsCallback Function that returns the options for the SDK initialization.\n * @param DurableObjectClass The Durable Object class to instrument.\n * @returns The instrumented Durable Object class.\n *\n * @example\n * ```ts\n * class MyDurableObjectBase extends DurableObject {\n * constructor(ctx: DurableObjectState, env: Env) {\n * super(ctx, env);\n * }\n * }\n *\n * export const MyDurableObject = instrumentDurableObjectWithSentry(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * }),\n * MyDurableObjectBase,\n * );\n * ```\n */\nexport function instrumentDurableObjectWithSentry<\n E,\n T extends DurableObject<E>,\n C extends new (state: DurableObjectState, env: E) => T,\n>(optionsCallback: (env: E) => CloudflareOptions, DurableObjectClass: C): C {\n return new Proxy(DurableObjectClass, {\n construct(target, [ctx, env]) {\n setAsyncLocalStorageAsyncContextStrategy();\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n const instrumentedEnv = instrumentEnv(env, options);\n\n const obj = new target(context, instrumentedEnv);\n\n // These are the methods that are available on a Durable Object\n // ref: https://developers.cloudflare.com/durable-objects/api/base/\n // obj.alarm\n // obj.fetch\n // obj.webSocketError\n // obj.webSocketClose\n // obj.webSocketMessage\n\n // Any other public methods on the Durable Object instance are RPC calls.\n\n if (obj.fetch && typeof obj.fetch === 'function') {\n obj.fetch = ensureInstrumented(\n obj.fetch,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args) {\n return wrapRequestHandler({ options, request: args[0], context }, () => {\n return Reflect.apply(target, thisArg, args);\n });\n },\n }),\n );\n }\n\n if (obj.alarm && typeof obj.alarm === 'function') {\n // Alarms are independent invocations, so we start a new trace and link to the previous alarm\n obj.alarm = wrapMethodWithSentry(\n { options, context, spanName: 'alarm', spanOp: 'function', startNewTrace: true },\n obj.alarm,\n );\n }\n\n if (obj.webSocketMessage && typeof obj.webSocketMessage === 'function') {\n obj.webSocketMessage = wrapMethodWithSentry(\n { options, context, spanName: 'webSocketMessage' },\n obj.webSocketMessage,\n );\n }\n\n if (obj.webSocketClose && typeof obj.webSocketClose === 'function') {\n obj.webSocketClose = wrapMethodWithSentry({ options, context, spanName: 'webSocketClose' }, obj.webSocketClose);\n }\n\n if (obj.webSocketError && typeof obj.webSocketError === 'function') {\n obj.webSocketError = wrapMethodWithSentry(\n { options, context, spanName: 'webSocketError' },\n obj.webSocketError,\n (_, error) =>\n captureException(error, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object_websocket',\n handled: false,\n },\n }),\n );\n }\n\n for (const method of Object.getOwnPropertyNames(obj)) {\n if (\n method === 'fetch' ||\n method === 'alarm' ||\n method === 'webSocketError' ||\n method === 'webSocketClose' ||\n method === 'webSocketMessage'\n ) {\n continue;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n const value = (obj as any)[method] as unknown;\n if (typeof value === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n (obj as any)[method] = wrapMethodWithSentry(\n { options, context, spanName: method, spanOp: 'rpc' },\n value as UncheckedMethod,\n );\n }\n }\n\n // Store context and options on the instance for prototype methods to access\n Object.defineProperty(obj, '__SENTRY_CONTEXT__', {\n value: context,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n\n Object.defineProperty(obj, '__SENTRY_OPTIONS__', {\n value: options,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n\n const methodFilter = getPrototypeMethodFilter(options);\n\n if (methodFilter) {\n instrumentPrototype(target, methodFilter);\n }\n\n return obj;\n },\n });\n}\n\nfunction instrumentPrototype<T extends NewableFunction>(target: T, methodsToInstrument: boolean | string[]): void {\n const proto = target.prototype;\n\n // Get all methods from the prototype chain\n const methodNames = new Set<string>();\n let current = proto;\n\n while (current && current !== Object.prototype) {\n Object.getOwnPropertyNames(current).forEach(name => {\n if (name !== 'constructor' && typeof (current as Record<string, unknown>)[name] === 'function') {\n methodNames.add(name);\n }\n });\n current = Object.getPrototypeOf(current);\n }\n\n // Create a set for efficient lookups when methodsToInstrument is an array\n const methodsToInstrumentSet = Array.isArray(methodsToInstrument) ? new Set(methodsToInstrument) : null;\n\n // Instrument each method on the prototype\n methodNames.forEach(methodName => {\n const originalMethod = (proto as Record<string, unknown>)[methodName];\n\n if (!originalMethod) {\n return;\n }\n\n const existingInstrumented = getInstrumented(originalMethod);\n if (existingInstrumented) {\n Object.defineProperty(proto, methodName, {\n value: existingInstrumented,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n return;\n }\n\n // If methodsToInstrument is an array, only instrument methods in that set\n if (methodsToInstrumentSet && !methodsToInstrumentSet.has(methodName)) {\n return;\n }\n\n // Create a wrapper that gets context/options from the instance at runtime\n const wrappedMethod = function (this: unknown, ...args: unknown[]): unknown {\n const thisWithSentry = this as {\n __SENTRY_CONTEXT__: DurableObjectState;\n __SENTRY_OPTIONS__: CloudflareOptions;\n };\n const instanceContext = thisWithSentry.__SENTRY_CONTEXT__;\n const instanceOptions = thisWithSentry.__SENTRY_OPTIONS__;\n\n if (!instanceOptions) {\n // Fallback to original method if no Sentry data found\n return (originalMethod as UncheckedMethod).apply(this, args);\n }\n\n // Use the existing wrapper but with instance-specific context/options\n const wrapper = wrapMethodWithSentry(\n {\n options: instanceOptions,\n context: instanceContext,\n spanName: methodName,\n spanOp: 'rpc',\n },\n originalMethod as UncheckedMethod,\n undefined,\n true, // noMark = true since we'll mark the prototype method\n );\n\n return wrapper.apply(this, args);\n };\n\n // Only mark wrappedMethod as instrumented (not originalMethod → wrappedMethod).\n // originalMethod must stay unmapped because wrappedMethod calls\n // wrapMethodWithSentry(options, originalMethod) on each invocation to create\n // a per-instance proxy. If originalMethod mapped to wrappedMethod, that call\n // would return wrappedMethod itself, causing infinite recursion.\n markAsInstrumented(wrappedMethod);\n\n // Replace the prototype method\n Object.defineProperty(proto, methodName, {\n value: wrappedMethod,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n });\n}\n"],"names":["setAsyncLocalStorageAsyncContextStrategy","instrumentContext","options","getFinalOptions","instrumentEnv","ensureInstrumented","wrapRequestHandler","wrapMethodWithSentry","captureException","getPrototypeMethodFilter","getInstrumented","markAsInstrumented"],"mappings":"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"}
1
+ {"version":3,"file":"durableobject.js","sources":["../../src/durableobject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport { captureException } from '@sentry/core';\nimport type { DurableObject } from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from './async';\nimport type { CloudflareOptions } from './client';\nimport { ensureInstrumented } from './instrument';\nimport { instrumentEnv } from './instrumentations/worker/instrumentEnv';\nimport { getFinalOptions } from './options';\nimport { wrapRequestHandler } from './request';\nimport { instrumentContext } from './utils/instrumentContext';\nimport { getEffectiveRpcPropagation } from './utils/rpcOptions';\nimport { type UncheckedMethod, wrapMethodWithSentry } from './wrapMethodWithSentry';\n\nconst BUILT_IN_DO_METHODS = new Set([\n 'constructor',\n 'fetch',\n 'alarm',\n 'webSocketError',\n 'webSocketClose',\n 'webSocketMessage',\n]);\n\n/**\n * Instruments a Durable Object class to capture errors and performance data.\n *\n * Instruments the following methods by default:\n * - fetch\n * - alarm\n * - webSocketMessage\n * - webSocketClose\n * - webSocketError\n *\n * To instrument RPC methods (prototype methods), enable the `enableRpcTracePropagation` option.\n *\n * @param optionsCallback Function that returns the options for the SDK initialization.\n * @param DurableObjectClass The Durable Object class to instrument.\n * @returns The instrumented Durable Object class.\n *\n * @example\n * ```ts\n * class MyDurableObjectBase extends DurableObject {\n * constructor(ctx: DurableObjectState, env: Env) {\n * super(ctx, env);\n * }\n * }\n *\n * export const MyDurableObject = instrumentDurableObjectWithSentry(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * }),\n * MyDurableObjectBase,\n * );\n * ```\n */\nexport function instrumentDurableObjectWithSentry<\n E,\n T extends DurableObject<E>,\n C extends new (state: DurableObjectState, env: E) => T,\n>(optionsCallback: (env: E) => CloudflareOptions, DurableObjectClass: C): C {\n return new Proxy(DurableObjectClass, {\n construct(target, [ctx, env]) {\n setAsyncLocalStorageAsyncContextStrategy();\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n const instrumentedEnv = instrumentEnv(env, options);\n\n const obj = new target(context, instrumentedEnv);\n\n // These are the methods that are available on a Durable Object\n // ref: https://developers.cloudflare.com/durable-objects/api/base/\n // obj.alarm\n // obj.fetch\n // obj.webSocketError\n // obj.webSocketClose\n // obj.webSocketMessage\n\n // Any other public methods on the Durable Object instance are RPC calls.\n\n if (obj.fetch && typeof obj.fetch === 'function') {\n obj.fetch = ensureInstrumented(\n obj.fetch,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args) {\n return wrapRequestHandler({ options, request: args[0], context }, () => {\n return Reflect.apply(target, thisArg, args);\n });\n },\n }),\n );\n }\n\n if (obj.alarm && typeof obj.alarm === 'function') {\n // Alarms are independent invocations, so we start a new trace and link to the previous alarm\n obj.alarm = wrapMethodWithSentry(\n { options, context, spanName: 'alarm', spanOp: 'function', startNewTrace: true },\n obj.alarm,\n );\n }\n\n if (obj.webSocketMessage && typeof obj.webSocketMessage === 'function') {\n obj.webSocketMessage = wrapMethodWithSentry(\n { options, context, spanName: 'webSocketMessage' },\n obj.webSocketMessage,\n );\n }\n\n if (obj.webSocketClose && typeof obj.webSocketClose === 'function') {\n obj.webSocketClose = wrapMethodWithSentry({ options, context, spanName: 'webSocketClose' }, obj.webSocketClose);\n }\n\n if (obj.webSocketError && typeof obj.webSocketError === 'function') {\n obj.webSocketError = wrapMethodWithSentry(\n { options, context, spanName: 'webSocketError' },\n obj.webSocketError,\n (_, error) =>\n captureException(error, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object_websocket',\n handled: false,\n },\n }),\n );\n }\n\n // Get effective RPC propagation setting (handles deprecation of instrumentPrototypeMethods)\n const rpcPropagation = getEffectiveRpcPropagation(options);\n\n // Skip RPC instrumentation if not enabled\n if (!rpcPropagation) {\n return obj;\n }\n\n // If `instrumentPrototypeMethods` was passed as an array (deprecated),\n // only the listed method names should be instrumented.\n const instrumentPrototypeMethods = Array.isArray(options.instrumentPrototypeMethods)\n ? options.instrumentPrototypeMethods\n : undefined;\n const allowSet = instrumentPrototypeMethods ? new Set(instrumentPrototypeMethods) : null;\n\n // Return a Proxy that lazily wraps prototype methods on access.\n // This avoids iterating the prototype chain at construction time —\n // we only check if a property is an RPC method when it's accessed.\n const rpcMethodCache = new Map<string, UncheckedMethod>();\n\n return new Proxy(obj, {\n get(proxyTarget, prop, receiver) {\n const value = Reflect.get(proxyTarget, prop, receiver);\n\n if (typeof prop !== 'string' || BUILT_IN_DO_METHODS.has(prop)) {\n return value;\n }\n\n const cached = rpcMethodCache.get(prop);\n\n if (cached) {\n return cached;\n }\n\n if (\n typeof value !== 'function' ||\n Object.prototype.hasOwnProperty.call(proxyTarget, prop) ||\n (allowSet && !allowSet.has(prop)) ||\n // Exclude inherited Object.prototype methods (toString, valueOf, etc.)\n // These are not RPC methods and should not create spans\n prop in Object.prototype\n ) {\n return value;\n }\n\n // Bind the method to the original object to ensure private fields work correctly.\n // When called via the Proxy, `this` would be the Proxy, but private fields require\n // the original object. Bound functions ignore the thisArg passed via Reflect.apply.\n const boundValue = (value as UncheckedMethod).bind(proxyTarget);\n\n const wrapped = wrapMethodWithSentry(\n { options, context, spanName: prop, spanOp: 'rpc' },\n boundValue,\n undefined,\n true,\n );\n\n rpcMethodCache.set(prop, wrapped);\n\n return wrapped;\n },\n });\n },\n });\n}\n"],"names":["setAsyncLocalStorageAsyncContextStrategy","instrumentContext","options","getFinalOptions","instrumentEnv","ensureInstrumented","wrapRequestHandler","wrapMethodWithSentry","captureException","getEffectiveRpcPropagation"],"mappings":"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"}
@@ -57,6 +57,7 @@ exports.getTraceMetaTags = core.getTraceMetaTags;
57
57
  exports.growthbookIntegration = core.growthbookIntegration;
58
58
  exports.inboundFiltersIntegration = core.inboundFiltersIntegration;
59
59
  exports.instrumentAnthropicAiClient = core.instrumentAnthropicAiClient;
60
+ exports.instrumentCreateReactAgent = core.instrumentCreateReactAgent;
60
61
  exports.instrumentGoogleGenAIClient = core.instrumentGoogleGenAIClient;
61
62
  exports.instrumentLangChainEmbeddings = core.instrumentLangChainEmbeddings;
62
63
  exports.instrumentLangGraph = core.instrumentLangGraph;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,7 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
+ const rpcMeta = require('../utils/rpcMeta.js');
3
4
  const instrumentFetcher = require('./worker/instrumentFetcher.js');
4
5
 
6
+ // Built-in DurableObjectStub methods that are not RPC calls.
7
+ const STUB_NON_RPC_METHODS = new Set(['fetch', 'connect', 'dup']);
8
+
5
9
  /**
6
10
  * Instruments a DurableObjectNamespace binding to create spans for DO interactions.
7
11
  *
@@ -34,17 +38,22 @@ function instrumentDurableObjectNamespace(namespace) {
34
38
  }
35
39
 
36
40
  /**
37
- * Instruments a DurableObjectStub to propagate trace context across fetch calls.
41
+ * Instruments a DurableObjectStub to create spans for outgoing fetch calls
42
+ * and propagate trace context across RPC calls.
38
43
  *
39
44
  * @param stub - The DurableObjectStub to instrument
40
45
  */
41
46
  function instrumentDurableObjectStub(stub) {
42
47
  return new Proxy(stub, {
43
- get(target, prop, receiver) {
44
- const value = Reflect.get(target, prop, receiver);
48
+ get(target, prop) {
49
+ const value = Reflect.get(target, prop);
45
50
 
46
51
  if (prop === 'fetch' && typeof value === 'function') {
47
- return instrumentFetcher.instrumentFetcher((input, init) => Reflect.apply(value, target, [input, init]));
52
+ return instrumentFetcher.instrumentFetcher((...args) => Reflect.apply(value, target, args));
53
+ }
54
+
55
+ if (typeof value === 'function' && typeof prop === 'string' && !STUB_NON_RPC_METHODS.has(prop)) {
56
+ return (...args) => Reflect.apply(value, target, rpcMeta.appendRpcMeta(args));
48
57
  }
49
58
 
50
59
  return value;
@@ -52,5 +61,6 @@ function instrumentDurableObjectStub(stub) {
52
61
  });
53
62
  }
54
63
 
64
+ exports.STUB_NON_RPC_METHODS = STUB_NON_RPC_METHODS;
55
65
  exports.instrumentDurableObjectNamespace = instrumentDurableObjectNamespace;
56
66
  //# sourceMappingURL=instrumentDurableObjectNamespace.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentDurableObjectNamespace.js","sources":["../../../src/instrumentations/instrumentDurableObjectNamespace.ts"],"sourcesContent":["import type { DurableObjectNamespace, DurableObjectStub } from '@cloudflare/workers-types';\nimport { instrumentFetcher } from './worker/instrumentFetcher';\n\n/**\n * Instruments a DurableObjectNamespace binding to create spans for DO interactions.\n *\n * Wraps:\n * - `namespace.get(id)` / `namespace.getByName(name)` with a span + instruments returned stub\n * - `namespace.idFromName(name)` / `namespace.idFromString(id)` / `namespace.newUniqueId()` with breadcrumbs\n *\n * @param namespace - The DurableObjectNamespace to instrument\n */\nexport function instrumentDurableObjectNamespace(namespace: DurableObjectNamespace): DurableObjectNamespace {\n return new Proxy(namespace, {\n get(target, prop, _receiver) {\n const value = Reflect.get(target, prop) as unknown;\n\n if (typeof value !== 'function') {\n return value;\n }\n\n if (prop === 'get' || prop === 'getByName') {\n return function (this: unknown, ...args: unknown[]) {\n const stub = Reflect.apply(value, target, args);\n\n return instrumentDurableObjectStub(stub);\n };\n }\n\n return value.bind(target);\n },\n });\n}\n\n/**\n * Instruments a DurableObjectStub to propagate trace context across fetch calls.\n *\n * @param stub - The DurableObjectStub to instrument\n */\nfunction instrumentDurableObjectStub(stub: DurableObjectStub): DurableObjectStub {\n return new Proxy(stub, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n\n if (prop === 'fetch' && typeof value === 'function') {\n return instrumentFetcher((input, init) => Reflect.apply(value, target, [input, init]));\n }\n\n return value;\n },\n });\n}\n"],"names":["instrumentFetcher"],"mappings":";;;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gCAAgC,CAAC,SAAS,EAAkD;AAC5G,EAAE,OAAO,IAAI,KAAK,CAAC,SAAS,EAAE;AAC9B,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;AACjC,MAAM,MAAM,KAAA,GAAQ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAA;;AAE5C,MAAM,IAAI,OAAO,KAAA,KAAU,UAAU,EAAE;AACvC,QAAQ,OAAO,KAAK;AACpB,MAAM;;AAEN,MAAM,IAAI,IAAA,KAAS,SAAS,IAAA,KAAS,WAAW,EAAE;AAClD,QAAQ,OAAO,WAAyB,GAAG,IAAI,EAAa;AAC5D,UAAU,MAAM,IAAA,GAAO,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC;;AAEzD,UAAU,OAAO,2BAA2B,CAAC,IAAI,CAAC;AAClD,QAAQ,CAAC;AACT,MAAM;;AAEN,MAAM,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;AAC/B,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAS,2BAA2B,CAAC,IAAI,EAAwC;AACjF,EAAE,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE;AACzB,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE;AAChC,MAAM,MAAM,KAAA,GAAQ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC;;AAEvD,MAAM,IAAI,IAAA,KAAS,OAAA,IAAW,OAAO,KAAA,KAAU,UAAU,EAAE;AAC3D,QAAQ,OAAOA,mCAAiB,CAAC,CAAC,KAAK,EAAE,IAAI,KAAK,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAC9F,MAAM;;AAEN,MAAM,OAAO,KAAK;AAClB,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;;;"}
1
+ {"version":3,"file":"instrumentDurableObjectNamespace.js","sources":["../../../src/instrumentations/instrumentDurableObjectNamespace.ts"],"sourcesContent":["import type { DurableObjectNamespace, DurableObjectStub } from '@cloudflare/workers-types';\nimport { appendRpcMeta } from '../utils/rpcMeta';\nimport { instrumentFetcher } from './worker/instrumentFetcher';\n\n// Built-in DurableObjectStub methods that are not RPC calls.\nexport const STUB_NON_RPC_METHODS = new Set(['fetch', 'connect', 'dup']);\n\n/**\n * Instruments a DurableObjectNamespace binding to create spans for DO interactions.\n *\n * Wraps:\n * - `namespace.get(id)` / `namespace.getByName(name)` with a span + instruments returned stub\n * - `namespace.idFromName(name)` / `namespace.idFromString(id)` / `namespace.newUniqueId()` with breadcrumbs\n *\n * @param namespace - The DurableObjectNamespace to instrument\n */\nexport function instrumentDurableObjectNamespace(namespace: DurableObjectNamespace): DurableObjectNamespace {\n return new Proxy(namespace, {\n get(target, prop, _receiver) {\n const value = Reflect.get(target, prop) as unknown;\n\n if (typeof value !== 'function') {\n return value;\n }\n\n if (prop === 'get' || prop === 'getByName') {\n return function (this: unknown, ...args: unknown[]) {\n const stub = Reflect.apply(value, target, args);\n\n return instrumentDurableObjectStub(stub);\n };\n }\n\n return value.bind(target);\n },\n });\n}\n\n/**\n * Instruments a DurableObjectStub to create spans for outgoing fetch calls\n * and propagate trace context across RPC calls.\n *\n * @param stub - The DurableObjectStub to instrument\n */\nfunction instrumentDurableObjectStub(stub: DurableObjectStub): DurableObjectStub {\n return new Proxy(stub, {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n if (prop === 'fetch' && typeof value === 'function') {\n return instrumentFetcher((...args) => Reflect.apply(value, target, args));\n }\n\n if (typeof value === 'function' && typeof prop === 'string' && !STUB_NON_RPC_METHODS.has(prop)) {\n return (...args: unknown[]) => Reflect.apply(value, target, appendRpcMeta(args));\n }\n\n return value;\n },\n });\n}\n"],"names":["instrumentFetcher","appendRpcMeta"],"mappings":";;;;;AAIA;AACO,MAAM,oBAAA,GAAuB,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC;;AAEvE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gCAAgC,CAAC,SAAS,EAAkD;AAC5G,EAAE,OAAO,IAAI,KAAK,CAAC,SAAS,EAAE;AAC9B,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;AACjC,MAAM,MAAM,KAAA,GAAQ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAA;;AAE5C,MAAM,IAAI,OAAO,KAAA,KAAU,UAAU,EAAE;AACvC,QAAQ,OAAO,KAAK;AACpB,MAAM;;AAEN,MAAM,IAAI,IAAA,KAAS,SAAS,IAAA,KAAS,WAAW,EAAE;AAClD,QAAQ,OAAO,WAAyB,GAAG,IAAI,EAAa;AAC5D,UAAU,MAAM,IAAA,GAAO,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC;;AAEzD,UAAU,OAAO,2BAA2B,CAAC,IAAI,CAAC;AAClD,QAAQ,CAAC;AACT,MAAM;;AAEN,MAAM,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;AAC/B,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,2BAA2B,CAAC,IAAI,EAAwC;AACjF,EAAE,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE;AACzB,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE;AACtB,MAAM,MAAM,KAAA,GAAQ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;;AAE7C,MAAM,IAAI,IAAA,KAAS,OAAA,IAAW,OAAO,KAAA,KAAU,UAAU,EAAE;AAC3D,QAAQ,OAAOA,mCAAiB,CAAC,CAAC,GAAG,IAAI,KAAK,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AACjF,MAAM;;AAEN,MAAM,IAAI,OAAO,UAAU,UAAA,IAAc,OAAO,IAAA,KAAS,QAAA,IAAY,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AACtG,QAAQ,OAAO,CAAC,GAAG,IAAI,KAAgB,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAEC,qBAAa,CAAC,IAAI,CAAC,CAAC;AACxF,MAAM;;AAEN,MAAM,OAAO,KAAK;AAClB,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;;;;"}
@@ -1,6 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const isBinding = require('../../utils/isBinding.js');
4
+ const rpcMeta = require('../../utils/rpcMeta.js');
4
5
  const rpcOptions = require('../../utils/rpcOptions.js');
5
6
  const instrumentDurableObjectNamespace = require('../instrumentDurableObjectNamespace.js');
6
7
  const instrumentFetcher = require('./instrumentFetcher.js');
@@ -59,11 +60,15 @@ function instrumentEnv(env, options) {
59
60
 
60
61
  if (isBinding.isJSRPC(item)) {
61
62
  const instrumented = new Proxy(item, {
62
- get(target, p, rcv) {
63
- const value = Reflect.get(target, p, rcv);
63
+ get(target, p) {
64
+ const value = Reflect.get(target, p);
64
65
 
65
66
  if (p === 'fetch' && typeof value === 'function') {
66
- return instrumentFetcher.instrumentFetcher(value.bind(target));
67
+ return instrumentFetcher.instrumentFetcher((...args) => Reflect.apply(value, target, args));
68
+ }
69
+
70
+ if (typeof value === 'function' && typeof p === 'string' && !instrumentDurableObjectNamespace.STUB_NON_RPC_METHODS.has(p)) {
71
+ return (...args) => Reflect.apply(value, target, rpcMeta.appendRpcMeta(args));
67
72
  }
68
73
 
69
74
  return value;
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentEnv.js","sources":["../../../../src/instrumentations/worker/instrumentEnv.ts"],"sourcesContent":["import type { CloudflareOptions } from '../../client';\nimport { isDurableObjectNamespace, isJSRPC } from '../../utils/isBinding';\nimport { getEffectiveRpcPropagation } from '../../utils/rpcOptions';\nimport { instrumentDurableObjectNamespace } from '../instrumentDurableObjectNamespace';\nimport { instrumentFetcher } from './instrumentFetcher';\n\nfunction isProxyable(item: unknown): item is object {\n return item !== null && (typeof item === 'object' || typeof item === 'function');\n}\n\nconst instrumentedBindings = new WeakMap<object, unknown>();\n\n/**\n * Wraps the Cloudflare `env` object in a Proxy that detects binding types\n * on property access and returns instrumented versions.\n *\n * Currently detects:\n * - DurableObjectNamespace (via `idFromName` duck-typing)\n * - Service bindings / JSRPC proxies (wraps `fetch` for trace propagation)\n *\n * Extensible for future binding types (KV, D1, Queue, etc.).\n *\n * @param env - The Cloudflare env object to instrument\n * @param options - Optional CloudflareOptions to control RPC trace propagation\n */\nexport function instrumentEnv<Env extends Record<string, unknown>>(env: Env, options?: CloudflareOptions): Env {\n if (!env || typeof env !== 'object') {\n return env;\n }\n\n const rpcPropagation = options ? getEffectiveRpcPropagation(options) : false;\n\n // As of now only trace propagation is used for the instrumentEnv\n // so this is an optimization to avoid wrapping the env in a proxy if trace propagation is disabled\n if (!rpcPropagation) {\n return env;\n }\n\n return new Proxy(env, {\n get(target, prop, receiver) {\n const item = Reflect.get(target, prop, receiver);\n\n if (!isProxyable(item)) {\n return item;\n }\n\n const cached = instrumentedBindings.get(item);\n\n if (cached) {\n return cached;\n }\n\n if (isDurableObjectNamespace(item)) {\n const instrumented = instrumentDurableObjectNamespace(item);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n if (isJSRPC(item)) {\n const instrumented = new Proxy(item, {\n get(target, p, rcv) {\n const value = Reflect.get(target, p, rcv);\n\n if (p === 'fetch' && typeof value === 'function') {\n return instrumentFetcher(value.bind(target));\n }\n\n return value;\n },\n });\n\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n return item;\n },\n });\n}\n"],"names":["getEffectiveRpcPropagation","isDurableObjectNamespace","instrumentDurableObjectNamespace","isJSRPC","instrumentFetcher"],"mappings":";;;;;;;AAMA,SAAS,WAAW,CAAC,IAAI,EAA2B;AACpD,EAAE,OAAO,IAAA,KAAS,IAAA,KAAS,OAAO,IAAA,KAAS,YAAY,OAAO,IAAA,KAAS,UAAU,CAAC;AAClF;;AAEA,MAAM,oBAAA,GAAuB,IAAI,OAAO,EAAmB;;AAE3D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,aAAa,CAAsC,GAAG,EAAO,OAAO,EAA2B;AAC/G,EAAE,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAQ,EAAE;AACvC,IAAI,OAAO,GAAG;AACd,EAAE;;AAEF,EAAE,MAAM,cAAA,GAAiB,OAAA,GAAUA,qCAA0B,CAAC,OAAO,CAAA,GAAI,KAAK;;AAE9E;AACA;AACA,EAAE,IAAI,CAAC,cAAc,EAAE;AACvB,IAAI,OAAO,GAAG;AACd,EAAE;;AAEF,EAAE,OAAO,IAAI,KAAK,CAAC,GAAG,EAAE;AACxB,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE;AAChC,MAAM,MAAM,IAAA,GAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC;;AAEtD,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE;AAC9B,QAAQ,OAAO,IAAI;AACnB,MAAM;;AAEN,MAAM,MAAM,SAAS,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC;;AAEnD,MAAM,IAAI,MAAM,EAAE;AAClB,QAAQ,OAAO,MAAM;AACrB,MAAM;;AAEN,MAAM,IAAIC,kCAAwB,CAAC,IAAI,CAAC,EAAE;AAC1C,QAAQ,MAAM,YAAA,GAAeC,iEAAgC,CAAC,IAAI,CAAC;AACnE,QAAQ,oBAAoB,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC;AACpD,QAAQ,OAAO,YAAY;AAC3B,MAAM;;AAEN,MAAM,IAAIC,iBAAO,CAAC,IAAI,CAAC,EAAE;AACzB,QAAQ,MAAM,YAAA,GAAe,IAAI,KAAK,CAAC,IAAI,EAAE;AAC7C,UAAU,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE;AAC9B,YAAY,MAAM,KAAA,GAAQ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC;;AAErD,YAAY,IAAI,CAAA,KAAM,OAAA,IAAW,OAAO,KAAA,KAAU,UAAU,EAAE;AAC9D,cAAc,OAAOC,mCAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC1D,YAAY;;AAEZ,YAAY,OAAO,KAAK;AACxB,UAAU,CAAC;AACX,SAAS,CAAC;;AAEV,QAAQ,oBAAoB,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC;AACpD,QAAQ,OAAO,YAAY;AAC3B,MAAM;;AAEN,MAAM,OAAO,IAAI;AACjB,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;;;"}
1
+ {"version":3,"file":"instrumentEnv.js","sources":["../../../../src/instrumentations/worker/instrumentEnv.ts"],"sourcesContent":["import type { CloudflareOptions } from '../../client';\nimport { isDurableObjectNamespace, isJSRPC } from '../../utils/isBinding';\nimport { appendRpcMeta } from '../../utils/rpcMeta';\nimport { getEffectiveRpcPropagation } from '../../utils/rpcOptions';\nimport { instrumentDurableObjectNamespace, STUB_NON_RPC_METHODS } from '../instrumentDurableObjectNamespace';\nimport { instrumentFetcher } from './instrumentFetcher';\n\nfunction isProxyable(item: unknown): item is object {\n return item !== null && (typeof item === 'object' || typeof item === 'function');\n}\n\nconst instrumentedBindings = new WeakMap<object, unknown>();\n\n/**\n * Wraps the Cloudflare `env` object in a Proxy that detects binding types\n * on property access and returns instrumented versions.\n *\n * Currently detects:\n * - DurableObjectNamespace (via `idFromName` duck-typing)\n * - Service bindings / JSRPC proxies (wraps `fetch` for trace propagation)\n *\n * Extensible for future binding types (KV, D1, Queue, etc.).\n *\n * @param env - The Cloudflare env object to instrument\n * @param options - Optional CloudflareOptions to control RPC trace propagation\n */\nexport function instrumentEnv<Env extends Record<string, unknown>>(env: Env, options?: CloudflareOptions): Env {\n if (!env || typeof env !== 'object') {\n return env;\n }\n\n const rpcPropagation = options ? getEffectiveRpcPropagation(options) : false;\n\n // As of now only trace propagation is used for the instrumentEnv\n // so this is an optimization to avoid wrapping the env in a proxy if trace propagation is disabled\n if (!rpcPropagation) {\n return env;\n }\n\n return new Proxy(env, {\n get(target, prop, receiver) {\n const item = Reflect.get(target, prop, receiver);\n\n if (!isProxyable(item)) {\n return item;\n }\n\n const cached = instrumentedBindings.get(item);\n\n if (cached) {\n return cached;\n }\n\n if (isDurableObjectNamespace(item)) {\n const instrumented = instrumentDurableObjectNamespace(item);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n if (isJSRPC(item)) {\n const instrumented = new Proxy(item, {\n get(target, p) {\n const value = Reflect.get(target, p);\n\n if (p === 'fetch' && typeof value === 'function') {\n return instrumentFetcher((...args) => Reflect.apply(value, target, args));\n }\n\n if (typeof value === 'function' && typeof p === 'string' && !STUB_NON_RPC_METHODS.has(p)) {\n return (...args: unknown[]) => Reflect.apply(value, target, appendRpcMeta(args));\n }\n\n return value;\n },\n });\n\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n return item;\n },\n });\n}\n"],"names":["getEffectiveRpcPropagation","isDurableObjectNamespace","instrumentDurableObjectNamespace","isJSRPC","instrumentFetcher","STUB_NON_RPC_METHODS","appendRpcMeta"],"mappings":";;;;;;;;AAOA,SAAS,WAAW,CAAC,IAAI,EAA2B;AACpD,EAAE,OAAO,IAAA,KAAS,IAAA,KAAS,OAAO,IAAA,KAAS,YAAY,OAAO,IAAA,KAAS,UAAU,CAAC;AAClF;;AAEA,MAAM,oBAAA,GAAuB,IAAI,OAAO,EAAmB;;AAE3D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,aAAa,CAAsC,GAAG,EAAO,OAAO,EAA2B;AAC/G,EAAE,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAQ,EAAE;AACvC,IAAI,OAAO,GAAG;AACd,EAAE;;AAEF,EAAE,MAAM,cAAA,GAAiB,OAAA,GAAUA,qCAA0B,CAAC,OAAO,CAAA,GAAI,KAAK;;AAE9E;AACA;AACA,EAAE,IAAI,CAAC,cAAc,EAAE;AACvB,IAAI,OAAO,GAAG;AACd,EAAE;;AAEF,EAAE,OAAO,IAAI,KAAK,CAAC,GAAG,EAAE;AACxB,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE;AAChC,MAAM,MAAM,IAAA,GAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC;;AAEtD,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE;AAC9B,QAAQ,OAAO,IAAI;AACnB,MAAM;;AAEN,MAAM,MAAM,SAAS,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC;;AAEnD,MAAM,IAAI,MAAM,EAAE;AAClB,QAAQ,OAAO,MAAM;AACrB,MAAM;;AAEN,MAAM,IAAIC,kCAAwB,CAAC,IAAI,CAAC,EAAE;AAC1C,QAAQ,MAAM,YAAA,GAAeC,iEAAgC,CAAC,IAAI,CAAC;AACnE,QAAQ,oBAAoB,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC;AACpD,QAAQ,OAAO,YAAY;AAC3B,MAAM;;AAEN,MAAM,IAAIC,iBAAO,CAAC,IAAI,CAAC,EAAE;AACzB,QAAQ,MAAM,YAAA,GAAe,IAAI,KAAK,CAAC,IAAI,EAAE;AAC7C,UAAU,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE;AACzB,YAAY,MAAM,KAAA,GAAQ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;;AAEhD,YAAY,IAAI,CAAA,KAAM,OAAA,IAAW,OAAO,KAAA,KAAU,UAAU,EAAE;AAC9D,cAAc,OAAOC,mCAAiB,CAAC,CAAC,GAAG,IAAI,KAAK,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AACvF,YAAY;;AAEZ,YAAY,IAAI,OAAO,UAAU,UAAA,IAAc,OAAO,CAAA,KAAM,QAAA,IAAY,CAACC,qDAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;AACtG,cAAc,OAAO,CAAC,GAAG,IAAI,KAAgB,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAEC,qBAAa,CAAC,IAAI,CAAC,CAAC;AAC9F,YAAY;;AAEZ,YAAY,OAAO,KAAK;AACxB,UAAU,CAAC;AACX,SAAS,CAAC;;AAEV,QAAQ,oBAAoB,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC;AACpD,QAAQ,OAAO,YAAY;AAC3B,MAAM;;AAEN,MAAM,OAAO,IAAI;AACjB,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;;;"}
@@ -100,40 +100,36 @@ function wrapRequestHandler(
100
100
  const classification = streaming.classifyResponseStreaming(res);
101
101
 
102
102
  if (classification.isStreaming && res.body) {
103
- // Streaming response detected - monitor consumption to keep span alive
104
103
  try {
105
- const [clientStream, monitorStream] = res.body.tee();
106
-
107
- // Monitor stream consumption and end span when complete
108
- const streamMonitor = (async () => {
109
- const reader = monitorStream.getReader();
110
-
111
- try {
112
- let done = false;
113
- while (!done) {
114
- const result = await reader.read();
115
- done = result.done;
116
- }
117
- } catch {
118
- // Stream error or cancellation - will end span in finally
119
- } finally {
120
- reader.releaseLock();
121
- span.end();
122
- waitUntil?.(flush.flushAndDispose(client));
123
- }
124
- })();
125
-
126
- // Keep worker alive until stream monitoring completes (otherwise span won't end)
127
- waitUntil?.(streamMonitor);
128
-
129
- // Return response with client stream
130
- return new Response(clientStream, {
104
+ let ended = false;
105
+
106
+ const endSpanOnce = () => {
107
+ if (ended) return;
108
+
109
+ ended = true;
110
+ span.end();
111
+ waitUntil?.(flush.flushAndDispose(client));
112
+ };
113
+
114
+ const transform = new TransformStream({
115
+ flush() {
116
+ // Source stream completed normally.
117
+ endSpanOnce();
118
+ },
119
+ cancel() {
120
+ // Client disconnected (or downstream cancelled). The `cancel`
121
+ // is being called while the response is still considered
122
+ // active, so this is a safe place to end the span.
123
+ endSpanOnce();
124
+ },
125
+ });
126
+
127
+ return new Response(res.body.pipeThrough(transform), {
131
128
  status: res.status,
132
129
  statusText: res.statusText,
133
130
  headers: res.headers,
134
131
  });
135
- } catch (_e) {
136
- // tee() failed (e.g stream already locked) - fall back to non-streaming handling
132
+ } catch {
137
133
  span.end();
138
134
  waitUntil?.(flush.flushAndDispose(client));
139
135
  return res;
@@ -1 +1 @@
1
- {"version":3,"file":"request.js","sources":["../../src/request.ts"],"sourcesContent":["import type { CfProperties, 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> | CfProperties<unknown>>;\n context: ExecutionContext | undefined;\n /**\n * If true, errors will be captured, rethrown and sent to Sentry.\n * Otherwise, errors are rethrown but not captured.\n *\n * You most likely don't want to set this to `false`, if you use `wrapRequestHandler` directly.\n * This is primarily meant as an escape hatch for higher-level SDKs relying on additional error\n * capturing mechanisms where this wrapper captures errors too early or too generally.\n *\n * @default true\n */\n captureErrors?: boolean;\n}\n\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 const context = wrapperOptions.context;\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\n if (typeof request.cf.httpProtocol === 'string') {\n attributes['network.protocol.name'] = request.cf.httpProtocol;\n }\n }\n\n // Do not capture spans for OPTIONS and HEAD requests\n if (request.method === 'OPTIONS' || request.method === 'HEAD') {\n try {\n return await handler();\n } catch (e) {\n if (captureErrors) {\n captureException(e, { mechanism: { handled: false, type: '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":["withIsolationScope","init","parseStringToURLObject","getHttpSpanDetailsFromUrlObject","httpHeadersToSpanAttributes","winterCGHeadersToDict","getClient","SEMANTIC_ATTRIBUTE_SENTRY_OP","addCloudResourceContext","addRequest","addCultureContext","captureException","flushAndDispose","continueTrace","startSpanManual","setHttpStatus","classifyResponseStreaming"],"mappings":"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"}
1
+ {"version":3,"file":"request.js","sources":["../../src/request.ts"],"sourcesContent":["import type { CfProperties, 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> | CfProperties<unknown>>;\n context: ExecutionContext | undefined;\n /**\n * If true, errors will be captured, rethrown and sent to Sentry.\n * Otherwise, errors are rethrown but not captured.\n *\n * You most likely don't want to set this to `false`, if you use `wrapRequestHandler` directly.\n * This is primarily meant as an escape hatch for higher-level SDKs relying on additional error\n * capturing mechanisms where this wrapper captures errors too early or too generally.\n *\n * @default true\n */\n captureErrors?: boolean;\n}\n\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 const context = wrapperOptions.context;\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\n if (typeof request.cf.httpProtocol === 'string') {\n attributes['network.protocol.name'] = request.cf.httpProtocol;\n }\n }\n\n // Do not capture spans for OPTIONS and HEAD requests\n if (request.method === 'OPTIONS' || request.method === 'HEAD') {\n try {\n return await handler();\n } catch (e) {\n if (captureErrors) {\n captureException(e, { mechanism: { handled: false, type: '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 try {\n let ended = false;\n\n const endSpanOnce = (): void => {\n if (ended) return;\n\n ended = true;\n span.end();\n waitUntil?.(flushAndDispose(client));\n };\n\n const transform = new TransformStream({\n flush() {\n // Source stream completed normally.\n endSpanOnce();\n },\n cancel() {\n // Client disconnected (or downstream cancelled). The `cancel`\n // is being called while the response is still considered\n // active, so this is a safe place to end the span.\n endSpanOnce();\n },\n });\n\n return new Response(res.body.pipeThrough(transform), {\n status: res.status,\n statusText: res.statusText,\n headers: res.headers,\n });\n } catch {\n span.end();\n waitUntil?.(flushAndDispose(client));\n return res;\n }\n }\n\n // Non-streaming response - end span immediately and return original\n span.end();\n\n // Don't dispose for protocol upgrades (101 Switching Protocols) - the connection stays alive.\n // This includes WebSocket upgrades where webSocketMessage/webSocketClose handlers\n // will still be called and may need the client to capture errors.\n if (res.status === 101) {\n waitUntil?.(client?.flush(2000));\n } else {\n waitUntil?.(flushAndDispose(client));\n }\n return res;\n });\n },\n );\n });\n}\n"],"names":["withIsolationScope","init","parseStringToURLObject","getHttpSpanDetailsFromUrlObject","httpHeadersToSpanAttributes","winterCGHeadersToDict","getClient","SEMANTIC_ATTRIBUTE_SENTRY_OP","addCloudResourceContext","addRequest","addCultureContext","captureException","flushAndDispose","continueTrace","startSpanManual","setHttpStatus","classifyResponseStreaming"],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+
5
+ /**
6
+ * Key used to identify Sentry RPC metadata in a trailing argument.
7
+ * This enables transparent trace propagation across Cloudflare Workers RPC
8
+ * calls (Cap'n Proto), which have no native header/metadata support.
9
+ */
10
+ const SENTRY_RPC_META_KEY = '__sentry_rpc_meta__';
11
+
12
+ function isSentryRpcMeta(value) {
13
+ if (typeof value !== 'object' || value === null || !(SENTRY_RPC_META_KEY in value)) {
14
+ return false;
15
+ }
16
+ const sentry = (value ).__sentry_rpc_meta__;
17
+ return typeof sentry === 'object' && sentry !== null;
18
+ }
19
+
20
+ /**
21
+ * Appends Sentry RPC metadata to an args array for trace propagation.
22
+ * If no active trace exists, returns the original args unchanged.
23
+ */
24
+ function appendRpcMeta(args) {
25
+ const traceData = core.getTraceData();
26
+
27
+ if (!traceData['sentry-trace']) {
28
+ return args;
29
+ }
30
+
31
+ return [...args, { [SENTRY_RPC_META_KEY]: traceData }];
32
+ }
33
+
34
+ /**
35
+ * Extracts Sentry RPC metadata from the trailing argument of an args array.
36
+ * Returns cleaned args (without meta) and the extracted trace data if found.
37
+ */
38
+ function extractRpcMeta(
39
+ args,
40
+ )
41
+
42
+ {
43
+ if (args.length === 0) {
44
+ return { args };
45
+ }
46
+
47
+ const last = args[args.length - 1];
48
+ if (isSentryRpcMeta(last)) {
49
+ return {
50
+ args: args.slice(0, -1) ,
51
+ rpcMeta: last.__sentry_rpc_meta__,
52
+ };
53
+ }
54
+
55
+ return { args };
56
+ }
57
+
58
+ exports.appendRpcMeta = appendRpcMeta;
59
+ exports.extractRpcMeta = extractRpcMeta;
60
+ //# sourceMappingURL=rpcMeta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpcMeta.js","sources":["../../../src/utils/rpcMeta.ts"],"sourcesContent":["import { getTraceData, type SerializedTraceData } from '@sentry/core';\n\n/**\n * Key used to identify Sentry RPC metadata in a trailing argument.\n * This enables transparent trace propagation across Cloudflare Workers RPC\n * calls (Cap'n Proto), which have no native header/metadata support.\n */\nconst SENTRY_RPC_META_KEY = '__sentry_rpc_meta__';\n\ninterface SentryRpcMeta {\n __sentry_rpc_meta__: SerializedTraceData;\n}\n\nfunction isSentryRpcMeta(value: unknown): value is SentryRpcMeta {\n if (typeof value !== 'object' || value === null || !(SENTRY_RPC_META_KEY in value)) {\n return false;\n }\n const sentry = (value as SentryRpcMeta).__sentry_rpc_meta__;\n return typeof sentry === 'object' && sentry !== null;\n}\n\n/**\n * Appends Sentry RPC metadata to an args array for trace propagation.\n * If no active trace exists, returns the original args unchanged.\n */\nexport function appendRpcMeta(args: unknown[]): unknown[] {\n const traceData = getTraceData();\n\n if (!traceData['sentry-trace']) {\n return args;\n }\n\n return [...args, { [SENTRY_RPC_META_KEY]: traceData }];\n}\n\n/**\n * Extracts Sentry RPC metadata from the trailing argument of an args array.\n * Returns cleaned args (without meta) and the extracted trace data if found.\n */\nexport function extractRpcMeta<T extends unknown[]>(\n args: T,\n): {\n args: T;\n rpcMeta?: SerializedTraceData;\n} {\n if (args.length === 0) {\n return { args };\n }\n\n const last = args[args.length - 1];\n if (isSentryRpcMeta(last)) {\n return {\n args: args.slice(0, -1) as T,\n rpcMeta: last.__sentry_rpc_meta__,\n };\n }\n\n return { args };\n}\n"],"names":["getTraceData"],"mappings":";;;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAM,mBAAA,GAAsB,qBAAqB;;AAMjD,SAAS,eAAe,CAAC,KAAK,EAAmC;AACjE,EAAE,IAAI,OAAO,KAAA,KAAU,YAAY,KAAA,KAAU,IAAA,IAAQ,EAAE,uBAAuB,KAAK,CAAC,EAAE;AACtF,IAAI,OAAO,KAAK;AAChB,EAAE;AACF,EAAE,MAAM,MAAA,GAAS,CAAC,KAAA,GAAwB,mBAAmB;AAC7D,EAAE,OAAO,OAAO,MAAA,KAAW,YAAY,MAAA,KAAW,IAAI;AACtD;;AAEA;AACA;AACA;AACA;AACO,SAAS,aAAa,CAAC,IAAI,EAAwB;AAC1D,EAAE,MAAM,SAAA,GAAYA,iBAAY,EAAE;;AAElC,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE;AAClC,IAAI,OAAO,IAAI;AACf,EAAE;;AAEF,EAAE,OAAO,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,mBAAmB,GAAG,SAAA,EAAW,CAAC;AACxD;;AAEA;AACA;AACA;AACA;AACO,SAAS,cAAc;AAC9B,EAAE,IAAI;AACN;;AAGA,CAAE;AACF,EAAE,IAAI,IAAI,CAAC,MAAA,KAAW,CAAC,EAAE;AACzB,IAAI,OAAO,EAAE,IAAA,EAAM;AACnB,EAAE;;AAEF,EAAE,MAAM,IAAA,GAAO,IAAI,CAAC,IAAI,CAAC,MAAA,GAAS,CAAC,CAAC;AACpC,EAAE,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE;AAC7B,IAAI,OAAO;AACX,MAAM,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAA;AAC5B,MAAM,OAAO,EAAE,IAAI,CAAC,mBAAmB;AACvC,KAAK;AACL,EAAE;;AAEF,EAAE,OAAO,EAAE,IAAA,EAAM;AACjB;;;;;"}