@sentry/cloudflare 10.50.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.
- package/build/cjs/durableobject.js +68 -130
- package/build/cjs/durableobject.js.map +1 -1
- package/build/cjs/index.js +1 -0
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/instrumentations/instrumentDurableObjectNamespace.js +14 -4
- package/build/cjs/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
- package/build/cjs/instrumentations/worker/instrumentEnv.js +8 -3
- package/build/cjs/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/cjs/utils/rpcMeta.js +60 -0
- package/build/cjs/utils/rpcMeta.js.map +1 -0
- package/build/cjs/utils/rpcOptions.js +1 -36
- package/build/cjs/utils/rpcOptions.js.map +1 -1
- package/build/cjs/wrapMethodWithSentry.js +21 -1
- package/build/cjs/wrapMethodWithSentry.js.map +1 -1
- package/build/esm/durableobject.js +70 -132
- package/build/esm/durableobject.js.map +1 -1
- package/build/esm/index.js +1 -1
- package/build/esm/instrumentations/instrumentDurableObjectNamespace.js +14 -5
- package/build/esm/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
- package/build/esm/instrumentations/worker/instrumentEnv.js +9 -4
- package/build/esm/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/utils/rpcMeta.js +57 -0
- package/build/esm/utils/rpcMeta.js.map +1 -0
- package/build/esm/utils/rpcOptions.js +2 -36
- package/build/esm/utils/rpcOptions.js.map +1 -1
- package/build/esm/wrapMethodWithSentry.js +22 -2
- package/build/esm/wrapMethodWithSentry.js.map +1 -1
- package/build/types/durableobject.d.ts +2 -2
- package/build/types/durableobject.d.ts.map +1 -1
- package/build/types/index.d.ts +1 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts +1 -0
- package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts.map +1 -1
- package/build/types/instrumentations/worker/instrumentEnv.d.ts.map +1 -1
- package/build/types/utils/rpcMeta.d.ts +15 -0
- package/build/types/utils/rpcMeta.d.ts.map +1 -0
- package/build/types/utils/rpcOptions.d.ts +1 -12
- package/build/types/utils/rpcOptions.d.ts.map +1 -1
- package/build/types/wrapMethodWithSentry.d.ts.map +1 -1
- package/build/types-ts3.8/durableobject.d.ts +2 -2
- package/build/types-ts3.8/index.d.ts +1 -1
- package/build/types-ts3.8/instrumentations/instrumentDurableObjectNamespace.d.ts +1 -0
- package/build/types-ts3.8/utils/rpcMeta.d.ts +15 -0
- package/build/types-ts3.8/utils/rpcOptions.d.ts +1 -12
- 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
|
-
*
|
|
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
|
-
|
|
118
|
-
|
|
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
|
|
157
|
-
|
|
129
|
+
// Skip RPC instrumentation if not enabled
|
|
130
|
+
if (!rpcPropagation) {
|
|
131
|
+
return obj;
|
|
158
132
|
}
|
|
159
133
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
|
|
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
|
-
|
|
222
|
-
const wrapper = wrapMethodWithSentry.wrapMethodWithSentry(
|
|
223
|
-
{
|
|
224
|
-
options: instanceOptions,
|
|
225
|
-
context: instanceContext,
|
|
226
|
-
spanName: methodName,
|
|
227
|
-
spanOp: 'rpc',
|
|
185
|
+
return wrapped;
|
|
228
186
|
},
|
|
229
|
-
|
|
230
|
-
|
|
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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"}
|
package/build/cjs/index.js
CHANGED
|
@@ -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;
|
package/build/cjs/index.js.map
CHANGED
|
@@ -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
|
|
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
|
|
44
|
-
const value = Reflect.get(target, prop
|
|
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((
|
|
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
|
|
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
|
|
63
|
-
const value = Reflect.get(target, p
|
|
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(
|
|
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
|
|
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;;;;"}
|
|
@@ -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;;;;;"}
|
|
@@ -8,7 +8,7 @@ const debugBuild = require('../debug-build.js');
|
|
|
8
8
|
*
|
|
9
9
|
* Priority:
|
|
10
10
|
* 1. If `enableRpcTracePropagation` is set, use it (ignore `instrumentPrototypeMethods`)
|
|
11
|
-
* 2. If only `instrumentPrototypeMethods` is set, use it with deprecation warning
|
|
11
|
+
* 2. If only `instrumentPrototypeMethods` is set, use it with deprecation warning
|
|
12
12
|
* 3. If neither is set, return `false`
|
|
13
13
|
*
|
|
14
14
|
* @returns The effective setting for RPC trace propagation
|
|
@@ -45,40 +45,5 @@ function getEffectiveRpcPropagation(options) {
|
|
|
45
45
|
return false;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
/**
|
|
49
|
-
* Gets the method filter for prototype method instrumentation.
|
|
50
|
-
*
|
|
51
|
-
* Returns:
|
|
52
|
-
* - `null` if no instrumentation should occur
|
|
53
|
-
* - `true` if all methods should be instrumented
|
|
54
|
-
* - `string[]` if only specific methods should be instrumented (deprecated behavior)
|
|
55
|
-
*
|
|
56
|
-
* @returns The method filter or null if no instrumentation
|
|
57
|
-
*/
|
|
58
|
-
function getPrototypeMethodFilter(options) {
|
|
59
|
-
const { enableRpcTracePropagation, instrumentPrototypeMethods } = options;
|
|
60
|
-
|
|
61
|
-
// If the new option is explicitly set, use it (boolean only, no filtering)
|
|
62
|
-
if (enableRpcTracePropagation !== undefined) {
|
|
63
|
-
return !!enableRpcTracePropagation;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Fall back to deprecated option - preserve array filtering behavior
|
|
67
|
-
if (instrumentPrototypeMethods !== undefined) {
|
|
68
|
-
if (instrumentPrototypeMethods === true) {
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (Array.isArray(instrumentPrototypeMethods) && instrumentPrototypeMethods.length > 0) {
|
|
73
|
-
return instrumentPrototypeMethods;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
48
|
exports.getEffectiveRpcPropagation = getEffectiveRpcPropagation;
|
|
83
|
-
exports.getPrototypeMethodFilter = getPrototypeMethodFilter;
|
|
84
49
|
//# sourceMappingURL=rpcOptions.js.map
|
|
@@ -1 +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
|
|
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\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"],"names":["DEBUG_BUILD","debug"],"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,MAAMA,sBAAA;AACN,QAAQC,UAAK,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,IAAID,sBAAA;AACJ,MAAMC,UAAK,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;;;;"}
|
|
@@ -4,6 +4,7 @@ const core = require('@sentry/core');
|
|
|
4
4
|
const flush = require('./flush.js');
|
|
5
5
|
const instrument = require('./instrument.js');
|
|
6
6
|
const sdk = require('./sdk.js');
|
|
7
|
+
const rpcMeta = require('./utils/rpcMeta.js');
|
|
7
8
|
const traceLinks = require('./utils/traceLinks.js');
|
|
8
9
|
|
|
9
10
|
/** Extended DurableObjectState with originalStorage exposed by instrumentContext */
|
|
@@ -28,9 +29,21 @@ function wrapMethodWithSentry(
|
|
|
28
29
|
handler,
|
|
29
30
|
original =>
|
|
30
31
|
new Proxy(original, {
|
|
31
|
-
apply(target, thisArg,
|
|
32
|
+
apply(target, thisArg, rawArgs) {
|
|
32
33
|
const { startNewTrace } = wrapperOptions;
|
|
33
34
|
|
|
35
|
+
// For RPC methods, extract Sentry trace context from the trailing argument.
|
|
36
|
+
// The caller side (instrumentDurableObjectStub / JSRPC proxy) appends it;
|
|
37
|
+
// we strip it here so the user's method never sees it.
|
|
38
|
+
let args = rawArgs;
|
|
39
|
+
let rpcMeta$1;
|
|
40
|
+
|
|
41
|
+
if (wrapperOptions.spanOp === 'rpc') {
|
|
42
|
+
const extracted = rpcMeta.extractRpcMeta(rawArgs);
|
|
43
|
+
args = extracted.args;
|
|
44
|
+
rpcMeta$1 = extracted.rpcMeta;
|
|
45
|
+
}
|
|
46
|
+
|
|
34
47
|
// For startNewTrace, always use withIsolationScope to ensure a fresh scope
|
|
35
48
|
// Otherwise, use existing client's scope or isolation scope
|
|
36
49
|
const currentClient = core.getClient();
|
|
@@ -177,6 +190,13 @@ function wrapMethodWithSentry(
|
|
|
177
190
|
});
|
|
178
191
|
};
|
|
179
192
|
|
|
193
|
+
if (rpcMeta$1) {
|
|
194
|
+
return core.continueTrace(
|
|
195
|
+
{ sentryTrace: rpcMeta$1['sentry-trace'] || '', baggage: rpcMeta$1.baggage || '' },
|
|
196
|
+
executeSpan,
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
180
200
|
if (startNewTrace) {
|
|
181
201
|
return core.startNewTrace(() => executeSpan());
|
|
182
202
|
}
|