@sentry/cloudflare 11.0.0-beta.1 → 11.0.0-beta.2
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/dev/durableobject.js +6 -2
- package/build/cjs/dev/durableobject.js.map +1 -1
- package/build/cjs/dev/index.js +15 -13
- package/build/cjs/dev/index.js.map +1 -1
- package/build/cjs/dev/instrument.js +4 -0
- package/build/cjs/dev/instrument.js.map +1 -1
- package/build/cjs/dev/instrumentations/instrumentSqlStorage.js +3 -3
- package/build/cjs/dev/instrumentations/instrumentSqlStorage.js.map +1 -1
- package/build/cjs/dev/instrumentations/instrumentWorkerEntrypoint.js +4 -1
- package/build/cjs/dev/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
- package/build/cjs/dev/instrumentations/worker/instrumentD1.js +2 -2
- package/build/cjs/dev/instrumentations/worker/instrumentD1.js.map +1 -1
- package/build/cjs/dev/vite/agentClass.js +3 -2
- package/build/cjs/dev/vite/agentClass.js.map +1 -1
- package/build/cjs/dev/vite/autoInstrument.js +1 -1
- package/build/cjs/dev/vite/autoInstrument.js.map +1 -1
- package/build/cjs/dev/vite/transform.js +79 -16
- package/build/cjs/dev/vite/transform.js.map +1 -1
- package/build/cjs/dev/workflows.js +4 -1
- package/build/cjs/dev/workflows.js.map +1 -1
- package/build/cjs/prod/durableobject.js +6 -2
- package/build/cjs/prod/durableobject.js.map +1 -1
- package/build/cjs/prod/index.js +15 -13
- package/build/cjs/prod/index.js.map +1 -1
- package/build/cjs/prod/instrument.js +4 -0
- package/build/cjs/prod/instrument.js.map +1 -1
- package/build/cjs/prod/instrumentations/instrumentSqlStorage.js +3 -3
- package/build/cjs/prod/instrumentations/instrumentSqlStorage.js.map +1 -1
- package/build/cjs/prod/instrumentations/instrumentWorkerEntrypoint.js +4 -1
- package/build/cjs/prod/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
- package/build/cjs/prod/instrumentations/worker/instrumentD1.js +2 -2
- package/build/cjs/prod/instrumentations/worker/instrumentD1.js.map +1 -1
- package/build/cjs/prod/vite/agentClass.js +3 -2
- package/build/cjs/prod/vite/agentClass.js.map +1 -1
- package/build/cjs/prod/vite/autoInstrument.js +1 -1
- package/build/cjs/prod/vite/autoInstrument.js.map +1 -1
- package/build/cjs/prod/vite/transform.js +79 -16
- package/build/cjs/prod/vite/transform.js.map +1 -1
- package/build/cjs/prod/workflows.js +4 -1
- package/build/cjs/prod/workflows.js.map +1 -1
- package/build/esm/dev/durableobject.js +6 -2
- package/build/esm/dev/durableobject.js.map +1 -1
- package/build/esm/dev/index.js +3 -2
- package/build/esm/dev/index.js.map +1 -1
- package/build/esm/dev/instrument.js +4 -1
- package/build/esm/dev/instrument.js.map +1 -1
- package/build/esm/dev/instrumentations/instrumentSqlStorage.js +3 -3
- package/build/esm/dev/instrumentations/instrumentSqlStorage.js.map +1 -1
- package/build/esm/dev/instrumentations/instrumentWorkerEntrypoint.js +4 -1
- package/build/esm/dev/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
- package/build/esm/dev/instrumentations/worker/instrumentD1.js +2 -2
- package/build/esm/dev/instrumentations/worker/instrumentD1.js.map +1 -1
- package/build/esm/dev/package.json +1 -1
- package/build/esm/dev/vite/agentClass.js +3 -2
- package/build/esm/dev/vite/agentClass.js.map +1 -1
- package/build/esm/dev/vite/autoInstrument.js +1 -1
- package/build/esm/dev/vite/autoInstrument.js.map +1 -1
- package/build/esm/dev/vite/transform.js +79 -16
- package/build/esm/dev/vite/transform.js.map +1 -1
- package/build/esm/dev/workflows.js +4 -1
- package/build/esm/dev/workflows.js.map +1 -1
- package/build/esm/prod/durableobject.js +6 -2
- package/build/esm/prod/durableobject.js.map +1 -1
- package/build/esm/prod/index.js +3 -2
- package/build/esm/prod/index.js.map +1 -1
- package/build/esm/prod/instrument.js +4 -1
- package/build/esm/prod/instrument.js.map +1 -1
- package/build/esm/prod/instrumentations/instrumentSqlStorage.js +3 -3
- package/build/esm/prod/instrumentations/instrumentSqlStorage.js.map +1 -1
- package/build/esm/prod/instrumentations/instrumentWorkerEntrypoint.js +4 -1
- package/build/esm/prod/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
- package/build/esm/prod/instrumentations/worker/instrumentD1.js +2 -2
- package/build/esm/prod/instrumentations/worker/instrumentD1.js.map +1 -1
- package/build/esm/prod/package.json +1 -1
- package/build/esm/prod/vite/agentClass.js +3 -2
- package/build/esm/prod/vite/agentClass.js.map +1 -1
- package/build/esm/prod/vite/autoInstrument.js +1 -1
- package/build/esm/prod/vite/autoInstrument.js.map +1 -1
- package/build/esm/prod/vite/transform.js +79 -16
- package/build/esm/prod/vite/transform.js.map +1 -1
- package/build/esm/prod/workflows.js +4 -1
- package/build/esm/prod/workflows.js.map +1 -1
- package/build/types/durableobject.d.ts.map +1 -1
- package/build/types/index.d.ts +3 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/instrument.d.ts +10 -0
- package/build/types/instrument.d.ts.map +1 -1
- package/build/types/instrumentations/instrumentWorkerEntrypoint.d.ts.map +1 -1
- package/build/types/vite/agentClass.d.ts +4 -3
- package/build/types/vite/agentClass.d.ts.map +1 -1
- package/build/types/vite/autoInstrument.d.ts.map +1 -1
- package/build/types/vite/transform.d.ts +5 -4
- package/build/types/vite/transform.d.ts.map +1 -1
- package/build/types/workflows.d.ts.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autoInstrument.js","sources":["../../../../src/vite/autoInstrument.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport { collectAgentCandidates, detectAgentClasses, type ModuleResolver } from './agentClass';\nimport { buildOptionsImport, ENV_FALLBACK_OPTIONS_FN, resolveInstrumentFile } from './instrumentFile';\nimport { applyAutoInstrumentTransforms, type ClassWrapperKind, type ProgramBody } from './transform';\nimport { resolveWranglerConfig, type WranglerConfig } from './wranglerConfig';\n\n// Vite normalizes module IDs to posix separators even on Windows, while\n// `path.resolve` yields backslashes there — normalize before comparing.\nfunction normalizePath(path: string): string {\n return path.replace(/\\\\/g, '/');\n}\n\n// Extensions the entry-module match may tolerate swapping (e.g. wrangler's\n// `main` says `.ts` but the served module is `.js`). Anything else — `.css`,\n// `.html`, … — sharing the entry's basename must never be treated as the entry.\nconst JS_EXTENSION_REGEX = /\\.[cm]?[jt]sx?$/;\n\nexport function sentryCloudflareAutoInstrumentPlugin(options: { wranglerConfigPath?: string } = {}) {\n let wranglerConfig: WranglerConfig | undefined;\n let entryFilePath: string | undefined;\n\n let optionsFn = ENV_FALLBACK_OPTIONS_FN;\n let optionsImport: string | undefined;\n\n return {\n name: 'sentry-cloudflare-auto-instrument',\n\n configResolved(config: { root: string; logger?: { warn(msg: string): void } }): void {\n const result = resolveWranglerConfig(config.root, options.wranglerConfigPath);\n if (!result) {\n // An explicit path that fails is a misconfiguration worth naming;\n // without one, hint at the option so custom-named configs (e.g. a\n // `configPath` handed to @cloudflare/vite-plugin) are discoverable.\n config.logger?.warn(\n options.wranglerConfigPath\n ? `[sentry] Could not find or parse the wrangler config \"${basename(options.wranglerConfigPath)}\" ` +\n '(resolved against the Vite root) — auto-instrumentation disabled.'\n : '[sentry] No parseable wrangler config found — auto-instrumentation disabled. ' +\n 'Set `wranglerConfigPath` if your config uses a custom name.',\n );\n return;\n }\n\n wranglerConfig = result.config;\n if (wranglerConfig.main) {\n // `main` is already absolute (wrangler resolves it); just normalize\n // separators so the entry-module comparison holds on Windows.\n entryFilePath = normalizePath(wranglerConfig.main);\n }\n\n if (entryFilePath) {\n const instrumentFilePath = resolveInstrumentFile(entryFilePath);\n if (instrumentFilePath) {\n const built = buildOptionsImport(entryFilePath, instrumentFilePath);\n optionsFn = built.optionsFn;\n optionsImport = built.importStmt;\n }\n }\n },\n\n async transform(\n this: ModuleResolver & { warn?(msg: string): void; environment?: { name?: string } },\n code: string,\n id: string,\n ): Promise<{ code: string; map: unknown } | undefined> {\n if (!wranglerConfig || !entryFilePath) return undefined;\n\n // The worker entry never belongs to the client (browser) environment.\n // Skipping it keeps a same-basename sibling (e.g. a `src/index.tsx`\n // client entry next to a `src/index.ts` worker) out of the browser bundle.\n if (this.environment?.name === 'client') return undefined;\n\n // Vite may append query/hash params to the module ID.\n const normalizedId = normalizePath(id.replace(/[?#].*$/, ''));\n if (normalizedId !== entryFilePath) {\n // Tolerate a differing JS-flavored extension (e.g. `.js` vs `.ts`).\n if (!JS_EXTENSION_REGEX.test(normalizedId) || !JS_EXTENSION_REGEX.test(entryFilePath)) return undefined;\n if (normalizedId.replace(JS_EXTENSION_REGEX, '') !== entryFilePath.replace(JS_EXTENSION_REGEX, '')) {\n return undefined;\n }\n }\n\n let ast: ProgramBody;\n try {\n ast = this.parse(code);\n } catch {\n // Raw TypeScript or syntax error — esbuild hasn't run yet (unlikely)\n // or the file is genuinely broken. Either way, skip silently.\n return undefined;\n }\n\n const classWrappers = new Map<string, ClassWrapperKind>();\n for (const { className } of wranglerConfig.durableObjects) {\n classWrappers.set(className, 'durableObject');\n }\n for (const { className } of wranglerConfig.workflows) {\n classWrappers.set(className, 'workflow');\n }\n for (const className of wranglerConfig.workerEntrypoints) {\n classWrappers.set(className, 'workerEntrypoint');\n }\n\n // An `agents` Agent is a Durable Object, so wrangler lists it among the DO bindings and only\n // its base-class chain tells the two apart. Detection walks the module graph (base classes\n // usually live in their own file), so it is limited to the configured DO classes.\n //\n // Only `resolve` is handed over — never `load`: awaiting `load()` from inside a transform\n // hook deadlocks the build, since the module can't finish loading while this transform is\n // still pending. `agentClass` reads sibling modules off disk instead.\n const agentCandidates = collectAgentCandidates(\n ast,\n [...classWrappers].filter(([, kind]) => kind === 'durableObject').map(([name]) => name),\n );\n const agentClasses =\n agentCandidates.size > 0\n ? await detectAgentClasses(ast, normalizedId, agentCandidates, {\n parse: code => this.parse(code),\n resolve: this.resolve ? (source, importer) => this.resolve!(source, importer) : undefined,\n })\n : undefined;\n\n // No registration import is injected here: the orchestrion plugin's\n // subscribe-injection makes each bundled package self-register its channel\n // subscriber on the global marker, so wrapping the entry with `withSentry`\n // is all this plugin needs to do.\n const result = applyAutoInstrumentTransforms(code, ast, {\n classWrappers,\n agentClasses,\n optionsFn,\n optionsImport,\n sameWorkerBindings: wranglerConfig.sameWorkerBindings,\n });\n\n const wrappedClasses = result?.wrappedClasses ?? new Set<string>();\n const missing = [...classWrappers.keys()].filter(name => !wrappedClasses.has(name));\n if (missing.length > 0) {\n this.warn?.(\n `[sentry] Could not auto-instrument class(es) ${missing.join(', ')}: no matching exported class ` +\n 'declaration found in the worker entry (re-exports from other modules cannot be wrapped ' +\n 'automatically). Wrap them manually with the matching `instrument*WithSentry` helper.',\n );\n }\n\n return result ?? undefined;\n },\n };\n}\n"],"names":["wranglerConfig","ENV_FALLBACK_OPTIONS_FN","resolveWranglerConfig","basename","resolveInstrumentFile","buildOptionsImport","collectAgentCandidates","detectAgentClasses","code","applyAutoInstrumentTransforms"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"autoInstrument.js","sources":["../../../../src/vite/autoInstrument.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport { collectAgentCandidates, detectAgentClasses, type ModuleResolver } from './agentClass';\nimport { buildOptionsImport, ENV_FALLBACK_OPTIONS_FN, resolveInstrumentFile } from './instrumentFile';\nimport { applyAutoInstrumentTransforms, type ClassWrapperKind, type ProgramBody } from './transform';\nimport { resolveWranglerConfig, type WranglerConfig } from './wranglerConfig';\n\n// Vite normalizes module IDs to posix separators even on Windows, while\n// `path.resolve` yields backslashes there — normalize before comparing.\nfunction normalizePath(path: string): string {\n return path.replace(/\\\\/g, '/');\n}\n\n// Extensions the entry-module match may tolerate swapping (e.g. wrangler's\n// `main` says `.ts` but the served module is `.js`). Anything else — `.css`,\n// `.html`, … — sharing the entry's basename must never be treated as the entry.\nconst JS_EXTENSION_REGEX = /\\.[cm]?[jt]sx?$/;\n\nexport function sentryCloudflareAutoInstrumentPlugin(options: { wranglerConfigPath?: string } = {}) {\n let wranglerConfig: WranglerConfig | undefined;\n let entryFilePath: string | undefined;\n\n let optionsFn = ENV_FALLBACK_OPTIONS_FN;\n let optionsImport: string | undefined;\n\n return {\n name: 'sentry-cloudflare-auto-instrument',\n\n configResolved(config: { root: string; logger?: { warn(msg: string): void } }): void {\n const result = resolveWranglerConfig(config.root, options.wranglerConfigPath);\n if (!result) {\n // An explicit path that fails is a misconfiguration worth naming;\n // without one, hint at the option so custom-named configs (e.g. a\n // `configPath` handed to @cloudflare/vite-plugin) are discoverable.\n config.logger?.warn(\n options.wranglerConfigPath\n ? `[sentry] Could not find or parse the wrangler config \"${basename(options.wranglerConfigPath)}\" ` +\n '(resolved against the Vite root) — auto-instrumentation disabled.'\n : '[sentry] No parseable wrangler config found — auto-instrumentation disabled. ' +\n 'Set `wranglerConfigPath` if your config uses a custom name.',\n );\n return;\n }\n\n wranglerConfig = result.config;\n if (wranglerConfig.main) {\n // `main` is already absolute (wrangler resolves it); just normalize\n // separators so the entry-module comparison holds on Windows.\n entryFilePath = normalizePath(wranglerConfig.main);\n }\n\n if (entryFilePath) {\n const instrumentFilePath = resolveInstrumentFile(entryFilePath);\n if (instrumentFilePath) {\n const built = buildOptionsImport(entryFilePath, instrumentFilePath);\n optionsFn = built.optionsFn;\n optionsImport = built.importStmt;\n }\n }\n },\n\n async transform(\n this: ModuleResolver & { warn?(msg: string): void; environment?: { name?: string } },\n code: string,\n id: string,\n ): Promise<{ code: string; map: unknown } | undefined> {\n if (!wranglerConfig || !entryFilePath) return undefined;\n\n // The worker entry never belongs to the client (browser) environment.\n // Skipping it keeps a same-basename sibling (e.g. a `src/index.tsx`\n // client entry next to a `src/index.ts` worker) out of the browser bundle.\n if (this.environment?.name === 'client') return undefined;\n\n // Vite may append query/hash params to the module ID.\n const normalizedId = normalizePath(id.replace(/[?#].*$/, ''));\n if (normalizedId !== entryFilePath) {\n // Tolerate a differing JS-flavored extension (e.g. `.js` vs `.ts`).\n if (!JS_EXTENSION_REGEX.test(normalizedId) || !JS_EXTENSION_REGEX.test(entryFilePath)) return undefined;\n if (normalizedId.replace(JS_EXTENSION_REGEX, '') !== entryFilePath.replace(JS_EXTENSION_REGEX, '')) {\n return undefined;\n }\n }\n\n let ast: ProgramBody;\n try {\n ast = this.parse(code);\n } catch {\n // Raw TypeScript or syntax error — esbuild hasn't run yet (unlikely)\n // or the file is genuinely broken. Either way, skip silently.\n return undefined;\n }\n\n const classWrappers = new Map<string, ClassWrapperKind>();\n for (const { className } of wranglerConfig.durableObjects) {\n classWrappers.set(className, 'durableObject');\n }\n for (const { className } of wranglerConfig.workflows) {\n classWrappers.set(className, 'workflow');\n }\n for (const className of wranglerConfig.workerEntrypoints) {\n classWrappers.set(className, 'workerEntrypoint');\n }\n\n // An `agents` Agent is a Durable Object, so wrangler lists it among the DO bindings and only\n // its base-class chain tells the two apart. Detection walks the module graph (base classes\n // usually live in their own file), so it is limited to the configured DO classes.\n //\n // Only `resolve` is handed over — never `load`: awaiting `load()` from inside a transform\n // hook deadlocks the build, since the module can't finish loading while this transform is\n // still pending. `agentClass` reads sibling modules off disk instead.\n const agentCandidates = collectAgentCandidates(\n ast,\n [...classWrappers].filter(([, kind]) => kind === 'durableObject').map(([name]) => name),\n );\n const agentClasses =\n agentCandidates.size > 0\n ? await detectAgentClasses(ast, normalizedId, agentCandidates, {\n parse: code => this.parse(code),\n resolve: this.resolve ? (source, importer) => this.resolve!(source, importer) : undefined,\n })\n : undefined;\n\n // No registration import is injected here: the orchestrion plugin's\n // subscribe-injection makes each bundled package self-register its channel\n // subscriber on the global marker, so wrapping the entry with `withSentry`\n // is all this plugin needs to do.\n const result = applyAutoInstrumentTransforms(code, ast, {\n classWrappers,\n agentClasses,\n optionsFn,\n optionsImport,\n sameWorkerBindings: wranglerConfig.sameWorkerBindings,\n });\n\n const wrappedClasses = result?.wrappedClasses ?? new Set<string>();\n const missing = [...classWrappers.keys()].filter(name => !wrappedClasses.has(name));\n if (missing.length > 0) {\n this.warn?.(\n `[sentry] Could not auto-instrument ${missing.join(', ')}.` +\n 'The worker entry has no export matching them. ' +\n 'Star re-exports (`export * from \"./do\"`) are not matched. ' +\n 'Export them by name or wrap them manually with corresponding `instrument*WithSentry` helpers.',\n );\n }\n\n return result ?? undefined;\n },\n };\n}\n"],"names":["wranglerConfig","ENV_FALLBACK_OPTIONS_FN","resolveWranglerConfig","basename","resolveInstrumentFile","buildOptionsImport","collectAgentCandidates","detectAgentClasses","code","applyAutoInstrumentTransforms"],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@ function isCallToMethod(node, methodName) {
|
|
|
12
12
|
if (callee.type === "Identifier" && callee.name === methodName) return true;
|
|
13
13
|
return callee.type === "MemberExpression" && callee.property?.type === "Identifier" && callee.property.name === methodName;
|
|
14
14
|
}
|
|
15
|
+
const DEFAULT_IMPORT = "default";
|
|
15
16
|
const WRAPPER_METHODS = {
|
|
16
17
|
durableObject: "instrumentDurableObjectWithSentry",
|
|
17
18
|
agent: "instrumentAgentWithSentry",
|
|
@@ -33,7 +34,8 @@ function applyAutoInstrumentTransforms(code, ast, ctx) {
|
|
|
33
34
|
workerEntrypointClasses: workerEntrypoint.detectWorkerEntrypointClasses(ast),
|
|
34
35
|
// The identifier must be chosen before wrapping, which bindings survive is only known after.
|
|
35
36
|
optionsFn: sameWorkerBindings.length > 0 ? MERGED_OPTIONS_IDENTIFIER : ctx.optionsFn,
|
|
36
|
-
autoWrapped: /* @__PURE__ */ new Set()
|
|
37
|
+
autoWrapped: /* @__PURE__ */ new Set(),
|
|
38
|
+
manuallyWrappedLocals: collectManuallyWrappedLocals(ast)
|
|
37
39
|
};
|
|
38
40
|
const { wrappedClasses } = state;
|
|
39
41
|
for (const node of ast.body) {
|
|
@@ -73,11 +75,28 @@ function buildMergedOptionsDeclaration(sameWorkerBindings, optionsFn, state) {
|
|
|
73
75
|
}
|
|
74
76
|
function resolveWrapperKind(exportedName, localName, state) {
|
|
75
77
|
const configured = state.classWrappers.get(exportedName);
|
|
76
|
-
if (configured === "durableObject" && localName && state.agentClasses.has(localName))
|
|
78
|
+
if (configured === "durableObject" && (localName && state.agentClasses.has(localName) || state.agentClasses.has(exportedName))) {
|
|
79
|
+
return "agent";
|
|
80
|
+
}
|
|
77
81
|
if (configured) return configured;
|
|
78
82
|
if (localName && state.workerEntrypointClasses.has(localName)) return "workerEntrypoint";
|
|
79
83
|
return void 0;
|
|
80
84
|
}
|
|
85
|
+
function collectManuallyWrappedLocals(ast) {
|
|
86
|
+
const wrapperMethods = Object.values(WRAPPER_METHODS);
|
|
87
|
+
const locals = /* @__PURE__ */ new Set();
|
|
88
|
+
for (const node of ast.body) {
|
|
89
|
+
if (node.type !== "VariableDeclaration") continue;
|
|
90
|
+
for (const declarator of node.declarations ?? []) {
|
|
91
|
+
const name = declarator.id?.type === "Identifier" ? declarator.id.name : void 0;
|
|
92
|
+
const init = declarator.init;
|
|
93
|
+
if (name && init && wrapperMethods.some((method) => isCallToMethod(init, method))) {
|
|
94
|
+
locals.add(name);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return locals;
|
|
99
|
+
}
|
|
81
100
|
function collectTopLevelClasses(ast) {
|
|
82
101
|
const classes = /* @__PURE__ */ new Map();
|
|
83
102
|
for (const node of ast.body) {
|
|
@@ -111,10 +130,7 @@ function handleNamedExport(node, ctx, state) {
|
|
|
111
130
|
wrapInlineClassExport(node, decl, ctx, state);
|
|
112
131
|
return;
|
|
113
132
|
}
|
|
114
|
-
|
|
115
|
-
for (const specifier of node.specifiers ?? []) {
|
|
116
|
-
wrapSpecifierExport(specifier, ctx, state);
|
|
117
|
-
}
|
|
133
|
+
wrapSpecifierExports(node, ctx, state);
|
|
118
134
|
}
|
|
119
135
|
function collectManuallyWrappedClassExports(varDecl, ctx, state) {
|
|
120
136
|
for (const declarator of varDecl.declarations ?? []) {
|
|
@@ -146,22 +162,69 @@ export const ${className} = __SENTRY__.${WRAPPER_METHODS[kind]}(${state.optionsF
|
|
|
146
162
|
state.renamedLocals.add(className);
|
|
147
163
|
state.needsImport = true;
|
|
148
164
|
}
|
|
149
|
-
function
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
165
|
+
function wrapSpecifierExports(node, ctx, state) {
|
|
166
|
+
const specifiers = node.specifiers ?? [];
|
|
167
|
+
if (specifiers.length === 0) return;
|
|
168
|
+
const sourceLiteral = node.source ? state.ms.original.slice(node.source.start, node.source.end) : void 0;
|
|
169
|
+
const prelude = [];
|
|
170
|
+
const wrappedPairs = [];
|
|
171
|
+
const kept = [];
|
|
172
|
+
for (const specifier of specifiers) {
|
|
173
|
+
const pair = wrapCrossModuleSpecifier(specifier, sourceLiteral, ctx, state, prelude);
|
|
174
|
+
if (pair) {
|
|
175
|
+
wrappedPairs.push(pair);
|
|
176
|
+
} else {
|
|
177
|
+
kept.push(state.ms.original.slice(specifier.start, specifier.end));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (wrappedPairs.length === 0) return;
|
|
181
|
+
const statements = [...prelude, `export { ${wrappedPairs.join(", ")} };`];
|
|
182
|
+
if (kept.length > 0) {
|
|
183
|
+
const clause = `export { ${kept.join(", ")} }`;
|
|
184
|
+
statements.push(sourceLiteral ? `${clause} from ${sourceLiteral};` : `${clause};`);
|
|
185
|
+
}
|
|
186
|
+
state.ms.overwrite(node.start, node.end, statements.join("\n"));
|
|
187
|
+
}
|
|
188
|
+
function wrapCrossModuleSpecifier(specifier, sourceLiteral, ctx, state, prelude) {
|
|
189
|
+
const exportedName = specifier.type === "ExportSpecifier" && specifier.exported?.type === "Identifier" ? specifier.exported.name : void 0;
|
|
153
190
|
const localName = specifier.local?.type === "Identifier" ? specifier.local.name : void 0;
|
|
154
|
-
const kind = resolveWrapperKind(exportedName, localName, state);
|
|
155
|
-
if (!kind) return;
|
|
156
|
-
|
|
157
|
-
|
|
191
|
+
const kind = exportedName ? resolveWrapperKind(exportedName, sourceLiteral ? void 0 : localName, state) : void 0;
|
|
192
|
+
if (!exportedName || !localName || !kind) return void 0;
|
|
193
|
+
if (!sourceLiteral) {
|
|
194
|
+
const localClass = state.topLevelClasses.get(localName);
|
|
195
|
+
if (localClass?.id) {
|
|
196
|
+
wrapLocalClassExport(localName, localClass, kind, ctx, state);
|
|
197
|
+
state.wrappedClasses.add(exportedName);
|
|
198
|
+
state.needsImport = true;
|
|
199
|
+
return void 0;
|
|
200
|
+
}
|
|
201
|
+
if (state.manuallyWrappedLocals.has(localName)) {
|
|
202
|
+
state.wrappedClasses.add(exportedName);
|
|
203
|
+
return void 0;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
let target = localName;
|
|
207
|
+
if (sourceLiteral) {
|
|
208
|
+
target = `__SENTRY_REEXPORT_${exportedName}__`;
|
|
209
|
+
prelude.push(
|
|
210
|
+
localName === DEFAULT_IMPORT ? `import ${target} from ${sourceLiteral};` : `import { ${localName} as ${target} } from ${sourceLiteral};`
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
const wrappedName = `__SENTRY_WRAPPED_${exportedName}__`;
|
|
214
|
+
prelude.push(
|
|
215
|
+
`const ${wrappedName} = __SENTRY__._INTERNAL_wrapUnlessInstrumented(__SENTRY__.${WRAPPER_METHODS[kind]}, ${state.optionsFn}, ${target});`
|
|
216
|
+
);
|
|
158
217
|
state.wrappedClasses.add(exportedName);
|
|
159
218
|
state.autoWrapped.add(exportedName);
|
|
160
219
|
state.needsImport = true;
|
|
161
|
-
|
|
220
|
+
return `${wrappedName} as ${exportedName}`;
|
|
221
|
+
}
|
|
222
|
+
function wrapLocalClassExport(localName, localClass, kind, ctx, state) {
|
|
223
|
+
const classId = localClass.id;
|
|
224
|
+
if (!classId || state.renamedLocals.has(localName)) return;
|
|
162
225
|
state.renamedLocals.add(localName);
|
|
163
226
|
const renamedClass = `__SENTRY_ORIGINAL_${localName}__`;
|
|
164
|
-
state.ms.overwrite(
|
|
227
|
+
state.ms.overwrite(classId.start, classId.end, renamedClass);
|
|
165
228
|
state.ms.appendLeft(
|
|
166
229
|
localClass.end,
|
|
167
230
|
`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.js","sources":["../../../../src/vite/transform.ts"],"sourcesContent":["import MagicString from 'magic-string';\nimport { DEFAULT_EXPORT, type ExportName, type SameWorkerBinding } from './wranglerConfig';\nimport { detectWorkerEntrypointClasses } from './workerEntrypoint';\n\nconst MERGED_OPTIONS_IDENTIFIER = '__SENTRY_OPTIONS__';\n\n// ---------------------------------------------------------------------------\n// Minimal ESTree node types for the AST nodes we inspect.\n// ---------------------------------------------------------------------------\n\nexport interface BaseNode {\n type: string;\n start: number;\n end: number;\n}\n\nexport interface ProgramBody {\n body: BaseNode[];\n}\n\ninterface IdentifierNode extends BaseNode {\n name: string;\n}\n\ninterface CalleeNode {\n type: string;\n name?: string;\n property?: { type: string; name?: string };\n}\n\ninterface CallExpressionNode extends BaseNode {\n callee?: CalleeNode;\n}\n\ninterface ClassDeclarationNode extends BaseNode {\n id?: IdentifierNode | null;\n}\n\ninterface ExportDefaultNode extends BaseNode {\n declaration: BaseNode;\n}\n\ninterface ExportSpecifierNode {\n type: string;\n local?: { type: string; name?: string };\n exported?: { type: string; name?: string };\n}\n\ninterface ExportNamedNode extends BaseNode {\n declaration?: BaseNode | null;\n source?: unknown;\n specifiers?: ExportSpecifierNode[];\n}\n\ninterface VariableDeclaratorNode {\n id?: { type: string; name?: string };\n init?: BaseNode | null;\n}\n\ninterface VariableDeclarationNode extends BaseNode {\n declarations?: VariableDeclaratorNode[];\n}\n\nfunction isCallToMethod(node: BaseNode, methodName: string): boolean {\n if (node.type !== 'CallExpression') return false;\n const callee = (node as CallExpressionNode).callee;\n if (!callee) return false;\n if (callee.type === 'Identifier' && callee.name === methodName) return true;\n return (\n callee.type === 'MemberExpression' && callee.property?.type === 'Identifier' && callee.property.name === methodName\n );\n}\n\n/**\n * The kind of Sentry wrapper to apply to an exported class.\n *\n * `durableObject` and `workflow` are keyed by name from the wrangler config\n * (`durable_objects.bindings`, `workflows`), since those class names are\n * authoritative there. `workerEntrypoint` is different: a worker's own\n * entrypoints aren't enumerated in its config, so they're detected structurally\n * (a class extending `WorkerEntrypoint` from `cloudflare:workers`), with the\n * config providing only a fallback for self-bound entrypoints whose base class\n * lives in another module.\n */\nexport type ClassWrapperKind = 'durableObject' | 'agent' | 'workflow' | 'workerEntrypoint';\n\n/**\n * The `@sentry/cloudflare` helper each wrapper kind emits. All share the same\n * `(optionsCallback, Class)` signature. `WorkerEntrypoint` classes use\n * `withSentry`, which runtime-detects the class type and routes accordingly.\n */\nconst WRAPPER_METHODS: Record<ClassWrapperKind, string> = {\n durableObject: 'instrumentDurableObjectWithSentry',\n agent: 'instrumentAgentWithSentry',\n workflow: 'instrumentWorkflowWithSentry',\n workerEntrypoint: 'withSentry',\n};\n\nexport interface TransformContext {\n /**\n * Exported class name → the kind of Sentry wrapper to apply. Populated from\n * the wrangler config, so the transform can wrap by name without resolving\n * each class's base type.\n */\n classWrappers: Map<string, ClassWrapperKind>;\n /**\n * Local class names detected as `agents` Agents. An Agent is configured as a Durable Object in\n * wrangler, so this upgrades those entries from `durableObject` to `agent`.\n */\n agentClasses?: ReadonlySet<string>;\n optionsFn: string;\n /** Import statement prepended when `optionsFn` references a separate module. */\n optionsImport?: string;\n /** @see {@link import('./wranglerConfig').WranglerConfig.sameWorkerBindings} */\n sameWorkerBindings?: readonly SameWorkerBinding[];\n}\n\nexport interface TransformResult {\n code: string;\n map: ReturnType<MagicString['generateMap']>;\n /**\n * The configured class names that were actually wrapped. Lets the plugin warn\n * about configured classes it could not find, instead of silently leaving\n * them uninstrumented.\n */\n wrappedClasses: Set<string>;\n}\n\n/**\n * Rewrite the worker entry source to wrap its default export with `withSentry`\n * and any configured class export with its matching Sentry wrapper (see\n * {@link TransformContext.classWrappers}, e.g. Durable Object classes with\n * `instrumentDurableObjectWithSentry`).\n *\n * Handles both `export class MyDO {}` and the specifier form\n * (`class MyDO {}` … `export { MyDO }` / `export { Foo as MyDO }`).\n * Re-exports from other modules (`export { MyDO } from './do'`) cannot be\n * wrapped here and are left alone — the plugin warns about them via\n * {@link TransformResult.wrappedClasses}.\n *\n * Exported (rather than inlined into the plugin) so it can be unit-tested with a\n * plain AST and no Vite context. Returns `undefined` when nothing was wrapped and\n * there are no already-manually-wrapped classes to report.\n */\nexport function applyAutoInstrumentTransforms(\n code: string,\n ast: ProgramBody,\n ctx: TransformContext,\n): TransformResult | undefined {\n const ms = new MagicString(code);\n const topLevelClasses = collectTopLevelClasses(ast);\n const sameWorkerBindings = ctx.sameWorkerBindings ?? [];\n const state: TransformState = {\n ms,\n needsImport: false,\n wrappedClasses: new Set<string>(),\n topLevelClasses,\n renamedLocals: new Set<string>(),\n classWrappers: ctx.classWrappers,\n agentClasses: ctx.agentClasses ?? new Set<string>(),\n workerEntrypointClasses: detectWorkerEntrypointClasses(ast),\n // The identifier must be chosen before wrapping, which bindings survive is only known after.\n optionsFn: sameWorkerBindings.length > 0 ? MERGED_OPTIONS_IDENTIFIER : ctx.optionsFn,\n autoWrapped: new Set<ExportName>(),\n };\n const { wrappedClasses } = state;\n\n // Named exports first, regardless of source order: the default-export handler\n // needs to know which local bindings a named export already wrapped, so it can\n // skip a class that is both exported by name and re-exported as default (which\n // would otherwise wrap it twice).\n for (const node of ast.body) {\n if (node.type === 'ExportNamedDeclaration') {\n handleNamedExport(node, ctx, state);\n }\n }\n for (const node of ast.body) {\n if (node.type === 'ExportDefaultDeclaration') {\n wrapDefaultExport(node as ExportDefaultNode, ctx, state);\n }\n }\n\n if (!state.needsImport) {\n // Nothing was rewritten. Still surface any classes found already wrapped\n // manually (via `wrappedClasses`) so the caller doesn't warn about them;\n // return undefined only when there was nothing to report either.\n if (wrappedClasses.size === 0) return undefined;\n return { code, map: ms.generateMap({ hires: true }), wrappedClasses };\n }\n\n // `prepend` inserts before earlier prepends, yielding: Sentry import, options import, declaration.\n if (sameWorkerBindings.length > 0) {\n ms.prepend(buildMergedOptionsDeclaration(sameWorkerBindings, ctx.optionsFn, state));\n }\n if (ctx.optionsImport) ms.prepend(ctx.optionsImport);\n ms.prepend(\"import * as __SENTRY__ from '@sentry/cloudflare';\\n\");\n\n return {\n code: ms.toString(),\n map: ms.generateMap({ hires: true }),\n wrappedClasses,\n };\n}\n\ninterface TransformState {\n ms: MagicString;\n needsImport: boolean;\n wrappedClasses: Set<string>;\n /**\n * Top-level (non-exported) class declarations, so specifier exports like\n * `export { MyDO }` can locate the class they refer to.\n */\n topLevelClasses: Map<string, ClassDeclarationNode>;\n /**\n * Local class names already renamed + wrapped, so two specifiers pointing at\n * the same class don't produce duplicate bindings.\n */\n renamedLocals: Set<string>;\n /** Class name → wrapper kind, keyed by the *exported* name (from config). */\n classWrappers: Map<string, ClassWrapperKind>;\n /** Local class names detected as `agents` Agents (see {@link TransformContext.agentClasses}). */\n agentClasses: ReadonlySet<string>;\n /**\n * Local class names detected as `WorkerEntrypoint` subclasses in this module,\n * so they can be wrapped without a config entry.\n */\n workerEntrypointClasses: Set<string>;\n optionsFn: string;\n /**\n * Export names wrapped by this transform, so their options can be extended with\n * `rpcTracePropagationBindings`. Hand-wrapped exports stay out, they keep the options they were\n * wrapped with. `wrappedClasses` counts both.\n */\n autoWrapped: Set<ExportName>;\n}\n\n/**\n * Builds the callback that merges same-worker binding names into `rpcTracePropagationBindings` at\n * runtime, the options object only exists once the callback runs with `env`. Only bindings whose\n * class this transform wrapped survive, a hand-wrapped class runs on its own options.\n */\nfunction buildMergedOptionsDeclaration(\n sameWorkerBindings: readonly SameWorkerBinding[],\n optionsFn: string,\n state: TransformState,\n): string {\n const bindingNames = sameWorkerBindings\n .filter(({ className }) => state.autoWrapped.has(className))\n .map(({ bindingName }) => bindingName);\n\n if (!bindingNames.length) {\n return `const ${MERGED_OPTIONS_IDENTIFIER} = ${optionsFn};\\n`;\n }\n\n const names = bindingNames.map(name => JSON.stringify(name)).join(', ');\n return (\n `const ${MERGED_OPTIONS_IDENTIFIER} = (env) => { ` +\n `const opts = (${optionsFn})(env); ` +\n `return { ...opts, rpcTracePropagationBindings: [${names}, ...(opts?.rpcTracePropagationBindings ?? [])] }; };\\n`\n );\n}\n\n/**\n * Resolve the wrapper kind for a class export.\n *\n * Config (`classWrappers`) wins — it's authoritative for Durable Objects and\n * Workflows, and provides the self-binding fallback for WorkerEntrypoints whose\n * base class this module can't see. Otherwise a structurally-detected\n * `WorkerEntrypoint` subclass (matched by its *local* name) gets wrapped with\n * `withSentry`.\n *\n * The one case where config is refined rather than obeyed is an `agents` Agent:\n * it *is* a Durable Object, so wrangler can only ever describe it as one, and\n * only the detected base chain distinguishes the two.\n */\nfunction resolveWrapperKind(\n exportedName: string,\n localName: string | undefined,\n state: TransformState,\n): ClassWrapperKind | undefined {\n const configured = state.classWrappers.get(exportedName);\n if (configured === 'durableObject' && localName && state.agentClasses.has(localName)) return 'agent';\n if (configured) return configured;\n if (localName && state.workerEntrypointClasses.has(localName)) return 'workerEntrypoint';\n return undefined;\n}\n\nfunction collectTopLevelClasses(ast: ProgramBody): Map<string, ClassDeclarationNode> {\n const classes = new Map<string, ClassDeclarationNode>();\n for (const node of ast.body) {\n if (node.type !== 'ClassDeclaration') continue;\n const classNode = node as ClassDeclarationNode;\n if (classNode.id?.name) classes.set(classNode.id.name, classNode);\n }\n return classes;\n}\n\nfunction wrapDefaultExport(node: ExportDefaultNode, ctx: TransformContext, state: TransformState): void {\n const decl = node.declaration;\n\n // Already wrapped — leave it alone\n if (isCallToMethod(decl, 'withSentry')) return;\n\n // `export default Foo` where `Foo` is a local class already wrapped by a named\n // export (e.g. a self-bound WorkerEntrypoint also used as the default handler).\n // Wrapping again would produce `withSentry(withSentry(...))`. The binding still\n // points at the wrapped class, so the default export counts as auto-wrapped.\n if (decl.type === 'Identifier' && state.renamedLocals.has((decl as IdentifierNode).name)) {\n state.autoWrapped.add(DEFAULT_EXPORT);\n return;\n }\n\n // `export default <expr>` → `const __SENTRY_DEFAULT_EXPORT__ = <expr>`\n // MagicString positions are always relative to the original source.\n state.ms.overwrite(node.start, decl.start, 'const __SENTRY_DEFAULT_EXPORT__ = ');\n state.ms.append(`\\nexport default __SENTRY__.withSentry(${state.optionsFn}, __SENTRY_DEFAULT_EXPORT__);\\n`);\n state.needsImport = true;\n state.autoWrapped.add(DEFAULT_EXPORT);\n}\n\nfunction handleNamedExport(node: ExportNamedNode, ctx: TransformContext, state: TransformState): void {\n const decl = node.declaration;\n\n // ---- Manually wrapped class export ----\n // `export const MyDO = instrumentDurableObjectWithSentry(...)` — count it\n // as wrapped so the plugin doesn't warn about it, but leave it alone.\n if (decl?.type === 'VariableDeclaration') {\n collectManuallyWrappedClassExports(decl, ctx, state);\n return;\n }\n\n // ---- Named class export matching a configured binding ----\n if (decl?.type === 'ClassDeclaration') {\n wrapInlineClassExport(node, decl, ctx, state);\n return;\n }\n\n // ---- Specifier export of a local class (`export { Foo as MyDO }`) ----\n // Re-exports from another module carry a `source` — nothing local to wrap.\n if (node.source) return;\n for (const specifier of node.specifiers ?? []) {\n wrapSpecifierExport(specifier, ctx, state);\n }\n}\n\nfunction collectManuallyWrappedClassExports(\n varDecl: VariableDeclarationNode,\n ctx: TransformContext,\n state: TransformState,\n): void {\n for (const declarator of varDecl.declarations ?? []) {\n const name = declarator.id?.type === 'Identifier' ? declarator.id.name : undefined;\n const kind = name ? ctx.classWrappers.get(name) : undefined;\n if (!name || !kind || !declarator.init) continue;\n\n // A hand-wrapped Agent is configured as a Durable Object, so accept either helper there —\n // otherwise an already-instrumented Agent would be reported as unwrapped.\n const accepted =\n kind === 'durableObject' ? [WRAPPER_METHODS.durableObject, WRAPPER_METHODS.agent] : [WRAPPER_METHODS[kind]];\n\n if (accepted.some(method => isCallToMethod(declarator.init as BaseNode, method))) {\n state.wrappedClasses.add(name);\n }\n }\n}\n\nfunction wrapInlineClassExport(\n exportNode: ExportNamedNode,\n classDecl: ClassDeclarationNode,\n ctx: TransformContext,\n state: TransformState,\n): void {\n const classId = classDecl.id;\n // Inline export: the exported name and the local class name are the same.\n const kind = classId ? resolveWrapperKind(classId.name, classId.name, state) : undefined;\n if (!classId || !kind) return;\n\n const className = classId.name;\n const renamedClass = `__SENTRY_ORIGINAL_${className}__`;\n\n // Strip the `export ` keyword\n state.ms.overwrite(exportNode.start, classDecl.start, '');\n\n // Rename the class to avoid a duplicate binding\n state.ms.overwrite(classId.start, classId.end, renamedClass);\n\n // Insert the wrapped re-export after the class body\n state.ms.appendLeft(\n exportNode.end,\n `\\nexport const ${className} = __SENTRY__.${WRAPPER_METHODS[kind]}(${state.optionsFn}, ${renamedClass});\\n`,\n );\n\n state.wrappedClasses.add(className);\n state.autoWrapped.add(className);\n state.renamedLocals.add(className);\n state.needsImport = true;\n}\n\nfunction wrapSpecifierExport(specifier: ExportSpecifierNode, ctx: TransformContext, state: TransformState): void {\n if (specifier.type !== 'ExportSpecifier' || specifier.exported?.type !== 'Identifier') return;\n const exportedName = specifier.exported.name;\n if (!exportedName) return;\n\n const localName = specifier.local?.type === 'Identifier' ? specifier.local.name : undefined;\n const kind = resolveWrapperKind(exportedName, localName, state);\n if (!kind) return;\n\n const localClass = localName ? state.topLevelClasses.get(localName) : undefined;\n if (!localName || !localClass?.id) return;\n\n state.wrappedClasses.add(exportedName);\n state.autoWrapped.add(exportedName);\n state.needsImport = true;\n if (state.renamedLocals.has(localName)) return;\n state.renamedLocals.add(localName);\n\n const renamedClass = `__SENTRY_ORIGINAL_${localName}__`;\n state.ms.overwrite(localClass.id.start, localClass.id.end, renamedClass);\n // The existing `export { ... }` statement keeps exporting the (now\n // wrapped) `localName` binding, so the wrapper is NOT exported here.\n state.ms.appendLeft(\n localClass.end,\n `\\nconst ${localName} = __SENTRY__.${WRAPPER_METHODS[kind]}(${state.optionsFn}, ${renamedClass});\\n`,\n );\n}\n"],"names":["MagicString","detectWorkerEntrypointClasses","DEFAULT_EXPORT"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transform.js","sources":["../../../../src/vite/transform.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport MagicString from 'magic-string';\nimport { DEFAULT_EXPORT, type ExportName, type SameWorkerBinding } from './wranglerConfig';\nimport { detectWorkerEntrypointClasses } from './workerEntrypoint';\n\nconst MERGED_OPTIONS_IDENTIFIER = '__SENTRY_OPTIONS__';\n\n// ---------------------------------------------------------------------------\n// Minimal ESTree node types for the AST nodes we inspect.\n// ---------------------------------------------------------------------------\n\nexport interface BaseNode {\n type: string;\n start: number;\n end: number;\n}\n\nexport interface ProgramBody {\n body: BaseNode[];\n}\n\ninterface IdentifierNode extends BaseNode {\n name: string;\n}\n\ninterface CalleeNode {\n type: string;\n name?: string;\n property?: { type: string; name?: string };\n}\n\ninterface CallExpressionNode extends BaseNode {\n callee?: CalleeNode;\n}\n\ninterface ClassDeclarationNode extends BaseNode {\n id?: IdentifierNode | null;\n}\n\ninterface ExportDefaultNode extends BaseNode {\n declaration: BaseNode;\n}\n\ninterface ExportSpecifierNode extends BaseNode {\n local?: { type: string; name?: string };\n exported?: { type: string; name?: string };\n}\n\ninterface ExportNamedNode extends BaseNode {\n declaration?: BaseNode | null;\n source?: BaseNode | null;\n specifiers?: ExportSpecifierNode[];\n}\n\ninterface VariableDeclaratorNode {\n id?: { type: string; name?: string };\n init?: BaseNode | null;\n}\n\ninterface VariableDeclarationNode extends BaseNode {\n declarations?: VariableDeclaratorNode[];\n}\n\nfunction isCallToMethod(node: BaseNode, methodName: string): boolean {\n if (node.type !== 'CallExpression') return false;\n const callee = (node as CallExpressionNode).callee;\n if (!callee) return false;\n if (callee.type === 'Identifier' && callee.name === methodName) return true;\n return (\n callee.type === 'MemberExpression' && callee.property?.type === 'Identifier' && callee.property.name === methodName\n );\n}\n\n/**\n * The kind of Sentry wrapper to apply to an exported class.\n *\n * `durableObject` and `workflow` are keyed by name from the wrangler config\n * (`durable_objects.bindings`, `workflows`), since those class names are\n * authoritative there. `workerEntrypoint` is different: a worker's own\n * entrypoints aren't enumerated in its config, so they're detected structurally\n * (a class extending `WorkerEntrypoint` from `cloudflare:workers`), with the\n * config providing only a fallback for self-bound entrypoints whose base class\n * lives in another module.\n */\nexport type ClassWrapperKind = 'durableObject' | 'agent' | 'workflow' | 'workerEntrypoint';\n\n/** Specifier name a `export { default as X } from '...'` re-export uses for the source's default. */\nconst DEFAULT_IMPORT = 'default';\n\n/**\n * The `@sentry/cloudflare` helper each wrapper kind emits. All share the same\n * `(optionsCallback, Class)` signature. `WorkerEntrypoint` classes use\n * `withSentry`, which runtime-detects the class type and routes accordingly.\n */\nconst WRAPPER_METHODS: Record<ClassWrapperKind, string> = {\n durableObject: 'instrumentDurableObjectWithSentry',\n agent: 'instrumentAgentWithSentry',\n workflow: 'instrumentWorkflowWithSentry',\n workerEntrypoint: 'withSentry',\n};\n\nexport interface TransformContext {\n /**\n * Exported class name → the kind of Sentry wrapper to apply. Populated from\n * the wrangler config, so the transform can wrap by name without resolving\n * each class's base type.\n */\n classWrappers: Map<string, ClassWrapperKind>;\n /**\n * Local class names detected as `agents` Agents. An Agent is configured as a Durable Object in\n * wrangler, so this upgrades those entries from `durableObject` to `agent`.\n */\n agentClasses?: ReadonlySet<string>;\n optionsFn: string;\n /** Import statement prepended when `optionsFn` references a separate module. */\n optionsImport?: string;\n /** @see {@link import('./wranglerConfig').WranglerConfig.sameWorkerBindings} */\n sameWorkerBindings?: readonly SameWorkerBinding[];\n}\n\nexport interface TransformResult {\n code: string;\n map: ReturnType<MagicString['generateMap']>;\n /**\n * The configured class names that were actually wrapped. Lets the plugin warn\n * about configured classes it could not find, instead of silently leaving\n * them uninstrumented.\n */\n wrappedClasses: Set<string>;\n}\n\n/**\n * Rewrite the worker entry source to wrap its default export with `withSentry`\n * and any configured class export with its matching Sentry wrapper (see\n * {@link TransformContext.classWrappers}, e.g. Durable Object classes with\n * `instrumentDurableObjectWithSentry`).\n *\n * Handles `export class MyDO {}`, the specifier form (`class MyDO {}` …\n * `export { MyDO }` / `export { Foo as MyDO }`), and classes that live in\n * another module (`import { MyDO } from './do'; export { MyDO }` or\n * `export { MyDO } from './do'`). Only star re-exports (`export * from './do'`)\n * are left alone — the plugin warns about those via\n * {@link TransformResult.wrappedClasses}.\n *\n * Exported (rather than inlined into the plugin) so it can be unit-tested with a\n * plain AST and no Vite context. Returns `undefined` when nothing was wrapped and\n * there are no already-manually-wrapped classes to report.\n */\nexport function applyAutoInstrumentTransforms(\n code: string,\n ast: ProgramBody,\n ctx: TransformContext,\n): TransformResult | undefined {\n const ms = new MagicString(code);\n const topLevelClasses = collectTopLevelClasses(ast);\n const sameWorkerBindings = ctx.sameWorkerBindings ?? [];\n const state: TransformState = {\n ms,\n needsImport: false,\n wrappedClasses: new Set<string>(),\n topLevelClasses,\n renamedLocals: new Set<string>(),\n classWrappers: ctx.classWrappers,\n agentClasses: ctx.agentClasses ?? new Set<string>(),\n workerEntrypointClasses: detectWorkerEntrypointClasses(ast),\n // The identifier must be chosen before wrapping, which bindings survive is only known after.\n optionsFn: sameWorkerBindings.length > 0 ? MERGED_OPTIONS_IDENTIFIER : ctx.optionsFn,\n autoWrapped: new Set<ExportName>(),\n manuallyWrappedLocals: collectManuallyWrappedLocals(ast),\n };\n const { wrappedClasses } = state;\n\n // Named exports first, regardless of source order: the default-export handler\n // needs to know which local bindings a named export already wrapped, so it can\n // skip a class that is both exported by name and re-exported as default (which\n // would otherwise wrap it twice).\n for (const node of ast.body) {\n if (node.type === 'ExportNamedDeclaration') {\n handleNamedExport(node, ctx, state);\n }\n }\n for (const node of ast.body) {\n if (node.type === 'ExportDefaultDeclaration') {\n wrapDefaultExport(node as ExportDefaultNode, ctx, state);\n }\n }\n\n if (!state.needsImport) {\n // Nothing was rewritten. Still surface any classes found already wrapped\n // manually (via `wrappedClasses`) so the caller doesn't warn about them;\n // return undefined only when there was nothing to report either.\n if (wrappedClasses.size === 0) return undefined;\n return { code, map: ms.generateMap({ hires: true }), wrappedClasses };\n }\n\n // `prepend` inserts before earlier prepends, yielding: Sentry import, options import, declaration.\n if (sameWorkerBindings.length > 0) {\n ms.prepend(buildMergedOptionsDeclaration(sameWorkerBindings, ctx.optionsFn, state));\n }\n if (ctx.optionsImport) ms.prepend(ctx.optionsImport);\n ms.prepend(\"import * as __SENTRY__ from '@sentry/cloudflare';\\n\");\n\n return {\n code: ms.toString(),\n map: ms.generateMap({ hires: true }),\n wrappedClasses,\n };\n}\n\ninterface TransformState {\n ms: MagicString;\n needsImport: boolean;\n wrappedClasses: Set<string>;\n /**\n * Top-level (non-exported) class declarations, so specifier exports like\n * `export { MyDO }` can locate the class they refer to.\n */\n topLevelClasses: Map<string, ClassDeclarationNode>;\n /**\n * Local class names already renamed + wrapped, so two specifiers pointing at\n * the same class don't produce duplicate bindings.\n */\n renamedLocals: Set<string>;\n /** Class name → wrapper kind, keyed by the *exported* name (from config). */\n classWrappers: Map<string, ClassWrapperKind>;\n /** Local class names detected as `agents` Agents (see {@link TransformContext.agentClasses}). */\n agentClasses: ReadonlySet<string>;\n /**\n * Local class names detected as `WorkerEntrypoint` subclasses in this module,\n * so they can be wrapped without a config entry.\n */\n workerEntrypointClasses: Set<string>;\n optionsFn: string;\n /**\n * Export names wrapped by this transform, so their options can be extended with\n * `rpcTracePropagationBindings`. Hand-wrapped exports stay out, they keep the options they were\n * wrapped with. `wrappedClasses` counts both.\n */\n autoWrapped: Set<ExportName>;\n /**\n * Top-level bindings already assigned an `instrument*WithSentry(...)` result\n * (`const MyDO = instrumentDurableObjectWithSentry(...)`). Exporting one by\n * specifier must report it as wrapped rather than wrap it a second time.\n */\n manuallyWrappedLocals: Set<string>;\n}\n\n/**\n * Builds the callback that merges same-worker binding names into `rpcTracePropagationBindings` at\n * runtime, the options object only exists once the callback runs with `env`. Only bindings whose\n * class this transform wrapped survive, a hand-wrapped class runs on its own options.\n */\nfunction buildMergedOptionsDeclaration(\n sameWorkerBindings: readonly SameWorkerBinding[],\n optionsFn: string,\n state: TransformState,\n): string {\n const bindingNames = sameWorkerBindings\n .filter(({ className }) => state.autoWrapped.has(className))\n .map(({ bindingName }) => bindingName);\n\n if (!bindingNames.length) {\n return `const ${MERGED_OPTIONS_IDENTIFIER} = ${optionsFn};\\n`;\n }\n\n const names = bindingNames.map(name => JSON.stringify(name)).join(', ');\n return (\n `const ${MERGED_OPTIONS_IDENTIFIER} = (env) => { ` +\n `const opts = (${optionsFn})(env); ` +\n `return { ...opts, rpcTracePropagationBindings: [${names}, ...(opts?.rpcTracePropagationBindings ?? [])] }; };\\n`\n );\n}\n\n/**\n * Resolve the wrapper kind for a class export.\n *\n * Config (`classWrappers`) wins — it's authoritative for Durable Objects and\n * Workflows, and provides the self-binding fallback for WorkerEntrypoints whose\n * base class this module can't see. Otherwise a structurally-detected\n * `WorkerEntrypoint` subclass (matched by its *local* name) gets wrapped with\n * `withSentry`.\n *\n * `localName` is the binding **in this module** the export refers to, and must be\n * left undefined for `export { X } from '...'`: there the specifier's name belongs\n * to the source module, so matching it against anything detected here would wrap a\n * class that merely shares a name.\n *\n * The one case where config is refined rather than obeyed is an `agents` Agent:\n * it *is* a Durable Object, so wrangler can only ever describe it as one, and\n * only the detected base chain distinguishes the two.\n */\nfunction resolveWrapperKind(\n exportedName: string,\n localName: string | undefined,\n state: TransformState,\n): ClassWrapperKind | undefined {\n const configured = state.classWrappers.get(exportedName);\n\n if (\n configured === 'durableObject' &&\n ((localName && state.agentClasses.has(localName)) || state.agentClasses.has(exportedName))\n ) {\n return 'agent';\n }\n\n if (configured) return configured;\n if (localName && state.workerEntrypointClasses.has(localName)) return 'workerEntrypoint';\n return undefined;\n}\n\n/**\n * Top-level `const X = instrument*WithSentry(...)` bindings — a hand-wrapped class that is exported\n * separately (`export { X }`) rather than inline.\n */\nfunction collectManuallyWrappedLocals(ast: ProgramBody): Set<string> {\n const wrapperMethods = Object.values(WRAPPER_METHODS);\n const locals = new Set<string>();\n\n for (const node of ast.body) {\n if (node.type !== 'VariableDeclaration') continue;\n for (const declarator of (node as VariableDeclarationNode).declarations ?? []) {\n const name = declarator.id?.type === 'Identifier' ? declarator.id.name : undefined;\n const init = declarator.init;\n if (name && init && wrapperMethods.some(method => isCallToMethod(init, method))) {\n locals.add(name);\n }\n }\n }\n\n return locals;\n}\n\nfunction collectTopLevelClasses(ast: ProgramBody): Map<string, ClassDeclarationNode> {\n const classes = new Map<string, ClassDeclarationNode>();\n for (const node of ast.body) {\n if (node.type !== 'ClassDeclaration') continue;\n const classNode = node as ClassDeclarationNode;\n if (classNode.id?.name) classes.set(classNode.id.name, classNode);\n }\n return classes;\n}\n\nfunction wrapDefaultExport(node: ExportDefaultNode, ctx: TransformContext, state: TransformState): void {\n const decl = node.declaration;\n\n // Already wrapped — leave it alone\n if (isCallToMethod(decl, 'withSentry')) return;\n\n // `export default Foo` where `Foo` is a local class already wrapped by a named\n // export (e.g. a self-bound WorkerEntrypoint also used as the default handler).\n // Wrapping again would produce `withSentry(withSentry(...))`. The binding still\n // points at the wrapped class, so the default export counts as auto-wrapped.\n if (decl.type === 'Identifier' && state.renamedLocals.has((decl as IdentifierNode).name)) {\n state.autoWrapped.add(DEFAULT_EXPORT);\n return;\n }\n\n // `export default <expr>` → `const __SENTRY_DEFAULT_EXPORT__ = <expr>`\n // MagicString positions are always relative to the original source.\n state.ms.overwrite(node.start, decl.start, 'const __SENTRY_DEFAULT_EXPORT__ = ');\n state.ms.append(`\\nexport default __SENTRY__.withSentry(${state.optionsFn}, __SENTRY_DEFAULT_EXPORT__);\\n`);\n state.needsImport = true;\n state.autoWrapped.add(DEFAULT_EXPORT);\n}\n\nfunction handleNamedExport(node: ExportNamedNode, ctx: TransformContext, state: TransformState): void {\n const decl = node.declaration;\n\n // ---- Manually wrapped class export ----\n // `export const MyDO = instrumentDurableObjectWithSentry(...)` — count it\n // as wrapped so the plugin doesn't warn about it, but leave it alone.\n if (decl?.type === 'VariableDeclaration') {\n collectManuallyWrappedClassExports(decl, ctx, state);\n return;\n }\n\n // ---- Named class export matching a configured binding ----\n if (decl?.type === 'ClassDeclaration') {\n wrapInlineClassExport(node, decl, ctx, state);\n return;\n }\n\n // ---- Specifier export (`export { Foo as MyDO }`, `export { MyDO } from './do'`) ----\n wrapSpecifierExports(node, ctx, state);\n}\n\nfunction collectManuallyWrappedClassExports(\n varDecl: VariableDeclarationNode,\n ctx: TransformContext,\n state: TransformState,\n): void {\n for (const declarator of varDecl.declarations ?? []) {\n const name = declarator.id?.type === 'Identifier' ? declarator.id.name : undefined;\n const kind = name ? ctx.classWrappers.get(name) : undefined;\n if (!name || !kind || !declarator.init) continue;\n\n // A hand-wrapped Agent is configured as a Durable Object, so accept either helper there —\n // otherwise an already-instrumented Agent would be reported as unwrapped.\n const accepted =\n kind === 'durableObject' ? [WRAPPER_METHODS.durableObject, WRAPPER_METHODS.agent] : [WRAPPER_METHODS[kind]];\n\n if (accepted.some(method => isCallToMethod(declarator.init as BaseNode, method))) {\n state.wrappedClasses.add(name);\n }\n }\n}\n\nfunction wrapInlineClassExport(\n exportNode: ExportNamedNode,\n classDecl: ClassDeclarationNode,\n ctx: TransformContext,\n state: TransformState,\n): void {\n const classId = classDecl.id;\n // Inline export: the exported name and the local class name are the same.\n const kind = classId ? resolveWrapperKind(classId.name, classId.name, state) : undefined;\n if (!classId || !kind) return;\n\n const className = classId.name;\n const renamedClass = `__SENTRY_ORIGINAL_${className}__`;\n\n // Strip the `export ` keyword\n state.ms.overwrite(exportNode.start, classDecl.start, '');\n\n // Rename the class to avoid a duplicate binding\n state.ms.overwrite(classId.start, classId.end, renamedClass);\n\n // Insert the wrapped re-export after the class body\n state.ms.appendLeft(\n exportNode.end,\n `\\nexport const ${className} = __SENTRY__.${WRAPPER_METHODS[kind]}(${state.optionsFn}, ${renamedClass});\\n`,\n );\n\n state.wrappedClasses.add(className);\n state.autoWrapped.add(className);\n state.renamedLocals.add(className);\n state.needsImport = true;\n}\n\n/**\n * Wrap the configured classes an `export { ... }` statement names.\n *\n * A class *declared* in this module keeps the statement intact: the declaration is renamed and the\n * wrapper takes over its binding, so the untouched specifier now exports the wrapped class.\n *\n * A class that lives in **another** module — imported and re-exported, or re-exported directly — has\n * no local binding to overwrite (import bindings are immutable). Those specifiers are re-pointed at\n * a fresh wrapper binding instead, which means rebuilding the statement; specifiers this plugin has\n * no business touching are carried over verbatim.\n */\nfunction wrapSpecifierExports(node: ExportNamedNode, ctx: TransformContext, state: TransformState): void {\n const specifiers = node.specifiers ?? [];\n if (specifiers.length === 0) return;\n\n const sourceLiteral = node.source ? state.ms.original.slice(node.source.start, node.source.end) : undefined;\n\n const prelude: string[] = [];\n const wrappedPairs: string[] = [];\n const kept: string[] = [];\n\n for (const specifier of specifiers) {\n const pair = wrapCrossModuleSpecifier(specifier, sourceLiteral, ctx, state, prelude);\n if (pair) {\n wrappedPairs.push(pair);\n } else {\n kept.push(state.ms.original.slice(specifier.start, specifier.end));\n }\n }\n\n if (wrappedPairs.length === 0) return;\n\n const statements = [...prelude, `export { ${wrappedPairs.join(', ')} };`];\n if (kept.length > 0) {\n const clause = `export { ${kept.join(', ')} }`;\n statements.push(sourceLiteral ? `${clause} from ${sourceLiteral};` : `${clause};`);\n }\n state.ms.overwrite(node.start, node.end, statements.join('\\n'));\n}\n\n/**\n * Handle one export specifier, returning the `Wrapped as Exported` pair to emit when its class has\n * to be wrapped through a fresh binding — the cross-module case. The import/wrapper statements that\n * pair depends on are pushed onto `prelude`.\n *\n * Returns `undefined` when the specifier can stay exactly as written: it doesn't name a configured\n * class, its class is declared locally (wrapped in place via {@link wrapLocalClassExport}, which\n * takes over the binding the specifier already exports), or the binding is already hand-wrapped.\n */\nfunction wrapCrossModuleSpecifier(\n specifier: ExportSpecifierNode,\n sourceLiteral: string | undefined,\n ctx: TransformContext,\n state: TransformState,\n prelude: string[],\n): string | undefined {\n const exportedName =\n specifier.type === 'ExportSpecifier' && specifier.exported?.type === 'Identifier'\n ? specifier.exported.name\n : undefined;\n const localName = specifier.local?.type === 'Identifier' ? specifier.local.name : undefined;\n // With a `from` clause the specifier names an export of the *source* module, not a binding here.\n const kind = exportedName\n ? resolveWrapperKind(exportedName, sourceLiteral ? undefined : localName, state)\n : undefined;\n\n if (!exportedName || !localName || !kind) return undefined;\n\n // Without a `from` clause the specifier points at a module-local binding, which may already be\n // (or become) the wrapped class without touching the export statement itself.\n if (!sourceLiteral) {\n const localClass = state.topLevelClasses.get(localName);\n\n if (localClass?.id) {\n wrapLocalClassExport(localName, localClass, kind, ctx, state);\n state.wrappedClasses.add(exportedName);\n state.needsImport = true;\n return undefined;\n }\n\n if (state.manuallyWrappedLocals.has(localName)) {\n state.wrappedClasses.add(exportedName);\n return undefined;\n }\n }\n\n // The class comes from another module: bind it under a private name (for the `from` form, which\n // has no local binding at all), wrap that, and export the wrapper under the configured name.\n let target = localName;\n\n if (sourceLiteral) {\n target = `__SENTRY_REEXPORT_${exportedName}__`;\n prelude.push(\n localName === DEFAULT_IMPORT\n ? `import ${target} from ${sourceLiteral};`\n : `import { ${localName} as ${target} } from ${sourceLiteral};`,\n );\n }\n\n const wrappedName = `__SENTRY_WRAPPED_${exportedName}__`;\n\n // The class may already be hand-wrapped in its own module, which this transform cannot see. The\n // emitted guard returns such a class as-is instead of nesting a second wrapper around it.\n prelude.push(\n `const ${wrappedName} = __SENTRY__._INTERNAL_wrapUnlessInstrumented(__SENTRY__.${WRAPPER_METHODS[kind]}, ${state.optionsFn}, ${target});`,\n );\n state.wrappedClasses.add(exportedName);\n state.autoWrapped.add(exportedName);\n state.needsImport = true;\n\n return `${wrappedName} as ${exportedName}`;\n}\n\n/** Rename a locally declared class and rebind its original name to the wrapper. */\nfunction wrapLocalClassExport(\n localName: string,\n localClass: ClassDeclarationNode,\n kind: ClassWrapperKind,\n ctx: TransformContext,\n state: TransformState,\n): void {\n const classId = localClass.id;\n if (!classId || state.renamedLocals.has(localName)) return;\n state.renamedLocals.add(localName);\n\n const renamedClass = `__SENTRY_ORIGINAL_${localName}__`;\n state.ms.overwrite(classId.start, classId.end, renamedClass);\n state.ms.appendLeft(\n localClass.end,\n `\\nconst ${localName} = __SENTRY__.${WRAPPER_METHODS[kind]}(${state.optionsFn}, ${renamedClass});\\n`,\n );\n}\n"],"names":["MagicString","detectWorkerEntrypointClasses","DEFAULT_EXPORT"],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ const op = require('@sentry/conventions/op');
|
|
|
5
5
|
const core = require('@sentry/core');
|
|
6
6
|
const noDiagnosticChannels = require('@sentry/server-utils/no-diagnostic-channels');
|
|
7
7
|
const flush = require('./flush.js');
|
|
8
|
+
const instrument = require('./instrument.js');
|
|
8
9
|
const instrumentEnv = require('./instrumentations/worker/instrumentEnv.js');
|
|
9
10
|
const scopeUtils = require('./scope-utils.js');
|
|
10
11
|
const sdk = require('./sdk.js');
|
|
@@ -104,7 +105,7 @@ class WrappedWorkflowStep {
|
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
function instrumentWorkflowWithSentry(optionsCallback, WorkFlowClass) {
|
|
107
|
-
|
|
108
|
+
const InstrumentedClass = new Proxy(WorkFlowClass, {
|
|
108
109
|
// oxlint-disable-next-line typescript/no-explicit-any
|
|
109
110
|
construct(target, args, newTarget) {
|
|
110
111
|
const [ctx, env] = args;
|
|
@@ -144,6 +145,8 @@ function instrumentWorkflowWithSentry(optionsCallback, WorkFlowClass) {
|
|
|
144
145
|
});
|
|
145
146
|
}
|
|
146
147
|
});
|
|
148
|
+
instrument.markAsInstrumented(InstrumentedClass);
|
|
149
|
+
return InstrumentedClass;
|
|
147
150
|
}
|
|
148
151
|
|
|
149
152
|
exports.deterministicTraceIdFromInstanceId = deterministicTraceIdFromInstanceId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflows.js","sources":["../../../src/workflows.ts"],"sourcesContent":["import { SENTRY_SEGMENT_NAME_SOURCE, CODE_FUNCTION_NAME, SENTRY_OP } from '@sentry/conventions/attributes';\nimport { FUNCTION } from '@sentry/conventions/op';\nimport type { PropagationContext, Scope } from '@sentry/core';\nimport {\n captureException,\n flush,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startSpan,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport type {\n WorkflowDelayDuration,\n WorkflowEntrypoint,\n WorkflowEvent,\n WorkflowSleepDuration,\n WorkflowStep,\n WorkflowStepConfig,\n WorkflowStepContext,\n WorkflowStepEvent,\n WorkflowStepRollbackOptions,\n WorkflowTimeoutDuration,\n} from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from '@sentry/server-utils/no-diagnostic-channels';\nimport type { CloudflareOptions } from './client';\nimport { flushAndDispose, getOriginalWaitUntil } from './flush';\nimport { instrumentEnv } from './instrumentations/worker/instrumentEnv';\nimport { addCloudResourceContext } from './scope-utils';\nimport { init } from './sdk';\nimport { instrumentContext } from './utils/instrumentContext';\nimport type { DefaultEnv, ResolveEnv, StrictCloudflareOptions } from './types';\nimport { withInvocationIsolationScope } from './utils/invocationScope';\n\nconst UUID_REGEX = /^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$/i;\n\n/**\n * Hashes a string to a UUID using SHA-1.\n */\nexport async function deterministicTraceIdFromInstanceId(instanceId: string): Promise<string> {\n const buf = await crypto.subtle.digest('SHA-1', new TextEncoder().encode(instanceId));\n return (\n Array.from(new Uint8Array(buf))\n // We only need the first 16 bytes for the 32 characters\n .slice(0, 16)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n );\n}\n\nasync function propagationContextFromInstanceId(instanceId: string): Promise<PropagationContext> {\n const traceId = UUID_REGEX.test(instanceId)\n ? instanceId.replace(/-/g, '')\n : await deterministicTraceIdFromInstanceId(instanceId);\n\n // Derive sampleRand from last 4 characters of the random UUID\n //\n // We cannot store any state between workflow steps, so we derive the\n // sampleRand from the traceId itself. This ensures that the sampling is\n // consistent across all steps in the same workflow instance.\n const sampleRand = parseInt(traceId.slice(-4), 16) / 0xffff;\n\n return {\n traceId,\n sampleRand,\n };\n}\n\nclass WrappedWorkflowStep implements WorkflowStep {\n public constructor(\n private _instanceId: string,\n private _options: CloudflareOptions,\n private _step: WorkflowStep,\n private _waitUntil: ExecutionContext['waitUntil'],\n private _isolationScope: Scope,\n ) {}\n\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n callback: (ctx: WorkflowStepContext) => Promise<T>,\n rollbackOptions?: WorkflowStepRollbackOptions<T>,\n ): Promise<T>;\n public async do<T extends Rpc.Serializable<T>, const C extends WorkflowStepConfig>(\n name: string,\n config: C,\n callback: (\n ctx: WorkflowStepContext<C['retries'] extends { delay: infer D } ? D : WorkflowDelayDuration | number>,\n ) => Promise<T>,\n rollbackOptions?: WorkflowStepRollbackOptions<T>,\n ): Promise<T>;\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n configOrCallback: WorkflowStepConfig | ((ctx: WorkflowStepContext) => Promise<T>),\n callbackOrRollback?: ((ctx: WorkflowStepContext) => Promise<T>) | WorkflowStepRollbackOptions<T>,\n maybeRollback?: WorkflowStepRollbackOptions<T>,\n ): Promise<T> {\n // Capture the current scope, so parent span (e.g., a startSpan surrounding step.do) is preserved\n const scopeForStep = getCurrentScope();\n\n const hasConfig = typeof configOrCallback !== 'function';\n const config = hasConfig ? configOrCallback : undefined;\n const userCallback = (hasConfig ? callbackOrRollback : configOrCallback) as (\n ctx: WorkflowStepContext,\n ) => Promise<T>;\n const rollbackOptions = (hasConfig ? maybeRollback : callbackOrRollback) as\n | WorkflowStepRollbackOptions<T>\n | undefined;\n\n const instrumentedCallback = async (...args: unknown[]): Promise<T> => {\n // Feature detection: Cloudflare Workflows (April 2026+) pass a step context\n // with `attempt` and `config.retries.limit`. When available, we only capture\n // errors on the final attempt to avoid duplicates during retries.\n const stepContext = args[0] as { attempt?: number; config?: { retries?: { limit?: number } } } | undefined;\n const attempt = stepContext?.attempt;\n const retryLimit = stepContext?.config?.retries?.limit;\n const hasStepContext = typeof attempt === 'number' && typeof retryLimit === 'number';\n\n // Only capture error on final attempt (attempt > retryLimit means no more retries left)\n // or when step context is unavailable (legacy behavior - capture all errors)\n const isFinalAttempt = !hasStepContext || attempt > retryLimit;\n\n // The engine invokes step callbacks outside the async context of `run`, so the\n // run's isolation scope (and with it the invocation state that ties eager sends\n // to this invocation's `waitUntil`) has to be restored explicitly.\n return withIsolationScope(this._isolationScope, () => {\n const stepResult = startSpan(\n {\n name,\n scope: scopeForStep,\n attributes: {\n [SENTRY_OP]: FUNCTION,\n [CODE_FUNCTION_NAME]: name,\n 'workflow.step.name': name,\n 'cloudflare.workflow.timeout': config?.timeout,\n 'cloudflare.workflow.retries.backoff': config?.retries?.backoff,\n // In workers-types v5, `delay` may be a `WorkflowDelayFunction`, which isn't a valid span attribute value.\n 'cloudflare.workflow.retries.delay':\n typeof config?.retries?.delay === 'function' ? undefined : config?.retries?.delay,\n 'cloudflare.workflow.retries.limit': config?.retries?.limit,\n 'cloudflare.workflow.attempt': attempt,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.workflow',\n [SENTRY_SEGMENT_NAME_SOURCE]: 'task',\n },\n },\n async span => {\n try {\n const result = await (userCallback as (...args: unknown[]) => Promise<T>)(...args);\n span.setStatus({ code: 1 });\n return result;\n } catch (error) {\n if (isFinalAttempt) {\n captureException(error, { mechanism: { handled: true, type: 'auto.faas.cloudflare.workflow' } });\n }\n throw error;\n }\n },\n );\n // Deliver after the step span has ended, so the span rides this flush instead of\n // starting an eager drain (same ordering as `wrapMethodWithSentry`'s teardown).\n return stepResult.then(\n result => {\n this._waitUntil(flush(2000));\n return result;\n },\n error => {\n this._waitUntil(flush(2000));\n throw error;\n },\n );\n });\n };\n\n if (config) {\n return rollbackOptions\n ? this._step.do(name, config, instrumentedCallback, rollbackOptions)\n : this._step.do(name, config, instrumentedCallback);\n }\n\n return rollbackOptions\n ? this._step.do(name, instrumentedCallback, rollbackOptions)\n : this._step.do(name, instrumentedCallback);\n }\n\n public async sleep(name: string, duration: WorkflowSleepDuration): Promise<void> {\n return this._step.sleep(name, duration);\n }\n\n public async sleepUntil(name: string, timestamp: Date | number): Promise<void> {\n return this._step.sleepUntil(name, timestamp);\n }\n\n public async waitForEvent<T extends Rpc.Serializable<T>>(\n name: string,\n options: { type: string; timeout?: WorkflowTimeoutDuration | number },\n ): Promise<WorkflowStepEvent<T>> {\n return this._step.waitForEvent<T>(name, options);\n }\n}\n\n/**\n * Instruments a Cloudflare Workflow class with Sentry.\n *\n * @example\n * ```typescript\n * const InstrumentedWorkflow = instrumentWorkflowWithSentry(\n * (env) => ({ dsn: env.SENTRY_DSN }),\n * MyWorkflowClass\n * );\n *\n * export default InstrumentedWorkflow;\n * ```\n *\n * @param optionsCallback - Function that returns Sentry options to initialize Sentry\n * @param WorkflowClass - The workflow class to instrument\n * @returns Instrumented workflow class with the same interface\n */\nexport function instrumentWorkflowWithSentry<\n E = DefaultEnv, // Environment type\n P = unknown, // Payload type\n // oxlint-disable-next-line typescript/no-explicit-any\n T extends WorkflowEntrypoint<any, any> = WorkflowEntrypoint<E, P>, // WorkflowEntrypoint type\n // The constraint must not route through `T`: workers-types defaults `WorkflowEntrypoint`'s\n // `Env` to `unknown` (unlike `WorkerEntrypoint`/`DurableObject`, which default to\n // `Cloudflare.Env`), so a bare subclass would be rejected in a `wrangler types` project.\n // The callback env is resolved from the inferred constructor via `ResolveEnv` instead.\n // oxlint-disable-next-line typescript/no-explicit-any\n C extends new (ctx: ExecutionContext, env: any) => WorkflowEntrypoint<any, any> = new (\n ctx: ExecutionContext,\n // oxlint-disable-next-line typescript/no-explicit-any\n env: any,\n ) => T, // Constructor type of the WorkflowEntrypoint class\n O = unknown,\n>(optionsCallback: (env: ResolveEnv<C, E>) => StrictCloudflareOptions<O>, WorkFlowClass: C): C {\n return new Proxy(WorkFlowClass, {\n // oxlint-disable-next-line typescript/no-explicit-any\n construct(target: C, args: [ctx: ExecutionContext, env: any], newTarget) {\n const [ctx, env] = args;\n const context = instrumentContext(ctx);\n const options = optionsCallback(env);\n args[0] = context;\n args[1] = instrumentEnv(env as Record<string, unknown>, options) as E;\n const instance = Reflect.construct(target, args, newTarget) as T;\n return new Proxy(instance, {\n get(obj, prop, receiver) {\n if (prop === 'run') {\n return async function (event: WorkflowEvent<P>, step: WorkflowStep): Promise<unknown> {\n setAsyncLocalStorageAsyncContextStrategy();\n\n return withInvocationIsolationScope(async isolationScope => {\n const waitUntil = getOriginalWaitUntil(context).bind(context);\n const client = init({ ...options, ctx: context, enableDedupe: false });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return withScope(async scope => {\n const propagationContext = await propagationContextFromInstanceId(event.instanceId);\n scope.setPropagationContext(propagationContext);\n\n try {\n return await obj.run.call(\n obj,\n event,\n new WrappedWorkflowStep(event.instanceId, options, step, waitUntil, isolationScope),\n );\n } finally {\n waitUntil(flushAndDispose(client));\n }\n });\n }, context);\n };\n }\n return Reflect.get(obj, prop, receiver);\n },\n });\n },\n });\n}\n"],"names":["getCurrentScope","withIsolationScope","startSpan","SENTRY_OP","FUNCTION","CODE_FUNCTION_NAME","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SENTRY_SEGMENT_NAME_SOURCE","captureException","flush","instrumentContext","instrumentEnv","setAsyncLocalStorageAsyncContextStrategy","withInvocationIsolationScope","getOriginalWaitUntil","init","addCloudResourceContext","withScope","flushAndDispose"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"workflows.js","sources":["../../../src/workflows.ts"],"sourcesContent":["import { SENTRY_SEGMENT_NAME_SOURCE, CODE_FUNCTION_NAME, SENTRY_OP } from '@sentry/conventions/attributes';\nimport { FUNCTION } from '@sentry/conventions/op';\nimport type { PropagationContext, Scope } from '@sentry/core';\nimport {\n captureException,\n flush,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startSpan,\n withIsolationScope,\n withScope,\n} from '@sentry/core';\nimport type {\n WorkflowDelayDuration,\n WorkflowEntrypoint,\n WorkflowEvent,\n WorkflowSleepDuration,\n WorkflowStep,\n WorkflowStepConfig,\n WorkflowStepContext,\n WorkflowStepEvent,\n WorkflowStepRollbackOptions,\n WorkflowTimeoutDuration,\n} from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from '@sentry/server-utils/no-diagnostic-channels';\nimport type { CloudflareOptions } from './client';\nimport { flushAndDispose, getOriginalWaitUntil } from './flush';\nimport { markAsInstrumented } from './instrument';\nimport { instrumentEnv } from './instrumentations/worker/instrumentEnv';\nimport { addCloudResourceContext } from './scope-utils';\nimport { init } from './sdk';\nimport { instrumentContext } from './utils/instrumentContext';\nimport type { DefaultEnv, ResolveEnv, StrictCloudflareOptions } from './types';\nimport { withInvocationIsolationScope } from './utils/invocationScope';\n\nconst UUID_REGEX = /^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$/i;\n\n/**\n * Hashes a string to a UUID using SHA-1.\n */\nexport async function deterministicTraceIdFromInstanceId(instanceId: string): Promise<string> {\n const buf = await crypto.subtle.digest('SHA-1', new TextEncoder().encode(instanceId));\n return (\n Array.from(new Uint8Array(buf))\n // We only need the first 16 bytes for the 32 characters\n .slice(0, 16)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n );\n}\n\nasync function propagationContextFromInstanceId(instanceId: string): Promise<PropagationContext> {\n const traceId = UUID_REGEX.test(instanceId)\n ? instanceId.replace(/-/g, '')\n : await deterministicTraceIdFromInstanceId(instanceId);\n\n // Derive sampleRand from last 4 characters of the random UUID\n //\n // We cannot store any state between workflow steps, so we derive the\n // sampleRand from the traceId itself. This ensures that the sampling is\n // consistent across all steps in the same workflow instance.\n const sampleRand = parseInt(traceId.slice(-4), 16) / 0xffff;\n\n return {\n traceId,\n sampleRand,\n };\n}\n\nclass WrappedWorkflowStep implements WorkflowStep {\n public constructor(\n private _instanceId: string,\n private _options: CloudflareOptions,\n private _step: WorkflowStep,\n private _waitUntil: ExecutionContext['waitUntil'],\n private _isolationScope: Scope,\n ) {}\n\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n callback: (ctx: WorkflowStepContext) => Promise<T>,\n rollbackOptions?: WorkflowStepRollbackOptions<T>,\n ): Promise<T>;\n public async do<T extends Rpc.Serializable<T>, const C extends WorkflowStepConfig>(\n name: string,\n config: C,\n callback: (\n ctx: WorkflowStepContext<C['retries'] extends { delay: infer D } ? D : WorkflowDelayDuration | number>,\n ) => Promise<T>,\n rollbackOptions?: WorkflowStepRollbackOptions<T>,\n ): Promise<T>;\n public async do<T extends Rpc.Serializable<T>>(\n name: string,\n configOrCallback: WorkflowStepConfig | ((ctx: WorkflowStepContext) => Promise<T>),\n callbackOrRollback?: ((ctx: WorkflowStepContext) => Promise<T>) | WorkflowStepRollbackOptions<T>,\n maybeRollback?: WorkflowStepRollbackOptions<T>,\n ): Promise<T> {\n // Capture the current scope, so parent span (e.g., a startSpan surrounding step.do) is preserved\n const scopeForStep = getCurrentScope();\n\n const hasConfig = typeof configOrCallback !== 'function';\n const config = hasConfig ? configOrCallback : undefined;\n const userCallback = (hasConfig ? callbackOrRollback : configOrCallback) as (\n ctx: WorkflowStepContext,\n ) => Promise<T>;\n const rollbackOptions = (hasConfig ? maybeRollback : callbackOrRollback) as\n | WorkflowStepRollbackOptions<T>\n | undefined;\n\n const instrumentedCallback = async (...args: unknown[]): Promise<T> => {\n // Feature detection: Cloudflare Workflows (April 2026+) pass a step context\n // with `attempt` and `config.retries.limit`. When available, we only capture\n // errors on the final attempt to avoid duplicates during retries.\n const stepContext = args[0] as { attempt?: number; config?: { retries?: { limit?: number } } } | undefined;\n const attempt = stepContext?.attempt;\n const retryLimit = stepContext?.config?.retries?.limit;\n const hasStepContext = typeof attempt === 'number' && typeof retryLimit === 'number';\n\n // Only capture error on final attempt (attempt > retryLimit means no more retries left)\n // or when step context is unavailable (legacy behavior - capture all errors)\n const isFinalAttempt = !hasStepContext || attempt > retryLimit;\n\n // The engine invokes step callbacks outside the async context of `run`, so the\n // run's isolation scope (and with it the invocation state that ties eager sends\n // to this invocation's `waitUntil`) has to be restored explicitly.\n return withIsolationScope(this._isolationScope, () => {\n const stepResult = startSpan(\n {\n name,\n scope: scopeForStep,\n attributes: {\n [SENTRY_OP]: FUNCTION,\n [CODE_FUNCTION_NAME]: name,\n 'workflow.step.name': name,\n 'cloudflare.workflow.timeout': config?.timeout,\n 'cloudflare.workflow.retries.backoff': config?.retries?.backoff,\n // In workers-types v5, `delay` may be a `WorkflowDelayFunction`, which isn't a valid span attribute value.\n 'cloudflare.workflow.retries.delay':\n typeof config?.retries?.delay === 'function' ? undefined : config?.retries?.delay,\n 'cloudflare.workflow.retries.limit': config?.retries?.limit,\n 'cloudflare.workflow.attempt': attempt,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.workflow',\n [SENTRY_SEGMENT_NAME_SOURCE]: 'task',\n },\n },\n async span => {\n try {\n const result = await (userCallback as (...args: unknown[]) => Promise<T>)(...args);\n span.setStatus({ code: 1 });\n return result;\n } catch (error) {\n if (isFinalAttempt) {\n captureException(error, { mechanism: { handled: true, type: 'auto.faas.cloudflare.workflow' } });\n }\n throw error;\n }\n },\n );\n // Deliver after the step span has ended, so the span rides this flush instead of\n // starting an eager drain (same ordering as `wrapMethodWithSentry`'s teardown).\n return stepResult.then(\n result => {\n this._waitUntil(flush(2000));\n return result;\n },\n error => {\n this._waitUntil(flush(2000));\n throw error;\n },\n );\n });\n };\n\n if (config) {\n return rollbackOptions\n ? this._step.do(name, config, instrumentedCallback, rollbackOptions)\n : this._step.do(name, config, instrumentedCallback);\n }\n\n return rollbackOptions\n ? this._step.do(name, instrumentedCallback, rollbackOptions)\n : this._step.do(name, instrumentedCallback);\n }\n\n public async sleep(name: string, duration: WorkflowSleepDuration): Promise<void> {\n return this._step.sleep(name, duration);\n }\n\n public async sleepUntil(name: string, timestamp: Date | number): Promise<void> {\n return this._step.sleepUntil(name, timestamp);\n }\n\n public async waitForEvent<T extends Rpc.Serializable<T>>(\n name: string,\n options: { type: string; timeout?: WorkflowTimeoutDuration | number },\n ): Promise<WorkflowStepEvent<T>> {\n return this._step.waitForEvent<T>(name, options);\n }\n}\n\n/**\n * Instruments a Cloudflare Workflow class with Sentry.\n *\n * @example\n * ```typescript\n * const InstrumentedWorkflow = instrumentWorkflowWithSentry(\n * (env) => ({ dsn: env.SENTRY_DSN }),\n * MyWorkflowClass\n * );\n *\n * export default InstrumentedWorkflow;\n * ```\n *\n * @param optionsCallback - Function that returns Sentry options to initialize Sentry\n * @param WorkflowClass - The workflow class to instrument\n * @returns Instrumented workflow class with the same interface\n */\nexport function instrumentWorkflowWithSentry<\n E = DefaultEnv, // Environment type\n P = unknown, // Payload type\n // oxlint-disable-next-line typescript/no-explicit-any\n T extends WorkflowEntrypoint<any, any> = WorkflowEntrypoint<E, P>, // WorkflowEntrypoint type\n // The constraint must not route through `T`: workers-types defaults `WorkflowEntrypoint`'s\n // `Env` to `unknown` (unlike `WorkerEntrypoint`/`DurableObject`, which default to\n // `Cloudflare.Env`), so a bare subclass would be rejected in a `wrangler types` project.\n // The callback env is resolved from the inferred constructor via `ResolveEnv` instead.\n // oxlint-disable-next-line typescript/no-explicit-any\n C extends new (ctx: ExecutionContext, env: any) => WorkflowEntrypoint<any, any> = new (\n ctx: ExecutionContext,\n // oxlint-disable-next-line typescript/no-explicit-any\n env: any,\n ) => T, // Constructor type of the WorkflowEntrypoint class\n O = unknown,\n>(optionsCallback: (env: ResolveEnv<C, E>) => StrictCloudflareOptions<O>, WorkFlowClass: C): C {\n const InstrumentedClass = new Proxy(WorkFlowClass, {\n // oxlint-disable-next-line typescript/no-explicit-any\n construct(target: C, args: [ctx: ExecutionContext, env: any], newTarget) {\n const [ctx, env] = args;\n const context = instrumentContext(ctx);\n const options = optionsCallback(env);\n args[0] = context;\n args[1] = instrumentEnv(env as Record<string, unknown>, options) as E;\n const instance = Reflect.construct(target, args, newTarget) as T;\n return new Proxy(instance, {\n get(obj, prop, receiver) {\n if (prop === 'run') {\n return async function (event: WorkflowEvent<P>, step: WorkflowStep): Promise<unknown> {\n setAsyncLocalStorageAsyncContextStrategy();\n\n return withInvocationIsolationScope(async isolationScope => {\n const waitUntil = getOriginalWaitUntil(context).bind(context);\n const client = init({ ...options, ctx: context, enableDedupe: false });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return withScope(async scope => {\n const propagationContext = await propagationContextFromInstanceId(event.instanceId);\n scope.setPropagationContext(propagationContext);\n\n try {\n return await obj.run.call(\n obj,\n event,\n new WrappedWorkflowStep(event.instanceId, options, step, waitUntil, isolationScope),\n );\n } finally {\n waitUntil(flushAndDispose(client));\n }\n });\n }, context);\n };\n }\n return Reflect.get(obj, prop, receiver);\n },\n });\n },\n });\n // Recognizable for `_INTERNAL_wrapUnlessInstrumented`, so auto-instrumentation never nests wrappers.\n markAsInstrumented(InstrumentedClass);\n return InstrumentedClass;\n}\n"],"names":["getCurrentScope","withIsolationScope","startSpan","SENTRY_OP","FUNCTION","CODE_FUNCTION_NAME","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SENTRY_SEGMENT_NAME_SOURCE","captureException","flush","instrumentContext","instrumentEnv","setAsyncLocalStorageAsyncContextStrategy","withInvocationIsolationScope","getOriginalWaitUntil","init","addCloudResourceContext","withScope","flushAndDispose","markAsInstrumented"],"mappings":";;;;;;;;;;;;;;AAmCA,MAAM,UAAA,GAAa,qEAAA;AAKnB,eAAsB,mCAAmC,UAAA,EAAqC;AAC5F,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,UAAU,CAAC,CAAA;AACpF,EAAA,OACE,KAAA,CAAM,KAAK,IAAI,UAAA,CAAW,GAAG,CAAC,CAAA,CAE3B,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,CACX,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAC,CAAA,CACxC,IAAA,CAAK,EAAE,CAAA;AAEd;AAEA,eAAe,iCAAiC,UAAA,EAAiD;AAC/F,EAAA,MAAM,OAAA,GAAU,UAAA,CAAW,IAAA,CAAK,UAAU,CAAA,GACtC,UAAA,CAAW,OAAA,CAAQ,IAAA,EAAM,EAAE,CAAA,GAC3B,MAAM,kCAAA,CAAmC,UAAU,CAAA;AAOvD,EAAA,MAAM,aAAa,QAAA,CAAS,OAAA,CAAQ,MAAM,EAAE,CAAA,EAAG,EAAE,CAAA,GAAI,KAAA;AAErD,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA;AAAA,GACF;AACF;AAEA,MAAM,mBAAA,CAA4C;AAAA,EACzC,WAAA,CACG,WAAA,EACA,QAAA,EACA,KAAA,EACA,YACA,eAAA,EACR;AALQ,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AACA,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AACA,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,eAAA,GAAA,eAAA;AAAA,EACP;AAAA,EAeH,MAAa,EAAA,CACX,IAAA,EACA,gBAAA,EACA,oBACA,aAAA,EACY;AAEZ,IAAA,MAAM,eAAeA,oBAAA,EAAgB;AAErC,IAAA,MAAM,SAAA,GAAY,OAAO,gBAAA,KAAqB,UAAA;AAC9C,IAAA,MAAM,MAAA,GAAS,YAAY,gBAAA,GAAmB,MAAA;AAC9C,IAAA,MAAM,YAAA,GAAgB,YAAY,kBAAA,GAAqB,gBAAA;AAGvD,IAAA,MAAM,eAAA,GAAmB,YAAY,aAAA,GAAgB,kBAAA;AAIrD,IAAA,MAAM,oBAAA,GAAuB,UAAU,IAAA,KAAgC;AAIrE,MAAA,MAAM,WAAA,GAAc,KAAK,CAAC,CAAA;AAC1B,MAAA,MAAM,UAAU,WAAA,EAAa,OAAA;AAC7B,MAAA,MAAM,UAAA,GAAa,WAAA,EAAa,MAAA,EAAQ,OAAA,EAAS,KAAA;AACjD,MAAA,MAAM,cAAA,GAAiB,OAAO,OAAA,KAAY,QAAA,IAAY,OAAO,UAAA,KAAe,QAAA;AAI5E,MAAA,MAAM,cAAA,GAAiB,CAAC,cAAA,IAAkB,OAAA,GAAU,UAAA;AAKpD,MAAA,OAAOC,uBAAA,CAAmB,IAAA,CAAK,eAAA,EAAiB,MAAM;AACpD,QAAA,MAAM,UAAA,GAAaC,cAAA;AAAA,UACjB;AAAA,YACE,IAAA;AAAA,YACA,KAAA,EAAO,YAAA;AAAA,YACP,UAAA,EAAY;AAAA,cACV,CAACC,oBAAS,GAAGC,WAAA;AAAA,cACb,CAACC,6BAAkB,GAAG,IAAA;AAAA,cACtB,oBAAA,EAAsB,IAAA;AAAA,cACtB,+BAA+B,MAAA,EAAQ,OAAA;AAAA,cACvC,qCAAA,EAAuC,QAAQ,OAAA,EAAS,OAAA;AAAA;AAAA,cAExD,mCAAA,EACE,OAAO,MAAA,EAAQ,OAAA,EAAS,UAAU,UAAA,GAAa,MAAA,GAAY,QAAQ,OAAA,EAAS,KAAA;AAAA,cAC9E,mCAAA,EAAqC,QAAQ,OAAA,EAAS,KAAA;AAAA,cACtD,6BAAA,EAA+B,OAAA;AAAA,cAC/B,CAACC,qCAAgC,GAAG,+BAAA;AAAA,cACpC,CAACC,qCAA0B,GAAG;AAAA;AAChC,WACF;AAAA,UACA,OAAM,IAAA,KAAQ;AACZ,YAAA,IAAI;AACF,cAAA,MAAM,MAAA,GAAS,MAAO,YAAA,CAAoD,GAAG,IAAI,CAAA;AACjF,cAAA,IAAA,CAAK,SAAA,CAAU,EAAE,IAAA,EAAM,CAAA,EAAG,CAAA;AAC1B,cAAA,OAAO,MAAA;AAAA,YACT,SAAS,KAAA,EAAO;AACd,cAAA,IAAI,cAAA,EAAgB;AAClB,gBAAAC,qBAAA,CAAiB,KAAA,EAAO,EAAE,SAAA,EAAW,EAAE,SAAS,IAAA,EAAM,IAAA,EAAM,+BAAA,EAAgC,EAAG,CAAA;AAAA,cACjG;AACA,cAAA,MAAM,KAAA;AAAA,YACR;AAAA,UACF;AAAA,SACF;AAGA,QAAA,OAAO,UAAA,CAAW,IAAA;AAAA,UAChB,CAAA,MAAA,KAAU;AACR,YAAA,IAAA,CAAK,UAAA,CAAWC,UAAA,CAAM,GAAI,CAAC,CAAA;AAC3B,YAAA,OAAO,MAAA;AAAA,UACT,CAAA;AAAA,UACA,CAAA,KAAA,KAAS;AACP,YAAA,IAAA,CAAK,UAAA,CAAWA,UAAA,CAAM,GAAI,CAAC,CAAA;AAC3B,YAAA,MAAM,KAAA;AAAA,UACR;AAAA,SACF;AAAA,MACF,CAAC,CAAA;AAAA,IACH,CAAA;AAEA,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,OAAO,eAAA,GACH,IAAA,CAAK,KAAA,CAAM,EAAA,CAAG,MAAM,MAAA,EAAQ,oBAAA,EAAsB,eAAe,CAAA,GACjE,IAAA,CAAK,KAAA,CAAM,EAAA,CAAG,IAAA,EAAM,QAAQ,oBAAoB,CAAA;AAAA,IACtD;AAEA,IAAA,OAAO,eAAA,GACH,IAAA,CAAK,KAAA,CAAM,EAAA,CAAG,IAAA,EAAM,oBAAA,EAAsB,eAAe,CAAA,GACzD,IAAA,CAAK,KAAA,CAAM,EAAA,CAAG,IAAA,EAAM,oBAAoB,CAAA;AAAA,EAC9C;AAAA,EAEA,MAAa,KAAA,CAAM,IAAA,EAAc,QAAA,EAAgD;AAC/E,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,IAAA,EAAM,QAAQ,CAAA;AAAA,EACxC;AAAA,EAEA,MAAa,UAAA,CAAW,IAAA,EAAc,SAAA,EAAyC;AAC7E,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,IAAA,EAAM,SAAS,CAAA;AAAA,EAC9C;AAAA,EAEA,MAAa,YAAA,CACX,IAAA,EACA,OAAA,EAC+B;AAC/B,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,YAAA,CAAgB,IAAA,EAAM,OAAO,CAAA;AAAA,EACjD;AACF;AAmBO,SAAS,4BAAA,CAgBd,iBAAwE,aAAA,EAAqB;AAC7F,EAAA,MAAM,iBAAA,GAAoB,IAAI,KAAA,CAAM,aAAA,EAAe;AAAA;AAAA,IAEjD,SAAA,CAAU,MAAA,EAAW,IAAA,EAAyC,SAAA,EAAW;AACvE,MAAA,MAAM,CAAC,GAAA,EAAK,GAAG,CAAA,GAAI,IAAA;AACnB,MAAA,MAAM,OAAA,GAAUC,oCAAkB,GAAG,CAAA;AACrC,MAAA,MAAM,OAAA,GAAU,gBAAgB,GAAG,CAAA;AACnC,MAAA,IAAA,CAAK,CAAC,CAAA,GAAI,OAAA;AACV,MAAA,IAAA,CAAK,CAAC,CAAA,GAAIC,2BAAA,CAAc,GAAA,EAAgC,OAAO,CAAA;AAC/D,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,SAAA,CAAU,MAAA,EAAQ,MAAM,SAAS,CAAA;AAC1D,MAAA,OAAO,IAAI,MAAM,QAAA,EAAU;AAAA,QACzB,GAAA,CAAI,GAAA,EAAK,IAAA,EAAM,QAAA,EAAU;AACvB,UAAA,IAAI,SAAS,KAAA,EAAO;AAClB,YAAA,OAAO,eAAgB,OAAyB,IAAA,EAAsC;AACpF,cAAAC,6DAAA,EAAyC;AAEzC,cAAA,OAAOC,4CAAA,CAA6B,OAAM,cAAA,KAAkB;AAC1D,gBAAA,MAAM,SAAA,GAAYC,0BAAA,CAAqB,OAAO,CAAA,CAAE,KAAK,OAAO,CAAA;AAC5D,gBAAA,MAAM,MAAA,GAASC,SAAK,EAAE,GAAG,SAAS,GAAA,EAAK,OAAA,EAAS,YAAA,EAAc,KAAA,EAAO,CAAA;AACrE,gBAAA,cAAA,CAAe,UAAU,MAAM,CAAA;AAE/B,gBAAAC,kCAAA,CAAwB,cAAc,CAAA;AAEtC,gBAAA,OAAOC,cAAA,CAAU,OAAM,KAAA,KAAS;AAC9B,kBAAA,MAAM,kBAAA,GAAqB,MAAM,gCAAA,CAAiC,KAAA,CAAM,UAAU,CAAA;AAClF,kBAAA,KAAA,CAAM,sBAAsB,kBAAkB,CAAA;AAE9C,kBAAA,IAAI;AACF,oBAAA,OAAO,MAAM,IAAI,GAAA,CAAI,IAAA;AAAA,sBACnB,GAAA;AAAA,sBACA,KAAA;AAAA,sBACA,IAAI,mBAAA,CAAoB,KAAA,CAAM,YAAY,OAAA,EAAS,IAAA,EAAM,WAAW,cAAc;AAAA,qBACpF;AAAA,kBACF,CAAA,SAAE;AACA,oBAAA,SAAA,CAAUC,qBAAA,CAAgB,MAAM,CAAC,CAAA;AAAA,kBACnC;AAAA,gBACF,CAAC,CAAA;AAAA,cACH,GAAG,OAAO,CAAA;AAAA,YACZ,CAAA;AAAA,UACF;AACA,UAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,IAAA,EAAM,QAAQ,CAAA;AAAA,QACxC;AAAA,OACD,CAAA;AAAA,IACH;AAAA,GACD,CAAA;AAED,EAAAC,6BAAA,CAAmB,iBAAiB,CAAA;AACpC,EAAA,OAAO,iBAAA;AACT;;;;;"}
|
|
@@ -140,7 +140,7 @@ function createRpcPrototypeWrapper(methodName, originalMethod) {
|
|
|
140
140
|
return wrapper;
|
|
141
141
|
}
|
|
142
142
|
function instrumentDurableObjectWithSentry(optionsCallback, DurableObjectClass) {
|
|
143
|
-
|
|
143
|
+
const InstrumentedClass = new Proxy(DurableObjectClass, {
|
|
144
144
|
construct(target, [ctx, env], newTarget) {
|
|
145
145
|
const { obj, options, context, frameworkManagedMethods } = constructInstrumentedDurableObject(
|
|
146
146
|
target,
|
|
@@ -152,9 +152,11 @@ function instrumentDurableObjectWithSentry(optionsCallback, DurableObjectClass)
|
|
|
152
152
|
return finalizeWithRpcInstrumentation(obj, options, context, frameworkManagedMethods);
|
|
153
153
|
}
|
|
154
154
|
});
|
|
155
|
+
instrument.markAsInstrumented(InstrumentedClass);
|
|
156
|
+
return InstrumentedClass;
|
|
155
157
|
}
|
|
156
158
|
function instrumentAgentWithSentry(optionsCallback, AgentClass) {
|
|
157
|
-
|
|
159
|
+
const InstrumentedClass = new Proxy(AgentClass, {
|
|
158
160
|
construct(target, [ctx, env], newTarget) {
|
|
159
161
|
const { obj, options, context, frameworkManagedMethods } = constructInstrumentedDurableObject(
|
|
160
162
|
target,
|
|
@@ -167,6 +169,8 @@ function instrumentAgentWithSentry(optionsCallback, AgentClass) {
|
|
|
167
169
|
return finalizeWithRpcInstrumentation(obj, options, context, frameworkManagedMethods);
|
|
168
170
|
}
|
|
169
171
|
});
|
|
172
|
+
instrument.markAsInstrumented(InstrumentedClass);
|
|
173
|
+
return InstrumentedClass;
|
|
170
174
|
}
|
|
171
175
|
|
|
172
176
|
exports.constructInstrumentedDurableObject = constructInstrumentedDurableObject;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durableobject.js","sources":["../../../src/durableobject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport { RPC } from '@sentry/conventions/op';\nimport { isObjectLike } from '@sentry/core';\nimport type { DurableObject } from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from '@sentry/server-utils/no-diagnostic-channels';\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 { instrumentCloudflareAgent } from './instrumentations/agents';\nimport type { DefaultEnv, ResolveEnv, StrictCloudflareOptions } from './types';\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 /** 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.\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 rpcInstanceStates.set(obj, { options, context });\n\n instrumentPrototypeRpcMethods(obj, excludedMethods);\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): PropertyDescriptor | undefined {\n if (\n RESERVED_RPC_METHOD_NAMES.has(methodName) ||\n Object.prototype.hasOwnProperty.call(obj, methodName) ||\n excludedMethods?.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 */\nfunction instrumentPrototypeRpcMethods(obj: object, excludedMethods?: ReadonlySet<string>): 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);\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 RPC metadata or instance state use the original method directly. The\n * original function name and 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 // Untraced calls are the common case — every internal call the instance makes to one of its\n // own methods lands here too — so check the arguments before touching per-instance state.\n if (!hasRpcMeta(args)) {\n return Reflect.apply(originalMethod, this, args);\n }\n\n const state = isObjectLike(this) ? rpcInstanceStates.get(this) : undefined;\n\n if (!state) {\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 * RPC methods (prototype methods) are instrumented too, so an incoming trace continues into them.\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 Env = DefaultEnv,\n // oxlint-disable-next-line typescript/no-explicit-any\n T extends DurableObject<any> = DurableObject<Env>,\n // oxlint-disable-next-line typescript/no-explicit-any\n C extends new (state: DurableObjectState, env: any) => T = new (state: DurableObjectState, env: any) => T,\n O = unknown,\n>(optionsCallback: (env: ResolveEnv<C, Env>) => StrictCloudflareOptions<O>, 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 * }),\n * MyAgentBase,\n * );\n * ```\n */\nexport function instrumentAgentWithSentry<\n Env = DefaultEnv,\n // oxlint-disable-next-line typescript/no-explicit-any\n T extends DurableObject<any> = DurableObject<Env>,\n // oxlint-disable-next-line typescript/no-explicit-any\n C extends new (state: DurableObjectState, env: any) => T = new (state: DurableObjectState, env: any) => T,\n O = unknown,\n>(optionsCallback: (env: ResolveEnv<C, Env>) => StrictCloudflareOptions<O>, 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","getInstrumented","markAsInstrumented","hasRpcMeta","isObjectLike","wrapMethodWithSentry","RPC","instrumentCloudflareAgent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"durableobject.js","sources":["../../../src/durableobject.ts"],"sourcesContent":["/* eslint-disable max-lines */\n/* eslint-disable @typescript-eslint/unbound-method */\nimport { RPC } from '@sentry/conventions/op';\nimport { isObjectLike } from '@sentry/core';\nimport type { DurableObject } from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from '@sentry/server-utils/no-diagnostic-channels';\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 { instrumentCloudflareAgent } from './instrumentations/agents';\nimport type { DefaultEnv, ResolveEnv, StrictCloudflareOptions } from './types';\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 /** 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.\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 rpcInstanceStates.set(obj, { options, context });\n\n instrumentPrototypeRpcMethods(obj, excludedMethods);\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): PropertyDescriptor | undefined {\n if (\n RESERVED_RPC_METHOD_NAMES.has(methodName) ||\n Object.prototype.hasOwnProperty.call(obj, methodName) ||\n excludedMethods?.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 */\nfunction instrumentPrototypeRpcMethods(obj: object, excludedMethods?: ReadonlySet<string>): 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);\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 RPC metadata or instance state use the original method directly. The\n * original function name and 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 // Untraced calls are the common case — every internal call the instance makes to one of its\n // own methods lands here too — so check the arguments before touching per-instance state.\n if (!hasRpcMeta(args)) {\n return Reflect.apply(originalMethod, this, args);\n }\n\n const state = isObjectLike(this) ? rpcInstanceStates.get(this) : undefined;\n\n if (!state) {\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 * RPC methods (prototype methods) are instrumented too, so an incoming trace continues into them.\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 Env = DefaultEnv,\n // oxlint-disable-next-line typescript/no-explicit-any\n T extends DurableObject<any> = DurableObject<Env>,\n // oxlint-disable-next-line typescript/no-explicit-any\n C extends new (state: DurableObjectState, env: any) => T = new (state: DurableObjectState, env: any) => T,\n O = unknown,\n>(optionsCallback: (env: ResolveEnv<C, Env>) => StrictCloudflareOptions<O>, DurableObjectClass: C): C {\n const InstrumentedClass = 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 // Recognizable for `_INTERNAL_wrapUnlessInstrumented`, so auto-instrumentation never nests wrappers.\n markAsInstrumented(InstrumentedClass);\n return InstrumentedClass;\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 * }),\n * MyAgentBase,\n * );\n * ```\n */\nexport function instrumentAgentWithSentry<\n Env = DefaultEnv,\n // oxlint-disable-next-line typescript/no-explicit-any\n T extends DurableObject<any> = DurableObject<Env>,\n // oxlint-disable-next-line typescript/no-explicit-any\n C extends new (state: DurableObjectState, env: any) => T = new (state: DurableObjectState, env: any) => T,\n O = unknown,\n>(optionsCallback: (env: ResolveEnv<C, Env>) => StrictCloudflareOptions<O>, AgentClass: C): C {\n const InstrumentedClass = 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 markAsInstrumented(InstrumentedClass);\n return InstrumentedClass;\n}\n"],"names":["setAsyncLocalStorageAsyncContextStrategy","options","getFinalOptions","instrumentContext","instrumentEnv","instrumentDurableObjectHandlers","getInstrumented","markAsInstrumented","hasRpcMeta","isObjectLike","wrapMethodWithSentry","RPC","instrumentCloudflareAgent"],"mappings":"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"}
|