@sentry/cloudflare 10.50.0-alpha.0 → 10.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/durableobject.js +68 -130
- package/build/cjs/durableobject.js.map +1 -1
- package/build/cjs/index.js +1 -0
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/instrumentations/instrumentDurableObjectNamespace.js +14 -4
- package/build/cjs/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
- package/build/cjs/instrumentations/worker/instrumentEnv.js +8 -3
- package/build/cjs/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/cjs/request.js +25 -29
- package/build/cjs/request.js.map +1 -1
- package/build/cjs/utils/rpcMeta.js +60 -0
- package/build/cjs/utils/rpcMeta.js.map +1 -0
- package/build/cjs/utils/rpcOptions.js +1 -36
- package/build/cjs/utils/rpcOptions.js.map +1 -1
- package/build/cjs/wrapMethodWithSentry.js +21 -1
- package/build/cjs/wrapMethodWithSentry.js.map +1 -1
- package/build/esm/durableobject.js +70 -132
- package/build/esm/durableobject.js.map +1 -1
- package/build/esm/index.js +1 -1
- package/build/esm/instrumentations/instrumentDurableObjectNamespace.js +14 -5
- package/build/esm/instrumentations/instrumentDurableObjectNamespace.js.map +1 -1
- package/build/esm/instrumentations/worker/instrumentEnv.js +9 -4
- package/build/esm/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/request.js +25 -29
- package/build/esm/request.js.map +1 -1
- package/build/esm/utils/rpcMeta.js +57 -0
- package/build/esm/utils/rpcMeta.js.map +1 -0
- package/build/esm/utils/rpcOptions.js +2 -36
- package/build/esm/utils/rpcOptions.js.map +1 -1
- package/build/esm/wrapMethodWithSentry.js +22 -2
- package/build/esm/wrapMethodWithSentry.js.map +1 -1
- package/build/types/durableobject.d.ts +2 -2
- package/build/types/durableobject.d.ts.map +1 -1
- package/build/types/index.d.ts +1 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts +1 -0
- package/build/types/instrumentations/instrumentDurableObjectNamespace.d.ts.map +1 -1
- package/build/types/instrumentations/worker/instrumentEnv.d.ts.map +1 -1
- package/build/types/request.d.ts.map +1 -1
- package/build/types/utils/rpcMeta.d.ts +15 -0
- package/build/types/utils/rpcMeta.d.ts.map +1 -0
- package/build/types/utils/rpcOptions.d.ts +1 -12
- package/build/types/utils/rpcOptions.d.ts.map +1 -1
- package/build/types/wrapMethodWithSentry.d.ts.map +1 -1
- package/build/types-ts3.8/durableobject.d.ts +2 -2
- package/build/types-ts3.8/index.d.ts +1 -1
- package/build/types-ts3.8/instrumentations/instrumentDurableObjectNamespace.d.ts +1 -0
- package/build/types-ts3.8/utils/rpcMeta.d.ts +15 -0
- package/build/types-ts3.8/utils/rpcOptions.d.ts +1 -12
- package/package.json +2 -2
|
@@ -8,7 +8,7 @@ const debugBuild = require('../debug-build.js');
|
|
|
8
8
|
*
|
|
9
9
|
* Priority:
|
|
10
10
|
* 1. If `enableRpcTracePropagation` is set, use it (ignore `instrumentPrototypeMethods`)
|
|
11
|
-
* 2. If only `instrumentPrototypeMethods` is set, use it with deprecation warning
|
|
11
|
+
* 2. If only `instrumentPrototypeMethods` is set, use it with deprecation warning
|
|
12
12
|
* 3. If neither is set, return `false`
|
|
13
13
|
*
|
|
14
14
|
* @returns The effective setting for RPC trace propagation
|
|
@@ -45,40 +45,5 @@ function getEffectiveRpcPropagation(options) {
|
|
|
45
45
|
return false;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
/**
|
|
49
|
-
* Gets the method filter for prototype method instrumentation.
|
|
50
|
-
*
|
|
51
|
-
* Returns:
|
|
52
|
-
* - `null` if no instrumentation should occur
|
|
53
|
-
* - `true` if all methods should be instrumented
|
|
54
|
-
* - `string[]` if only specific methods should be instrumented (deprecated behavior)
|
|
55
|
-
*
|
|
56
|
-
* @returns The method filter or null if no instrumentation
|
|
57
|
-
*/
|
|
58
|
-
function getPrototypeMethodFilter(options) {
|
|
59
|
-
const { enableRpcTracePropagation, instrumentPrototypeMethods } = options;
|
|
60
|
-
|
|
61
|
-
// If the new option is explicitly set, use it (boolean only, no filtering)
|
|
62
|
-
if (enableRpcTracePropagation !== undefined) {
|
|
63
|
-
return !!enableRpcTracePropagation;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Fall back to deprecated option - preserve array filtering behavior
|
|
67
|
-
if (instrumentPrototypeMethods !== undefined) {
|
|
68
|
-
if (instrumentPrototypeMethods === true) {
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (Array.isArray(instrumentPrototypeMethods) && instrumentPrototypeMethods.length > 0) {
|
|
73
|
-
return instrumentPrototypeMethods;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
48
|
exports.getEffectiveRpcPropagation = getEffectiveRpcPropagation;
|
|
83
|
-
exports.getPrototypeMethodFilter = getPrototypeMethodFilter;
|
|
84
49
|
//# sourceMappingURL=rpcOptions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpcOptions.js","sources":["../../../src/utils/rpcOptions.ts"],"sourcesContent":["import { debug } from '@sentry/core';\nimport type { CloudflareOptions } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\n\n/**\n * Gets the effective RPC propagation setting, handling deprecation of `instrumentPrototypeMethods`.\n *\n * Priority:\n * 1. If `enableRpcTracePropagation` is set, use it (ignore `instrumentPrototypeMethods`)\n * 2. If only `instrumentPrototypeMethods` is set, use it with deprecation warning
|
|
1
|
+
{"version":3,"file":"rpcOptions.js","sources":["../../../src/utils/rpcOptions.ts"],"sourcesContent":["import { debug } from '@sentry/core';\nimport type { CloudflareOptions } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\n\n/**\n * Gets the effective RPC propagation setting, handling deprecation of `instrumentPrototypeMethods`.\n *\n * Priority:\n * 1. If `enableRpcTracePropagation` is set, use it (ignore `instrumentPrototypeMethods`)\n * 2. If only `instrumentPrototypeMethods` is set, use it with deprecation warning\n * 3. If neither is set, return `false`\n *\n * @returns The effective setting for RPC trace propagation\n */\nexport function getEffectiveRpcPropagation(options: CloudflareOptions): boolean {\n const { enableRpcTracePropagation, instrumentPrototypeMethods } = options;\n\n // If the new option is explicitly set, use it\n if (enableRpcTracePropagation !== undefined) {\n if (instrumentPrototypeMethods !== undefined) {\n DEBUG_BUILD &&\n debug.warn(\n '[Sentry] Both `enableRpcTracePropagation` and `instrumentPrototypeMethods` are set. ' +\n 'Using `enableRpcTracePropagation` and ignoring `instrumentPrototypeMethods`.',\n );\n }\n return enableRpcTracePropagation;\n }\n\n // Fall back to deprecated option with warning\n if (instrumentPrototypeMethods !== undefined) {\n DEBUG_BUILD &&\n debug.warn(\n '[Sentry] `instrumentPrototypeMethods` is deprecated and will be removed in a future major version. ' +\n 'Please use `enableRpcTracePropagation` instead.',\n );\n // instrumentPrototypeMethods can be boolean or string[], convert to boolean\n return (\n instrumentPrototypeMethods === true ||\n (Array.isArray(instrumentPrototypeMethods) && instrumentPrototypeMethods.length > 0)\n );\n }\n\n return false;\n}\n"],"names":["DEBUG_BUILD","debug"],"mappings":";;;;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,0BAA0B,CAAC,OAAO,EAA8B;AAChF,EAAE,MAAM,EAAE,yBAAyB,EAAE,0BAAA,EAA2B,GAAI,OAAO;;AAE3E;AACA,EAAE,IAAI,yBAAA,KAA8B,SAAS,EAAE;AAC/C,IAAI,IAAI,0BAAA,KAA+B,SAAS,EAAE;AAClD,MAAMA,sBAAA;AACN,QAAQC,UAAK,CAAC,IAAI;AAClB,UAAU,sFAAA;AACV,YAAY,8EAA8E;AAC1F,SAAS;AACT,IAAI;AACJ,IAAI,OAAO,yBAAyB;AACpC,EAAE;;AAEF;AACA,EAAE,IAAI,0BAAA,KAA+B,SAAS,EAAE;AAChD,IAAID,sBAAA;AACJ,MAAMC,UAAK,CAAC,IAAI;AAChB,QAAQ,qGAAA;AACR,UAAU,iDAAiD;AAC3D,OAAO;AACP;AACA,IAAI;AACJ,MAAM,0BAAA,KAA+B,IAAA;AACrC,OAAO,KAAK,CAAC,OAAO,CAAC,0BAA0B,CAAA,IAAK,0BAA0B,CAAC,MAAA,GAAS,CAAC;AACzF;AACA,EAAE;;AAEF,EAAE,OAAO,KAAK;AACd;;;;"}
|
|
@@ -4,6 +4,7 @@ const core = require('@sentry/core');
|
|
|
4
4
|
const flush = require('./flush.js');
|
|
5
5
|
const instrument = require('./instrument.js');
|
|
6
6
|
const sdk = require('./sdk.js');
|
|
7
|
+
const rpcMeta = require('./utils/rpcMeta.js');
|
|
7
8
|
const traceLinks = require('./utils/traceLinks.js');
|
|
8
9
|
|
|
9
10
|
/** Extended DurableObjectState with originalStorage exposed by instrumentContext */
|
|
@@ -28,9 +29,21 @@ function wrapMethodWithSentry(
|
|
|
28
29
|
handler,
|
|
29
30
|
original =>
|
|
30
31
|
new Proxy(original, {
|
|
31
|
-
apply(target, thisArg,
|
|
32
|
+
apply(target, thisArg, rawArgs) {
|
|
32
33
|
const { startNewTrace } = wrapperOptions;
|
|
33
34
|
|
|
35
|
+
// For RPC methods, extract Sentry trace context from the trailing argument.
|
|
36
|
+
// The caller side (instrumentDurableObjectStub / JSRPC proxy) appends it;
|
|
37
|
+
// we strip it here so the user's method never sees it.
|
|
38
|
+
let args = rawArgs;
|
|
39
|
+
let rpcMeta$1;
|
|
40
|
+
|
|
41
|
+
if (wrapperOptions.spanOp === 'rpc') {
|
|
42
|
+
const extracted = rpcMeta.extractRpcMeta(rawArgs);
|
|
43
|
+
args = extracted.args;
|
|
44
|
+
rpcMeta$1 = extracted.rpcMeta;
|
|
45
|
+
}
|
|
46
|
+
|
|
34
47
|
// For startNewTrace, always use withIsolationScope to ensure a fresh scope
|
|
35
48
|
// Otherwise, use existing client's scope or isolation scope
|
|
36
49
|
const currentClient = core.getClient();
|
|
@@ -177,6 +190,13 @@ function wrapMethodWithSentry(
|
|
|
177
190
|
});
|
|
178
191
|
};
|
|
179
192
|
|
|
193
|
+
if (rpcMeta$1) {
|
|
194
|
+
return core.continueTrace(
|
|
195
|
+
{ sentryTrace: rpcMeta$1['sentry-trace'] || '', baggage: rpcMeta$1.baggage || '' },
|
|
196
|
+
executeSpan,
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
180
200
|
if (startNewTrace) {
|
|
181
201
|
return core.startNewTrace(() => executeSpan());
|
|
182
202
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapMethodWithSentry.js","sources":["../../src/wrapMethodWithSentry.ts"],"sourcesContent":["import type { DurableObjectStorage } from '@cloudflare/workers-types';\nimport {\n captureException,\n getClient,\n isThenable,\n type Scope,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startNewTrace as startNewTraceCore,\n startSpan,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from './client';\nimport { flushAndDispose } from './flush';\nimport { ensureInstrumented } from './instrument';\nimport { init } from './sdk';\nimport { buildSpanLinks, getStoredSpanContext, storeSpanContext } from './utils/traceLinks';\n\n/** Extended DurableObjectState with originalStorage exposed by instrumentContext */\ninterface InstrumentedDurableObjectState extends DurableObjectState {\n originalStorage?: DurableObjectStorage;\n}\n\ntype MethodWrapperOptions = {\n spanName?: string;\n spanOp?: string;\n options: CloudflareOptions;\n context: ExecutionContext | InstrumentedDurableObjectState;\n /**\n * If true, starts a fresh trace instead of inheriting from a parent trace.\n * Useful for scheduled/independent invocations like alarms.\n *\n * If true, it also stores the current span context and links to the previous invocation's span.\n * Uses Durable Object storage to persist the link. The link is set asynchronously via `span.addLinks()`\n * in a `waitUntil` to avoid blocking.\n *\n * @default false\n */\n startNewTrace?: boolean;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type UncheckedMethod = (...args: any[]) => any;\ntype OriginalMethod = UncheckedMethod;\n\n/**\n * Wraps a method with Sentry error tracking and optional tracing.\n * Supports starting new traces and linking to previous invocations via Durable Object storage.\n *\n * @param wrapperOptions - The options for the wrapper.\n * @param handler - The method to wrap.\n * @param callback - The callback to call.\n * @param noMark - Whether to mark the method as instrumented.\n * @returns The wrapped method.\n */\nexport function wrapMethodWithSentry<T extends OriginalMethod>(\n wrapperOptions: MethodWrapperOptions,\n handler: T,\n callback?: (...args: Parameters<T>) => void,\n noMark?: true,\n): T {\n return ensureInstrumented(\n handler,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args: Parameters<T>) {\n const { startNewTrace } = wrapperOptions;\n\n // For startNewTrace, always use withIsolationScope to ensure a fresh scope\n // Otherwise, use existing client's scope or isolation scope\n const currentClient = getClient();\n const sentryWithScope = startNewTrace ? withIsolationScope : currentClient ? withScope : withIsolationScope;\n\n const wrappedFunction = (scope: Scope): unknown | Promise<unknown> => {\n // In certain situations, the passed context can become undefined.\n // For example, for Astro while prerendering pages at build time.\n // see: https://github.com/getsentry/sentry-javascript/issues/13217\n const context: typeof wrapperOptions.context | undefined = wrapperOptions.context;\n\n const waitUntil = context?.waitUntil?.bind?.(context);\n const storage = context && 'originalStorage' in context ? context.originalStorage : undefined;\n\n let scopeClient = scope.getClient();\n // Check if client exists AND is still usable (transport not disposed)\n // This handles the case where a previous handler disposed the client\n // but the scope still holds a reference to it (e.g., alarm handlers in Durable Objects)\n // For startNewTrace, always create a fresh client\n if (startNewTrace || !scopeClient?.getTransport()) {\n const client = init({\n ...wrapperOptions.options,\n ctx: context as unknown as ExecutionContext | undefined,\n });\n scope.setClient(client);\n scopeClient = client;\n }\n\n const clientToDispose = scopeClient;\n const methodName = wrapperOptions.spanName || 'unknown';\n\n const teardown = async (): Promise<void> => {\n if (startNewTrace && storage) {\n await storeSpanContext(storage, methodName);\n }\n await flushAndDispose(clientToDispose);\n };\n\n if (!wrapperOptions.spanName) {\n try {\n if (callback) {\n callback(...args);\n }\n\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(\n (res: unknown) => {\n waitUntil?.(teardown());\n return res;\n },\n (e: unknown) => {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(teardown());\n throw e;\n },\n );\n } else {\n waitUntil?.(teardown());\n return result;\n }\n } catch (e) {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(teardown());\n throw e;\n }\n }\n\n const attributes = wrapperOptions.spanOp\n ? {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: wrapperOptions.spanOp,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.durable_object',\n }\n : {};\n\n const executeSpan = (): unknown => {\n return startSpan({ name: methodName, attributes }, span => {\n // When linking to previous trace, fetch the stored context and add links asynchronously\n // This avoids blocking the response while fetching from storage\n if (startNewTrace && storage) {\n waitUntil?.(\n getStoredSpanContext(storage, methodName).then(storedContext => {\n if (storedContext) {\n span.addLinks(buildSpanLinks(storedContext));\n // TODO: Remove this once EAP can store span links. We currently only set this attribute so that we\n // can obtain the previous trace information from the EAP store. Long-term, EAP will handle\n // span links and then we should remove this again. Also throwing in a TODO(v11), to remind us\n // to check this at v11 time :)\n const sampledFlag = storedContext.sampled ? '1' : '0';\n span.setAttribute(\n 'sentry.previous_trace',\n `${storedContext.traceId}-${storedContext.spanId}-${sampledFlag}`,\n );\n }\n }),\n );\n }\n\n try {\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(\n (res: unknown) => {\n waitUntil?.(teardown());\n return res;\n },\n (e: unknown) => {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(teardown());\n throw e;\n },\n );\n } else {\n waitUntil?.(teardown());\n return result;\n }\n } catch (e) {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(teardown());\n throw e;\n }\n });\n };\n\n if (startNewTrace) {\n return startNewTraceCore(() => executeSpan());\n }\n\n return executeSpan();\n };\n\n return sentryWithScope(wrappedFunction);\n },\n }),\n noMark,\n );\n}\n"],"names":["ensureInstrumented","getClient","withIsolationScope","withScope","init","storeSpanContext","flushAndDispose","isThenable","captureException","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","startSpan","getStoredSpanContext","buildSpanLinks","startNewTraceCore"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"wrapMethodWithSentry.js","sources":["../../src/wrapMethodWithSentry.ts"],"sourcesContent":["import type { DurableObjectStorage } from '@cloudflare/workers-types';\nimport type { SerializedTraceData } from '@sentry/core';\nimport {\n captureException,\n continueTrace,\n getClient,\n isThenable,\n type Scope,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startNewTrace as startNewTraceCore,\n startSpan,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport type { CloudflareOptions } from './client';\nimport { flushAndDispose } from './flush';\nimport { ensureInstrumented } from './instrument';\nimport { init } from './sdk';\nimport { extractRpcMeta } from './utils/rpcMeta';\nimport { buildSpanLinks, getStoredSpanContext, storeSpanContext } from './utils/traceLinks';\n\n/** Extended DurableObjectState with originalStorage exposed by instrumentContext */\ninterface InstrumentedDurableObjectState extends DurableObjectState {\n originalStorage?: DurableObjectStorage;\n}\n\ntype MethodWrapperOptions = {\n spanName?: string;\n spanOp?: string;\n options: CloudflareOptions;\n context: ExecutionContext | InstrumentedDurableObjectState;\n /**\n * If true, starts a fresh trace instead of inheriting from a parent trace.\n * Useful for scheduled/independent invocations like alarms.\n *\n * If true, it also stores the current span context and links to the previous invocation's span.\n * Uses Durable Object storage to persist the link. The link is set asynchronously via `span.addLinks()`\n * in a `waitUntil` to avoid blocking.\n *\n * @default false\n */\n startNewTrace?: boolean;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type UncheckedMethod = (...args: any[]) => any;\ntype OriginalMethod = UncheckedMethod;\n\n/**\n * Wraps a method with Sentry error tracking and optional tracing.\n * Supports starting new traces and linking to previous invocations via Durable Object storage.\n *\n * @param wrapperOptions - The options for the wrapper.\n * @param handler - The method to wrap.\n * @param callback - The callback to call.\n * @param noMark - Whether to mark the method as instrumented.\n * @returns The wrapped method.\n */\nexport function wrapMethodWithSentry<T extends OriginalMethod>(\n wrapperOptions: MethodWrapperOptions,\n handler: T,\n callback?: (...args: Parameters<T>) => void,\n noMark?: true,\n): T {\n return ensureInstrumented(\n handler,\n original =>\n new Proxy(original, {\n apply(target, thisArg, rawArgs: Parameters<T>) {\n const { startNewTrace } = wrapperOptions;\n\n // For RPC methods, extract Sentry trace context from the trailing argument.\n // The caller side (instrumentDurableObjectStub / JSRPC proxy) appends it;\n // we strip it here so the user's method never sees it.\n let args = rawArgs;\n let rpcMeta: SerializedTraceData | undefined;\n\n if (wrapperOptions.spanOp === 'rpc') {\n const extracted = extractRpcMeta(rawArgs);\n args = extracted.args;\n rpcMeta = extracted.rpcMeta;\n }\n\n // For startNewTrace, always use withIsolationScope to ensure a fresh scope\n // Otherwise, use existing client's scope or isolation scope\n const currentClient = getClient();\n const sentryWithScope = startNewTrace ? withIsolationScope : currentClient ? withScope : withIsolationScope;\n\n const wrappedFunction = (scope: Scope): unknown | Promise<unknown> => {\n // In certain situations, the passed context can become undefined.\n // For example, for Astro while prerendering pages at build time.\n // see: https://github.com/getsentry/sentry-javascript/issues/13217\n const context: typeof wrapperOptions.context | undefined = wrapperOptions.context;\n\n const waitUntil = context?.waitUntil?.bind?.(context);\n const storage = context && 'originalStorage' in context ? context.originalStorage : undefined;\n\n let scopeClient = scope.getClient();\n // Check if client exists AND is still usable (transport not disposed)\n // This handles the case where a previous handler disposed the client\n // but the scope still holds a reference to it (e.g., alarm handlers in Durable Objects)\n // For startNewTrace, always create a fresh client\n if (startNewTrace || !scopeClient?.getTransport()) {\n const client = init({\n ...wrapperOptions.options,\n ctx: context as unknown as ExecutionContext | undefined,\n });\n scope.setClient(client);\n scopeClient = client;\n }\n\n const clientToDispose = scopeClient;\n const methodName = wrapperOptions.spanName || 'unknown';\n\n const teardown = async (): Promise<void> => {\n if (startNewTrace && storage) {\n await storeSpanContext(storage, methodName);\n }\n await flushAndDispose(clientToDispose);\n };\n\n if (!wrapperOptions.spanName) {\n try {\n if (callback) {\n callback(...args);\n }\n\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(\n (res: unknown) => {\n waitUntil?.(teardown());\n return res;\n },\n (e: unknown) => {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(teardown());\n throw e;\n },\n );\n } else {\n waitUntil?.(teardown());\n return result;\n }\n } catch (e) {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(teardown());\n throw e;\n }\n }\n\n const attributes = wrapperOptions.spanOp\n ? {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: wrapperOptions.spanOp,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.durable_object',\n }\n : {};\n\n const executeSpan = (): unknown => {\n return startSpan({ name: methodName, attributes }, span => {\n // When linking to previous trace, fetch the stored context and add links asynchronously\n // This avoids blocking the response while fetching from storage\n if (startNewTrace && storage) {\n waitUntil?.(\n getStoredSpanContext(storage, methodName).then(storedContext => {\n if (storedContext) {\n span.addLinks(buildSpanLinks(storedContext));\n // TODO: Remove this once EAP can store span links. We currently only set this attribute so that we\n // can obtain the previous trace information from the EAP store. Long-term, EAP will handle\n // span links and then we should remove this again. Also throwing in a TODO(v11), to remind us\n // to check this at v11 time :)\n const sampledFlag = storedContext.sampled ? '1' : '0';\n span.setAttribute(\n 'sentry.previous_trace',\n `${storedContext.traceId}-${storedContext.spanId}-${sampledFlag}`,\n );\n }\n }),\n );\n }\n\n try {\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(\n (res: unknown) => {\n waitUntil?.(teardown());\n return res;\n },\n (e: unknown) => {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(teardown());\n throw e;\n },\n );\n } else {\n waitUntil?.(teardown());\n return result;\n }\n } catch (e) {\n captureException(e, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object',\n handled: false,\n },\n });\n waitUntil?.(teardown());\n throw e;\n }\n });\n };\n\n if (rpcMeta) {\n return continueTrace(\n { sentryTrace: rpcMeta['sentry-trace'] || '', baggage: rpcMeta.baggage || '' },\n executeSpan,\n );\n }\n\n if (startNewTrace) {\n return startNewTraceCore(() => executeSpan());\n }\n\n return executeSpan();\n };\n\n return sentryWithScope(wrappedFunction);\n },\n }),\n noMark,\n );\n}\n"],"names":["ensureInstrumented","rpcMeta","extractRpcMeta","getClient","withIsolationScope","withScope","init","storeSpanContext","flushAndDispose","isThenable","captureException","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","startSpan","getStoredSpanContext","buildSpanLinks","continueTrace","startNewTraceCore"],"mappings":"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"}
|
|
@@ -1,26 +1,35 @@
|
|
|
1
1
|
import { captureException } from '@sentry/core';
|
|
2
2
|
import { setAsyncLocalStorageAsyncContextStrategy } from './async.js';
|
|
3
|
-
import { ensureInstrumented
|
|
3
|
+
import { ensureInstrumented } from './instrument.js';
|
|
4
4
|
import { instrumentEnv } from './instrumentations/worker/instrumentEnv.js';
|
|
5
5
|
import { getFinalOptions } from './options.js';
|
|
6
6
|
import { wrapRequestHandler } from './request.js';
|
|
7
7
|
import { instrumentContext } from './utils/instrumentContext.js';
|
|
8
|
-
import {
|
|
8
|
+
import { getEffectiveRpcPropagation } from './utils/rpcOptions.js';
|
|
9
9
|
import { wrapMethodWithSentry } from './wrapMethodWithSentry.js';
|
|
10
10
|
|
|
11
11
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
12
12
|
|
|
13
|
+
const BUILT_IN_DO_METHODS = new Set([
|
|
14
|
+
'constructor',
|
|
15
|
+
'fetch',
|
|
16
|
+
'alarm',
|
|
17
|
+
'webSocketError',
|
|
18
|
+
'webSocketClose',
|
|
19
|
+
'webSocketMessage',
|
|
20
|
+
]);
|
|
21
|
+
|
|
13
22
|
/**
|
|
14
23
|
* Instruments a Durable Object class to capture errors and performance data.
|
|
15
24
|
*
|
|
16
|
-
* Instruments the following methods:
|
|
25
|
+
* Instruments the following methods by default:
|
|
17
26
|
* - fetch
|
|
18
27
|
* - alarm
|
|
19
28
|
* - webSocketMessage
|
|
20
29
|
* - webSocketClose
|
|
21
30
|
* - webSocketError
|
|
22
31
|
*
|
|
23
|
-
*
|
|
32
|
+
* To instrument RPC methods (prototype methods), enable the `enableRpcTracePropagation` option.
|
|
24
33
|
*
|
|
25
34
|
* @param optionsCallback Function that returns the options for the SDK initialization.
|
|
26
35
|
* @param DurableObjectClass The Durable Object class to instrument.
|
|
@@ -112,140 +121,69 @@ function instrumentDurableObjectWithSentry
|
|
|
112
121
|
);
|
|
113
122
|
}
|
|
114
123
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
method === 'fetch' ||
|
|
118
|
-
method === 'alarm' ||
|
|
119
|
-
method === 'webSocketError' ||
|
|
120
|
-
method === 'webSocketClose' ||
|
|
121
|
-
method === 'webSocketMessage'
|
|
122
|
-
) {
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
|
|
127
|
-
const value = (obj )[method] ;
|
|
128
|
-
if (typeof value === 'function') {
|
|
129
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
|
|
130
|
-
(obj )[method] = wrapMethodWithSentry(
|
|
131
|
-
{ options, context, spanName: method, spanOp: 'rpc' },
|
|
132
|
-
value ,
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Store context and options on the instance for prototype methods to access
|
|
138
|
-
Object.defineProperty(obj, '__SENTRY_CONTEXT__', {
|
|
139
|
-
value: context,
|
|
140
|
-
enumerable: false,
|
|
141
|
-
writable: false,
|
|
142
|
-
configurable: false,
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
Object.defineProperty(obj, '__SENTRY_OPTIONS__', {
|
|
146
|
-
value: options,
|
|
147
|
-
enumerable: false,
|
|
148
|
-
writable: false,
|
|
149
|
-
configurable: false,
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
const methodFilter = getPrototypeMethodFilter(options);
|
|
124
|
+
// Get effective RPC propagation setting (handles deprecation of instrumentPrototypeMethods)
|
|
125
|
+
const rpcPropagation = getEffectiveRpcPropagation(options);
|
|
153
126
|
|
|
154
|
-
if
|
|
155
|
-
|
|
127
|
+
// Skip RPC instrumentation if not enabled
|
|
128
|
+
if (!rpcPropagation) {
|
|
129
|
+
return obj;
|
|
156
130
|
}
|
|
157
131
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
// Create a wrapper that gets context/options from the instance at runtime
|
|
207
|
-
const wrappedMethod = function ( ...args) {
|
|
208
|
-
const thisWithSentry = this
|
|
209
|
-
|
|
210
|
-
;
|
|
211
|
-
const instanceContext = thisWithSentry.__SENTRY_CONTEXT__;
|
|
212
|
-
const instanceOptions = thisWithSentry.__SENTRY_OPTIONS__;
|
|
132
|
+
// If `instrumentPrototypeMethods` was passed as an array (deprecated),
|
|
133
|
+
// only the listed method names should be instrumented.
|
|
134
|
+
const instrumentPrototypeMethods = Array.isArray(options.instrumentPrototypeMethods)
|
|
135
|
+
? options.instrumentPrototypeMethods
|
|
136
|
+
: undefined;
|
|
137
|
+
const allowSet = instrumentPrototypeMethods ? new Set(instrumentPrototypeMethods) : null;
|
|
138
|
+
|
|
139
|
+
// Return a Proxy that lazily wraps prototype methods on access.
|
|
140
|
+
// This avoids iterating the prototype chain at construction time —
|
|
141
|
+
// we only check if a property is an RPC method when it's accessed.
|
|
142
|
+
const rpcMethodCache = new Map();
|
|
143
|
+
|
|
144
|
+
return new Proxy(obj, {
|
|
145
|
+
get(proxyTarget, prop, receiver) {
|
|
146
|
+
const value = Reflect.get(proxyTarget, prop, receiver);
|
|
147
|
+
|
|
148
|
+
if (typeof prop !== 'string' || BUILT_IN_DO_METHODS.has(prop)) {
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const cached = rpcMethodCache.get(prop);
|
|
153
|
+
|
|
154
|
+
if (cached) {
|
|
155
|
+
return cached;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (
|
|
159
|
+
typeof value !== 'function' ||
|
|
160
|
+
Object.prototype.hasOwnProperty.call(proxyTarget, prop) ||
|
|
161
|
+
(allowSet && !allowSet.has(prop)) ||
|
|
162
|
+
// Exclude inherited Object.prototype methods (toString, valueOf, etc.)
|
|
163
|
+
// These are not RPC methods and should not create spans
|
|
164
|
+
prop in Object.prototype
|
|
165
|
+
) {
|
|
166
|
+
return value;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Bind the method to the original object to ensure private fields work correctly.
|
|
170
|
+
// When called via the Proxy, `this` would be the Proxy, but private fields require
|
|
171
|
+
// the original object. Bound functions ignore the thisArg passed via Reflect.apply.
|
|
172
|
+
const boundValue = (value ).bind(proxyTarget);
|
|
173
|
+
|
|
174
|
+
const wrapped = wrapMethodWithSentry(
|
|
175
|
+
{ options, context, spanName: prop, spanOp: 'rpc' },
|
|
176
|
+
boundValue,
|
|
177
|
+
undefined,
|
|
178
|
+
true,
|
|
179
|
+
);
|
|
213
180
|
|
|
214
|
-
|
|
215
|
-
// Fallback to original method if no Sentry data found
|
|
216
|
-
return (originalMethod ).apply(this, args);
|
|
217
|
-
}
|
|
181
|
+
rpcMethodCache.set(prop, wrapped);
|
|
218
182
|
|
|
219
|
-
|
|
220
|
-
const wrapper = wrapMethodWithSentry(
|
|
221
|
-
{
|
|
222
|
-
options: instanceOptions,
|
|
223
|
-
context: instanceContext,
|
|
224
|
-
spanName: methodName,
|
|
225
|
-
spanOp: 'rpc',
|
|
183
|
+
return wrapped;
|
|
226
184
|
},
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
true, // noMark = true since we'll mark the prototype method
|
|
230
|
-
);
|
|
231
|
-
|
|
232
|
-
return wrapper.apply(this, args);
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
// Only mark wrappedMethod as instrumented (not originalMethod → wrappedMethod).
|
|
236
|
-
// originalMethod must stay unmapped because wrappedMethod calls
|
|
237
|
-
// wrapMethodWithSentry(options, originalMethod) on each invocation to create
|
|
238
|
-
// a per-instance proxy. If originalMethod mapped to wrappedMethod, that call
|
|
239
|
-
// would return wrappedMethod itself, causing infinite recursion.
|
|
240
|
-
markAsInstrumented(wrappedMethod);
|
|
241
|
-
|
|
242
|
-
// Replace the prototype method
|
|
243
|
-
Object.defineProperty(proto, methodName, {
|
|
244
|
-
value: wrappedMethod,
|
|
245
|
-
enumerable: false,
|
|
246
|
-
writable: true,
|
|
247
|
-
configurable: true,
|
|
248
|
-
});
|
|
185
|
+
});
|
|
186
|
+
},
|
|
249
187
|
});
|
|
250
188
|
}
|
|
251
189
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durableobject.js","sources":["../../src/durableobject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport { captureException } from '@sentry/core';\nimport type { DurableObject } from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from './async';\nimport type { CloudflareOptions } from './client';\nimport { ensureInstrumented, getInstrumented, markAsInstrumented } from './instrument';\nimport { instrumentEnv } from './instrumentations/worker/instrumentEnv';\nimport { getFinalOptions } from './options';\nimport { wrapRequestHandler } from './request';\nimport { instrumentContext } from './utils/instrumentContext';\nimport { getPrototypeMethodFilter } from './utils/rpcOptions';\nimport type { UncheckedMethod } from './wrapMethodWithSentry';\nimport { wrapMethodWithSentry } from './wrapMethodWithSentry';\n\n/**\n * Instruments a Durable Object class to capture errors and performance data.\n *\n * Instruments the following methods:\n * - fetch\n * - alarm\n * - webSocketMessage\n * - webSocketClose\n * - webSocketError\n *\n * as well as any other public RPC methods on the Durable Object instance.\n *\n * @param optionsCallback Function that returns the options for the SDK initialization.\n * @param DurableObjectClass The Durable Object class to instrument.\n * @returns The instrumented Durable Object class.\n *\n * @example\n * ```ts\n * class MyDurableObjectBase extends DurableObject {\n * constructor(ctx: DurableObjectState, env: Env) {\n * super(ctx, env);\n * }\n * }\n *\n * export const MyDurableObject = instrumentDurableObjectWithSentry(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * }),\n * MyDurableObjectBase,\n * );\n * ```\n */\nexport function instrumentDurableObjectWithSentry<\n E,\n T extends DurableObject<E>,\n C extends new (state: DurableObjectState, env: E) => T,\n>(optionsCallback: (env: E) => CloudflareOptions, DurableObjectClass: C): C {\n return new Proxy(DurableObjectClass, {\n construct(target, [ctx, env]) {\n setAsyncLocalStorageAsyncContextStrategy();\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n const instrumentedEnv = instrumentEnv(env, options);\n\n const obj = new target(context, instrumentedEnv);\n\n // These are the methods that are available on a Durable Object\n // ref: https://developers.cloudflare.com/durable-objects/api/base/\n // obj.alarm\n // obj.fetch\n // obj.webSocketError\n // obj.webSocketClose\n // obj.webSocketMessage\n\n // Any other public methods on the Durable Object instance are RPC calls.\n\n if (obj.fetch && typeof obj.fetch === 'function') {\n obj.fetch = ensureInstrumented(\n obj.fetch,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args) {\n return wrapRequestHandler({ options, request: args[0], context }, () => {\n return Reflect.apply(target, thisArg, args);\n });\n },\n }),\n );\n }\n\n if (obj.alarm && typeof obj.alarm === 'function') {\n // Alarms are independent invocations, so we start a new trace and link to the previous alarm\n obj.alarm = wrapMethodWithSentry(\n { options, context, spanName: 'alarm', spanOp: 'function', startNewTrace: true },\n obj.alarm,\n );\n }\n\n if (obj.webSocketMessage && typeof obj.webSocketMessage === 'function') {\n obj.webSocketMessage = wrapMethodWithSentry(\n { options, context, spanName: 'webSocketMessage' },\n obj.webSocketMessage,\n );\n }\n\n if (obj.webSocketClose && typeof obj.webSocketClose === 'function') {\n obj.webSocketClose = wrapMethodWithSentry({ options, context, spanName: 'webSocketClose' }, obj.webSocketClose);\n }\n\n if (obj.webSocketError && typeof obj.webSocketError === 'function') {\n obj.webSocketError = wrapMethodWithSentry(\n { options, context, spanName: 'webSocketError' },\n obj.webSocketError,\n (_, error) =>\n captureException(error, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object_websocket',\n handled: false,\n },\n }),\n );\n }\n\n for (const method of Object.getOwnPropertyNames(obj)) {\n if (\n method === 'fetch' ||\n method === 'alarm' ||\n method === 'webSocketError' ||\n method === 'webSocketClose' ||\n method === 'webSocketMessage'\n ) {\n continue;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n const value = (obj as any)[method] as unknown;\n if (typeof value === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n (obj as any)[method] = wrapMethodWithSentry(\n { options, context, spanName: method, spanOp: 'rpc' },\n value as UncheckedMethod,\n );\n }\n }\n\n // Store context and options on the instance for prototype methods to access\n Object.defineProperty(obj, '__SENTRY_CONTEXT__', {\n value: context,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n\n Object.defineProperty(obj, '__SENTRY_OPTIONS__', {\n value: options,\n enumerable: false,\n writable: false,\n configurable: false,\n });\n\n const methodFilter = getPrototypeMethodFilter(options);\n\n if (methodFilter) {\n instrumentPrototype(target, methodFilter);\n }\n\n return obj;\n },\n });\n}\n\nfunction instrumentPrototype<T extends NewableFunction>(target: T, methodsToInstrument: boolean | string[]): void {\n const proto = target.prototype;\n\n // Get all methods from the prototype chain\n const methodNames = new Set<string>();\n let current = proto;\n\n while (current && current !== Object.prototype) {\n Object.getOwnPropertyNames(current).forEach(name => {\n if (name !== 'constructor' && typeof (current as Record<string, unknown>)[name] === 'function') {\n methodNames.add(name);\n }\n });\n current = Object.getPrototypeOf(current);\n }\n\n // Create a set for efficient lookups when methodsToInstrument is an array\n const methodsToInstrumentSet = Array.isArray(methodsToInstrument) ? new Set(methodsToInstrument) : null;\n\n // Instrument each method on the prototype\n methodNames.forEach(methodName => {\n const originalMethod = (proto as Record<string, unknown>)[methodName];\n\n if (!originalMethod) {\n return;\n }\n\n const existingInstrumented = getInstrumented(originalMethod);\n if (existingInstrumented) {\n Object.defineProperty(proto, methodName, {\n value: existingInstrumented,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n return;\n }\n\n // If methodsToInstrument is an array, only instrument methods in that set\n if (methodsToInstrumentSet && !methodsToInstrumentSet.has(methodName)) {\n return;\n }\n\n // Create a wrapper that gets context/options from the instance at runtime\n const wrappedMethod = function (this: unknown, ...args: unknown[]): unknown {\n const thisWithSentry = this as {\n __SENTRY_CONTEXT__: DurableObjectState;\n __SENTRY_OPTIONS__: CloudflareOptions;\n };\n const instanceContext = thisWithSentry.__SENTRY_CONTEXT__;\n const instanceOptions = thisWithSentry.__SENTRY_OPTIONS__;\n\n if (!instanceOptions) {\n // Fallback to original method if no Sentry data found\n return (originalMethod as UncheckedMethod).apply(this, args);\n }\n\n // Use the existing wrapper but with instance-specific context/options\n const wrapper = wrapMethodWithSentry(\n {\n options: instanceOptions,\n context: instanceContext,\n spanName: methodName,\n spanOp: 'rpc',\n },\n originalMethod as UncheckedMethod,\n undefined,\n true, // noMark = true since we'll mark the prototype method\n );\n\n return wrapper.apply(this, args);\n };\n\n // Only mark wrappedMethod as instrumented (not originalMethod → wrappedMethod).\n // originalMethod must stay unmapped because wrappedMethod calls\n // wrapMethodWithSentry(options, originalMethod) on each invocation to create\n // a per-instance proxy. If originalMethod mapped to wrappedMethod, that call\n // would return wrappedMethod itself, causing infinite recursion.\n markAsInstrumented(wrappedMethod);\n\n // Replace the prototype method\n Object.defineProperty(proto, methodName, {\n value: wrappedMethod,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n });\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"durableobject.js","sources":["../../src/durableobject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport { captureException } from '@sentry/core';\nimport type { DurableObject } from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from './async';\nimport type { CloudflareOptions } from './client';\nimport { ensureInstrumented } from './instrument';\nimport { instrumentEnv } from './instrumentations/worker/instrumentEnv';\nimport { getFinalOptions } from './options';\nimport { wrapRequestHandler } from './request';\nimport { instrumentContext } from './utils/instrumentContext';\nimport { getEffectiveRpcPropagation } from './utils/rpcOptions';\nimport { type UncheckedMethod, wrapMethodWithSentry } from './wrapMethodWithSentry';\n\nconst BUILT_IN_DO_METHODS = new Set([\n 'constructor',\n 'fetch',\n 'alarm',\n 'webSocketError',\n 'webSocketClose',\n 'webSocketMessage',\n]);\n\n/**\n * Instruments a Durable Object class to capture errors and performance data.\n *\n * Instruments the following methods by default:\n * - fetch\n * - alarm\n * - webSocketMessage\n * - webSocketClose\n * - webSocketError\n *\n * To instrument RPC methods (prototype methods), enable the `enableRpcTracePropagation` option.\n *\n * @param optionsCallback Function that returns the options for the SDK initialization.\n * @param DurableObjectClass The Durable Object class to instrument.\n * @returns The instrumented Durable Object class.\n *\n * @example\n * ```ts\n * class MyDurableObjectBase extends DurableObject {\n * constructor(ctx: DurableObjectState, env: Env) {\n * super(ctx, env);\n * }\n * }\n *\n * export const MyDurableObject = instrumentDurableObjectWithSentry(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * }),\n * MyDurableObjectBase,\n * );\n * ```\n */\nexport function instrumentDurableObjectWithSentry<\n E,\n T extends DurableObject<E>,\n C extends new (state: DurableObjectState, env: E) => T,\n>(optionsCallback: (env: E) => CloudflareOptions, DurableObjectClass: C): C {\n return new Proxy(DurableObjectClass, {\n construct(target, [ctx, env]) {\n setAsyncLocalStorageAsyncContextStrategy();\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n const instrumentedEnv = instrumentEnv(env, options);\n\n const obj = new target(context, instrumentedEnv);\n\n // These are the methods that are available on a Durable Object\n // ref: https://developers.cloudflare.com/durable-objects/api/base/\n // obj.alarm\n // obj.fetch\n // obj.webSocketError\n // obj.webSocketClose\n // obj.webSocketMessage\n\n // Any other public methods on the Durable Object instance are RPC calls.\n\n if (obj.fetch && typeof obj.fetch === 'function') {\n obj.fetch = ensureInstrumented(\n obj.fetch,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args) {\n return wrapRequestHandler({ options, request: args[0], context }, () => {\n return Reflect.apply(target, thisArg, args);\n });\n },\n }),\n );\n }\n\n if (obj.alarm && typeof obj.alarm === 'function') {\n // Alarms are independent invocations, so we start a new trace and link to the previous alarm\n obj.alarm = wrapMethodWithSentry(\n { options, context, spanName: 'alarm', spanOp: 'function', startNewTrace: true },\n obj.alarm,\n );\n }\n\n if (obj.webSocketMessage && typeof obj.webSocketMessage === 'function') {\n obj.webSocketMessage = wrapMethodWithSentry(\n { options, context, spanName: 'webSocketMessage' },\n obj.webSocketMessage,\n );\n }\n\n if (obj.webSocketClose && typeof obj.webSocketClose === 'function') {\n obj.webSocketClose = wrapMethodWithSentry({ options, context, spanName: 'webSocketClose' }, obj.webSocketClose);\n }\n\n if (obj.webSocketError && typeof obj.webSocketError === 'function') {\n obj.webSocketError = wrapMethodWithSentry(\n { options, context, spanName: 'webSocketError' },\n obj.webSocketError,\n (_, error) =>\n captureException(error, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object_websocket',\n handled: false,\n },\n }),\n );\n }\n\n // Get effective RPC propagation setting (handles deprecation of instrumentPrototypeMethods)\n const rpcPropagation = getEffectiveRpcPropagation(options);\n\n // Skip RPC instrumentation if not enabled\n if (!rpcPropagation) {\n return obj;\n }\n\n // If `instrumentPrototypeMethods` was passed as an array (deprecated),\n // only the listed method names should be instrumented.\n const instrumentPrototypeMethods = Array.isArray(options.instrumentPrototypeMethods)\n ? options.instrumentPrototypeMethods\n : undefined;\n const allowSet = instrumentPrototypeMethods ? new Set(instrumentPrototypeMethods) : null;\n\n // Return a Proxy that lazily wraps prototype methods on access.\n // This avoids iterating the prototype chain at construction time —\n // we only check if a property is an RPC method when it's accessed.\n const rpcMethodCache = new Map<string, UncheckedMethod>();\n\n return new Proxy(obj, {\n get(proxyTarget, prop, receiver) {\n const value = Reflect.get(proxyTarget, prop, receiver);\n\n if (typeof prop !== 'string' || BUILT_IN_DO_METHODS.has(prop)) {\n return value;\n }\n\n const cached = rpcMethodCache.get(prop);\n\n if (cached) {\n return cached;\n }\n\n if (\n typeof value !== 'function' ||\n Object.prototype.hasOwnProperty.call(proxyTarget, prop) ||\n (allowSet && !allowSet.has(prop)) ||\n // Exclude inherited Object.prototype methods (toString, valueOf, etc.)\n // These are not RPC methods and should not create spans\n prop in Object.prototype\n ) {\n return value;\n }\n\n // Bind the method to the original object to ensure private fields work correctly.\n // When called via the Proxy, `this` would be the Proxy, but private fields require\n // the original object. Bound functions ignore the thisArg passed via Reflect.apply.\n const boundValue = (value as UncheckedMethod).bind(proxyTarget);\n\n const wrapped = wrapMethodWithSentry(\n { options, context, spanName: prop, spanOp: 'rpc' },\n boundValue,\n undefined,\n true,\n );\n\n rpcMethodCache.set(prop, wrapped);\n\n return wrapped;\n },\n });\n },\n });\n}\n"],"names":[],"mappings":"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"}
|
package/build/esm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, captureCheckIn, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, close, consoleIntegration, consoleLoggingIntegration, continueTrace, createConsolaReporter, createLangChainCallbackHandler, createTransport, dedupeIntegration, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, getTraceMetaTags, growthbookIntegration, inboundFiltersIntegration, instrumentAnthropicAiClient, instrumentGoogleGenAIClient, instrumentLangChainEmbeddings, instrumentLangGraph, instrumentOpenAiClient, instrumentPostgresJsSql, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, linkedErrorsIntegration, logger, metrics, moduleMetadataIntegration, requestDataIntegration, rewriteFramesIntegration, setContext, setConversationId, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanStreamingIntegration, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSpan, startSpanManual, supabaseIntegration, suppressTracing, trpcMiddleware, updateSpanName, withActiveSpan, withIsolationScope, withMonitor, withScope, withStreamedSpan, wrapMcpServerWithSentry, zodErrorsIntegration } from '@sentry/core';
|
|
1
|
+
export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, captureCheckIn, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, close, consoleIntegration, consoleLoggingIntegration, continueTrace, createConsolaReporter, createLangChainCallbackHandler, createTransport, dedupeIntegration, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, getTraceMetaTags, growthbookIntegration, inboundFiltersIntegration, instrumentAnthropicAiClient, instrumentCreateReactAgent, instrumentGoogleGenAIClient, instrumentLangChainEmbeddings, instrumentLangGraph, instrumentOpenAiClient, instrumentPostgresJsSql, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, linkedErrorsIntegration, logger, metrics, moduleMetadataIntegration, requestDataIntegration, rewriteFramesIntegration, setContext, setConversationId, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanStreamingIntegration, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSpan, startSpanManual, supabaseIntegration, suppressTracing, trpcMiddleware, updateSpanName, withActiveSpan, withIsolationScope, withMonitor, withScope, withStreamedSpan, wrapMcpServerWithSentry, zodErrorsIntegration } from '@sentry/core';
|
|
2
2
|
export { withSentry } from './withSentry.js';
|
|
3
3
|
export { instrumentDurableObjectWithSentry } from './durableobject.js';
|
|
4
4
|
export { sentryPagesPlugin } from './pages-plugin.js';
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { appendRpcMeta } from '../utils/rpcMeta.js';
|
|
1
2
|
import { instrumentFetcher } from './worker/instrumentFetcher.js';
|
|
2
3
|
|
|
4
|
+
// Built-in DurableObjectStub methods that are not RPC calls.
|
|
5
|
+
const STUB_NON_RPC_METHODS = new Set(['fetch', 'connect', 'dup']);
|
|
6
|
+
|
|
3
7
|
/**
|
|
4
8
|
* Instruments a DurableObjectNamespace binding to create spans for DO interactions.
|
|
5
9
|
*
|
|
@@ -32,17 +36,22 @@ function instrumentDurableObjectNamespace(namespace) {
|
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
/**
|
|
35
|
-
* Instruments a DurableObjectStub to
|
|
39
|
+
* Instruments a DurableObjectStub to create spans for outgoing fetch calls
|
|
40
|
+
* and propagate trace context across RPC calls.
|
|
36
41
|
*
|
|
37
42
|
* @param stub - The DurableObjectStub to instrument
|
|
38
43
|
*/
|
|
39
44
|
function instrumentDurableObjectStub(stub) {
|
|
40
45
|
return new Proxy(stub, {
|
|
41
|
-
get(target, prop
|
|
42
|
-
const value = Reflect.get(target, prop
|
|
46
|
+
get(target, prop) {
|
|
47
|
+
const value = Reflect.get(target, prop);
|
|
43
48
|
|
|
44
49
|
if (prop === 'fetch' && typeof value === 'function') {
|
|
45
|
-
return instrumentFetcher((
|
|
50
|
+
return instrumentFetcher((...args) => Reflect.apply(value, target, args));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (typeof value === 'function' && typeof prop === 'string' && !STUB_NON_RPC_METHODS.has(prop)) {
|
|
54
|
+
return (...args) => Reflect.apply(value, target, appendRpcMeta(args));
|
|
46
55
|
}
|
|
47
56
|
|
|
48
57
|
return value;
|
|
@@ -50,5 +59,5 @@ function instrumentDurableObjectStub(stub) {
|
|
|
50
59
|
});
|
|
51
60
|
}
|
|
52
61
|
|
|
53
|
-
export { instrumentDurableObjectNamespace };
|
|
62
|
+
export { STUB_NON_RPC_METHODS, instrumentDurableObjectNamespace };
|
|
54
63
|
//# sourceMappingURL=instrumentDurableObjectNamespace.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentDurableObjectNamespace.js","sources":["../../../src/instrumentations/instrumentDurableObjectNamespace.ts"],"sourcesContent":["import type { DurableObjectNamespace, DurableObjectStub } from '@cloudflare/workers-types';\nimport { instrumentFetcher } from './worker/instrumentFetcher';\n\n/**\n * Instruments a DurableObjectNamespace binding to create spans for DO interactions.\n *\n * Wraps:\n * - `namespace.get(id)` / `namespace.getByName(name)` with a span + instruments returned stub\n * - `namespace.idFromName(name)` / `namespace.idFromString(id)` / `namespace.newUniqueId()` with breadcrumbs\n *\n * @param namespace - The DurableObjectNamespace to instrument\n */\nexport function instrumentDurableObjectNamespace(namespace: DurableObjectNamespace): DurableObjectNamespace {\n return new Proxy(namespace, {\n get(target, prop, _receiver) {\n const value = Reflect.get(target, prop) as unknown;\n\n if (typeof value !== 'function') {\n return value;\n }\n\n if (prop === 'get' || prop === 'getByName') {\n return function (this: unknown, ...args: unknown[]) {\n const stub = Reflect.apply(value, target, args);\n\n return instrumentDurableObjectStub(stub);\n };\n }\n\n return value.bind(target);\n },\n });\n}\n\n/**\n * Instruments a DurableObjectStub to propagate trace context across
|
|
1
|
+
{"version":3,"file":"instrumentDurableObjectNamespace.js","sources":["../../../src/instrumentations/instrumentDurableObjectNamespace.ts"],"sourcesContent":["import type { DurableObjectNamespace, DurableObjectStub } from '@cloudflare/workers-types';\nimport { appendRpcMeta } from '../utils/rpcMeta';\nimport { instrumentFetcher } from './worker/instrumentFetcher';\n\n// Built-in DurableObjectStub methods that are not RPC calls.\nexport const STUB_NON_RPC_METHODS = new Set(['fetch', 'connect', 'dup']);\n\n/**\n * Instruments a DurableObjectNamespace binding to create spans for DO interactions.\n *\n * Wraps:\n * - `namespace.get(id)` / `namespace.getByName(name)` with a span + instruments returned stub\n * - `namespace.idFromName(name)` / `namespace.idFromString(id)` / `namespace.newUniqueId()` with breadcrumbs\n *\n * @param namespace - The DurableObjectNamespace to instrument\n */\nexport function instrumentDurableObjectNamespace(namespace: DurableObjectNamespace): DurableObjectNamespace {\n return new Proxy(namespace, {\n get(target, prop, _receiver) {\n const value = Reflect.get(target, prop) as unknown;\n\n if (typeof value !== 'function') {\n return value;\n }\n\n if (prop === 'get' || prop === 'getByName') {\n return function (this: unknown, ...args: unknown[]) {\n const stub = Reflect.apply(value, target, args);\n\n return instrumentDurableObjectStub(stub);\n };\n }\n\n return value.bind(target);\n },\n });\n}\n\n/**\n * Instruments a DurableObjectStub to create spans for outgoing fetch calls\n * and propagate trace context across RPC calls.\n *\n * @param stub - The DurableObjectStub to instrument\n */\nfunction instrumentDurableObjectStub(stub: DurableObjectStub): DurableObjectStub {\n return new Proxy(stub, {\n get(target, prop) {\n const value = Reflect.get(target, prop);\n\n if (prop === 'fetch' && typeof value === 'function') {\n return instrumentFetcher((...args) => Reflect.apply(value, target, args));\n }\n\n if (typeof value === 'function' && typeof prop === 'string' && !STUB_NON_RPC_METHODS.has(prop)) {\n return (...args: unknown[]) => Reflect.apply(value, target, appendRpcMeta(args));\n }\n\n return value;\n },\n });\n}\n"],"names":[],"mappings":";;;AAIA;AACO,MAAM,oBAAA,GAAuB,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC;;AAEvE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gCAAgC,CAAC,SAAS,EAAkD;AAC5G,EAAE,OAAO,IAAI,KAAK,CAAC,SAAS,EAAE;AAC9B,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;AACjC,MAAM,MAAM,KAAA,GAAQ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAA;;AAE5C,MAAM,IAAI,OAAO,KAAA,KAAU,UAAU,EAAE;AACvC,QAAQ,OAAO,KAAK;AACpB,MAAM;;AAEN,MAAM,IAAI,IAAA,KAAS,SAAS,IAAA,KAAS,WAAW,EAAE;AAClD,QAAQ,OAAO,WAAyB,GAAG,IAAI,EAAa;AAC5D,UAAU,MAAM,IAAA,GAAO,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC;;AAEzD,UAAU,OAAO,2BAA2B,CAAC,IAAI,CAAC;AAClD,QAAQ,CAAC;AACT,MAAM;;AAEN,MAAM,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;AAC/B,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,2BAA2B,CAAC,IAAI,EAAwC;AACjF,EAAE,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE;AACzB,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE;AACtB,MAAM,MAAM,KAAA,GAAQ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;;AAE7C,MAAM,IAAI,IAAA,KAAS,OAAA,IAAW,OAAO,KAAA,KAAU,UAAU,EAAE;AAC3D,QAAQ,OAAO,iBAAiB,CAAC,CAAC,GAAG,IAAI,KAAK,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AACjF,MAAM;;AAEN,MAAM,IAAI,OAAO,UAAU,UAAA,IAAc,OAAO,IAAA,KAAS,QAAA,IAAY,CAAC,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AACtG,QAAQ,OAAO,CAAC,GAAG,IAAI,KAAgB,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC;AACxF,MAAM;;AAEN,MAAM,OAAO,KAAK;AAClB,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;;;"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isDurableObjectNamespace, isJSRPC } from '../../utils/isBinding.js';
|
|
2
|
+
import { appendRpcMeta } from '../../utils/rpcMeta.js';
|
|
2
3
|
import { getEffectiveRpcPropagation } from '../../utils/rpcOptions.js';
|
|
3
|
-
import { instrumentDurableObjectNamespace } from '../instrumentDurableObjectNamespace.js';
|
|
4
|
+
import { instrumentDurableObjectNamespace, STUB_NON_RPC_METHODS } from '../instrumentDurableObjectNamespace.js';
|
|
4
5
|
import { instrumentFetcher } from './instrumentFetcher.js';
|
|
5
6
|
|
|
6
7
|
function isProxyable(item) {
|
|
@@ -57,11 +58,15 @@ function instrumentEnv(env, options) {
|
|
|
57
58
|
|
|
58
59
|
if (isJSRPC(item)) {
|
|
59
60
|
const instrumented = new Proxy(item, {
|
|
60
|
-
get(target, p
|
|
61
|
-
const value = Reflect.get(target, p
|
|
61
|
+
get(target, p) {
|
|
62
|
+
const value = Reflect.get(target, p);
|
|
62
63
|
|
|
63
64
|
if (p === 'fetch' && typeof value === 'function') {
|
|
64
|
-
return instrumentFetcher(
|
|
65
|
+
return instrumentFetcher((...args) => Reflect.apply(value, target, args));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (typeof value === 'function' && typeof p === 'string' && !STUB_NON_RPC_METHODS.has(p)) {
|
|
69
|
+
return (...args) => Reflect.apply(value, target, appendRpcMeta(args));
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
return value;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentEnv.js","sources":["../../../../src/instrumentations/worker/instrumentEnv.ts"],"sourcesContent":["import type { CloudflareOptions } from '../../client';\nimport { isDurableObjectNamespace, isJSRPC } from '../../utils/isBinding';\nimport { getEffectiveRpcPropagation } from '../../utils/rpcOptions';\nimport { instrumentDurableObjectNamespace } from '../instrumentDurableObjectNamespace';\nimport { instrumentFetcher } from './instrumentFetcher';\n\nfunction isProxyable(item: unknown): item is object {\n return item !== null && (typeof item === 'object' || typeof item === 'function');\n}\n\nconst instrumentedBindings = new WeakMap<object, unknown>();\n\n/**\n * Wraps the Cloudflare `env` object in a Proxy that detects binding types\n * on property access and returns instrumented versions.\n *\n * Currently detects:\n * - DurableObjectNamespace (via `idFromName` duck-typing)\n * - Service bindings / JSRPC proxies (wraps `fetch` for trace propagation)\n *\n * Extensible for future binding types (KV, D1, Queue, etc.).\n *\n * @param env - The Cloudflare env object to instrument\n * @param options - Optional CloudflareOptions to control RPC trace propagation\n */\nexport function instrumentEnv<Env extends Record<string, unknown>>(env: Env, options?: CloudflareOptions): Env {\n if (!env || typeof env !== 'object') {\n return env;\n }\n\n const rpcPropagation = options ? getEffectiveRpcPropagation(options) : false;\n\n // As of now only trace propagation is used for the instrumentEnv\n // so this is an optimization to avoid wrapping the env in a proxy if trace propagation is disabled\n if (!rpcPropagation) {\n return env;\n }\n\n return new Proxy(env, {\n get(target, prop, receiver) {\n const item = Reflect.get(target, prop, receiver);\n\n if (!isProxyable(item)) {\n return item;\n }\n\n const cached = instrumentedBindings.get(item);\n\n if (cached) {\n return cached;\n }\n\n if (isDurableObjectNamespace(item)) {\n const instrumented = instrumentDurableObjectNamespace(item);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n if (isJSRPC(item)) {\n const instrumented = new Proxy(item, {\n get(target, p
|
|
1
|
+
{"version":3,"file":"instrumentEnv.js","sources":["../../../../src/instrumentations/worker/instrumentEnv.ts"],"sourcesContent":["import type { CloudflareOptions } from '../../client';\nimport { isDurableObjectNamespace, isJSRPC } from '../../utils/isBinding';\nimport { appendRpcMeta } from '../../utils/rpcMeta';\nimport { getEffectiveRpcPropagation } from '../../utils/rpcOptions';\nimport { instrumentDurableObjectNamespace, STUB_NON_RPC_METHODS } from '../instrumentDurableObjectNamespace';\nimport { instrumentFetcher } from './instrumentFetcher';\n\nfunction isProxyable(item: unknown): item is object {\n return item !== null && (typeof item === 'object' || typeof item === 'function');\n}\n\nconst instrumentedBindings = new WeakMap<object, unknown>();\n\n/**\n * Wraps the Cloudflare `env` object in a Proxy that detects binding types\n * on property access and returns instrumented versions.\n *\n * Currently detects:\n * - DurableObjectNamespace (via `idFromName` duck-typing)\n * - Service bindings / JSRPC proxies (wraps `fetch` for trace propagation)\n *\n * Extensible for future binding types (KV, D1, Queue, etc.).\n *\n * @param env - The Cloudflare env object to instrument\n * @param options - Optional CloudflareOptions to control RPC trace propagation\n */\nexport function instrumentEnv<Env extends Record<string, unknown>>(env: Env, options?: CloudflareOptions): Env {\n if (!env || typeof env !== 'object') {\n return env;\n }\n\n const rpcPropagation = options ? getEffectiveRpcPropagation(options) : false;\n\n // As of now only trace propagation is used for the instrumentEnv\n // so this is an optimization to avoid wrapping the env in a proxy if trace propagation is disabled\n if (!rpcPropagation) {\n return env;\n }\n\n return new Proxy(env, {\n get(target, prop, receiver) {\n const item = Reflect.get(target, prop, receiver);\n\n if (!isProxyable(item)) {\n return item;\n }\n\n const cached = instrumentedBindings.get(item);\n\n if (cached) {\n return cached;\n }\n\n if (isDurableObjectNamespace(item)) {\n const instrumented = instrumentDurableObjectNamespace(item);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n if (isJSRPC(item)) {\n const instrumented = new Proxy(item, {\n get(target, p) {\n const value = Reflect.get(target, p);\n\n if (p === 'fetch' && typeof value === 'function') {\n return instrumentFetcher((...args) => Reflect.apply(value, target, args));\n }\n\n if (typeof value === 'function' && typeof p === 'string' && !STUB_NON_RPC_METHODS.has(p)) {\n return (...args: unknown[]) => Reflect.apply(value, target, appendRpcMeta(args));\n }\n\n return value;\n },\n });\n\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n return item;\n },\n });\n}\n"],"names":[],"mappings":";;;;;;AAOA,SAAS,WAAW,CAAC,IAAI,EAA2B;AACpD,EAAE,OAAO,IAAA,KAAS,IAAA,KAAS,OAAO,IAAA,KAAS,YAAY,OAAO,IAAA,KAAS,UAAU,CAAC;AAClF;;AAEA,MAAM,oBAAA,GAAuB,IAAI,OAAO,EAAmB;;AAE3D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,aAAa,CAAsC,GAAG,EAAO,OAAO,EAA2B;AAC/G,EAAE,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAQ,EAAE;AACvC,IAAI,OAAO,GAAG;AACd,EAAE;;AAEF,EAAE,MAAM,cAAA,GAAiB,OAAA,GAAU,0BAA0B,CAAC,OAAO,CAAA,GAAI,KAAK;;AAE9E;AACA;AACA,EAAE,IAAI,CAAC,cAAc,EAAE;AACvB,IAAI,OAAO,GAAG;AACd,EAAE;;AAEF,EAAE,OAAO,IAAI,KAAK,CAAC,GAAG,EAAE;AACxB,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE;AAChC,MAAM,MAAM,IAAA,GAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC;;AAEtD,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE;AAC9B,QAAQ,OAAO,IAAI;AACnB,MAAM;;AAEN,MAAM,MAAM,SAAS,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC;;AAEnD,MAAM,IAAI,MAAM,EAAE;AAClB,QAAQ,OAAO,MAAM;AACrB,MAAM;;AAEN,MAAM,IAAI,wBAAwB,CAAC,IAAI,CAAC,EAAE;AAC1C,QAAQ,MAAM,YAAA,GAAe,gCAAgC,CAAC,IAAI,CAAC;AACnE,QAAQ,oBAAoB,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC;AACpD,QAAQ,OAAO,YAAY;AAC3B,MAAM;;AAEN,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE;AACzB,QAAQ,MAAM,YAAA,GAAe,IAAI,KAAK,CAAC,IAAI,EAAE;AAC7C,UAAU,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE;AACzB,YAAY,MAAM,KAAA,GAAQ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;;AAEhD,YAAY,IAAI,CAAA,KAAM,OAAA,IAAW,OAAO,KAAA,KAAU,UAAU,EAAE;AAC9D,cAAc,OAAO,iBAAiB,CAAC,CAAC,GAAG,IAAI,KAAK,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AACvF,YAAY;;AAEZ,YAAY,IAAI,OAAO,UAAU,UAAA,IAAc,OAAO,CAAA,KAAM,QAAA,IAAY,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;AACtG,cAAc,OAAO,CAAC,GAAG,IAAI,KAAgB,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC;AAC9F,YAAY;;AAEZ,YAAY,OAAO,KAAK;AACxB,UAAU,CAAC;AACX,SAAS,CAAC;;AAEV,QAAQ,oBAAoB,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC;AACpD,QAAQ,OAAO,YAAY;AAC3B,MAAM;;AAEN,MAAM,OAAO,IAAI;AACjB,IAAI,CAAC;AACL,GAAG,CAAC;AACJ;;;;"}
|
package/build/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"10.
|
|
1
|
+
{"type":"module","version":"10.51.0","sideEffects":false}
|