@sentry/cloudflare 10.71.0 → 10.73.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/client.js.map +1 -1
- package/build/cjs/durableobject.js +2 -53
- package/build/cjs/durableobject.js.map +1 -1
- package/build/cjs/instrumentations/instrumentDurableObjectHandlers.js +114 -0
- package/build/cjs/instrumentations/instrumentDurableObjectHandlers.js.map +1 -0
- package/build/cjs/instrumentations/instrumentDurableObjectNamespace.js +4 -4
- package/build/cjs/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
- package/build/cjs/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
- package/build/cjs/instrumentations/worker/instrumentEnv.js +5 -7
- package/build/cjs/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/cjs/utils/rpcPropagation.js +20 -0
- package/build/cjs/utils/rpcPropagation.js.map +1 -0
- package/build/cjs/vite/autoInstrument.js +2 -1
- package/build/cjs/vite/autoInstrument.js.map +1 -1
- package/build/cjs/vite/bindings.js +6 -0
- package/build/cjs/vite/bindings.js.map +1 -0
- package/build/cjs/vite/index.js.map +1 -1
- package/build/cjs/vite/transform.js +30 -5
- package/build/cjs/vite/transform.js.map +1 -1
- package/build/cjs/vite/wranglerConfig.js +21 -1
- package/build/cjs/vite/wranglerConfig.js.map +1 -1
- package/build/esm/client.js.map +1 -1
- package/build/esm/durableobject.js +3 -54
- package/build/esm/durableobject.js.map +1 -1
- package/build/esm/instrumentations/instrumentDurableObjectHandlers.js +112 -0
- package/build/esm/instrumentations/instrumentDurableObjectHandlers.js.map +1 -0
- package/build/esm/instrumentations/instrumentDurableObjectNamespace.js +4 -4
- package/build/esm/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
- package/build/esm/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
- package/build/esm/instrumentations/worker/instrumentEnv.js +5 -7
- package/build/esm/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/utils/rpcPropagation.js +18 -0
- package/build/esm/utils/rpcPropagation.js.map +1 -0
- package/build/esm/vite/autoInstrument.js +2 -1
- package/build/esm/vite/autoInstrument.js.map +1 -1
- package/build/esm/vite/bindings.js +4 -0
- package/build/esm/vite/bindings.js.map +1 -0
- package/build/esm/vite/index.js.map +1 -1
- package/build/esm/vite/transform.js +30 -5
- package/build/esm/vite/transform.js.map +1 -1
- package/build/esm/vite/wranglerConfig.js +21 -2
- package/build/esm/vite/wranglerConfig.js.map +1 -1
- package/build/types/client.d.ts +39 -29
- package/build/types/client.d.ts.map +1 -1
- package/build/types/durableobject.d.ts.map +1 -1
- package/build/types/instrumentations/instrumentDurableObjectHandlers.d.ts +28 -0
- package/build/types/instrumentations/instrumentDurableObjectHandlers.d.ts.map +1 -0
- package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts +2 -1
- package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts.map +1 -1
- package/build/types/instrumentations/instrumentWorkerEntrypoint.d.ts.map +1 -1
- package/build/types/instrumentations/worker/instrumentEnv.d.ts.map +1 -1
- package/build/types/utils/rpcPropagation.d.ts +15 -0
- package/build/types/utils/rpcPropagation.d.ts.map +1 -0
- package/build/types/vite/autoInstrument.d.ts.map +1 -1
- package/build/types/vite/bindings.d.ts +15 -0
- package/build/types/vite/bindings.d.ts.map +1 -0
- package/build/types/vite/index.d.ts +4 -0
- package/build/types/vite/index.d.ts.map +1 -1
- package/build/types/vite/transform.d.ts +3 -0
- package/build/types/vite/transform.d.ts.map +1 -1
- package/build/types/vite/wranglerConfig.d.ts +7 -0
- package/build/types/vite/wranglerConfig.d.ts.map +1 -1
- package/build/types-ts3.8/client.d.ts +39 -29
- package/build/types-ts3.8/instrumentations/instrumentDurableObjectHandlers.d.ts +28 -0
- package/build/types-ts3.8/instrumentations/instrumentDurableObjectNamespace.d.ts +2 -1
- package/build/types-ts3.8/utils/rpcPropagation.d.ts +15 -0
- package/build/types-ts3.8/vite/bindings.d.ts +15 -0
- package/build/types-ts3.8/vite/index.d.ts +4 -0
- package/build/types-ts3.8/vite/transform.d.ts +3 -0
- package/build/types-ts3.8/vite/wranglerConfig.d.ts +7 -0
- package/package.json +3 -3
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { isObjectLike
|
|
1
|
+
import { isObjectLike } from '@sentry/core';
|
|
2
2
|
import { setAsyncLocalStorageAsyncContextStrategy } from './async.js';
|
|
3
|
-
import {
|
|
3
|
+
import { markAsInstrumented, getInstrumented } from './instrument.js';
|
|
4
|
+
import { instrumentDurableObjectHandlers } from './instrumentations/instrumentDurableObjectHandlers.js';
|
|
4
5
|
import { instrumentEnv } from './instrumentations/worker/instrumentEnv.js';
|
|
5
6
|
import { getFinalOptions } from './options.js';
|
|
6
|
-
import { wrapRequestHandler } from './request.js';
|
|
7
7
|
import { instrumentContext } from './utils/instrumentContext.js';
|
|
8
8
|
import { hasRpcMeta } from './utils/rpcMeta.js';
|
|
9
9
|
import { getEffectiveRpcPropagation } from './utils/rpcOptions.js';
|
|
@@ -59,57 +59,6 @@ function resolveFrameworkManagedMethods(prototype, obj, methodsBeforeConstructio
|
|
|
59
59
|
frameworkManagedMethodsCache.set(prototype, managed);
|
|
60
60
|
return managed;
|
|
61
61
|
}
|
|
62
|
-
function instrumentDurableObjectHandlers(obj, options, context) {
|
|
63
|
-
if (obj.fetch && typeof obj.fetch === "function") {
|
|
64
|
-
obj.fetch = ensureInstrumented(
|
|
65
|
-
obj.fetch.bind(obj),
|
|
66
|
-
(original) => new Proxy(original, {
|
|
67
|
-
apply(target, thisArg, args) {
|
|
68
|
-
return wrapRequestHandler({ options, request: args[0], context }, () => {
|
|
69
|
-
return Reflect.apply(target, thisArg, args);
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
})
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
if (obj.alarm && typeof obj.alarm === "function") {
|
|
76
|
-
obj.alarm = wrapMethodWithSentry(
|
|
77
|
-
{
|
|
78
|
-
options,
|
|
79
|
-
context,
|
|
80
|
-
spanName: "alarm",
|
|
81
|
-
spanOp: "function",
|
|
82
|
-
startNewTrace: true,
|
|
83
|
-
origin: "auto.faas.cloudflare.durable_object"
|
|
84
|
-
},
|
|
85
|
-
obj.alarm.bind(obj)
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
if (obj.webSocketMessage && typeof obj.webSocketMessage === "function") {
|
|
89
|
-
obj.webSocketMessage = wrapMethodWithSentry(
|
|
90
|
-
{ options, context, spanName: "webSocketMessage", origin: "auto.faas.cloudflare.durable_object" },
|
|
91
|
-
obj.webSocketMessage.bind(obj)
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
if (obj.webSocketClose && typeof obj.webSocketClose === "function") {
|
|
95
|
-
obj.webSocketClose = wrapMethodWithSentry(
|
|
96
|
-
{ options, context, spanName: "webSocketClose", origin: "auto.faas.cloudflare.durable_object" },
|
|
97
|
-
obj.webSocketClose.bind(obj)
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
if (obj.webSocketError && typeof obj.webSocketError === "function") {
|
|
101
|
-
obj.webSocketError = wrapMethodWithSentry(
|
|
102
|
-
{ options, context, spanName: "webSocketError", origin: "auto.faas.cloudflare.durable_object" },
|
|
103
|
-
obj.webSocketError.bind(obj),
|
|
104
|
-
(_, error) => captureException(error, {
|
|
105
|
-
mechanism: {
|
|
106
|
-
type: "auto.faas.cloudflare.durable_object_websocket",
|
|
107
|
-
handled: false
|
|
108
|
-
}
|
|
109
|
-
})
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
62
|
const RESERVED_RPC_METHOD_NAMES = /* @__PURE__ */ new Set([
|
|
114
63
|
"constructor",
|
|
115
64
|
"fetch",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durableobject.js","sources":["../../src/durableobject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport { captureException, isObjectLike } 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 { hasRpcMeta } from './utils/rpcMeta';\nimport { getEffectiveRpcPropagation } from './utils/rpcOptions';\nimport { instrumentCloudflareAgent } from './instrumentations/agents';\nimport { type UncheckedMethod, wrapMethodWithSentry } from './wrapMethodWithSentry';\n\n/**\n * The instrumented context passed between the shared construction helpers.\n *\n * This is intentionally `any` rather than `ReturnType<typeof instrumentContext<DurableObjectState>>`.\n * A concrete `DurableObjectState` here forces `tsc` to structurally relate its `storage: SqlStorage`\n * graph against the `ExecutionContext | InstrumentedDurableObjectState` parameter of\n * `wrapMethodWithSentry`, while the RPC-branded `DurableObject` from `cloudflare:workers` is also in\n * scope. That union comparison explodes (1296×1296) and hangs the type build. The original inline\n * implementation avoided this only incidentally, because `ctx` reached it as `any` through the Proxy\n * `construct` trap. Keeping the shared context `any` preserves that behavior.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InstrumentedDurableObjectContext = any;\n\n/**\n * Constructs a Durable Object instance and instruments its built-in handler methods\n * (`fetch`, `alarm`, `webSocketMessage`, `webSocketClose`, `webSocketError`).\n *\n * This is the shared construction path used by both {@link instrumentDurableObjectWithSentry}\n * and {@link instrumentAgentWithSentry}. It intentionally does NOT apply the RPC prototype-method\n * instrumentation — callers apply that last via {@link finalizeWithRpcInstrumentation}, after any\n * additional per-instance instrumentation has been layered onto the returned object.\n *\n * @internal\n */\nexport function constructInstrumentedDurableObject<E, T extends DurableObject<E>>(\n target: new (state: DurableObjectState, env: E) => T,\n ctx: DurableObjectState,\n env: E,\n newTarget: NewableFunction,\n optionsCallback: (env: E) => CloudflareOptions,\n): {\n obj: T;\n options: CloudflareOptions;\n context: InstrumentedDurableObjectContext;\n frameworkManagedMethods: ReadonlySet<string>;\n} {\n setAsyncLocalStorageAsyncContextStrategy();\n const options = getFinalOptions(optionsCallback(env), env);\n // See InstrumentedDurableObjectContext — `ctx` is widened to `any` so the concrete\n // `DurableObjectState` type never enters the checker's relation graph in this module.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const context = instrumentContext(ctx as any);\n const instrumentedEnv = instrumentEnv(env as Record<string, unknown>, options);\n\n const prototype = (newTarget as unknown as { prototype?: object }).prototype ?? target.prototype;\n const cachedFrameworkManagedMethods = frameworkManagedMethodsCache.get(prototype);\n const methodsBeforeConstruction = cachedFrameworkManagedMethods ? undefined : resolvePrototypeMethods(prototype);\n\n // Pass `newTarget` so that subclasses of the instrumented class (e.g. the wrapper classes\n // created by wrangler's local dev tooling or `@cloudflare/vitest-pool-workers`) keep their\n // own prototype — otherwise subclass methods disappear and `instanceof` checks break.\n const obj = Reflect.construct(target, [context, instrumentedEnv], newTarget) as T;\n\n const frameworkManagedMethods = resolveFrameworkManagedMethods(\n prototype,\n obj,\n methodsBeforeConstruction,\n cachedFrameworkManagedMethods,\n );\n\n instrumentDurableObjectHandlers(obj, options, context);\n\n return { obj, options, context, frameworkManagedMethods };\n}\n\nconst frameworkManagedMethodsCache = new WeakMap<object, ReadonlySet<string>>();\n\n/**\n * Collects the methods visible from a prototype, using normal property lookup precedence.\n * Methods inherited from `Object.prototype` are excluded because they cannot be Durable Object RPC methods.\n */\nfunction resolvePrototypeMethods(prototype: object | null): Map<string, unknown> {\n const methods = new Map<string, unknown>();\n\n for (let current = prototype; current && current !== Object.prototype; current = Object.getPrototypeOf(current)) {\n for (const name of Object.getOwnPropertyNames(current)) {\n // The first occurrence wins, mirroring what a property lookup on the instance would find\n if (name === 'constructor' || methods.has(name)) {\n continue;\n }\n\n const descriptor = Object.getOwnPropertyDescriptor(current, name);\n\n if (descriptor && typeof descriptor.value === 'function') {\n methods.set(name, descriptor.value);\n }\n }\n }\n\n return methods;\n}\n\n/**\n * Finds methods that a framework replaced while constructing the first instance.\n *\n * Some frameworks register methods by function identity, so replacing one of their wrappers would\n * break dispatch. The result is cached because frameworks commonly install their wrappers only\n * once; later constructions would no longer reveal which methods they manage.\n */\nfunction resolveFrameworkManagedMethods(\n prototype: object,\n obj: object,\n methodsBeforeConstruction: Map<string, unknown> | undefined,\n cached: ReadonlySet<string> | undefined,\n): ReadonlySet<string> {\n if (cached) {\n return cached;\n }\n\n const methodsAfterConstruction = resolvePrototypeMethods(Object.getPrototypeOf(obj) as object);\n const managed = new Set<string>();\n\n for (const [name, method] of methodsAfterConstruction) {\n const before = methodsBeforeConstruction?.get(name);\n\n if (before && before !== method) {\n managed.add(name);\n }\n }\n\n frameworkManagedMethodsCache.set(prototype, managed);\n\n return managed;\n}\n\n/**\n * Instruments the built-in Durable Object handler methods on a constructed instance.\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 */\nfunction instrumentDurableObjectHandlers<E, T extends DurableObject<E>>(\n obj: T,\n options: CloudflareOptions,\n context: InstrumentedDurableObjectContext,\n): void {\n // Bind each built-in handler to this instance before wrapping.\n // See https://github.com/getsentry/sentry-javascript/issues/22328\n if (obj.fetch && typeof obj.fetch === 'function') {\n obj.fetch = ensureInstrumented(\n obj.fetch.bind(obj),\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 {\n options,\n context,\n spanName: 'alarm',\n spanOp: 'function',\n startNewTrace: true,\n origin: 'auto.faas.cloudflare.durable_object',\n },\n obj.alarm.bind(obj),\n );\n }\n\n if (obj.webSocketMessage && typeof obj.webSocketMessage === 'function') {\n obj.webSocketMessage = wrapMethodWithSentry(\n { options, context, spanName: 'webSocketMessage', origin: 'auto.faas.cloudflare.durable_object' },\n obj.webSocketMessage.bind(obj),\n );\n }\n\n if (obj.webSocketClose && typeof obj.webSocketClose === 'function') {\n obj.webSocketClose = wrapMethodWithSentry(\n { options, context, spanName: 'webSocketClose', origin: 'auto.faas.cloudflare.durable_object' },\n obj.webSocketClose.bind(obj),\n );\n }\n\n if (obj.webSocketError && typeof obj.webSocketError === 'function') {\n obj.webSocketError = wrapMethodWithSentry(\n { options, context, spanName: 'webSocketError', origin: 'auto.faas.cloudflare.durable_object' },\n obj.webSocketError.bind(obj),\n (_, error) =>\n captureException(error, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object_websocket',\n handled: false,\n },\n }),\n );\n }\n}\n\ntype RpcInstanceState = {\n options: CloudflareOptions;\n context: InstrumentedDurableObjectContext;\n /**\n * Whether to trace calls that carry no RPC metadata. Only the deprecated\n * `instrumentPrototypeMethods` option does, because it predates metadata propagation.\n */\n alwaysTrace: boolean;\n /** Per-instance cache of the traced method wrappers, keyed by method name. Created on first use. */\n tracedMethods?: Map<string, UncheckedMethod>;\n};\n\n/**\n * Method names the runtime never dispatches over RPC, so wrapping them buys no tracing.\n *\n * Mirrors `isReservedName` in workerd (`src/workerd/api/worker-rpc.c++`): the runtime rejects these\n * before any property lookup happens. `fetch`, `alarm` and the `webSocket*` handlers are also\n * instrumented per-instance as own properties, and `constructor` is on every prototype.\n */\nconst RESERVED_RPC_METHOD_NAMES: ReadonlySet<string> = new Set([\n 'constructor',\n 'fetch',\n 'connect',\n 'alarm',\n 'webSocketMessage',\n 'webSocketClose',\n 'webSocketError',\n 'dup',\n]);\n\n// Prototype wrappers are shared by all instances, while SDK options and traced method caches are not.\nconst rpcInstanceStates = new WeakMap<object, RpcInstanceState>();\n\n/**\n * Adds trace propagation to a constructed Durable Object's RPC methods.\n *\n * RPC methods are wrapped on the prototype because Cloudflare dispatches them with the Durable\n * Object instance as the receiver. This preserves native private-field access and keeps the methods\n * visible to Cloudflare's RPC dispatcher. Built-in handlers, Agent handlers, and methods managed by\n * another framework are left untouched.\n *\n * Call this after all per-instance instrumentation has been applied. If RPC trace propagation is\n * disabled, the object is returned unchanged.\n *\n * @param obj The constructed Durable Object instance.\n * @param options The resolved SDK options for this instance.\n * @param context The instrumented execution context for this instance.\n * @param excludedMethods Method names owned by another framework and therefore not safe to wrap.\n * @returns The same Durable Object instance, with eligible prototype methods instrumented.\n * @internal\n */\nexport function finalizeWithRpcInstrumentation<T extends object>(\n obj: T,\n options: CloudflareOptions,\n context: InstrumentedDurableObjectContext,\n excludedMethods?: ReadonlySet<string>,\n): T {\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 // eslint-disable-next-line typescript/no-deprecated\n const allowedMethods = Array.isArray(options.instrumentPrototypeMethods)\n ? // eslint-disable-next-line typescript/no-deprecated\n new Set(options.instrumentPrototypeMethods)\n : undefined;\n\n // When using the deprecated `instrumentPrototypeMethods` option, always create spans.\n // When using the new `enableRpcTracePropagation`, only create spans when RPC metadata is present.\n const alwaysTrace = options.enableRpcTracePropagation === undefined;\n\n rpcInstanceStates.set(obj, { options, context, alwaysTrace });\n\n instrumentPrototypeRpcMethods(obj, excludedMethods, allowedMethods);\n\n return obj;\n}\n\n/**\n * Returns a prototype method when it is eligible for RPC instrumentation.\n */\nfunction getRpcMethodDescriptor(\n obj: object,\n prototype: object,\n methodName: string,\n excludedMethods?: ReadonlySet<string>,\n allowedMethods?: ReadonlySet<string>,\n): PropertyDescriptor | undefined {\n if (\n RESERVED_RPC_METHOD_NAMES.has(methodName) ||\n Object.prototype.hasOwnProperty.call(obj, methodName) ||\n excludedMethods?.has(methodName) ||\n (allowedMethods && !allowedMethods.has(methodName))\n ) {\n return undefined;\n }\n\n const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);\n\n if (!descriptor || typeof descriptor.value !== 'function' || getInstrumented(descriptor.value)) {\n return undefined;\n }\n\n return descriptor;\n}\n\n/**\n * Wraps eligible methods on the instance's prototype chain once per class.\n *\n * Because the wrappers live on the prototype, the allow-list of the first constructed instance\n * decides which methods carry a wrapper for every later instance of that class. This only affects\n * the deprecated array form of `instrumentPrototypeMethods`, where differing options per instance\n * of the same class were never a supported configuration.\n */\nfunction instrumentPrototypeRpcMethods(\n obj: object,\n excludedMethods?: ReadonlySet<string>,\n allowedMethods?: ReadonlySet<string>,\n): void {\n let prototype: object | null = Object.getPrototypeOf(obj);\n\n while (prototype && prototype !== Object.prototype) {\n for (const methodName of Object.getOwnPropertyNames(prototype)) {\n const descriptor = getRpcMethodDescriptor(obj, prototype, methodName, excludedMethods, allowedMethods);\n\n if (!descriptor) {\n continue;\n }\n\n const wrapped = createRpcPrototypeWrapper(methodName, descriptor.value as UncheckedMethod);\n\n try {\n Object.defineProperty(prototype, methodName, { ...descriptor, value: wrapped });\n } catch {}\n\n // Only the wrapper is marked, not the original method: `wrapMethodWithSentry` resolves\n // through the same global map and must not resolve the original to this wrapper,\n // which would recurse.\n markAsInstrumented(wrapped);\n }\n\n prototype = Object.getPrototypeOf(prototype);\n }\n}\n\n/**\n * Creates a prototype wrapper that traces RPC calls carrying Sentry metadata.\n *\n * The wrapper looks up SDK state from its receiver, allowing one prototype function to serve every\n * instance. Calls without instance state use the original method directly, as do calls without RPC\n * metadata unless the instance opted into unconditional tracing. The original function name and\n * arity are preserved because frameworks may inspect them for dispatch.\n */\nfunction createRpcPrototypeWrapper(methodName: string, originalMethod: UncheckedMethod): UncheckedMethod {\n const wrapper = function (this: unknown, ...args: unknown[]): unknown {\n const state = isObjectLike(this) ? rpcInstanceStates.get(this) : undefined;\n\n // Untraced calls are the common case — every internal call the instance makes to one of its\n // own methods lands here too, and those never carry RPC metadata.\n if (!state || (!state.alwaysTrace && !hasRpcMeta(args))) {\n return Reflect.apply(originalMethod, this, args);\n }\n\n const tracedMethods = (state.tracedMethods ??= new Map());\n let traced = tracedMethods.get(methodName);\n\n if (!traced) {\n traced = wrapMethodWithSentry(\n {\n options: state.options,\n context: state.context,\n spanName: methodName,\n spanOp: 'rpc',\n origin: 'auto.faas.cloudflare.durable_object',\n },\n originalMethod,\n undefined,\n true,\n );\n tracedMethods.set(methodName, traced);\n }\n\n return Reflect.apply(traced, this, args);\n };\n\n Object.defineProperties(wrapper, {\n name: { value: originalMethod.name, configurable: true },\n length: { value: originalMethod.length, configurable: true },\n });\n\n return wrapper as UncheckedMethod;\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], newTarget) {\n const { obj, options, context, frameworkManagedMethods } = constructInstrumentedDurableObject(\n target,\n ctx,\n env,\n newTarget,\n optionsCallback,\n );\n\n return finalizeWithRpcInstrumentation(obj, options, context, frameworkManagedMethods);\n },\n });\n}\n\n/**\n * Instruments a Cloudflare [`agents`](https://www.npmjs.com/package/agents) Agent class with Sentry.\n *\n * An `Agent` is a Durable Object under the hood, so this applies the same instrumentation as\n * {@link instrumentDurableObjectWithSentry} (request transactions, `alarm`, WebSocket handlers, RPC\n * trace propagation, SQL spans) and additionally captures Agent-specific telemetry via\n * `instrumentCloudflareAgent`:\n *\n * - **Callable RPC spans** — a span (op `rpc`) for each `@callable()` method invoked over WebSocket.\n * - **Breadcrumbs** — for every Agent observability event (`rpc`, `state:update`, `connect`,\n * `disconnect`, `schedule:*`, `queue:*`, `workflow:*`, `email:*`, `mcp:*`, ...).\n *\n * Cloudflare Workers cannot auto-instrument, so the Agent class must be wrapped manually.\n *\n * @param optionsCallback Function that returns the options for the SDK initialization.\n * @param AgentClass The Agent class to instrument.\n * @returns The instrumented Agent class.\n *\n * @example\n * ```ts\n * import { Agent, callable, routeAgentRequest } from 'agents';\n * import * as Sentry from '@sentry/cloudflare';\n *\n * class MyAgentBase extends Agent<Env> {\n * @callable()\n * async greet(name: string): Promise<string> {\n * return `Hello, ${name}!`;\n * }\n * }\n *\n * export const MyAgent = Sentry.instrumentAgentWithSentry(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * enableRpcTracePropagation: true,\n * }),\n * MyAgentBase,\n * );\n * ```\n */\nexport function instrumentAgentWithSentry<\n E,\n T extends DurableObject<E>,\n C extends new (state: DurableObjectState, env: E) => T,\n>(optionsCallback: (env: E) => CloudflareOptions, AgentClass: C): C {\n return new Proxy(AgentClass, {\n construct(target, [ctx, env], newTarget) {\n const { obj, options, context, frameworkManagedMethods } = constructInstrumentedDurableObject(\n target,\n ctx,\n env,\n newTarget,\n optionsCallback,\n );\n\n instrumentCloudflareAgent(obj);\n\n // Apply RPC prototype-method instrumentation last, so the Agent-specific own-property\n // handlers we just installed are excluded from RPC method tracing. Methods the Agent\n // framework installed itself are excluded too — `instrumentCloudflareAgent` traces those by\n // wrapping the dispatch instead of the method.\n return finalizeWithRpcInstrumentation(obj, options, context, frameworkManagedMethods);\n },\n });\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"durableobject.js","sources":["../../src/durableobject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport { isObjectLike } from '@sentry/core';\nimport type { DurableObject } from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from './async';\nimport type { CloudflareOptions } from './client';\nimport { getInstrumented, markAsInstrumented } from './instrument';\nimport { instrumentDurableObjectHandlers } from './instrumentations/instrumentDurableObjectHandlers';\nimport { instrumentEnv } from './instrumentations/worker/instrumentEnv';\nimport { getFinalOptions } from './options';\nimport { instrumentContext } from './utils/instrumentContext';\nimport { hasRpcMeta } from './utils/rpcMeta';\nimport { getEffectiveRpcPropagation } from './utils/rpcOptions';\nimport { instrumentCloudflareAgent } from './instrumentations/agents';\nimport { type UncheckedMethod, wrapMethodWithSentry } from './wrapMethodWithSentry';\n\n/**\n * The instrumented context passed between the shared construction helpers.\n *\n * This is intentionally `any` rather than `ReturnType<typeof instrumentContext<DurableObjectState>>`.\n * A concrete `DurableObjectState` here forces `tsc` to structurally relate its `storage: SqlStorage`\n * graph against the `ExecutionContext | InstrumentedDurableObjectState` parameter of\n * `wrapMethodWithSentry`, while the RPC-branded `DurableObject` from `cloudflare:workers` is also in\n * scope. That union comparison explodes (1296×1296) and hangs the type build. The original inline\n * implementation avoided this only incidentally, because `ctx` reached it as `any` through the Proxy\n * `construct` trap. Keeping the shared context `any` preserves that behavior.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InstrumentedDurableObjectContext = any;\n\n/**\n * Constructs a Durable Object instance and instruments its built-in handler methods\n * (`fetch`, `alarm`, `webSocketMessage`, `webSocketClose`, `webSocketError`).\n *\n * This is the shared construction path used by both {@link instrumentDurableObjectWithSentry}\n * and {@link instrumentAgentWithSentry}. It intentionally does NOT apply the RPC prototype-method\n * instrumentation — callers apply that last via {@link finalizeWithRpcInstrumentation}, after any\n * additional per-instance instrumentation has been layered onto the returned object.\n *\n * @internal\n */\nexport function constructInstrumentedDurableObject<E, T extends DurableObject<E>>(\n target: new (state: DurableObjectState, env: E) => T,\n ctx: DurableObjectState,\n env: E,\n newTarget: NewableFunction,\n optionsCallback: (env: E) => CloudflareOptions,\n): {\n obj: T;\n options: CloudflareOptions;\n context: InstrumentedDurableObjectContext;\n frameworkManagedMethods: ReadonlySet<string>;\n} {\n setAsyncLocalStorageAsyncContextStrategy();\n const options = getFinalOptions(optionsCallback(env), env);\n // See InstrumentedDurableObjectContext — `ctx` is widened to `any` so the concrete\n // `DurableObjectState` type never enters the checker's relation graph in this module.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const context = instrumentContext(ctx as any);\n const instrumentedEnv = instrumentEnv(env as Record<string, unknown>, options);\n\n const prototype = (newTarget as unknown as { prototype?: object }).prototype ?? target.prototype;\n const cachedFrameworkManagedMethods = frameworkManagedMethodsCache.get(prototype);\n const methodsBeforeConstruction = cachedFrameworkManagedMethods ? undefined : resolvePrototypeMethods(prototype);\n\n // Pass `newTarget` so that subclasses of the instrumented class (e.g. the wrapper classes\n // created by wrangler's local dev tooling or `@cloudflare/vitest-pool-workers`) keep their\n // own prototype — otherwise subclass methods disappear and `instanceof` checks break.\n const obj = Reflect.construct(target, [context, instrumentedEnv], newTarget) as T;\n\n const frameworkManagedMethods = resolveFrameworkManagedMethods(\n prototype,\n obj,\n methodsBeforeConstruction,\n cachedFrameworkManagedMethods,\n );\n\n instrumentDurableObjectHandlers(obj, options, context);\n\n return { obj, options, context, frameworkManagedMethods };\n}\n\nconst frameworkManagedMethodsCache = new WeakMap<object, ReadonlySet<string>>();\n\n/**\n * Collects the methods visible from a prototype, using normal property lookup precedence.\n * Methods inherited from `Object.prototype` are excluded because they cannot be Durable Object RPC methods.\n */\nfunction resolvePrototypeMethods(prototype: object | null): Map<string, unknown> {\n const methods = new Map<string, unknown>();\n\n for (let current = prototype; current && current !== Object.prototype; current = Object.getPrototypeOf(current)) {\n for (const name of Object.getOwnPropertyNames(current)) {\n // The first occurrence wins, mirroring what a property lookup on the instance would find\n if (name === 'constructor' || methods.has(name)) {\n continue;\n }\n\n const descriptor = Object.getOwnPropertyDescriptor(current, name);\n\n if (descriptor && typeof descriptor.value === 'function') {\n methods.set(name, descriptor.value);\n }\n }\n }\n\n return methods;\n}\n\n/**\n * Finds methods that a framework replaced while constructing the first instance.\n *\n * Some frameworks register methods by function identity, so replacing one of their wrappers would\n * break dispatch. The result is cached because frameworks commonly install their wrappers only\n * once; later constructions would no longer reveal which methods they manage.\n */\nfunction resolveFrameworkManagedMethods(\n prototype: object,\n obj: object,\n methodsBeforeConstruction: Map<string, unknown> | undefined,\n cached: ReadonlySet<string> | undefined,\n): ReadonlySet<string> {\n if (cached) {\n return cached;\n }\n\n const methodsAfterConstruction = resolvePrototypeMethods(Object.getPrototypeOf(obj) as object);\n const managed = new Set<string>();\n\n for (const [name, method] of methodsAfterConstruction) {\n const before = methodsBeforeConstruction?.get(name);\n\n if (before && before !== method) {\n managed.add(name);\n }\n }\n\n frameworkManagedMethodsCache.set(prototype, managed);\n\n return managed;\n}\n\ntype RpcInstanceState = {\n options: CloudflareOptions;\n context: InstrumentedDurableObjectContext;\n /**\n * Whether to trace calls that carry no RPC metadata. Only the deprecated\n * `instrumentPrototypeMethods` option does, because it predates metadata propagation.\n */\n alwaysTrace: boolean;\n /** Per-instance cache of the traced method wrappers, keyed by method name. Created on first use. */\n tracedMethods?: Map<string, UncheckedMethod>;\n};\n\n/**\n * Method names the runtime never dispatches over RPC, so wrapping them buys no tracing.\n *\n * Mirrors `isReservedName` in workerd (`src/workerd/api/worker-rpc.c++`): the runtime rejects these\n * before any property lookup happens. `fetch`, `alarm` and the `webSocket*` handlers are also\n * instrumented per-instance as own properties, and `constructor` is on every prototype.\n */\nconst RESERVED_RPC_METHOD_NAMES: ReadonlySet<string> = new Set([\n 'constructor',\n 'fetch',\n 'connect',\n 'alarm',\n 'webSocketMessage',\n 'webSocketClose',\n 'webSocketError',\n 'dup',\n]);\n\n// Prototype wrappers are shared by all instances, while SDK options and traced method caches are not.\nconst rpcInstanceStates = new WeakMap<object, RpcInstanceState>();\n\n/**\n * Adds trace propagation to a constructed Durable Object's RPC methods.\n *\n * RPC methods are wrapped on the prototype because Cloudflare dispatches them with the Durable\n * Object instance as the receiver. This preserves native private-field access and keeps the methods\n * visible to Cloudflare's RPC dispatcher. Built-in handlers, Agent handlers, and methods managed by\n * another framework are left untouched.\n *\n * Call this after all per-instance instrumentation has been applied. If RPC trace propagation is\n * disabled, the object is returned unchanged.\n *\n * @param obj The constructed Durable Object instance.\n * @param options The resolved SDK options for this instance.\n * @param context The instrumented execution context for this instance.\n * @param excludedMethods Method names owned by another framework and therefore not safe to wrap.\n * @returns The same Durable Object instance, with eligible prototype methods instrumented.\n * @internal\n */\nexport function finalizeWithRpcInstrumentation<T extends object>(\n obj: T,\n options: CloudflareOptions,\n context: InstrumentedDurableObjectContext,\n excludedMethods?: ReadonlySet<string>,\n): T {\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 // eslint-disable-next-line typescript/no-deprecated\n const allowedMethods = Array.isArray(options.instrumentPrototypeMethods)\n ? // eslint-disable-next-line typescript/no-deprecated\n new Set(options.instrumentPrototypeMethods)\n : undefined;\n\n // When using the deprecated `instrumentPrototypeMethods` option, always create spans.\n // When using the new `enableRpcTracePropagation`, only create spans when RPC metadata is present.\n // eslint-disable-next-line typescript/no-deprecated\n const alwaysTrace = options.enableRpcTracePropagation === undefined;\n\n rpcInstanceStates.set(obj, { options, context, alwaysTrace });\n\n instrumentPrototypeRpcMethods(obj, excludedMethods, allowedMethods);\n\n return obj;\n}\n\n/**\n * Returns a prototype method when it is eligible for RPC instrumentation.\n */\nfunction getRpcMethodDescriptor(\n obj: object,\n prototype: object,\n methodName: string,\n excludedMethods?: ReadonlySet<string>,\n allowedMethods?: ReadonlySet<string>,\n): PropertyDescriptor | undefined {\n if (\n RESERVED_RPC_METHOD_NAMES.has(methodName) ||\n Object.prototype.hasOwnProperty.call(obj, methodName) ||\n excludedMethods?.has(methodName) ||\n (allowedMethods && !allowedMethods.has(methodName))\n ) {\n return undefined;\n }\n\n const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);\n\n if (!descriptor || typeof descriptor.value !== 'function' || getInstrumented(descriptor.value)) {\n return undefined;\n }\n\n return descriptor;\n}\n\n/**\n * Wraps eligible methods on the instance's prototype chain once per class.\n *\n * Because the wrappers live on the prototype, the allow-list of the first constructed instance\n * decides which methods carry a wrapper for every later instance of that class. This only affects\n * the deprecated array form of `instrumentPrototypeMethods`, where differing options per instance\n * of the same class were never a supported configuration.\n */\nfunction instrumentPrototypeRpcMethods(\n obj: object,\n excludedMethods?: ReadonlySet<string>,\n allowedMethods?: ReadonlySet<string>,\n): void {\n let prototype: object | null = Object.getPrototypeOf(obj);\n\n while (prototype && prototype !== Object.prototype) {\n for (const methodName of Object.getOwnPropertyNames(prototype)) {\n const descriptor = getRpcMethodDescriptor(obj, prototype, methodName, excludedMethods, allowedMethods);\n\n if (!descriptor) {\n continue;\n }\n\n const wrapped = createRpcPrototypeWrapper(methodName, descriptor.value as UncheckedMethod);\n\n try {\n Object.defineProperty(prototype, methodName, { ...descriptor, value: wrapped });\n } catch {}\n\n // Only the wrapper is marked, not the original method: `wrapMethodWithSentry` resolves\n // through the same global map and must not resolve the original to this wrapper,\n // which would recurse.\n markAsInstrumented(wrapped);\n }\n\n prototype = Object.getPrototypeOf(prototype);\n }\n}\n\n/**\n * Creates a prototype wrapper that traces RPC calls carrying Sentry metadata.\n *\n * The wrapper looks up SDK state from its receiver, allowing one prototype function to serve every\n * instance. Calls without instance state use the original method directly, as do calls without RPC\n * metadata unless the instance opted into unconditional tracing. The original function name and\n * arity are preserved because frameworks may inspect them for dispatch.\n */\nfunction createRpcPrototypeWrapper(methodName: string, originalMethod: UncheckedMethod): UncheckedMethod {\n const wrapper = function (this: unknown, ...args: unknown[]): unknown {\n const state = isObjectLike(this) ? rpcInstanceStates.get(this) : undefined;\n\n // Untraced calls are the common case — every internal call the instance makes to one of its\n // own methods lands here too, and those never carry RPC metadata.\n if (!state || (!state.alwaysTrace && !hasRpcMeta(args))) {\n return Reflect.apply(originalMethod, this, args);\n }\n\n const tracedMethods = (state.tracedMethods ??= new Map());\n let traced = tracedMethods.get(methodName);\n\n if (!traced) {\n traced = wrapMethodWithSentry(\n {\n options: state.options,\n context: state.context,\n spanName: methodName,\n spanOp: 'rpc',\n origin: 'auto.faas.cloudflare.durable_object',\n },\n originalMethod,\n undefined,\n true,\n );\n tracedMethods.set(methodName, traced);\n }\n\n return Reflect.apply(traced, this, args);\n };\n\n Object.defineProperties(wrapper, {\n name: { value: originalMethod.name, configurable: true },\n length: { value: originalMethod.length, configurable: true },\n });\n\n return wrapper as UncheckedMethod;\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], newTarget) {\n const { obj, options, context, frameworkManagedMethods } = constructInstrumentedDurableObject(\n target,\n ctx,\n env,\n newTarget,\n optionsCallback,\n );\n\n return finalizeWithRpcInstrumentation(obj, options, context, frameworkManagedMethods);\n },\n });\n}\n\n/**\n * Instruments a Cloudflare [`agents`](https://www.npmjs.com/package/agents) Agent class with Sentry.\n *\n * An `Agent` is a Durable Object under the hood, so this applies the same instrumentation as\n * {@link instrumentDurableObjectWithSentry} (request transactions, `alarm`, WebSocket handlers, RPC\n * trace propagation, SQL spans) and additionally captures Agent-specific telemetry via\n * `instrumentCloudflareAgent`:\n *\n * - **Callable RPC spans** — a span (op `rpc`) for each `@callable()` method invoked over WebSocket.\n * - **Breadcrumbs** — for every Agent observability event (`rpc`, `state:update`, `connect`,\n * `disconnect`, `schedule:*`, `queue:*`, `workflow:*`, `email:*`, `mcp:*`, ...).\n *\n * Cloudflare Workers cannot auto-instrument, so the Agent class must be wrapped manually.\n *\n * @param optionsCallback Function that returns the options for the SDK initialization.\n * @param AgentClass The Agent class to instrument.\n * @returns The instrumented Agent class.\n *\n * @example\n * ```ts\n * import { Agent, callable, routeAgentRequest } from 'agents';\n * import * as Sentry from '@sentry/cloudflare';\n *\n * class MyAgentBase extends Agent<Env> {\n * @callable()\n * async greet(name: string): Promise<string> {\n * return `Hello, ${name}!`;\n * }\n * }\n *\n * export const MyAgent = Sentry.instrumentAgentWithSentry(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * enableRpcTracePropagation: true,\n * }),\n * MyAgentBase,\n * );\n * ```\n */\nexport function instrumentAgentWithSentry<\n E,\n T extends DurableObject<E>,\n C extends new (state: DurableObjectState, env: E) => T,\n>(optionsCallback: (env: E) => CloudflareOptions, AgentClass: C): C {\n return new Proxy(AgentClass, {\n construct(target, [ctx, env], newTarget) {\n const { obj, options, context, frameworkManagedMethods } = constructInstrumentedDurableObject(\n target,\n ctx,\n env,\n newTarget,\n optionsCallback,\n );\n\n instrumentCloudflareAgent(obj);\n\n // Apply RPC prototype-method instrumentation last, so the Agent-specific own-property\n // handlers we just installed are excluded from RPC method tracing. Methods the Agent\n // framework installed itself are excluded too — `instrumentCloudflareAgent` traces those by\n // wrapping the dispatch instead of the method.\n return finalizeWithRpcInstrumentation(obj, options, context, frameworkManagedMethods);\n },\n });\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { debug, captureException } from '@sentry/core';
|
|
2
|
+
import { DEBUG_BUILD } from '../debug-build.js';
|
|
3
|
+
import { ensureInstrumented } from '../instrument.js';
|
|
4
|
+
import { wrapRequestHandler } from '../request.js';
|
|
5
|
+
import { wrapMethodWithSentry } from '../wrapMethodWithSentry.js';
|
|
6
|
+
|
|
7
|
+
function instrumentDurableObjectHandlers(obj, options, context) {
|
|
8
|
+
if (obj.fetch && typeof obj.fetch === "function") {
|
|
9
|
+
setInstanceHandler(
|
|
10
|
+
obj,
|
|
11
|
+
"fetch",
|
|
12
|
+
ensureInstrumented(
|
|
13
|
+
obj.fetch.bind(obj),
|
|
14
|
+
(original) => new Proxy(original, {
|
|
15
|
+
apply(target, thisArg, args) {
|
|
16
|
+
return wrapRequestHandler({ options, request: args[0], context }, () => {
|
|
17
|
+
return Reflect.apply(target, thisArg, args);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
)
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
if (obj.alarm && typeof obj.alarm === "function") {
|
|
25
|
+
setInstanceHandler(
|
|
26
|
+
obj,
|
|
27
|
+
"alarm",
|
|
28
|
+
wrapMethodWithSentry(
|
|
29
|
+
{
|
|
30
|
+
options,
|
|
31
|
+
context,
|
|
32
|
+
spanName: "alarm",
|
|
33
|
+
spanOp: "function",
|
|
34
|
+
startNewTrace: true,
|
|
35
|
+
origin: "auto.faas.cloudflare.durable_object"
|
|
36
|
+
},
|
|
37
|
+
obj.alarm.bind(obj)
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
if (obj.webSocketMessage && typeof obj.webSocketMessage === "function") {
|
|
42
|
+
setInstanceHandler(
|
|
43
|
+
obj,
|
|
44
|
+
"webSocketMessage",
|
|
45
|
+
wrapMethodWithSentry(
|
|
46
|
+
{
|
|
47
|
+
options,
|
|
48
|
+
context,
|
|
49
|
+
spanName: "webSocketMessage",
|
|
50
|
+
origin: "auto.faas.cloudflare.durable_object"
|
|
51
|
+
},
|
|
52
|
+
obj.webSocketMessage.bind(obj)
|
|
53
|
+
)
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
if (obj.webSocketClose && typeof obj.webSocketClose === "function") {
|
|
57
|
+
setInstanceHandler(
|
|
58
|
+
obj,
|
|
59
|
+
"webSocketClose",
|
|
60
|
+
wrapMethodWithSentry(
|
|
61
|
+
{
|
|
62
|
+
options,
|
|
63
|
+
context,
|
|
64
|
+
spanName: "webSocketClose",
|
|
65
|
+
origin: "auto.faas.cloudflare.durable_object"
|
|
66
|
+
},
|
|
67
|
+
obj.webSocketClose.bind(obj)
|
|
68
|
+
)
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
if (obj.webSocketError && typeof obj.webSocketError === "function") {
|
|
72
|
+
setInstanceHandler(
|
|
73
|
+
obj,
|
|
74
|
+
"webSocketError",
|
|
75
|
+
wrapMethodWithSentry(
|
|
76
|
+
{
|
|
77
|
+
options,
|
|
78
|
+
context,
|
|
79
|
+
spanName: "webSocketError",
|
|
80
|
+
origin: "auto.faas.cloudflare.durable_object"
|
|
81
|
+
},
|
|
82
|
+
obj.webSocketError.bind(obj),
|
|
83
|
+
(_, error) => captureException(error, {
|
|
84
|
+
mechanism: {
|
|
85
|
+
type: "auto.faas.cloudflare.durable_object_websocket",
|
|
86
|
+
handled: false
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
)
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function setInstanceHandler(obj, name, handler) {
|
|
94
|
+
const descriptor = Object.getOwnPropertyDescriptor(obj, name);
|
|
95
|
+
try {
|
|
96
|
+
if (descriptor?.writable === false) {
|
|
97
|
+
Object.defineProperty(obj, name, {
|
|
98
|
+
value: handler,
|
|
99
|
+
writable: true,
|
|
100
|
+
enumerable: descriptor.enumerable,
|
|
101
|
+
configurable: descriptor.configurable
|
|
102
|
+
});
|
|
103
|
+
} else {
|
|
104
|
+
obj[name] = handler;
|
|
105
|
+
}
|
|
106
|
+
} catch (error) {
|
|
107
|
+
DEBUG_BUILD && debug.warn(`Failed to instrument Durable Object handler "${name}"`, error);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export { instrumentDurableObjectHandlers };
|
|
112
|
+
//# sourceMappingURL=instrumentDurableObjectHandlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrumentDurableObjectHandlers.js","sources":["../../../src/instrumentations/instrumentDurableObjectHandlers.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport { captureException, debug } from '@sentry/core';\nimport type { DurableObject } from 'cloudflare:workers';\nimport type { CloudflareOptions } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { ensureInstrumented } from '../instrument';\nimport { wrapRequestHandler } from '../request';\nimport { wrapMethodWithSentry } from '../wrapMethodWithSentry';\n\n/**\n * The instrumented context of the Durable Object being wrapped.\n *\n * Kept as `any` for the same reason as in `durableobject.ts`: a concrete `DurableObjectState` here\n * makes `tsc` relate its `SqlStorage` graph against the parameter union of `wrapMethodWithSentry`,\n * which hangs the type build.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InstrumentedDurableObjectContext = any;\n\n/**\n * Instruments the built-in Durable Object handler methods on a constructed instance.\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 * @internal\n */\nexport function instrumentDurableObjectHandlers<E, T extends DurableObject<E>>(\n obj: T,\n options: CloudflareOptions,\n context: InstrumentedDurableObjectContext,\n): void {\n // Bind each built-in handler to this instance before wrapping.\n // See https://github.com/getsentry/sentry-javascript/issues/22328\n if (obj.fetch && typeof obj.fetch === 'function') {\n setInstanceHandler(\n obj,\n 'fetch',\n ensureInstrumented(\n obj.fetch.bind(obj),\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\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 setInstanceHandler(\n obj,\n 'alarm',\n wrapMethodWithSentry(\n {\n options,\n context,\n spanName: 'alarm',\n spanOp: 'function',\n startNewTrace: true,\n origin: 'auto.faas.cloudflare.durable_object',\n },\n obj.alarm.bind(obj),\n ),\n );\n }\n\n if (obj.webSocketMessage && typeof obj.webSocketMessage === 'function') {\n setInstanceHandler(\n obj,\n 'webSocketMessage',\n wrapMethodWithSentry(\n {\n options,\n context,\n spanName: 'webSocketMessage',\n origin: 'auto.faas.cloudflare.durable_object',\n },\n obj.webSocketMessage.bind(obj),\n ),\n );\n }\n\n if (obj.webSocketClose && typeof obj.webSocketClose === 'function') {\n setInstanceHandler(\n obj,\n 'webSocketClose',\n wrapMethodWithSentry(\n {\n options,\n context,\n spanName: 'webSocketClose',\n origin: 'auto.faas.cloudflare.durable_object',\n },\n obj.webSocketClose.bind(obj),\n ),\n );\n }\n\n if (obj.webSocketError && typeof obj.webSocketError === 'function') {\n setInstanceHandler(\n obj,\n 'webSocketError',\n wrapMethodWithSentry(\n {\n options,\n context,\n spanName: 'webSocketError',\n origin: 'auto.faas.cloudflare.durable_object',\n },\n obj.webSocketError.bind(obj),\n (_, error) =>\n captureException(error, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object_websocket',\n handled: false,\n },\n }),\n ),\n );\n }\n}\n\n/**\n * Installs an instrumented handler as an own property of the Durable Object instance.\n *\n * A plain assignment is not always possible. The `agents` package installs its handlers with\n * `Object.defineProperty(instance, name, { value, configurable: true })`, and `defineProperty`\n * leaves `writable` at `false`. Assigning to such a property throws a `TypeError` in strict mode,\n * so a read-only property is redefined instead. When the property can be neither assigned nor\n * redefined, the handler stays uninstrumented rather than breaking the object.\n */\nfunction setInstanceHandler(obj: object, name: string, handler: unknown): void {\n const descriptor = Object.getOwnPropertyDescriptor(obj, name);\n\n try {\n if (descriptor?.writable === false) {\n Object.defineProperty(obj, name, {\n value: handler,\n writable: true,\n enumerable: descriptor.enumerable,\n configurable: descriptor.configurable,\n });\n } else {\n (obj as Record<string, unknown>)[name] = handler;\n }\n } catch (error) {\n DEBUG_BUILD && debug.warn(`Failed to instrument Durable Object handler \"${name}\"`, error);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { appendRpcMeta } from '../utils/rpcMeta.js';
|
|
|
2
2
|
import { instrumentFetcher } from './worker/instrumentFetcher.js';
|
|
3
3
|
|
|
4
4
|
const STUB_NON_RPC_METHODS = /* @__PURE__ */ new Set(["fetch", "connect", "dup"]);
|
|
5
|
-
function instrumentDurableObjectNamespace(namespace) {
|
|
5
|
+
function instrumentDurableObjectNamespace(namespace, propagateRpcTrace = false) {
|
|
6
6
|
return new Proxy(namespace, {
|
|
7
7
|
get(target, prop, _receiver) {
|
|
8
8
|
const value = Reflect.get(target, prop);
|
|
@@ -12,21 +12,21 @@ function instrumentDurableObjectNamespace(namespace) {
|
|
|
12
12
|
if (prop === "get" || prop === "getByName") {
|
|
13
13
|
return function(...args) {
|
|
14
14
|
const stub = Reflect.apply(value, target, args);
|
|
15
|
-
return instrumentDurableObjectStub(stub);
|
|
15
|
+
return instrumentDurableObjectStub(stub, propagateRpcTrace);
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
18
|
return value.bind(target);
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
|
-
function instrumentDurableObjectStub(stub) {
|
|
22
|
+
function instrumentDurableObjectStub(stub, propagateRpcTrace) {
|
|
23
23
|
return new Proxy(stub, {
|
|
24
24
|
get(target, prop) {
|
|
25
25
|
const value = Reflect.get(target, prop);
|
|
26
26
|
if (prop === "fetch" && typeof value === "function") {
|
|
27
27
|
return instrumentFetcher((...args) => Reflect.apply(value, target, args));
|
|
28
28
|
}
|
|
29
|
-
if (typeof value === "function" && typeof prop === "string" && !STUB_NON_RPC_METHODS.has(prop)) {
|
|
29
|
+
if (propagateRpcTrace && typeof value === "function" && typeof prop === "string" && !STUB_NON_RPC_METHODS.has(prop)) {
|
|
30
30
|
return (...args) => Reflect.apply(value, target, appendRpcMeta(args));
|
|
31
31
|
}
|
|
32
32
|
return value;
|
|
@@ -1 +1 @@
|
|
|
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'
|
|
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 * @param propagateRpcTrace - Whether RPC method calls on the returned stubs carry trace context\n */\nexport function instrumentDurableObjectNamespace(\n namespace: DurableObjectNamespace,\n propagateRpcTrace = false,\n): 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, propagateRpcTrace);\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 * @param propagateRpcTrace - Whether RPC method calls carry trace context\n */\nfunction instrumentDurableObjectStub(stub: DurableObjectStub, propagateRpcTrace: boolean): 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 (\n propagateRpcTrace &&\n typeof value === 'function' &&\n typeof prop === 'string' &&\n !STUB_NON_RPC_METHODS.has(prop)\n ) {\n return (...args: unknown[]) => Reflect.apply(value, target, appendRpcMeta(args));\n }\n\n return value;\n },\n });\n}\n"],"names":[],"mappings":";;;AAKO,MAAM,uCAAuB,IAAI,GAAA,CAAI,CAAC,OAAA,EAAS,SAAA,EAAW,KAAK,CAAC;AAYhE,SAAS,gCAAA,CACd,SAAA,EACA,iBAAA,GAAoB,KAAA,EACI;AACxB,EAAA,OAAO,IAAI,MAAM,SAAA,EAAW;AAAA,IAC1B,GAAA,CAAI,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAW;AAC3B,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,IAAI,CAAA;AAEtC,MAAA,IAAI,OAAO,UAAU,UAAA,EAAY;AAC/B,QAAA,OAAO,KAAA;AAAA,MACT;AAEA,MAAA,IAAI,IAAA,KAAS,KAAA,IAAS,IAAA,KAAS,WAAA,EAAa;AAC1C,QAAA,OAAO,YAA4B,IAAA,EAAiB;AAClD,UAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,CAAM,KAAA,EAAO,QAAQ,IAAI,CAAA;AAE9C,UAAA,OAAO,2BAAA,CAA4B,MAAM,iBAAiB,CAAA;AAAA,QAC5D,CAAA;AAAA,MACF;AAEA,MAAA,OAAO,KAAA,CAAM,KAAK,MAAM,CAAA;AAAA,IAC1B;AAAA,GACD,CAAA;AACH;AASA,SAAS,2BAAA,CAA4B,MAAyB,iBAAA,EAA+C;AAC3G,EAAA,OAAO,IAAI,MAAM,IAAA,EAAM;AAAA,IACrB,GAAA,CAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,IAAI,CAAA;AAEtC,MAAA,IAAI,IAAA,KAAS,OAAA,IAAW,OAAO,KAAA,KAAU,UAAA,EAAY;AACnD,QAAA,OAAO,iBAAA,CAAkB,IAAI,IAAA,KAAS,OAAA,CAAQ,MAAM,KAAA,EAAO,MAAA,EAAQ,IAAI,CAAC,CAAA;AAAA,MAC1E;AAEA,MAAA,IACE,iBAAA,IACA,OAAO,KAAA,KAAU,UAAA,IACjB,OAAO,IAAA,KAAS,QAAA,IAChB,CAAC,oBAAA,CAAqB,GAAA,CAAI,IAAI,CAAA,EAC9B;AACA,QAAA,OAAO,CAAA,GAAI,SAAoB,OAAA,CAAQ,KAAA,CAAM,OAAO,MAAA,EAAQ,aAAA,CAAc,IAAI,CAAC,CAAA;AAAA,MACjF;AAEA,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,GACD,CAAA;AACH;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentWorkerEntrypoint.js","sources":["../../../src/instrumentations/instrumentWorkerEntrypoint.ts"],"sourcesContent":["import type { RpcStub, WorkerEntrypoint } from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from '../async';\nimport type { CloudflareOptions } from '../client';\nimport { getFinalOptions } from '../options';\nimport { instrumentContext } from '../utils/instrumentContext';\nimport { extractRpcMeta } from '../utils/rpcMeta';\nimport { type UncheckedMethod, wrapMethodWithSentry } from '../wrapMethodWithSentry';\nimport { instrumentEnv } from './worker/instrumentEnv';\nimport { instrumentWorkerEntrypointFetch } from './worker/instrumentFetch';\nimport { instrumentWorkerEntrypointQueue } from './worker/instrumentQueue';\nimport { instrumentWorkerEntrypointScheduled } from './worker/instrumentScheduled';\nimport { instrumentWorkerEntrypointTail } from './worker/instrumentTail';\n\nconst WORKER_ENTRYPOINT_ORIGIN = 'auto.faas.cloudflare.worker_entrypoint';\n\ntype ReservedMethod =\n | Exclude<Extract<keyof WorkerEntrypoint, string>, '__WORKER_ENTRYPOINT_BRAND'>\n | Extract<keyof ExportedHandler, string>\n | Exclude<Extract<keyof RpcStub<(...args: unknown[]) => unknown>, string>, '__RPC_STUB_BRAND'>\n | 'constructor';\n\nconst RESERVED_METHODS = new Set<string>([\n 'connect',\n 'constructor',\n 'dup',\n 'email',\n 'fetch',\n 'queue',\n 'scheduled',\n 'tail',\n 'tailStream',\n 'test',\n 'trace',\n] satisfies ReservedMethod[]);\n\ninterface CachedMethod {\n source: UncheckedMethod;\n wrapped: UncheckedMethod;\n}\n\nexport type WorkerEntrypointConstructor<Env = unknown, Props = {}> = new (\n ctx: ExecutionContext,\n // WorkerEntrypoint subclasses can define different `env` shapes, so this constructor must accept all of them.\n // oxlint-disable-next-line typescript/no-explicit-any\n env: any,\n) => InstanceType<typeof WorkerEntrypoint<Env, Props>>;\n\nfunction isPrototypeMethod(instance: object, prop: string, method: UncheckedMethod): boolean {\n let prototype = Object.getPrototypeOf(instance);\n\n while (prototype && prototype !== Object.prototype) {\n const descriptor = Object.getOwnPropertyDescriptor(prototype, prop);\n if (descriptor) {\n return descriptor.value === method;\n }\n prototype = Object.getPrototypeOf(prototype);\n }\n\n return false;\n}\n\nfunction bindToInstance(instance: object, proxy: object, method: UncheckedMethod): UncheckedMethod {\n return new Proxy(method, {\n apply(target, thisArg, args) {\n return Reflect.apply(target, thisArg === proxy ? instance : thisArg, args);\n },\n });\n}\n\nfunction instrumentMethod(\n instance: object,\n proxy: object,\n prop: PropertyKey,\n method: UncheckedMethod,\n options: CloudflareOptions,\n context: ExecutionContext,\n): UncheckedMethod {\n const ownDescriptor = Object.getOwnPropertyDescriptor(instance, prop);\n if (ownDescriptor && 'value' in ownDescriptor && !ownDescriptor.configurable && !ownDescriptor.writable) {\n return method;\n }\n\n const boundMethod = bindToInstance(instance, proxy, method);\n\n if (typeof prop !== 'string' || RESERVED_METHODS.has(prop) || !isPrototypeMethod(instance, prop, method)) {\n return boundMethod;\n }\n\n const captureMethod = wrapMethodWithSentry(\n { options, context, spanOp: 'rpc', origin: WORKER_ENTRYPOINT_ORIGIN },\n boundMethod,\n undefined,\n true,\n );\n\n if (!options.enableRpcTracePropagation) {\n return captureMethod;\n }\n\n const tracedMethod = wrapMethodWithSentry(\n { options, context, spanName: prop, spanOp: 'rpc', origin: WORKER_ENTRYPOINT_ORIGIN },\n boundMethod,\n undefined,\n true,\n );\n\n return (...args: unknown[]) => {\n const { rpcMeta } = extractRpcMeta(args);\n return rpcMeta ? tracedMethod.call(proxy, ...args) : captureMethod.call(proxy, ...args);\n };\n}\n\n/**\n * Instruments a WorkerEntrypoint class to capture errors and performance data.\n *\n * Instruments the following methods (same as `withSentry` for ExportedHandler):\n * - fetch (HTTP requests)\n * - scheduled (cron triggers)\n * - queue (queue consumers)\n * - email (email handlers)\n * - tail (tail workers)\n *\n * as well as any other public RPC methods on the WorkerEntrypoint instance.\n *\n * @param optionsCallback Function that returns the options for the SDK initialization.\n * @param WorkerEntrypointClass The WorkerEntrypoint class to instrument.\n * @returns The instrumented WorkerEntrypoint class.\n *\n * @example\n * ```ts\n * class MyWorkerBase extends WorkerEntrypoint<Env> {\n * async fetch(request: Request): Promise<Response> {\n * return new Response('Hello World!');\n * }\n *\n * async myRpcMethod(arg: string): Promise<string> {\n * return `Hello ${arg}!`;\n * }\n * }\n *\n * export default instrumentWorkerEntrypoint(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * }),\n * MyWorkerBase,\n * );\n * ```\n */\nexport function instrumentWorkerEntrypoint<\n Env,\n Props,\n T extends InstanceType<typeof WorkerEntrypoint<Env, Props>>,\n C extends new (ctx: ExecutionContext, env: Env) => T,\n>(optionsCallback: (env: Env) => CloudflareOptions | undefined, WorkerEntrypointClass: C): C {\n // Set up AsyncLocalStorage strategy ONCE at instrumentation time, not per-request\n // This is critical - calling this per-request would create a new AsyncLocalStorage\n // each time, breaking scope isolation for concurrent requests\n setAsyncLocalStorageAsyncContextStrategy();\n\n return new Proxy(WorkerEntrypointClass, {\n construct(target, [ctx, env]) {\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n const instrumentedEnv = instrumentEnv(env, options);\n const obj = new target(context, instrumentedEnv);\n\n // Override this.ctx to ensure the instrumented context is used\n // This is necessary because the base WorkerEntrypoint class sets this.ctx\n // from the constructor parameter, but we want users accessing this.ctx\n // to get the instrumented version\n if ('ctx' in obj) {\n Object.defineProperty(obj, 'ctx', {\n value: context,\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n\n if ('env' in obj) {\n Object.defineProperty(obj, 'env', {\n value: instrumentedEnv,\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n\n Object.defineProperty(obj, '__SENTRY_CONTEXT__', {\n value: context,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n\n Object.defineProperty(obj, '__SENTRY_OPTIONS__', {\n value: options,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n\n const entrypoint = obj as WorkerEntrypoint;\n instrumentWorkerEntrypointFetch(entrypoint, options, context);\n instrumentWorkerEntrypointScheduled(entrypoint, options, context);\n instrumentWorkerEntrypointQueue(entrypoint, options, context);\n instrumentWorkerEntrypointTail(entrypoint, options, context);\n\n // workerd resolves RPC methods through property access.\n const methodCache = new Map<PropertyKey, CachedMethod>();\n\n const proxy: typeof obj = new Proxy(obj, {\n get(instance, prop) {\n const value = Reflect.get(instance, prop, instance);\n\n if (typeof value !== 'function') {\n return value;\n }\n\n const method = value as UncheckedMethod;\n\n const cached = methodCache.get(prop);\n if (cached?.source === method) {\n return cached.wrapped;\n }\n\n const wrapped = instrumentMethod(instance, proxy, prop, method, options, context);\n methodCache.set(prop, { source: method, wrapped });\n return wrapped;\n },\n });\n\n return proxy;\n },\n });\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"instrumentWorkerEntrypoint.js","sources":["../../../src/instrumentations/instrumentWorkerEntrypoint.ts"],"sourcesContent":["import type { RpcStub, WorkerEntrypoint } from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from '../async';\nimport type { CloudflareOptions } from '../client';\nimport { getFinalOptions } from '../options';\nimport { instrumentContext } from '../utils/instrumentContext';\nimport { extractRpcMeta } from '../utils/rpcMeta';\nimport { type UncheckedMethod, wrapMethodWithSentry } from '../wrapMethodWithSentry';\nimport { instrumentEnv } from './worker/instrumentEnv';\nimport { instrumentWorkerEntrypointFetch } from './worker/instrumentFetch';\nimport { instrumentWorkerEntrypointQueue } from './worker/instrumentQueue';\nimport { instrumentWorkerEntrypointScheduled } from './worker/instrumentScheduled';\nimport { instrumentWorkerEntrypointTail } from './worker/instrumentTail';\n\nconst WORKER_ENTRYPOINT_ORIGIN = 'auto.faas.cloudflare.worker_entrypoint';\n\ntype ReservedMethod =\n | Exclude<Extract<keyof WorkerEntrypoint, string>, '__WORKER_ENTRYPOINT_BRAND'>\n | Extract<keyof ExportedHandler, string>\n | Exclude<Extract<keyof RpcStub<(...args: unknown[]) => unknown>, string>, '__RPC_STUB_BRAND'>\n | 'constructor';\n\nconst RESERVED_METHODS = new Set<string>([\n 'connect',\n 'constructor',\n 'dup',\n 'email',\n 'fetch',\n 'queue',\n 'scheduled',\n 'tail',\n 'tailStream',\n 'test',\n 'trace',\n] satisfies ReservedMethod[]);\n\ninterface CachedMethod {\n source: UncheckedMethod;\n wrapped: UncheckedMethod;\n}\n\nexport type WorkerEntrypointConstructor<Env = unknown, Props = {}> = new (\n ctx: ExecutionContext,\n // WorkerEntrypoint subclasses can define different `env` shapes, so this constructor must accept all of them.\n // oxlint-disable-next-line typescript/no-explicit-any\n env: any,\n) => InstanceType<typeof WorkerEntrypoint<Env, Props>>;\n\nfunction isPrototypeMethod(instance: object, prop: string, method: UncheckedMethod): boolean {\n let prototype = Object.getPrototypeOf(instance);\n\n while (prototype && prototype !== Object.prototype) {\n const descriptor = Object.getOwnPropertyDescriptor(prototype, prop);\n if (descriptor) {\n return descriptor.value === method;\n }\n prototype = Object.getPrototypeOf(prototype);\n }\n\n return false;\n}\n\nfunction bindToInstance(instance: object, proxy: object, method: UncheckedMethod): UncheckedMethod {\n return new Proxy(method, {\n apply(target, thisArg, args) {\n return Reflect.apply(target, thisArg === proxy ? instance : thisArg, args);\n },\n });\n}\n\nfunction instrumentMethod(\n instance: object,\n proxy: object,\n prop: PropertyKey,\n method: UncheckedMethod,\n options: CloudflareOptions,\n context: ExecutionContext,\n): UncheckedMethod {\n const ownDescriptor = Object.getOwnPropertyDescriptor(instance, prop);\n if (ownDescriptor && 'value' in ownDescriptor && !ownDescriptor.configurable && !ownDescriptor.writable) {\n return method;\n }\n\n const boundMethod = bindToInstance(instance, proxy, method);\n\n if (typeof prop !== 'string' || RESERVED_METHODS.has(prop) || !isPrototypeMethod(instance, prop, method)) {\n return boundMethod;\n }\n\n const captureMethod = wrapMethodWithSentry(\n { options, context, spanOp: 'rpc', origin: WORKER_ENTRYPOINT_ORIGIN },\n boundMethod,\n undefined,\n true,\n );\n\n // eslint-disable-next-line typescript/no-deprecated\n if (!options.enableRpcTracePropagation) {\n return captureMethod;\n }\n\n const tracedMethod = wrapMethodWithSentry(\n { options, context, spanName: prop, spanOp: 'rpc', origin: WORKER_ENTRYPOINT_ORIGIN },\n boundMethod,\n undefined,\n true,\n );\n\n return (...args: unknown[]) => {\n const { rpcMeta } = extractRpcMeta(args);\n return rpcMeta ? tracedMethod.call(proxy, ...args) : captureMethod.call(proxy, ...args);\n };\n}\n\n/**\n * Instruments a WorkerEntrypoint class to capture errors and performance data.\n *\n * Instruments the following methods (same as `withSentry` for ExportedHandler):\n * - fetch (HTTP requests)\n * - scheduled (cron triggers)\n * - queue (queue consumers)\n * - email (email handlers)\n * - tail (tail workers)\n *\n * as well as any other public RPC methods on the WorkerEntrypoint instance.\n *\n * @param optionsCallback Function that returns the options for the SDK initialization.\n * @param WorkerEntrypointClass The WorkerEntrypoint class to instrument.\n * @returns The instrumented WorkerEntrypoint class.\n *\n * @example\n * ```ts\n * class MyWorkerBase extends WorkerEntrypoint<Env> {\n * async fetch(request: Request): Promise<Response> {\n * return new Response('Hello World!');\n * }\n *\n * async myRpcMethod(arg: string): Promise<string> {\n * return `Hello ${arg}!`;\n * }\n * }\n *\n * export default instrumentWorkerEntrypoint(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * }),\n * MyWorkerBase,\n * );\n * ```\n */\nexport function instrumentWorkerEntrypoint<\n Env,\n Props,\n T extends InstanceType<typeof WorkerEntrypoint<Env, Props>>,\n C extends new (ctx: ExecutionContext, env: Env) => T,\n>(optionsCallback: (env: Env) => CloudflareOptions | undefined, WorkerEntrypointClass: C): C {\n // Set up AsyncLocalStorage strategy ONCE at instrumentation time, not per-request\n // This is critical - calling this per-request would create a new AsyncLocalStorage\n // each time, breaking scope isolation for concurrent requests\n setAsyncLocalStorageAsyncContextStrategy();\n\n return new Proxy(WorkerEntrypointClass, {\n construct(target, [ctx, env]) {\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n const instrumentedEnv = instrumentEnv(env, options);\n const obj = new target(context, instrumentedEnv);\n\n // Override this.ctx to ensure the instrumented context is used\n // This is necessary because the base WorkerEntrypoint class sets this.ctx\n // from the constructor parameter, but we want users accessing this.ctx\n // to get the instrumented version\n if ('ctx' in obj) {\n Object.defineProperty(obj, 'ctx', {\n value: context,\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n\n if ('env' in obj) {\n Object.defineProperty(obj, 'env', {\n value: instrumentedEnv,\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n\n Object.defineProperty(obj, '__SENTRY_CONTEXT__', {\n value: context,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n\n Object.defineProperty(obj, '__SENTRY_OPTIONS__', {\n value: options,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n\n const entrypoint = obj as WorkerEntrypoint;\n instrumentWorkerEntrypointFetch(entrypoint, options, context);\n instrumentWorkerEntrypointScheduled(entrypoint, options, context);\n instrumentWorkerEntrypointQueue(entrypoint, options, context);\n instrumentWorkerEntrypointTail(entrypoint, options, context);\n\n // workerd resolves RPC methods through property access.\n const methodCache = new Map<PropertyKey, CachedMethod>();\n\n const proxy: typeof obj = new Proxy(obj, {\n get(instance, prop) {\n const value = Reflect.get(instance, prop, instance);\n\n if (typeof value !== 'function') {\n return value;\n }\n\n const method = value as UncheckedMethod;\n\n const cached = methodCache.get(prop);\n if (cached?.source === method) {\n return cached.wrapped;\n }\n\n const wrapped = instrumentMethod(instance, proxy, prop, method, options, context);\n methodCache.set(prop, { source: method, wrapped });\n return wrapped;\n },\n });\n\n return proxy;\n },\n });\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { instrumentWorkersAiClient, isObjectLike } from '@sentry/core';
|
|
|
2
2
|
import { isD1Database, isQueue, isR2Bucket, isRateLimit, isAiBinding, isDurableObjectNamespace, isJSRPC } from '../../utils/isBinding.js';
|
|
3
3
|
import { instrumentD1 } from './instrumentD1.js';
|
|
4
4
|
import { appendRpcMeta } from '../../utils/rpcMeta.js';
|
|
5
|
-
import {
|
|
5
|
+
import { createRpcPropagationResolver } from '../../utils/rpcPropagation.js';
|
|
6
6
|
import { instrumentDurableObjectNamespace, STUB_NON_RPC_METHODS } from '../instrumentDurableObjectNamespace.js';
|
|
7
7
|
import { instrumentFetcher } from './instrumentFetcher.js';
|
|
8
8
|
import { instrumentQueueProducer } from './instrumentQueueProducer.js';
|
|
@@ -17,7 +17,7 @@ function instrumentEnv(env, options) {
|
|
|
17
17
|
if (!env || typeof env !== "object") {
|
|
18
18
|
return env;
|
|
19
19
|
}
|
|
20
|
-
const
|
|
20
|
+
const shouldPropagateRpcTrace = createRpcPropagationResolver(options);
|
|
21
21
|
return new Proxy(env, {
|
|
22
22
|
get(target, prop, receiver) {
|
|
23
23
|
const item = Reflect.get(target, prop, receiver);
|
|
@@ -56,11 +56,9 @@ function instrumentEnv(env, options) {
|
|
|
56
56
|
instrumentedBindings.set(item, instrumented);
|
|
57
57
|
return instrumented;
|
|
58
58
|
}
|
|
59
|
-
|
|
60
|
-
return item;
|
|
61
|
-
}
|
|
59
|
+
const propagateRpcTrace = shouldPropagateRpcTrace(String(prop));
|
|
62
60
|
if (isDurableObjectNamespace(item)) {
|
|
63
|
-
const instrumented = instrumentDurableObjectNamespace(item);
|
|
61
|
+
const instrumented = instrumentDurableObjectNamespace(item, propagateRpcTrace);
|
|
64
62
|
instrumentedBindings.set(item, instrumented);
|
|
65
63
|
return instrumented;
|
|
66
64
|
}
|
|
@@ -71,7 +69,7 @@ function instrumentEnv(env, options) {
|
|
|
71
69
|
if (p === "fetch" && typeof value === "function") {
|
|
72
70
|
return instrumentFetcher((...args) => Reflect.apply(value, target2, args));
|
|
73
71
|
}
|
|
74
|
-
if (typeof value === "function" && typeof p === "string" && !STUB_NON_RPC_METHODS.has(p)) {
|
|
72
|
+
if (propagateRpcTrace && typeof value === "function" && typeof p === "string" && !STUB_NON_RPC_METHODS.has(p)) {
|
|
75
73
|
return (...args) => Reflect.apply(value, target2, appendRpcMeta(args));
|
|
76
74
|
}
|
|
77
75
|
return value;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentEnv.js","sources":["../../../../src/instrumentations/worker/instrumentEnv.ts"],"sourcesContent":["import { isObjectLike } from '@sentry/core';\nimport { instrumentWorkersAiClient } from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport {\n isAiBinding,\n isD1Database,\n isDurableObjectNamespace,\n isJSRPC,\n isQueue,\n isR2Bucket,\n isRateLimit,\n} from '../../utils/isBinding';\nimport { instrumentD1 } from './instrumentD1';\nimport { appendRpcMeta } from '../../utils/rpcMeta';\nimport {
|
|
1
|
+
{"version":3,"file":"instrumentEnv.js","sources":["../../../../src/instrumentations/worker/instrumentEnv.ts"],"sourcesContent":["import { isObjectLike } from '@sentry/core';\nimport { instrumentWorkersAiClient } from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport {\n isAiBinding,\n isD1Database,\n isDurableObjectNamespace,\n isJSRPC,\n isQueue,\n isR2Bucket,\n isRateLimit,\n} from '../../utils/isBinding';\nimport { instrumentD1 } from './instrumentD1';\nimport { appendRpcMeta } from '../../utils/rpcMeta';\nimport { createRpcPropagationResolver } from '../../utils/rpcPropagation';\nimport { instrumentDurableObjectNamespace, STUB_NON_RPC_METHODS } from '../instrumentDurableObjectNamespace';\nimport { instrumentFetcher } from './instrumentFetcher';\nimport { instrumentQueueProducer } from './instrumentQueueProducer';\nimport { instrumentR2Bucket } from './instrumentR2';\nimport { instrumentRateLimit } from './instrumentRateLimit';\n\nfunction isProxyable(item: unknown): item is object {\n return isObjectLike(item) || 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\n * - Queue producers (via `send` + `sendBatch` duck-typing)\n * - R2 Buckets (via `head` + `put` + `createMultipartUpload` duck-typing)\n * - Rate limiters (via `limit` duck-typing)\n * - Workers AI (via `run` + `gateway` + `toMarkdown` duck-typing)\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 shouldPropagateRpcTrace = createRpcPropagationResolver(options);\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 (isD1Database(item)) {\n const instrumented = instrumentD1(item);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n if (isQueue(item)) {\n const bindingName = typeof prop === 'string' ? prop : String(prop);\n const instrumented = instrumentQueueProducer(item, bindingName);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n if (isR2Bucket(item)) {\n const bindingName = typeof prop === 'string' ? prop : String(prop);\n const instrumented = instrumentR2Bucket(item, bindingName);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n if (isRateLimit(item)) {\n const bindingName = typeof prop === 'string' ? prop : String(prop);\n const instrumented = instrumentRateLimit(item, bindingName);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n if (isAiBinding(item)) {\n const instrumented = instrumentWorkersAiClient(item);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n const propagateRpcTrace = shouldPropagateRpcTrace(String(prop));\n\n if (isDurableObjectNamespace(item)) {\n const instrumented = instrumentDurableObjectNamespace(item, propagateRpcTrace);\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 (\n propagateRpcTrace &&\n typeof value === 'function' &&\n typeof p === 'string' &&\n !STUB_NON_RPC_METHODS.has(p)\n ) {\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":["target"],"mappings":"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"}
|
package/build/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"10.
|
|
1
|
+
{"type":"module","version":"10.73.0","sideEffects":false}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { stringMatchesSomePattern } from '@sentry/core';
|
|
2
|
+
import { getEffectiveRpcPropagation } from './rpcOptions.js';
|
|
3
|
+
|
|
4
|
+
const PROPAGATE_TO_NONE = () => false;
|
|
5
|
+
const PROPAGATE_TO_ALL = () => true;
|
|
6
|
+
function createRpcPropagationResolver(options) {
|
|
7
|
+
const bindings = options?.rpcTracePropagationBindings;
|
|
8
|
+
if (bindings === void 0) {
|
|
9
|
+
return options && getEffectiveRpcPropagation(options) ? PROPAGATE_TO_ALL : PROPAGATE_TO_NONE;
|
|
10
|
+
}
|
|
11
|
+
if (!bindings.length) {
|
|
12
|
+
return PROPAGATE_TO_NONE;
|
|
13
|
+
}
|
|
14
|
+
return (bindingName) => stringMatchesSomePattern(bindingName, bindings, true);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { createRpcPropagationResolver };
|
|
18
|
+
//# sourceMappingURL=rpcPropagation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpcPropagation.js","sources":["../../../src/utils/rpcPropagation.ts"],"sourcesContent":["import { stringMatchesSomePattern } from '@sentry/core';\nimport type { CloudflareOptions } from '../client';\nimport { getEffectiveRpcPropagation } from './rpcOptions';\n\nconst PROPAGATE_TO_NONE = (): boolean => false;\nconst PROPAGATE_TO_ALL = (): boolean => true;\n\n/**\n * Builds the per-binding predicate that decides whether a binding takes part in RPC trace\n * propagation.\n *\n * `rpcTracePropagationBindings` wins over `enableRpcTracePropagation` as soon as it is set, an\n * allow list is the more precise statement. An empty list therefore propagates to nothing, even\n * next to `enableRpcTracePropagation: true`, which is how a receiver opts out of being a caller.\n * Only leaving it unset falls back to the boolean.\n *\n * Callers only. Receivers continue an incoming trace whenever `enableRpcTracePropagation` is on,\n * so they have nothing to match against.\n */\nexport function createRpcPropagationResolver(options: CloudflareOptions | undefined): (bindingName: string) => boolean {\n const bindings = options?.rpcTracePropagationBindings;\n\n if (bindings === undefined) {\n return options && getEffectiveRpcPropagation(options) ? PROPAGATE_TO_ALL : PROPAGATE_TO_NONE;\n }\n\n if (!bindings.length) {\n return PROPAGATE_TO_NONE;\n }\n\n // Strings must match a binding name exactly, without this, an entry of `DB` would also enable\n // propagation for a binding named `MY_DB`. Regular expressions still give pattern matching.\n return (bindingName: string) => stringMatchesSomePattern(bindingName, bindings, true);\n}\n"],"names":[],"mappings":";;;AAIA,MAAM,oBAAoB,MAAe,KAAA;AACzC,MAAM,mBAAmB,MAAe,IAAA;AAcjC,SAAS,6BAA6B,OAAA,EAA0E;AACrH,EAAA,MAAM,WAAW,OAAA,EAAS,2BAAA;AAE1B,EAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,IAAA,OAAO,OAAA,IAAW,0BAAA,CAA2B,OAAO,CAAA,GAAI,gBAAA,GAAmB,iBAAA;AAAA,EAC7E;AAEA,EAAA,IAAI,CAAC,SAAS,MAAA,EAAQ;AACpB,IAAA,OAAO,iBAAA;AAAA,EACT;AAIA,EAAA,OAAO,CAAC,WAAA,KAAwB,wBAAA,CAAyB,WAAA,EAAa,UAAU,IAAI,CAAA;AACtF;;;;"}
|
|
@@ -74,7 +74,8 @@ function sentryCloudflareAutoInstrumentPlugin(options = {}) {
|
|
|
74
74
|
classWrappers,
|
|
75
75
|
agentClasses,
|
|
76
76
|
optionsFn,
|
|
77
|
-
optionsImport
|
|
77
|
+
optionsImport,
|
|
78
|
+
sameWorkerBindings: wranglerConfig.sameWorkerBindings
|
|
78
79
|
});
|
|
79
80
|
const wrappedClasses = result?.wrappedClasses ?? /* @__PURE__ */ new Set();
|
|
80
81
|
const missing = [...classWrappers.keys()].filter((name) => !wrappedClasses.has(name));
|