@sentry/cloudflare 10.72.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/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/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/package.json +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-ts3.8/instrumentations/instrumentDurableObjectHandlers.d.ts +28 -0
- package/package.json +3 -3
|
@@ -3,9 +3,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3
3
|
const core = require('@sentry/core');
|
|
4
4
|
const async = require('./async.js');
|
|
5
5
|
const instrument = require('./instrument.js');
|
|
6
|
+
const instrumentDurableObjectHandlers = require('./instrumentations/instrumentDurableObjectHandlers.js');
|
|
6
7
|
const instrumentEnv = require('./instrumentations/worker/instrumentEnv.js');
|
|
7
8
|
const options = require('./options.js');
|
|
8
|
-
const request = require('./request.js');
|
|
9
9
|
const instrumentContext = require('./utils/instrumentContext.js');
|
|
10
10
|
const rpcMeta = require('./utils/rpcMeta.js');
|
|
11
11
|
const rpcOptions = require('./utils/rpcOptions.js');
|
|
@@ -27,7 +27,7 @@ function constructInstrumentedDurableObject(target, ctx, env, newTarget, options
|
|
|
27
27
|
methodsBeforeConstruction,
|
|
28
28
|
cachedFrameworkManagedMethods
|
|
29
29
|
);
|
|
30
|
-
instrumentDurableObjectHandlers(obj, options$1, context);
|
|
30
|
+
instrumentDurableObjectHandlers.instrumentDurableObjectHandlers(obj, options$1, context);
|
|
31
31
|
return { obj, options: options$1, context, frameworkManagedMethods };
|
|
32
32
|
}
|
|
33
33
|
const frameworkManagedMethodsCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -61,57 +61,6 @@ function resolveFrameworkManagedMethods(prototype, obj, methodsBeforeConstructio
|
|
|
61
61
|
frameworkManagedMethodsCache.set(prototype, managed);
|
|
62
62
|
return managed;
|
|
63
63
|
}
|
|
64
|
-
function instrumentDurableObjectHandlers(obj, options, context) {
|
|
65
|
-
if (obj.fetch && typeof obj.fetch === "function") {
|
|
66
|
-
obj.fetch = instrument.ensureInstrumented(
|
|
67
|
-
obj.fetch.bind(obj),
|
|
68
|
-
(original) => new Proxy(original, {
|
|
69
|
-
apply(target, thisArg, args) {
|
|
70
|
-
return request.wrapRequestHandler({ options, request: args[0], context }, () => {
|
|
71
|
-
return Reflect.apply(target, thisArg, args);
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
if (obj.alarm && typeof obj.alarm === "function") {
|
|
78
|
-
obj.alarm = wrapMethodWithSentry.wrapMethodWithSentry(
|
|
79
|
-
{
|
|
80
|
-
options,
|
|
81
|
-
context,
|
|
82
|
-
spanName: "alarm",
|
|
83
|
-
spanOp: "function",
|
|
84
|
-
startNewTrace: true,
|
|
85
|
-
origin: "auto.faas.cloudflare.durable_object"
|
|
86
|
-
},
|
|
87
|
-
obj.alarm.bind(obj)
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
if (obj.webSocketMessage && typeof obj.webSocketMessage === "function") {
|
|
91
|
-
obj.webSocketMessage = wrapMethodWithSentry.wrapMethodWithSentry(
|
|
92
|
-
{ options, context, spanName: "webSocketMessage", origin: "auto.faas.cloudflare.durable_object" },
|
|
93
|
-
obj.webSocketMessage.bind(obj)
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
if (obj.webSocketClose && typeof obj.webSocketClose === "function") {
|
|
97
|
-
obj.webSocketClose = wrapMethodWithSentry.wrapMethodWithSentry(
|
|
98
|
-
{ options, context, spanName: "webSocketClose", origin: "auto.faas.cloudflare.durable_object" },
|
|
99
|
-
obj.webSocketClose.bind(obj)
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
if (obj.webSocketError && typeof obj.webSocketError === "function") {
|
|
103
|
-
obj.webSocketError = wrapMethodWithSentry.wrapMethodWithSentry(
|
|
104
|
-
{ options, context, spanName: "webSocketError", origin: "auto.faas.cloudflare.durable_object" },
|
|
105
|
-
obj.webSocketError.bind(obj),
|
|
106
|
-
(_, error) => core.captureException(error, {
|
|
107
|
-
mechanism: {
|
|
108
|
-
type: "auto.faas.cloudflare.durable_object_websocket",
|
|
109
|
-
handled: false
|
|
110
|
-
}
|
|
111
|
-
})
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
64
|
const RESERVED_RPC_METHOD_NAMES = /* @__PURE__ */ new Set([
|
|
116
65
|
"constructor",
|
|
117
66
|
"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 // 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":["setAsyncLocalStorageAsyncContextStrategy","options","getFinalOptions","instrumentContext","instrumentEnv","ensureInstrumented","wrapRequestHandler","wrapMethodWithSentry","captureException","getEffectiveRpcPropagation","getInstrumented","markAsInstrumented","isObjectLike","hasRpcMeta","instrumentCloudflareAgent"],"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":["setAsyncLocalStorageAsyncContextStrategy","options","getFinalOptions","instrumentContext","instrumentEnv","instrumentDurableObjectHandlers","getEffectiveRpcPropagation","getInstrumented","markAsInstrumented","isObjectLike","hasRpcMeta","wrapMethodWithSentry","instrumentCloudflareAgent"],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const core = require('@sentry/core');
|
|
4
|
+
const debugBuild = require('../debug-build.js');
|
|
5
|
+
const instrument = require('../instrument.js');
|
|
6
|
+
const request = require('../request.js');
|
|
7
|
+
const wrapMethodWithSentry = require('../wrapMethodWithSentry.js');
|
|
8
|
+
|
|
9
|
+
function instrumentDurableObjectHandlers(obj, options, context) {
|
|
10
|
+
if (obj.fetch && typeof obj.fetch === "function") {
|
|
11
|
+
setInstanceHandler(
|
|
12
|
+
obj,
|
|
13
|
+
"fetch",
|
|
14
|
+
instrument.ensureInstrumented(
|
|
15
|
+
obj.fetch.bind(obj),
|
|
16
|
+
(original) => new Proxy(original, {
|
|
17
|
+
apply(target, thisArg, args) {
|
|
18
|
+
return request.wrapRequestHandler({ options, request: args[0], context }, () => {
|
|
19
|
+
return Reflect.apply(target, thisArg, args);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
)
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
if (obj.alarm && typeof obj.alarm === "function") {
|
|
27
|
+
setInstanceHandler(
|
|
28
|
+
obj,
|
|
29
|
+
"alarm",
|
|
30
|
+
wrapMethodWithSentry.wrapMethodWithSentry(
|
|
31
|
+
{
|
|
32
|
+
options,
|
|
33
|
+
context,
|
|
34
|
+
spanName: "alarm",
|
|
35
|
+
spanOp: "function",
|
|
36
|
+
startNewTrace: true,
|
|
37
|
+
origin: "auto.faas.cloudflare.durable_object"
|
|
38
|
+
},
|
|
39
|
+
obj.alarm.bind(obj)
|
|
40
|
+
)
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
if (obj.webSocketMessage && typeof obj.webSocketMessage === "function") {
|
|
44
|
+
setInstanceHandler(
|
|
45
|
+
obj,
|
|
46
|
+
"webSocketMessage",
|
|
47
|
+
wrapMethodWithSentry.wrapMethodWithSentry(
|
|
48
|
+
{
|
|
49
|
+
options,
|
|
50
|
+
context,
|
|
51
|
+
spanName: "webSocketMessage",
|
|
52
|
+
origin: "auto.faas.cloudflare.durable_object"
|
|
53
|
+
},
|
|
54
|
+
obj.webSocketMessage.bind(obj)
|
|
55
|
+
)
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
if (obj.webSocketClose && typeof obj.webSocketClose === "function") {
|
|
59
|
+
setInstanceHandler(
|
|
60
|
+
obj,
|
|
61
|
+
"webSocketClose",
|
|
62
|
+
wrapMethodWithSentry.wrapMethodWithSentry(
|
|
63
|
+
{
|
|
64
|
+
options,
|
|
65
|
+
context,
|
|
66
|
+
spanName: "webSocketClose",
|
|
67
|
+
origin: "auto.faas.cloudflare.durable_object"
|
|
68
|
+
},
|
|
69
|
+
obj.webSocketClose.bind(obj)
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
if (obj.webSocketError && typeof obj.webSocketError === "function") {
|
|
74
|
+
setInstanceHandler(
|
|
75
|
+
obj,
|
|
76
|
+
"webSocketError",
|
|
77
|
+
wrapMethodWithSentry.wrapMethodWithSentry(
|
|
78
|
+
{
|
|
79
|
+
options,
|
|
80
|
+
context,
|
|
81
|
+
spanName: "webSocketError",
|
|
82
|
+
origin: "auto.faas.cloudflare.durable_object"
|
|
83
|
+
},
|
|
84
|
+
obj.webSocketError.bind(obj),
|
|
85
|
+
(_, error) => core.captureException(error, {
|
|
86
|
+
mechanism: {
|
|
87
|
+
type: "auto.faas.cloudflare.durable_object_websocket",
|
|
88
|
+
handled: false
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
)
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function setInstanceHandler(obj, name, handler) {
|
|
96
|
+
const descriptor = Object.getOwnPropertyDescriptor(obj, name);
|
|
97
|
+
try {
|
|
98
|
+
if (descriptor?.writable === false) {
|
|
99
|
+
Object.defineProperty(obj, name, {
|
|
100
|
+
value: handler,
|
|
101
|
+
writable: true,
|
|
102
|
+
enumerable: descriptor.enumerable,
|
|
103
|
+
configurable: descriptor.configurable
|
|
104
|
+
});
|
|
105
|
+
} else {
|
|
106
|
+
obj[name] = handler;
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
debugBuild.DEBUG_BUILD && core.debug.warn(`Failed to instrument Durable Object handler "${name}"`, error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
exports.instrumentDurableObjectHandlers = instrumentDurableObjectHandlers;
|
|
114
|
+
//# 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":["ensureInstrumented","wrapRequestHandler","wrapMethodWithSentry","captureException","DEBUG_BUILD","debug"],"mappings":"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"}
|
|
@@ -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 // 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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"}
|
|
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":";;;;;;AAkCO,SAAS,+BAAA,CACd,GAAA,EACA,OAAA,EACA,OAAA,EACM;AAGN,EAAA,IAAI,GAAA,CAAI,KAAA,IAAS,OAAO,GAAA,CAAI,UAAU,UAAA,EAAY;AAChD,IAAA,kBAAA;AAAA,MACE,GAAA;AAAA,MACA,OAAA;AAAA,MACA,kBAAA;AAAA,QACE,GAAA,CAAI,KAAA,CAAM,IAAA,CAAK,GAAG,CAAA;AAAA,QAClB,CAAA,QAAA,KACE,IAAI,KAAA,CAAM,QAAA,EAAU;AAAA,UAClB,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM;AAC3B,YAAA,OAAO,kBAAA,CAAmB,EAAE,OAAA,EAAS,OAAA,EAAS,KAAK,CAAC,CAAA,EAAG,OAAA,EAAQ,EAAG,MAAM;AACtE,cAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAAA,YAC5C,CAAC,CAAA;AAAA,UACH;AAAA,SACD;AAAA;AACL,KACF;AAAA,EACF;AAEA,EAAA,IAAI,GAAA,CAAI,KAAA,IAAS,OAAO,GAAA,CAAI,UAAU,UAAA,EAAY;AAEhD,IAAA,kBAAA;AAAA,MACE,GAAA;AAAA,MACA,OAAA;AAAA,MACA,oBAAA;AAAA,QACE;AAAA,UACE,OAAA;AAAA,UACA,OAAA;AAAA,UACA,QAAA,EAAU,OAAA;AAAA,UACV,MAAA,EAAQ,UAAA;AAAA,UACR,aAAA,EAAe,IAAA;AAAA,UACf,MAAA,EAAQ;AAAA,SACV;AAAA,QACA,GAAA,CAAI,KAAA,CAAM,IAAA,CAAK,GAAG;AAAA;AACpB,KACF;AAAA,EACF;AAEA,EAAA,IAAI,GAAA,CAAI,gBAAA,IAAoB,OAAO,GAAA,CAAI,qBAAqB,UAAA,EAAY;AACtE,IAAA,kBAAA;AAAA,MACE,GAAA;AAAA,MACA,kBAAA;AAAA,MACA,oBAAA;AAAA,QACE;AAAA,UACE,OAAA;AAAA,UACA,OAAA;AAAA,UACA,QAAA,EAAU,kBAAA;AAAA,UACV,MAAA,EAAQ;AAAA,SACV;AAAA,QACA,GAAA,CAAI,gBAAA,CAAiB,IAAA,CAAK,GAAG;AAAA;AAC/B,KACF;AAAA,EACF;AAEA,EAAA,IAAI,GAAA,CAAI,cAAA,IAAkB,OAAO,GAAA,CAAI,mBAAmB,UAAA,EAAY;AAClE,IAAA,kBAAA;AAAA,MACE,GAAA;AAAA,MACA,gBAAA;AAAA,MACA,oBAAA;AAAA,QACE;AAAA,UACE,OAAA;AAAA,UACA,OAAA;AAAA,UACA,QAAA,EAAU,gBAAA;AAAA,UACV,MAAA,EAAQ;AAAA,SACV;AAAA,QACA,GAAA,CAAI,cAAA,CAAe,IAAA,CAAK,GAAG;AAAA;AAC7B,KACF;AAAA,EACF;AAEA,EAAA,IAAI,GAAA,CAAI,cAAA,IAAkB,OAAO,GAAA,CAAI,mBAAmB,UAAA,EAAY;AAClE,IAAA,kBAAA;AAAA,MACE,GAAA;AAAA,MACA,gBAAA;AAAA,MACA,oBAAA;AAAA,QACE;AAAA,UACE,OAAA;AAAA,UACA,OAAA;AAAA,UACA,QAAA,EAAU,gBAAA;AAAA,UACV,MAAA,EAAQ;AAAA,SACV;AAAA,QACA,GAAA,CAAI,cAAA,CAAe,IAAA,CAAK,GAAG,CAAA;AAAA,QAC3B,CAAC,CAAA,EAAG,KAAA,KACF,gBAAA,CAAiB,KAAA,EAAO;AAAA,UACtB,SAAA,EAAW;AAAA,YACT,IAAA,EAAM,+CAAA;AAAA,YACN,OAAA,EAAS;AAAA;AACX,SACD;AAAA;AACL,KACF;AAAA,EACF;AACF;AAWA,SAAS,kBAAA,CAAmB,GAAA,EAAa,IAAA,EAAc,OAAA,EAAwB;AAC7E,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,wBAAA,CAAyB,GAAA,EAAK,IAAI,CAAA;AAE5D,EAAA,IAAI;AACF,IAAA,IAAI,UAAA,EAAY,aAAa,KAAA,EAAO;AAClC,MAAA,MAAA,CAAO,cAAA,CAAe,KAAK,IAAA,EAAM;AAAA,QAC/B,KAAA,EAAO,OAAA;AAAA,QACP,QAAA,EAAU,IAAA;AAAA,QACV,YAAY,UAAA,CAAW,UAAA;AAAA,QACvB,cAAc,UAAA,CAAW;AAAA,OAC1B,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAC,GAAA,CAAgC,IAAI,CAAA,GAAI,OAAA;AAAA,IAC3C;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAA,WAAA,IAAe,KAAA,CAAM,IAAA,CAAK,CAAA,6CAAA,EAAgD,IAAI,KAAK,KAAK,CAAA;AAAA,EAC1F;AACF;;;;"}
|
package/build/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"10.
|
|
1
|
+
{"type":"module","version":"10.73.0","sideEffects":false}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durableobject.d.ts","sourceRoot":"","sources":["../../src/durableobject.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAWlD;;;;;;;;;;GAUG;AAEH,KAAK,gCAAgC,GAAG,GAAG,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,wBAAgB,kCAAkC,CAAC,CAAC,EAAE,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,EAC9E,MAAM,EAAE,KAAK,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EACpD,GAAG,EAAE,kBAAkB,EACvB,GAAG,EAAE,CAAC,EACN,SAAS,EAAE,eAAe,EAC1B,eAAe,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,iBAAiB,GAC7C;IACD,GAAG,EAAE,CAAC,CAAC;IACP,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,gCAAgC,CAAC;IAC1C,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC9C,CA4BA;
|
|
1
|
+
{"version":3,"file":"durableobject.d.ts","sourceRoot":"","sources":["../../src/durableobject.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAWlD;;;;;;;;;;GAUG;AAEH,KAAK,gCAAgC,GAAG,GAAG,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,wBAAgB,kCAAkC,CAAC,CAAC,EAAE,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,EAC9E,MAAM,EAAE,KAAK,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EACpD,GAAG,EAAE,kBAAkB,EACvB,GAAG,EAAE,CAAC,EACN,SAAS,EAAE,eAAe,EAC1B,eAAe,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,iBAAiB,GAC7C;IACD,GAAG,EAAE,CAAC,CAAC;IACP,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,gCAAgC,CAAC;IAC1C,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC9C,CA4BA;AA+FD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,8BAA8B,CAAC,CAAC,SAAS,MAAM,EAC7D,GAAG,EAAE,CAAC,EACN,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,gCAAgC,EACzC,eAAe,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GACpC,CAAC,CA2BH;AAqHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,iCAAiC,CAC/C,CAAC,EACD,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,EAC1B,CAAC,SAAS,KAAK,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EACtD,eAAe,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,iBAAiB,EAAE,kBAAkB,EAAE,CAAC,GAAG,CAAC,CAc1E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,yBAAyB,CACvC,CAAC,EACD,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,EAC1B,CAAC,SAAS,KAAK,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,EACtD,eAAe,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,iBAAiB,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,CAoBlE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { DurableObject } from 'cloudflare:workers';
|
|
2
|
+
import type { CloudflareOptions } from '../client';
|
|
3
|
+
/**
|
|
4
|
+
* The instrumented context of the Durable Object being wrapped.
|
|
5
|
+
*
|
|
6
|
+
* Kept as `any` for the same reason as in `durableobject.ts`: a concrete `DurableObjectState` here
|
|
7
|
+
* makes `tsc` relate its `SqlStorage` graph against the parameter union of `wrapMethodWithSentry`,
|
|
8
|
+
* which hangs the type build.
|
|
9
|
+
*/
|
|
10
|
+
type InstrumentedDurableObjectContext = any;
|
|
11
|
+
/**
|
|
12
|
+
* Instruments the built-in Durable Object handler methods on a constructed instance.
|
|
13
|
+
*
|
|
14
|
+
* These are the methods that are available on a Durable Object
|
|
15
|
+
* ref: https://developers.cloudflare.com/durable-objects/api/base/
|
|
16
|
+
* - obj.alarm
|
|
17
|
+
* - obj.fetch
|
|
18
|
+
* - obj.webSocketError
|
|
19
|
+
* - obj.webSocketClose
|
|
20
|
+
* - obj.webSocketMessage
|
|
21
|
+
*
|
|
22
|
+
* Any other public methods on the Durable Object instance are RPC calls.
|
|
23
|
+
*
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
export declare function instrumentDurableObjectHandlers<E, T extends DurableObject<E>>(obj: T, options: CloudflareOptions, context: InstrumentedDurableObjectContext): void;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=instrumentDurableObjectHandlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrumentDurableObjectHandlers.d.ts","sourceRoot":"","sources":["../../../src/instrumentations/instrumentDurableObjectHandlers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAMnD;;;;;;GAMG;AAEH,KAAK,gCAAgC,GAAG,GAAG,CAAC;AAE5C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,+BAA+B,CAAC,CAAC,EAAE,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,EAC3E,GAAG,EAAE,CAAC,EACN,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,gCAAgC,GACxC,IAAI,CA8FN"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DurableObject } from 'cloudflare:workers';
|
|
2
|
+
import { CloudflareOptions } from '../client';
|
|
3
|
+
/**
|
|
4
|
+
* The instrumented context of the Durable Object being wrapped.
|
|
5
|
+
*
|
|
6
|
+
* Kept as `any` for the same reason as in `durableobject.ts`: a concrete `DurableObjectState` here
|
|
7
|
+
* makes `tsc` relate its `SqlStorage` graph against the parameter union of `wrapMethodWithSentry`,
|
|
8
|
+
* which hangs the type build.
|
|
9
|
+
*/
|
|
10
|
+
type InstrumentedDurableObjectContext = any;
|
|
11
|
+
/**
|
|
12
|
+
* Instruments the built-in Durable Object handler methods on a constructed instance.
|
|
13
|
+
*
|
|
14
|
+
* These are the methods that are available on a Durable Object
|
|
15
|
+
* ref: https://developers.cloudflare.com/durable-objects/api/base/
|
|
16
|
+
* - obj.alarm
|
|
17
|
+
* - obj.fetch
|
|
18
|
+
* - obj.webSocketError
|
|
19
|
+
* - obj.webSocketClose
|
|
20
|
+
* - obj.webSocketMessage
|
|
21
|
+
*
|
|
22
|
+
* Any other public methods on the Durable Object instance are RPC calls.
|
|
23
|
+
*
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
export declare function instrumentDurableObjectHandlers<E, T extends DurableObject<E>>(obj: T, options: CloudflareOptions, context: InstrumentedDurableObjectContext): void;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=instrumentDurableObjectHandlers.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/cloudflare",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.73.0",
|
|
4
4
|
"description": "Official Sentry SDK for Cloudflare Workers and Pages",
|
|
5
5
|
"repository": "git://github.com/getsentry/sentry-javascript.git",
|
|
6
6
|
"homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/cloudflare",
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@opentelemetry/api": "^1.9.1",
|
|
73
|
-
"@sentry/core": "10.
|
|
74
|
-
"@sentry/server-utils": "10.
|
|
73
|
+
"@sentry/core": "10.73.0",
|
|
74
|
+
"@sentry/server-utils": "10.73.0",
|
|
75
75
|
"magic-string": "~0.30.21"
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|