@rasputin-ai/node 0.5.0-alpha.9 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +219 -188
- package/dist/auto-instrumentation/bun-plugin.d.ts.map +1 -1
- package/dist/auto-instrumentation/format-configuration-report.d.ts +4 -0
- package/dist/auto-instrumentation/format-configuration-report.d.ts.map +1 -1
- package/dist/auto-instrumentation/instrument-compiled-esm.d.ts +1 -3
- package/dist/auto-instrumentation/instrument-compiled-esm.d.ts.map +1 -1
- package/dist/auto-instrumentation/instrumentation-manifest-delta.d.ts +10 -2
- package/dist/auto-instrumentation/instrumentation-manifest-delta.d.ts.map +1 -1
- package/dist/auto-instrumentation/instrumentation-manifest-registry.d.ts +6 -0
- package/dist/auto-instrumentation/instrumentation-manifest-registry.d.ts.map +1 -1
- package/dist/auto-instrumentation/node-hooks.d.ts.map +1 -1
- package/dist/auto-instrumentation/parameter-initializer-may-run-code.d.ts +3 -0
- package/dist/auto-instrumentation/parameter-initializer-may-run-code.d.ts.map +1 -0
- package/dist/auto-instrumentation/schedule-instrumentation-manifest-upload.d.ts +1 -1
- package/dist/auto-instrumentation/schedule-instrumentation-manifest-upload.d.ts.map +1 -1
- package/dist/auto-instrumentation/source-map-locations.d.ts +1 -0
- package/dist/auto-instrumentation/source-map-locations.d.ts.map +1 -1
- package/dist/auto-instrumentation/suspension-whitelist.d.ts +33 -0
- package/dist/auto-instrumentation/suspension-whitelist.d.ts.map +1 -0
- package/dist/auto-instrumentation/transform-disk-cache.d.ts +7 -0
- package/dist/auto-instrumentation/transform-disk-cache.d.ts.map +1 -0
- package/dist/auto-instrumentation/transform-source.d.ts +9 -6
- package/dist/auto-instrumentation/transform-source.d.ts.map +1 -1
- package/dist/auto-instrumentation/verify-instrumentation-isomorphism.d.ts +2 -0
- package/dist/auto-instrumentation/verify-instrumentation-isomorphism.d.ts.map +1 -0
- package/dist/auto-instrumentation/verify-transformed-source.d.ts +2 -0
- package/dist/auto-instrumentation/verify-transformed-source.d.ts.map +1 -0
- package/dist/execution-recorder/automatic-runtime.d.ts +17 -7
- package/dist/execution-recorder/automatic-runtime.d.ts.map +1 -1
- package/dist/execution-recorder/encode-frozen.d.ts +16 -0
- package/dist/execution-recorder/encode-frozen.d.ts.map +1 -0
- package/dist/execution-recorder/execution-journal.d.ts.map +1 -1
- package/dist/execution-recorder/execution-recorder-types.d.ts +124 -36
- package/dist/execution-recorder/execution-recorder-types.d.ts.map +1 -1
- package/dist/execution-recorder/execution-recorder.d.ts +2 -2
- package/dist/execution-recorder/execution-recorder.d.ts.map +1 -1
- package/dist/execution-recorder/function-plan.d.ts +8 -1
- package/dist/execution-recorder/function-plan.d.ts.map +1 -1
- package/dist/execution-recorder/index.d.ts +1 -1
- package/dist/execution-recorder/index.d.ts.map +1 -1
- package/dist/execution-recorder/recorder-memory-budget.d.ts +1 -0
- package/dist/execution-recorder/recorder-memory-budget.d.ts.map +1 -1
- package/dist/execution-recorder/redact-keys.d.ts +4 -0
- package/dist/execution-recorder/redact-keys.d.ts.map +1 -0
- package/dist/execution-recorder/run-exactly-once.d.ts +7 -0
- package/dist/execution-recorder/run-exactly-once.d.ts.map +1 -0
- package/dist/execution-recorder/runtime-state-size-budget.d.ts +14 -0
- package/dist/execution-recorder/runtime-state-size-budget.d.ts.map +1 -0
- package/dist/execution-recorder/safe-serialize.d.ts +9 -3
- package/dist/execution-recorder/safe-serialize.d.ts.map +1 -1
- package/dist/execution-recorder/value-freeze.d.ts +43 -0
- package/dist/execution-recorder/value-freeze.d.ts.map +1 -0
- package/dist/execution-recorder/warn-missing-async-context-frame.d.ts +10 -0
- package/dist/execution-recorder/warn-missing-async-context-frame.d.ts.map +1 -0
- package/dist/index.d.ts +1 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2612 -893
- package/dist/install-global-handlers.d.ts +29 -8
- package/dist/install-global-handlers.d.ts.map +1 -1
- package/dist/instrument/build.js +947 -805
- package/dist/instrument/bun.js +1098 -778
- package/dist/instrument/node.js +1078 -780
- package/dist/internal.d.ts +7 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +4072 -0
- package/dist/rasputin-init.d.ts +25 -5
- package/dist/rasputin-init.d.ts.map +1 -1
- package/dist/sdk-meta.d.ts +1 -1
- package/dist/sdk-meta.d.ts.map +1 -1
- package/package.json +8 -3
- package/dist/derivation/analyze-function.d.ts +0 -42
- package/dist/derivation/analyze-function.d.ts.map +0 -1
- package/dist/derivation/build-dependency-graph.d.ts +0 -21
- package/dist/derivation/build-dependency-graph.d.ts.map +0 -1
- package/dist/derivation/derivation-ir.d.ts +0 -33
- package/dist/derivation/derivation-ir.d.ts.map +0 -1
- package/dist/derivation/derivation-proof.d.ts +0 -14
- package/dist/derivation/derivation-proof.d.ts.map +0 -1
- package/dist/derivation/emit-capture-plan.d.ts +0 -8
- package/dist/derivation/emit-capture-plan.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,107 +1,10 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/rasputin-init.ts
|
|
2
|
+
import { join } from "node:path";
|
|
2
3
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
uploadInstrumentationManifest
|
|
4
|
+
createClient,
|
|
5
|
+
isClientEnabled
|
|
6
6
|
} from "@rasputin-ai/core";
|
|
7
7
|
|
|
8
|
-
// src/auto-instrumentation/format-configuration-report.ts
|
|
9
|
-
var RULE = "-".repeat(64);
|
|
10
|
-
var BANNER = [
|
|
11
|
-
RULE,
|
|
12
|
-
" ____ _ ____ ____ _ _ _____ ___ _ _",
|
|
13
|
-
"| _ \\ / \\ / ___| | _ \\ | | | | |_ _| |_ _| | \\ | |",
|
|
14
|
-
"| |_) | / _ \\ \\___ \\ | |_) | | | | | | | | | | \\| |",
|
|
15
|
-
"| _ < / ___ \\ ___) | | __/ | |_| | | | | | | |\\ |",
|
|
16
|
-
"|_| \\_\\ /_/ \\_\\ |____/ |_| \\___/ |_| |___| |_| \\_|",
|
|
17
|
-
"",
|
|
18
|
-
"",
|
|
19
|
-
"CONFIGURATION:"
|
|
20
|
-
];
|
|
21
|
-
var counted = (n, singular, plural) => `${n} ${n === 1 ? singular : plural}`;
|
|
22
|
-
var issueHeadline = (issue) => {
|
|
23
|
-
const target = issue.packageName ? `package ${issue.packageName}` : issue.packageRelativePath;
|
|
24
|
-
if (issue.reason === "ambiguous") return `Could not uniquely locate ${target}.`;
|
|
25
|
-
if (issue.reason === "not_found") return `Could not find ${target} in this Git release.`;
|
|
26
|
-
if (issue.reason === "invalid_mapping") {
|
|
27
|
-
return `The configured package root for ${target} does not match this Git release.`;
|
|
28
|
-
}
|
|
29
|
-
return `GitHub could not be reached while locating ${target}.`;
|
|
30
|
-
};
|
|
31
|
-
var formatIssue = (issue) => {
|
|
32
|
-
const lines = [
|
|
33
|
-
`! ${issueHeadline(issue)}`,
|
|
34
|
-
"",
|
|
35
|
-
" Captured:",
|
|
36
|
-
` ${issue.packageRelativePath}`
|
|
37
|
-
];
|
|
38
|
-
if (issue.candidates?.length) {
|
|
39
|
-
lines.push("", " Possible repository locations:");
|
|
40
|
-
for (const candidate of issue.candidates) lines.push(` ${candidate}`);
|
|
41
|
-
}
|
|
42
|
-
return lines;
|
|
43
|
-
};
|
|
44
|
-
var formatConfigurationReport = (input) => {
|
|
45
|
-
const packages = input.verification.packages ?? [];
|
|
46
|
-
const unresolved = input.verification.unresolved;
|
|
47
|
-
const mappingIssues = unresolved.filter((issue) => issue.reason !== "github_unavailable");
|
|
48
|
-
const githubUnavailable = input.verification.status === "unavailable" || unresolved.some((issue) => issue.reason === "github_unavailable");
|
|
49
|
-
const verified = input.uploaded && input.verification.status === "verified";
|
|
50
|
-
const lines = [
|
|
51
|
-
...BANNER,
|
|
52
|
-
"",
|
|
53
|
-
"Release",
|
|
54
|
-
`\u2713 ${input.release}`,
|
|
55
|
-
"",
|
|
56
|
-
"Runtime",
|
|
57
|
-
`\u2713 ${input.runtime}`,
|
|
58
|
-
"",
|
|
59
|
-
"Instrumentation",
|
|
60
|
-
`\u2713 ${counted(input.modules, "application module", "application modules")} observed`,
|
|
61
|
-
`\u2713 ${counted(input.functions, "function", "functions")} instrumented`,
|
|
62
|
-
`\u2713 ${counted(input.packageNames.length, "workspace package", "workspace packages")} detected`
|
|
63
|
-
];
|
|
64
|
-
if (packages.length > 0 || mappingIssues.length > 0) {
|
|
65
|
-
lines.push("", "Package roots");
|
|
66
|
-
for (const mapping of packages) {
|
|
67
|
-
lines.push(
|
|
68
|
-
mapping.packageName ? `\u2713 ${mapping.packageName} \u2192 ${mapping.repositoryRoot}` : `\u2713 ${mapping.repositoryRoot}`
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
for (const [index, issue] of mappingIssues.entries()) {
|
|
72
|
-
if (packages.length > 0 || index > 0) lines.push("");
|
|
73
|
-
lines.push(...formatIssue(issue));
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
lines.push("", "Manifest");
|
|
77
|
-
if (!input.uploaded) {
|
|
78
|
-
lines.push("! upload failed");
|
|
79
|
-
} else {
|
|
80
|
-
lines.push("\u2713 uploaded");
|
|
81
|
-
lines.push(
|
|
82
|
-
verified ? "\u2713 verified against GitHub" : "! some source files could not be mapped to this Git release"
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
lines.push("", "GitHub");
|
|
86
|
-
if (!input.uploaded) {
|
|
87
|
-
lines.push("! not verified");
|
|
88
|
-
} else if (githubUnavailable) {
|
|
89
|
-
lines.push("! repository is not connected, or this release could not be read");
|
|
90
|
-
} else {
|
|
91
|
-
lines.push("\u2713 repository connected");
|
|
92
|
-
}
|
|
93
|
-
if (input.uploaded && input.verification.status !== "verified") {
|
|
94
|
-
lines.push("", "Runtime recording is unaffected.");
|
|
95
|
-
}
|
|
96
|
-
lines.push(RULE);
|
|
97
|
-
return lines.join("\n");
|
|
98
|
-
};
|
|
99
|
-
var runtimeLabel = () => {
|
|
100
|
-
const bun = globalThis.Bun;
|
|
101
|
-
if (typeof bun?.version === "string" && bun.version) return `Bun ${bun.version}`;
|
|
102
|
-
return `Node ${process.versions.node}`;
|
|
103
|
-
};
|
|
104
|
-
|
|
105
8
|
// src/auto-instrumentation/instrumentation-manifest-registry.ts
|
|
106
9
|
import { createHash } from "node:crypto";
|
|
107
10
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -115,6 +18,8 @@ import {
|
|
|
115
18
|
runtimeFunctionId,
|
|
116
19
|
sourceLocatorFromFile
|
|
117
20
|
} from "@rasputin-ai/core";
|
|
21
|
+
var encodedPlanOmitsCallValues = (plan) => plan[6] === 1;
|
|
22
|
+
var encodedPlanHasPreBodyParameterEvaluation = (plan) => plan[7] === 1;
|
|
118
23
|
var EVENT_PAIR_BASE_ESTIMATED_BYTES = 512;
|
|
119
24
|
var definitionFromEncodedPlan = (plan) => {
|
|
120
25
|
const [functionId, name, packageName, packageRelativePath, line, column] = plan;
|
|
@@ -127,7 +32,8 @@ var definitionFromEncodedPlan = (plan) => {
|
|
|
127
32
|
return {
|
|
128
33
|
functionId,
|
|
129
34
|
name,
|
|
130
|
-
...source ? { source } : {}
|
|
35
|
+
...source ? { source } : {},
|
|
36
|
+
...encodedPlanHasPreBodyParameterEvaluation(plan) ? { parentAttribution: "pre_body_parameter_evaluation" } : {}
|
|
131
37
|
};
|
|
132
38
|
};
|
|
133
39
|
var estimatedCallBytesFor = (functionId) => EVENT_PAIR_BASE_ESTIMATED_BYTES + Buffer.byteLength(functionId, "utf8") * 2;
|
|
@@ -138,13 +44,16 @@ var registrySymbol = Symbol.for(INSTRUMENTATION_MANIFEST_SYMBOL);
|
|
|
138
44
|
var getRegistry = () => {
|
|
139
45
|
const existing = Reflect.get(globalThis, registrySymbol);
|
|
140
46
|
if (existing?.__rasputinManifestRegistry && existing.files instanceof Map && typeof existing.generation === "number" && typeof existing.uploadedGeneration === "number") {
|
|
141
|
-
|
|
47
|
+
const registry2 = existing;
|
|
48
|
+
if (typeof registry2.alreadyInstrumented !== "number") registry2.alreadyInstrumented = 0;
|
|
49
|
+
return registry2;
|
|
142
50
|
}
|
|
143
51
|
const registry = {
|
|
144
52
|
__rasputinManifestRegistry: true,
|
|
145
53
|
files: /* @__PURE__ */ new Map(),
|
|
146
54
|
generation: 0,
|
|
147
|
-
uploadedGeneration: 0
|
|
55
|
+
uploadedGeneration: 0,
|
|
56
|
+
alreadyInstrumented: 0
|
|
148
57
|
};
|
|
149
58
|
Reflect.set(globalThis, registrySymbol, registry);
|
|
150
59
|
return registry;
|
|
@@ -180,18 +89,60 @@ var isInstrumentationManifestDirty = () => {
|
|
|
180
89
|
return registry.generation !== registry.uploadedGeneration && (registry.files.size > 0 || registry.prebuilt !== void 0);
|
|
181
90
|
};
|
|
182
91
|
var instrumentationManifestGeneration = () => getRegistry().generation;
|
|
92
|
+
var instrumentationCoverageStats = () => {
|
|
93
|
+
const registry = getRegistry();
|
|
94
|
+
let instrumented = 0;
|
|
95
|
+
let instrumentedAsync = 0;
|
|
96
|
+
const skippedByReason = {};
|
|
97
|
+
for (const delta of registry.files.values()) {
|
|
98
|
+
for (const fn of delta.functions) {
|
|
99
|
+
if (fn.instrumented === false) {
|
|
100
|
+
if (!fn.skipReason) continue;
|
|
101
|
+
skippedByReason[fn.skipReason] = (skippedByReason[fn.skipReason] ?? 0) + 1;
|
|
102
|
+
} else {
|
|
103
|
+
instrumented += 1;
|
|
104
|
+
if (fn.asyncFunction) instrumentedAsync += 1;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (registry.alreadyInstrumented > 0) {
|
|
109
|
+
skippedByReason.already_instrumented = registry.alreadyInstrumented;
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
instrumented,
|
|
113
|
+
instrumentedAsync,
|
|
114
|
+
alreadyInstrumented: registry.alreadyInstrumented,
|
|
115
|
+
skippedByReason
|
|
116
|
+
};
|
|
117
|
+
};
|
|
183
118
|
var instrumentationManifestModuleCount = () => {
|
|
184
119
|
const registry = getRegistry();
|
|
185
120
|
if (registry.files.size > 0) return registry.files.size;
|
|
186
121
|
if (!registry.prebuilt) return 0;
|
|
187
122
|
return new Set(registry.prebuilt.functions.map((fn) => fn.source.packageRelativePath)).size;
|
|
188
123
|
};
|
|
124
|
+
var snapshotOptionsKey = (options) => JSON.stringify({
|
|
125
|
+
sourceRoot: options.sourceRoot ?? "",
|
|
126
|
+
sourceRoots: options.sourceRoots ?? {}
|
|
127
|
+
});
|
|
189
128
|
var snapshotInstrumentationManifest = (options = {}) => {
|
|
129
|
+
const registry = getRegistry();
|
|
130
|
+
const optionsKey = snapshotOptionsKey(options);
|
|
131
|
+
if (registry.snapshotCache && registry.snapshotCache.generation === registry.generation && registry.snapshotCache.optionsKey === optionsKey) {
|
|
132
|
+
return registry.snapshotCache.manifest;
|
|
133
|
+
}
|
|
190
134
|
const functions = [];
|
|
191
135
|
const callSites = [];
|
|
192
136
|
const destructures = [];
|
|
193
|
-
const
|
|
194
|
-
|
|
137
|
+
const remember = (manifest) => {
|
|
138
|
+
registry.snapshotCache = {
|
|
139
|
+
generation: registry.generation,
|
|
140
|
+
optionsKey,
|
|
141
|
+
manifest
|
|
142
|
+
};
|
|
143
|
+
return manifest;
|
|
144
|
+
};
|
|
145
|
+
for (const delta of registry.files.values()) {
|
|
195
146
|
for (const fn of delta.functions) {
|
|
196
147
|
const definition = definitionFromEncodedPlan(fn.plan);
|
|
197
148
|
if (!definition.source) continue;
|
|
@@ -203,7 +154,8 @@ var snapshotInstrumentationManifest = (options = {}) => {
|
|
|
203
154
|
startColumn: fn.startColumn,
|
|
204
155
|
endLine: fn.endLine,
|
|
205
156
|
endColumn: fn.endColumn,
|
|
206
|
-
params: fn.params
|
|
157
|
+
params: fn.params,
|
|
158
|
+
...fn.instrumented === false ? { instrumented: false, skipReason: fn.skipReason } : {}
|
|
207
159
|
});
|
|
208
160
|
}
|
|
209
161
|
for (const site of delta.callSites) {
|
|
@@ -242,25 +194,23 @@ var snapshotInstrumentationManifest = (options = {}) => {
|
|
|
242
194
|
binding: destructure.binding
|
|
243
195
|
});
|
|
244
196
|
}
|
|
245
|
-
derivationPlans.push(...delta.derivationPlans ?? []);
|
|
246
197
|
}
|
|
247
|
-
const registry = getRegistry();
|
|
248
198
|
if (registry.prebuilt && registry.files.size === 0) {
|
|
249
199
|
const prebuilt = registry.prebuilt;
|
|
250
|
-
if (!options.sourceRoot && !options.sourceRoots) return prebuilt;
|
|
251
|
-
return {
|
|
200
|
+
if (!options.sourceRoot && !options.sourceRoots) return remember(prebuilt);
|
|
201
|
+
return remember({
|
|
252
202
|
...prebuilt,
|
|
253
203
|
sourceRoots: {
|
|
254
204
|
...options.sourceRoot ? { default: options.sourceRoot } : {},
|
|
255
205
|
packages: { ...options.sourceRoots ?? {} }
|
|
256
206
|
}
|
|
257
|
-
};
|
|
207
|
+
});
|
|
258
208
|
}
|
|
259
209
|
if (functions.length === 0 && callSites.length === 0 && destructures.length === 0) {
|
|
260
|
-
return void 0;
|
|
210
|
+
return remember(void 0);
|
|
261
211
|
}
|
|
262
212
|
const packages = { ...options.sourceRoots ?? {} };
|
|
263
|
-
return {
|
|
213
|
+
return remember({
|
|
264
214
|
schema_version: INSTRUMENTATION_MANIFEST_SCHEMA_VERSION,
|
|
265
215
|
...options.sourceRoot || Object.keys(packages).length > 0 ? {
|
|
266
216
|
sourceRoots: {
|
|
@@ -270,9 +220,8 @@ var snapshotInstrumentationManifest = (options = {}) => {
|
|
|
270
220
|
} : {},
|
|
271
221
|
functions,
|
|
272
222
|
callSites,
|
|
273
|
-
destructures
|
|
274
|
-
|
|
275
|
-
};
|
|
223
|
+
destructures
|
|
224
|
+
});
|
|
276
225
|
};
|
|
277
226
|
var markInstrumentationManifestUploaded = (generation) => {
|
|
278
227
|
const registry = getRegistry();
|
|
@@ -282,6 +231,116 @@ var setInstrumentationManifestOnDirty = (onDirty) => {
|
|
|
282
231
|
getRegistry().onDirty = onDirty;
|
|
283
232
|
};
|
|
284
233
|
|
|
234
|
+
// src/auto-instrumentation/schedule-instrumentation-manifest-upload.ts
|
|
235
|
+
import {
|
|
236
|
+
detectRelease,
|
|
237
|
+
resolveEndpointUrls,
|
|
238
|
+
uploadInstrumentationManifest
|
|
239
|
+
} from "@rasputin-ai/core";
|
|
240
|
+
|
|
241
|
+
// src/auto-instrumentation/format-configuration-report.ts
|
|
242
|
+
var RULE = "-".repeat(64);
|
|
243
|
+
var BANNER = [
|
|
244
|
+
RULE,
|
|
245
|
+
" ____ _ ____ ____ _ _ _____ ___ _ _",
|
|
246
|
+
"| _ \\ / \\ / ___| | _ \\ | | | | |_ _| |_ _| | \\ | |",
|
|
247
|
+
"| |_) | / _ \\ \\___ \\ | |_) | | | | | | | | | | \\| |",
|
|
248
|
+
"| _ < / ___ \\ ___) | | __/ | |_| | | | | | | |\\ |",
|
|
249
|
+
"|_| \\_\\ /_/ \\_\\ |____/ |_| \\___/ |_| |___| |_| \\_|",
|
|
250
|
+
"",
|
|
251
|
+
"",
|
|
252
|
+
"CONFIGURATION:"
|
|
253
|
+
];
|
|
254
|
+
var counted = (n, singular, plural) => `${n} ${n === 1 ? singular : plural}`;
|
|
255
|
+
var issueHeadline = (issue) => {
|
|
256
|
+
const target = issue.packageName ? `package ${issue.packageName}` : issue.packageRelativePath;
|
|
257
|
+
if (issue.reason === "ambiguous") return `Could not uniquely locate ${target}.`;
|
|
258
|
+
if (issue.reason === "not_found") return `Could not find ${target} in this Git release.`;
|
|
259
|
+
if (issue.reason === "invalid_mapping") {
|
|
260
|
+
return `The configured package root for ${target} does not match this Git release.`;
|
|
261
|
+
}
|
|
262
|
+
return `GitHub could not be reached while locating ${target}.`;
|
|
263
|
+
};
|
|
264
|
+
var formatIssue = (issue) => {
|
|
265
|
+
const lines = [
|
|
266
|
+
`! ${issueHeadline(issue)}`,
|
|
267
|
+
"",
|
|
268
|
+
" Captured:",
|
|
269
|
+
` ${issue.packageRelativePath}`
|
|
270
|
+
];
|
|
271
|
+
if (issue.candidates?.length) {
|
|
272
|
+
lines.push("", " Possible repository locations:");
|
|
273
|
+
for (const candidate of issue.candidates) lines.push(` ${candidate}`);
|
|
274
|
+
}
|
|
275
|
+
return lines;
|
|
276
|
+
};
|
|
277
|
+
var formatConfigurationReport = (input) => {
|
|
278
|
+
const packages = input.verification.packages ?? [];
|
|
279
|
+
const unresolved = input.verification.unresolved;
|
|
280
|
+
const mappingIssues = unresolved.filter((issue) => issue.reason !== "github_unavailable");
|
|
281
|
+
const githubUnavailable = input.verification.status === "unavailable" || unresolved.some((issue) => issue.reason === "github_unavailable");
|
|
282
|
+
const verified = input.uploaded && input.verification.status === "verified";
|
|
283
|
+
const lines = [
|
|
284
|
+
...BANNER,
|
|
285
|
+
"",
|
|
286
|
+
"Release",
|
|
287
|
+
`\u2713 ${input.release}`,
|
|
288
|
+
"",
|
|
289
|
+
"Runtime",
|
|
290
|
+
`\u2713 ${input.runtime}`,
|
|
291
|
+
"",
|
|
292
|
+
"Instrumentation",
|
|
293
|
+
`\u2713 ${counted(input.modules, "application module", "application modules")} observed`,
|
|
294
|
+
`\u2713 ${counted(input.functions, "function", "functions")} instrumented`,
|
|
295
|
+
...input.instrumentedAsync ? [`\u2713 ${counted(input.instrumentedAsync, "async function", "async functions")} instrumented`] : [],
|
|
296
|
+
...input.skippedFunctions ? [`! ${counted(input.skippedFunctions, "function", "functions")} skipped`] : [],
|
|
297
|
+
...Object.entries(input.skippedByReason ?? {}).filter(([, count]) => (count ?? 0) > 0).sort(([left], [right]) => left.localeCompare(right)).map(([reason, count]) => ` ${reason}: ${count}`),
|
|
298
|
+
...input.attributionDegradations ? [
|
|
299
|
+
`! ${counted(input.attributionDegradations, "runtime attribution degradation", "runtime attribution degradations")}`
|
|
300
|
+
] : [],
|
|
301
|
+
`\u2713 ${counted(input.packageNames.length, "workspace package", "workspace packages")} detected`
|
|
302
|
+
];
|
|
303
|
+
if (packages.length > 0 || mappingIssues.length > 0) {
|
|
304
|
+
lines.push("", "Package roots");
|
|
305
|
+
for (const mapping of packages) {
|
|
306
|
+
lines.push(
|
|
307
|
+
mapping.packageName ? `\u2713 ${mapping.packageName} \u2192 ${mapping.repositoryRoot}` : `\u2713 ${mapping.repositoryRoot}`
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
for (const [index, issue] of mappingIssues.entries()) {
|
|
311
|
+
if (packages.length > 0 || index > 0) lines.push("");
|
|
312
|
+
lines.push(...formatIssue(issue));
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
lines.push("", "Manifest");
|
|
316
|
+
if (!input.uploaded) {
|
|
317
|
+
lines.push("! upload failed");
|
|
318
|
+
} else {
|
|
319
|
+
lines.push("\u2713 uploaded");
|
|
320
|
+
lines.push(
|
|
321
|
+
verified ? "\u2713 verified against GitHub" : "! some source files could not be mapped to this Git release"
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
lines.push("", "GitHub");
|
|
325
|
+
if (!input.uploaded) {
|
|
326
|
+
lines.push("! not verified");
|
|
327
|
+
} else if (githubUnavailable) {
|
|
328
|
+
lines.push("! repository is not connected, or this release could not be read");
|
|
329
|
+
} else {
|
|
330
|
+
lines.push("\u2713 repository connected");
|
|
331
|
+
}
|
|
332
|
+
if (input.uploaded && input.verification.status !== "verified") {
|
|
333
|
+
lines.push("", "Runtime recording is unaffected.");
|
|
334
|
+
}
|
|
335
|
+
lines.push(RULE);
|
|
336
|
+
return lines.join("\n");
|
|
337
|
+
};
|
|
338
|
+
var runtimeLabel = () => {
|
|
339
|
+
const bun = globalThis.Bun;
|
|
340
|
+
if (typeof bun?.version === "string" && bun.version) return `Bun ${bun.version}`;
|
|
341
|
+
return `Node ${process.versions.node}`;
|
|
342
|
+
};
|
|
343
|
+
|
|
285
344
|
// src/auto-instrumentation/schedule-instrumentation-manifest-upload.ts
|
|
286
345
|
var unavailable = () => ({
|
|
287
346
|
status: "unavailable",
|
|
@@ -301,81 +360,162 @@ var noopHandle = {
|
|
|
301
360
|
}
|
|
302
361
|
};
|
|
303
362
|
var scheduleInstrumentationManifestUpload = (options) => {
|
|
304
|
-
|
|
305
|
-
if (!options.enabled || !release || !options.projectApiKey.trim()) {
|
|
363
|
+
if (!options.enabled || !(options.projectApiKey ?? "").trim()) {
|
|
306
364
|
return noopHandle;
|
|
307
365
|
}
|
|
366
|
+
const release = detectRelease({ release: options.release });
|
|
367
|
+
if (!release) return noopHandle;
|
|
308
368
|
const { instrumentationManifestUrl } = resolveEndpointUrls(options.apiUrl);
|
|
309
|
-
let inflight;
|
|
369
|
+
let inflight = Promise.resolve();
|
|
310
370
|
let verification = unavailable();
|
|
311
371
|
let loggedSuccess = false;
|
|
312
372
|
let loggedFailure = false;
|
|
373
|
+
let stopped = false;
|
|
374
|
+
let working = false;
|
|
375
|
+
let debounceTimer;
|
|
376
|
+
const sessionAbort = new AbortController();
|
|
377
|
+
const debounceMs = 500;
|
|
313
378
|
const packageNamesOf = (manifest) => [
|
|
314
379
|
...new Set(
|
|
315
380
|
manifest.functions.map((fn) => fn.source.packageName).filter((name) => Boolean(name))
|
|
316
381
|
)
|
|
317
382
|
].sort();
|
|
318
383
|
const report = (manifest, uploaded, next) => {
|
|
384
|
+
const coverage = instrumentationCoverageStats();
|
|
319
385
|
return formatConfigurationReport({
|
|
320
386
|
release,
|
|
321
387
|
runtime: runtimeLabel(),
|
|
322
388
|
modules: instrumentationManifestModuleCount(),
|
|
323
|
-
functions: manifest.functions.length,
|
|
389
|
+
functions: manifest.functions.filter((fn) => fn.instrumented !== false).length,
|
|
390
|
+
skippedFunctions: manifest.functions.filter((fn) => fn.instrumented === false).length,
|
|
391
|
+
instrumentedAsync: coverage.instrumentedAsync,
|
|
392
|
+
skippedByReason: coverage.skippedByReason,
|
|
324
393
|
packageNames: packageNamesOf(manifest),
|
|
325
394
|
verification: next,
|
|
326
395
|
uploaded
|
|
327
396
|
});
|
|
328
397
|
};
|
|
398
|
+
const clearDebounce = () => {
|
|
399
|
+
if (debounceTimer === void 0) return;
|
|
400
|
+
clearTimeout(debounceTimer);
|
|
401
|
+
debounceTimer = void 0;
|
|
402
|
+
};
|
|
329
403
|
const flushSoon = () => {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
if (
|
|
352
|
-
|
|
353
|
-
|
|
404
|
+
clearDebounce();
|
|
405
|
+
if (stopped || !isInstrumentationManifestDirty() || working) return;
|
|
406
|
+
working = true;
|
|
407
|
+
inflight = inflight.catch(() => {
|
|
408
|
+
}).then(async () => {
|
|
409
|
+
try {
|
|
410
|
+
while (!stopped && isInstrumentationManifestDirty()) {
|
|
411
|
+
const generation = instrumentationManifestGeneration();
|
|
412
|
+
const manifest = snapshotInstrumentationManifest({
|
|
413
|
+
sourceRoot: options.sourceRoot,
|
|
414
|
+
sourceRoots: options.sourceRoots
|
|
415
|
+
});
|
|
416
|
+
if (!manifest) {
|
|
417
|
+
markInstrumentationManifestUploaded(generation);
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
const controller = new AbortController();
|
|
421
|
+
const timeout = setTimeout(() => controller.abort(), 2e3);
|
|
422
|
+
timeout.unref?.();
|
|
423
|
+
const abortUpload = () => controller.abort();
|
|
424
|
+
sessionAbort.signal.addEventListener("abort", abortUpload, { once: true });
|
|
425
|
+
if (sessionAbort.signal.aborted) controller.abort();
|
|
426
|
+
const aborted = new Promise((_, reject) => {
|
|
427
|
+
const fail = () => reject(controller.signal.reason ?? new Error("aborted"));
|
|
428
|
+
if (controller.signal.aborted) {
|
|
429
|
+
fail();
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
controller.signal.addEventListener("abort", fail, { once: true });
|
|
433
|
+
});
|
|
434
|
+
try {
|
|
435
|
+
const result = await Promise.race([
|
|
436
|
+
uploadInstrumentationManifest({
|
|
437
|
+
url: instrumentationManifestUrl,
|
|
438
|
+
projectApiKey: options.projectApiKey,
|
|
439
|
+
release,
|
|
440
|
+
manifest,
|
|
441
|
+
fetch: options.fetch,
|
|
442
|
+
signal: controller.signal
|
|
443
|
+
}),
|
|
444
|
+
aborted
|
|
445
|
+
]);
|
|
446
|
+
if (stopped) return;
|
|
447
|
+
if (result.ok) {
|
|
448
|
+
verification = result.verification;
|
|
449
|
+
markInstrumentationManifestUploaded(generation);
|
|
450
|
+
if (verification.status === "verified") {
|
|
451
|
+
if (!loggedSuccess && options.logSuccess !== false) {
|
|
452
|
+
loggedSuccess = true;
|
|
453
|
+
console.info(report(manifest, true, verification));
|
|
454
|
+
}
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
if (!loggedFailure) {
|
|
458
|
+
loggedFailure = true;
|
|
459
|
+
console.warn(report(manifest, true, verification));
|
|
460
|
+
}
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
if (!loggedFailure) {
|
|
464
|
+
loggedFailure = true;
|
|
465
|
+
console.warn(report(manifest, false, unavailable()));
|
|
466
|
+
}
|
|
467
|
+
break;
|
|
468
|
+
} catch {
|
|
469
|
+
if (stopped) return;
|
|
470
|
+
break;
|
|
471
|
+
} finally {
|
|
472
|
+
clearTimeout(timeout);
|
|
473
|
+
sessionAbort.signal.removeEventListener("abort", abortUpload);
|
|
354
474
|
}
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
if (!loggedFailure) {
|
|
358
|
-
loggedFailure = true;
|
|
359
|
-
console.warn(report(manifest, true, verification));
|
|
360
475
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
if (!loggedFailure) {
|
|
364
|
-
loggedFailure = true;
|
|
365
|
-
console.warn(report(manifest, false, unavailable()));
|
|
476
|
+
} finally {
|
|
477
|
+
working = false;
|
|
366
478
|
}
|
|
367
479
|
});
|
|
368
|
-
inflight = inflight ? inflight.then(() => work) : work;
|
|
369
480
|
};
|
|
370
|
-
|
|
371
|
-
|
|
481
|
+
const armFlush = () => {
|
|
482
|
+
if (stopped || !isInstrumentationManifestDirty()) return;
|
|
483
|
+
clearDebounce();
|
|
484
|
+
debounceTimer = setTimeout(() => {
|
|
485
|
+
debounceTimer = void 0;
|
|
486
|
+
flushSoon();
|
|
487
|
+
}, debounceMs);
|
|
488
|
+
debounceTimer.unref?.();
|
|
489
|
+
};
|
|
490
|
+
setInstrumentationManifestOnDirty(armFlush);
|
|
491
|
+
if (isInstrumentationManifestDirty()) armFlush();
|
|
372
492
|
return {
|
|
373
493
|
flushSoon,
|
|
374
|
-
wait: async () => {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
494
|
+
wait: async (timeoutMs) => {
|
|
495
|
+
flushSoon();
|
|
496
|
+
if (timeoutMs === void 0) {
|
|
497
|
+
await inflight;
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
await new Promise((resolve) => {
|
|
501
|
+
const timer = setTimeout(resolve, timeoutMs);
|
|
502
|
+
void inflight.then(
|
|
503
|
+
() => {
|
|
504
|
+
clearTimeout(timer);
|
|
505
|
+
resolve();
|
|
506
|
+
},
|
|
507
|
+
() => {
|
|
508
|
+
clearTimeout(timer);
|
|
509
|
+
resolve();
|
|
510
|
+
}
|
|
511
|
+
);
|
|
512
|
+
});
|
|
513
|
+
},
|
|
514
|
+
disconnect: () => {
|
|
515
|
+
stopped = true;
|
|
516
|
+
clearDebounce();
|
|
378
517
|
setInstrumentationManifestOnDirty(void 0);
|
|
518
|
+
sessionAbort.abort();
|
|
379
519
|
},
|
|
380
520
|
verify: async () => {
|
|
381
521
|
flushSoon();
|
|
@@ -388,8 +528,6 @@ var scheduleInstrumentationManifestUpload = (options) => {
|
|
|
388
528
|
// src/execution-recorder/execution-recorder.ts
|
|
389
529
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
390
530
|
import {
|
|
391
|
-
capturedValueCompleteness,
|
|
392
|
-
hashInstrumentationManifest,
|
|
393
531
|
rasputinOmitted,
|
|
394
532
|
rasputinTagKind,
|
|
395
533
|
runtimeFunctionId as runtimeFunctionId2
|
|
@@ -476,13 +614,18 @@ var ExecutionJournal = class {
|
|
|
476
614
|
args,
|
|
477
615
|
NO_SUPPRESSION
|
|
478
616
|
)) {
|
|
617
|
+
this.dropped += 2;
|
|
479
618
|
return;
|
|
480
619
|
}
|
|
481
620
|
this.openCallIds.add(callId);
|
|
482
621
|
}
|
|
483
622
|
finishCall(kind, callId, timestampNs, durationNs, payload) {
|
|
484
|
-
if (!this.openCallIds.
|
|
485
|
-
this.write(kind, 0, callId, void 0, timestampNs, durationNs, payload, NO_SUPPRESSION)
|
|
623
|
+
if (!this.openCallIds.has(callId)) return;
|
|
624
|
+
if (!this.write(kind, 0, callId, void 0, timestampNs, durationNs, payload, NO_SUPPRESSION)) {
|
|
625
|
+
this.dropped++;
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
this.openCallIds.delete(callId);
|
|
486
629
|
}
|
|
487
630
|
dropCall() {
|
|
488
631
|
this.dropped += 2;
|
|
@@ -813,6 +956,10 @@ var RecorderMemoryBudget = class {
|
|
|
813
956
|
return allocation;
|
|
814
957
|
}
|
|
815
958
|
captureValue(allocation, serialize) {
|
|
959
|
+
if (allocation.released) {
|
|
960
|
+
this.dropValues(allocation, 1);
|
|
961
|
+
return MEMORY_BUDGET_VALUE_MARKER;
|
|
962
|
+
}
|
|
816
963
|
if (allocation.mode !== "full") {
|
|
817
964
|
this.dropValues(allocation, 1);
|
|
818
965
|
return MEMORY_BUDGET_VALUE_MARKER;
|
|
@@ -857,6 +1004,13 @@ var RecorderMemoryBudget = class {
|
|
|
857
1004
|
this.markPressure(allocation, "metadata-only");
|
|
858
1005
|
return false;
|
|
859
1006
|
}
|
|
1007
|
+
releaseStorage(allocation, bytes) {
|
|
1008
|
+
if (allocation.released) return;
|
|
1009
|
+
const boundedBytes = Math.max(0, Math.ceil(bytes));
|
|
1010
|
+
allocation.estimatedBytes = Math.max(0, allocation.estimatedBytes - boundedBytes);
|
|
1011
|
+
this.activeEstimatedBytes = Math.max(0, this.activeEstimatedBytes - boundedBytes);
|
|
1012
|
+
this.stats.activeEstimatedBytes = this.activeEstimatedBytes;
|
|
1013
|
+
}
|
|
860
1014
|
release(allocation) {
|
|
861
1015
|
if (allocation.released) return;
|
|
862
1016
|
allocation.released = true;
|
|
@@ -867,6 +1021,7 @@ var RecorderMemoryBudget = class {
|
|
|
867
1021
|
return { ...this.stats };
|
|
868
1022
|
}
|
|
869
1023
|
reserve(allocation, bytes) {
|
|
1024
|
+
if (allocation.released) return false;
|
|
870
1025
|
const boundedBytes = Math.max(0, Math.ceil(bytes));
|
|
871
1026
|
if (this.activeEstimatedBytes + boundedBytes > this.maximumBytes) return false;
|
|
872
1027
|
this.activeEstimatedBytes += boundedBytes;
|
|
@@ -899,17 +1054,248 @@ var RecorderMemoryBudget = class {
|
|
|
899
1054
|
}
|
|
900
1055
|
};
|
|
901
1056
|
|
|
902
|
-
// src/execution-recorder/
|
|
1057
|
+
// src/execution-recorder/run-exactly-once.ts
|
|
1058
|
+
var runExactlyOnce = function __rasputinHandleRun__(invoke, callback) {
|
|
1059
|
+
let outcome;
|
|
1060
|
+
const wrapped = function __rasputinHandleRun__3() {
|
|
1061
|
+
try {
|
|
1062
|
+
const value = callback();
|
|
1063
|
+
outcome = { kind: "value", value };
|
|
1064
|
+
return value;
|
|
1065
|
+
} catch (caught) {
|
|
1066
|
+
outcome = { kind: "throw", error: caught };
|
|
1067
|
+
throw caught;
|
|
1068
|
+
}
|
|
1069
|
+
};
|
|
1070
|
+
try {
|
|
1071
|
+
invoke(wrapped);
|
|
1072
|
+
} catch {
|
|
1073
|
+
}
|
|
1074
|
+
if (outcome?.kind === "throw") throw outcome.error;
|
|
1075
|
+
if (outcome?.kind === "value") return outcome.value;
|
|
1076
|
+
return callback();
|
|
1077
|
+
};
|
|
1078
|
+
|
|
1079
|
+
// src/execution-recorder/runtime-state-size-budget.ts
|
|
1080
|
+
import {
|
|
1081
|
+
rasputinUnavailable
|
|
1082
|
+
} from "@rasputin-ai/core";
|
|
1083
|
+
var DEFAULT_RUNTIME_STATE_TARGET_BYTES = 256 * 1024;
|
|
1084
|
+
var DEFAULT_MAX_RUNTIME_STATE_BYTES = 512 * 1024;
|
|
1085
|
+
var VALUE_OMITTED_REASON = "runtime_state_size_budget";
|
|
1086
|
+
var encodedBytes = (value) => Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
1087
|
+
var boundedLimit = (value, fallback) => Number.isFinite(value) ? Math.max(4 * 1024, Math.floor(value)) : fallback;
|
|
1088
|
+
var sizeMetadata = (originalBytes, targetBytes, maximumBytes) => ({
|
|
1089
|
+
reason: "runtime_state_size_budget",
|
|
1090
|
+
originalBytes,
|
|
1091
|
+
finalBytes: 0,
|
|
1092
|
+
targetBytes,
|
|
1093
|
+
maximumBytes,
|
|
1094
|
+
eventValuesDropped: 0,
|
|
1095
|
+
eventsDropped: 0,
|
|
1096
|
+
functionDefinitionsDropped: 0
|
|
1097
|
+
});
|
|
1098
|
+
var withSizeMetadata = (state, size) => ({
|
|
1099
|
+
...state,
|
|
1100
|
+
truncated: {
|
|
1101
|
+
eventsDropped: state.truncated?.eventsDropped ?? 0,
|
|
1102
|
+
...state.truncated,
|
|
1103
|
+
size
|
|
1104
|
+
}
|
|
1105
|
+
});
|
|
1106
|
+
var settleFinalBytes = (state) => {
|
|
1107
|
+
const size = state.truncated?.size;
|
|
1108
|
+
if (!size) return state;
|
|
1109
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
1110
|
+
const encoded = encodedBytes(state);
|
|
1111
|
+
if (size.finalBytes === encoded) break;
|
|
1112
|
+
size.finalBytes = encoded;
|
|
1113
|
+
}
|
|
1114
|
+
return state;
|
|
1115
|
+
};
|
|
1116
|
+
var dropEventValues = (events) => {
|
|
1117
|
+
let dropped = 0;
|
|
1118
|
+
const marker = () => rasputinUnavailable(VALUE_OMITTED_REASON);
|
|
1119
|
+
const bounded = events.map((event) => {
|
|
1120
|
+
if (event.type === "function_enter") {
|
|
1121
|
+
dropped += event.args.length;
|
|
1122
|
+
return { ...event, args: event.args.map(marker) };
|
|
1123
|
+
}
|
|
1124
|
+
if (event.type === "function_exit" && "returnValue" in event) {
|
|
1125
|
+
dropped++;
|
|
1126
|
+
return { ...event, returnValue: marker() };
|
|
1127
|
+
}
|
|
1128
|
+
if (event.type === "function_throw" && "error" in event) {
|
|
1129
|
+
dropped++;
|
|
1130
|
+
return { ...event, error: marker() };
|
|
1131
|
+
}
|
|
1132
|
+
return { ...event };
|
|
1133
|
+
});
|
|
1134
|
+
return { events: bounded, dropped };
|
|
1135
|
+
};
|
|
1136
|
+
var truncateUtf8 = (value, maximumBytes) => {
|
|
1137
|
+
if (value === void 0 || Buffer.byteLength(value, "utf8") <= maximumBytes) return value;
|
|
1138
|
+
let low = 0;
|
|
1139
|
+
let high = value.length;
|
|
1140
|
+
while (low < high) {
|
|
1141
|
+
const middle = Math.ceil((low + high) / 2);
|
|
1142
|
+
if (Buffer.byteLength(value.slice(0, middle), "utf8") <= maximumBytes) low = middle;
|
|
1143
|
+
else high = middle - 1;
|
|
1144
|
+
}
|
|
1145
|
+
return value.slice(0, low);
|
|
1146
|
+
};
|
|
1147
|
+
var minimalState = (state, size) => {
|
|
1148
|
+
const request = state.execution.request;
|
|
1149
|
+
const execution = {
|
|
1150
|
+
kind: state.execution.kind,
|
|
1151
|
+
...state.execution.name === void 0 ? {} : { name: truncateUtf8(state.execution.name, 4 * 1024) },
|
|
1152
|
+
...request ? {
|
|
1153
|
+
request: {
|
|
1154
|
+
...request.method == null ? {} : { method: truncateUtf8(request.method, 1024) },
|
|
1155
|
+
...request.route == null ? {} : { route: truncateUtf8(request.route, 4 * 1024) },
|
|
1156
|
+
...request.status == null ? {} : { status: request.status }
|
|
1157
|
+
}
|
|
1158
|
+
} : {}
|
|
1159
|
+
};
|
|
1160
|
+
return withSizeMetadata(
|
|
1161
|
+
{
|
|
1162
|
+
version: 4,
|
|
1163
|
+
captureProfile: {
|
|
1164
|
+
source: state.captureProfile.source,
|
|
1165
|
+
functionBoundaries: state.captureProfile.functionBoundaries === "none" ? "none" : "partial",
|
|
1166
|
+
functionValues: "none",
|
|
1167
|
+
timings: state.captureProfile.timings === "none" ? "none" : "partial"
|
|
1168
|
+
},
|
|
1169
|
+
executionId: truncateUtf8(state.executionId, 256) ?? "",
|
|
1170
|
+
startedAt: truncateUtf8(state.startedAt, 128) ?? "",
|
|
1171
|
+
durationMs: Number.isFinite(state.durationMs) ? state.durationMs : 0,
|
|
1172
|
+
recorder: {
|
|
1173
|
+
inlineWallTimeMs: Number.isFinite(state.recorder?.inlineWallTimeMs) ? state.recorder.inlineWallTimeMs : 0
|
|
1174
|
+
},
|
|
1175
|
+
execution,
|
|
1176
|
+
functions: [],
|
|
1177
|
+
events: [],
|
|
1178
|
+
...state.capture ? { capture: { ...state.capture } } : {}
|
|
1179
|
+
},
|
|
1180
|
+
size
|
|
1181
|
+
);
|
|
1182
|
+
};
|
|
1183
|
+
var enforceRuntimeStateSizeBudget = (input, options = {}) => {
|
|
1184
|
+
const maximumBytes = boundedLimit(options.maximumBytes, DEFAULT_MAX_RUNTIME_STATE_BYTES);
|
|
1185
|
+
const targetBytes = Math.min(
|
|
1186
|
+
maximumBytes,
|
|
1187
|
+
boundedLimit(options.targetBytes, DEFAULT_RUNTIME_STATE_TARGET_BYTES)
|
|
1188
|
+
);
|
|
1189
|
+
const initialBytes = encodedBytes(input);
|
|
1190
|
+
const existingSize = input.truncated?.size;
|
|
1191
|
+
if (existingSize && initialBytes <= maximumBytes) return settleFinalBytes(input);
|
|
1192
|
+
if (initialBytes <= maximumBytes) return input;
|
|
1193
|
+
const originalBytes = existingSize?.originalBytes ?? initialBytes;
|
|
1194
|
+
const size = sizeMetadata(originalBytes, targetBytes, maximumBytes);
|
|
1195
|
+
let state = input;
|
|
1196
|
+
const stripped = dropEventValues(state.events);
|
|
1197
|
+
size.eventValuesDropped += stripped.dropped;
|
|
1198
|
+
state = settleFinalBytes(
|
|
1199
|
+
withSizeMetadata(
|
|
1200
|
+
{
|
|
1201
|
+
...state,
|
|
1202
|
+
captureProfile: {
|
|
1203
|
+
...state.captureProfile,
|
|
1204
|
+
functionValues: state.captureProfile.functionValues === "none" ? "none" : "selective"
|
|
1205
|
+
},
|
|
1206
|
+
events: stripped.events
|
|
1207
|
+
},
|
|
1208
|
+
size
|
|
1209
|
+
)
|
|
1210
|
+
);
|
|
1211
|
+
if (encodedBytes(state) <= maximumBytes) return state;
|
|
1212
|
+
size.eventsDropped += state.events.length;
|
|
1213
|
+
size.functionDefinitionsDropped += state.functions.length;
|
|
1214
|
+
state = settleFinalBytes(
|
|
1215
|
+
withSizeMetadata(
|
|
1216
|
+
{
|
|
1217
|
+
...state,
|
|
1218
|
+
captureProfile: {
|
|
1219
|
+
...state.captureProfile,
|
|
1220
|
+
functionBoundaries: state.captureProfile.functionBoundaries === "none" ? "none" : "partial",
|
|
1221
|
+
functionValues: "none",
|
|
1222
|
+
timings: state.captureProfile.timings === "none" ? "none" : "partial"
|
|
1223
|
+
},
|
|
1224
|
+
functions: [],
|
|
1225
|
+
events: [],
|
|
1226
|
+
truncated: {
|
|
1227
|
+
eventsDropped: (state.truncated?.eventsDropped ?? 0) + size.eventsDropped,
|
|
1228
|
+
size
|
|
1229
|
+
}
|
|
1230
|
+
},
|
|
1231
|
+
size
|
|
1232
|
+
)
|
|
1233
|
+
);
|
|
1234
|
+
if (encodedBytes(state) <= maximumBytes) return state;
|
|
1235
|
+
state = settleFinalBytes(minimalState(state, size));
|
|
1236
|
+
if (encodedBytes(state) <= maximumBytes) return state;
|
|
1237
|
+
const emergency = {
|
|
1238
|
+
version: 4,
|
|
1239
|
+
captureProfile: {
|
|
1240
|
+
source: state.captureProfile.source,
|
|
1241
|
+
functionBoundaries: "partial",
|
|
1242
|
+
functionValues: "none",
|
|
1243
|
+
timings: "partial"
|
|
1244
|
+
},
|
|
1245
|
+
executionId: "",
|
|
1246
|
+
startedAt: "",
|
|
1247
|
+
durationMs: 0,
|
|
1248
|
+
execution: { kind: state.execution.kind },
|
|
1249
|
+
functions: [],
|
|
1250
|
+
events: [],
|
|
1251
|
+
truncated: { eventsDropped: size.eventsDropped, size }
|
|
1252
|
+
};
|
|
1253
|
+
return settleFinalBytes(emergency);
|
|
1254
|
+
};
|
|
1255
|
+
|
|
1256
|
+
// src/execution-recorder/encode-frozen.ts
|
|
1257
|
+
import { Buffer as Buffer3 } from "node:buffer";
|
|
1258
|
+
|
|
1259
|
+
// src/execution-recorder/value-freeze.ts
|
|
903
1260
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
"
|
|
911
|
-
|
|
912
|
-
|
|
1261
|
+
import { types } from "node:util";
|
|
1262
|
+
import { RASPUTIN_WIRE_TAG } from "@rasputin-ai/core";
|
|
1263
|
+
|
|
1264
|
+
// src/execution-recorder/redact-keys.ts
|
|
1265
|
+
import { defaultSensitivePropertyNames, propertyNameIsSensitive } from "@rasputin-ai/core";
|
|
1266
|
+
var compactKey = (key) => {
|
|
1267
|
+
let compacted = "";
|
|
1268
|
+
for (let index = 0; index < key.length; index++) {
|
|
1269
|
+
const code = key.charCodeAt(index);
|
|
1270
|
+
if (code === 45 || code === 46 || code === 95) continue;
|
|
1271
|
+
compacted += code >= 65 && code <= 90 ? String.fromCharCode(code + 32) : key[index];
|
|
1272
|
+
}
|
|
1273
|
+
return compacted;
|
|
1274
|
+
};
|
|
1275
|
+
var stripTrailingDigits = (value) => {
|
|
1276
|
+
let end = value.length;
|
|
1277
|
+
while (end > 0) {
|
|
1278
|
+
const code = value.charCodeAt(end - 1);
|
|
1279
|
+
if (code < 48 || code > 57) break;
|
|
1280
|
+
end--;
|
|
1281
|
+
}
|
|
1282
|
+
return end === 0 ? value : value.slice(0, end);
|
|
1283
|
+
};
|
|
1284
|
+
var normalizeKey = (key) => stripTrailingDigits(compactKey(key));
|
|
1285
|
+
var compileRedactKeys = (extra) => {
|
|
1286
|
+
if (!extra?.length) return defaultSensitivePropertyNames();
|
|
1287
|
+
return /* @__PURE__ */ new Set([...defaultSensitivePropertyNames(), ...extra.map(normalizeKey)]);
|
|
1288
|
+
};
|
|
1289
|
+
var keyIsRedacted = (key, redactKeys) => {
|
|
1290
|
+
if (propertyNameIsSensitive(key)) return true;
|
|
1291
|
+
if (redactKeys.has(key)) return true;
|
|
1292
|
+
const compacted = compactKey(key);
|
|
1293
|
+
if (redactKeys.has(compacted)) return true;
|
|
1294
|
+
return redactKeys.has(stripTrailingDigits(compacted));
|
|
1295
|
+
};
|
|
1296
|
+
|
|
1297
|
+
// src/execution-recorder/value-freeze.ts
|
|
1298
|
+
var REDACTED = "[RASPUTIN_REDACTED]";
|
|
913
1299
|
var defaults = {
|
|
914
1300
|
maxDepth: 3,
|
|
915
1301
|
maxObjectKeys: 30,
|
|
@@ -917,441 +1303,1017 @@ var defaults = {
|
|
|
917
1303
|
maxStringLength: 500,
|
|
918
1304
|
maxSerializedValueBytes: 8 * 1024
|
|
919
1305
|
};
|
|
920
|
-
var
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
1306
|
+
var compileFreezeLimits = (options) => ({
|
|
1307
|
+
maxDepth: options.maxDepth ?? defaults.maxDepth,
|
|
1308
|
+
maxObjectKeys: options.maxObjectKeys ?? defaults.maxObjectKeys,
|
|
1309
|
+
maxArrayElements: options.maxArrayElements ?? defaults.maxArrayElements,
|
|
1310
|
+
maxStringLength: options.maxStringLength ?? defaults.maxStringLength,
|
|
1311
|
+
maxSerializedValueBytes: options.maxSerializedValueBytes ?? defaults.maxSerializedValueBytes
|
|
925
1312
|
});
|
|
926
|
-
var
|
|
927
|
-
|
|
928
|
-
|
|
1313
|
+
var FROZEN = Symbol("rasputin.frozen");
|
|
1314
|
+
var NODE = 24;
|
|
1315
|
+
var taggedNumberKind = (value) => {
|
|
1316
|
+
if (Number.isNaN(value)) return "NaN";
|
|
1317
|
+
if (value === Infinity) return "Infinity";
|
|
1318
|
+
if (value === -Infinity) return "-Infinity";
|
|
1319
|
+
if (Object.is(value, -0)) return "-0";
|
|
1320
|
+
return void 0;
|
|
1321
|
+
};
|
|
1322
|
+
var atom = (kind, extra = {}) => ({
|
|
1323
|
+
[FROZEN]: kind,
|
|
1324
|
+
...extra
|
|
929
1325
|
});
|
|
930
|
-
var
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
if (
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1326
|
+
var ownData = (value, key) => {
|
|
1327
|
+
try {
|
|
1328
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
1329
|
+
if (!descriptor) return void 0;
|
|
1330
|
+
if ("value" in descriptor) return { present: true, value: descriptor.value };
|
|
1331
|
+
return void 0;
|
|
1332
|
+
} catch {
|
|
1333
|
+
return void 0;
|
|
1334
|
+
}
|
|
1335
|
+
};
|
|
1336
|
+
var nativeErrorStackGet = (() => {
|
|
1337
|
+
try {
|
|
1338
|
+
return Object.getOwnPropertyDescriptor(Error.prototype, "stack")?.get;
|
|
1339
|
+
} catch {
|
|
1340
|
+
return void 0;
|
|
1341
|
+
}
|
|
1342
|
+
})();
|
|
1343
|
+
var nativeInstanceStackGet = (() => {
|
|
1344
|
+
try {
|
|
1345
|
+
const probe = new Error("rasputin-stack-probe");
|
|
1346
|
+
return Object.getOwnPropertyDescriptor(probe, "stack")?.get;
|
|
1347
|
+
} catch {
|
|
1348
|
+
return void 0;
|
|
1349
|
+
}
|
|
1350
|
+
})();
|
|
1351
|
+
var nativeErrorMessageGet = (() => {
|
|
1352
|
+
try {
|
|
1353
|
+
return Object.getOwnPropertyDescriptor(Error.prototype, "message")?.get;
|
|
1354
|
+
} catch {
|
|
1355
|
+
return void 0;
|
|
1356
|
+
}
|
|
1357
|
+
})();
|
|
1358
|
+
var typedArrayProto = Object.getPrototypeOf(Uint8Array.prototype);
|
|
1359
|
+
var typedArrayByteLengthGet = typedArrayProto ? Object.getOwnPropertyDescriptor(typedArrayProto, "byteLength")?.get : void 0;
|
|
1360
|
+
var typedArrayByteOffsetGet = typedArrayProto ? Object.getOwnPropertyDescriptor(typedArrayProto, "byteOffset")?.get : void 0;
|
|
1361
|
+
var typedArrayBufferGet = typedArrayProto ? Object.getOwnPropertyDescriptor(typedArrayProto, "buffer")?.get : void 0;
|
|
1362
|
+
var dataViewByteLengthGet = Object.getOwnPropertyDescriptor(
|
|
1363
|
+
DataView.prototype,
|
|
1364
|
+
"byteLength"
|
|
1365
|
+
)?.get;
|
|
1366
|
+
var domExceptionNameGet = typeof DOMException === "undefined" ? void 0 : Object.getOwnPropertyDescriptor(DOMException.prototype, "name")?.get;
|
|
1367
|
+
var domExceptionMessageGet = typeof DOMException === "undefined" ? void 0 : Object.getOwnPropertyDescriptor(DOMException.prototype, "message")?.get;
|
|
1368
|
+
var prepareStackTraceDepth = 0;
|
|
1369
|
+
var savedPrepareStackTrace;
|
|
1370
|
+
var withoutPrepareStackTrace = (read) => {
|
|
1371
|
+
if (prepareStackTraceDepth === 0) {
|
|
1372
|
+
savedPrepareStackTrace = Error.prepareStackTrace;
|
|
1373
|
+
Error.prepareStackTrace = void 0;
|
|
1374
|
+
}
|
|
1375
|
+
prepareStackTraceDepth += 1;
|
|
1376
|
+
try {
|
|
1377
|
+
return read();
|
|
1378
|
+
} finally {
|
|
1379
|
+
prepareStackTraceDepth -= 1;
|
|
1380
|
+
if (prepareStackTraceDepth === 0) Error.prepareStackTrace = savedPrepareStackTrace;
|
|
1381
|
+
}
|
|
1382
|
+
};
|
|
1383
|
+
var isDomException = (value) => {
|
|
1384
|
+
try {
|
|
1385
|
+
return typeof DOMException !== "undefined" && value instanceof DOMException;
|
|
1386
|
+
} catch {
|
|
1387
|
+
return false;
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1390
|
+
var functionNameOf = (value) => {
|
|
1391
|
+
const own = ownData(value, "name");
|
|
1392
|
+
if (own && typeof own.value === "string" && own.value.length > 0) return own.value;
|
|
1393
|
+
return "anonymous";
|
|
1394
|
+
};
|
|
1395
|
+
var errorNameOf = (value) => {
|
|
1396
|
+
if (isDomException(value) && domExceptionNameGet) {
|
|
1397
|
+
try {
|
|
1398
|
+
const name = domExceptionNameGet.call(value);
|
|
1399
|
+
if (typeof name === "string" && name.length > 0) return name;
|
|
1400
|
+
} catch {
|
|
941
1401
|
}
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1402
|
+
}
|
|
1403
|
+
let current = value;
|
|
1404
|
+
while (current) {
|
|
1405
|
+
const slot = ownData(current, "name");
|
|
1406
|
+
if (slot && typeof slot.value === "string" && slot.value.length > 0) return slot.value;
|
|
1407
|
+
try {
|
|
1408
|
+
current = Object.getPrototypeOf(current);
|
|
1409
|
+
} catch {
|
|
1410
|
+
break;
|
|
945
1411
|
}
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1412
|
+
}
|
|
1413
|
+
return "Error";
|
|
1414
|
+
};
|
|
1415
|
+
var errorMessageOf = (value) => {
|
|
1416
|
+
if (isDomException(value) && domExceptionMessageGet) {
|
|
1417
|
+
try {
|
|
1418
|
+
return domExceptionMessageGet.call(value);
|
|
1419
|
+
} catch {
|
|
949
1420
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1421
|
+
}
|
|
1422
|
+
const own = ownData(value, "message");
|
|
1423
|
+
if (own) return own.value;
|
|
1424
|
+
if (!nativeErrorMessageGet) return void 0;
|
|
1425
|
+
try {
|
|
1426
|
+
return nativeErrorMessageGet.call(value);
|
|
1427
|
+
} catch {
|
|
1428
|
+
return void 0;
|
|
1429
|
+
}
|
|
1430
|
+
};
|
|
1431
|
+
var errorStackOf = (value) => withoutPrepareStackTrace(() => {
|
|
1432
|
+
const own = ownData(value, "stack");
|
|
1433
|
+
if (own && typeof own.value === "string" && own.value.length > 0) return own.value;
|
|
1434
|
+
try {
|
|
1435
|
+
const getter = Object.getOwnPropertyDescriptor(value, "stack")?.get;
|
|
1436
|
+
if (getter && nativeInstanceStackGet && getter === nativeInstanceStackGet) {
|
|
1437
|
+
const stack = getter.call(value);
|
|
1438
|
+
if (typeof stack === "string" && stack.length > 0) return stack;
|
|
953
1439
|
}
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1440
|
+
} catch {
|
|
1441
|
+
}
|
|
1442
|
+
if (!nativeErrorStackGet) return void 0;
|
|
1443
|
+
try {
|
|
1444
|
+
const stack = nativeErrorStackGet.call(value);
|
|
1445
|
+
return typeof stack === "string" && stack.length > 0 ? stack : void 0;
|
|
1446
|
+
} catch {
|
|
1447
|
+
return void 0;
|
|
1448
|
+
}
|
|
1449
|
+
});
|
|
1450
|
+
var viewByteLength = (value) => {
|
|
1451
|
+
try {
|
|
1452
|
+
if (types.isDataView(value)) {
|
|
1453
|
+
return dataViewByteLengthGet ? dataViewByteLengthGet.call(value) : 0;
|
|
963
1454
|
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
1455
|
+
return typedArrayByteLengthGet ? typedArrayByteLengthGet.call(value) : 0;
|
|
1456
|
+
} catch {
|
|
1457
|
+
return 0;
|
|
1458
|
+
}
|
|
1459
|
+
};
|
|
1460
|
+
var typedArrayName = (value) => {
|
|
1461
|
+
if (types.isUint8Array(value)) return "Uint8Array";
|
|
1462
|
+
if (types.isUint8ClampedArray(value)) return "Uint8ClampedArray";
|
|
1463
|
+
if (types.isInt8Array(value)) return "Int8Array";
|
|
1464
|
+
if (types.isUint16Array(value)) return "Uint16Array";
|
|
1465
|
+
if (types.isInt16Array(value)) return "Int16Array";
|
|
1466
|
+
if (types.isUint32Array(value)) return "Uint32Array";
|
|
1467
|
+
if (types.isInt32Array(value)) return "Int32Array";
|
|
1468
|
+
if (types.isFloat32Array(value)) return "Float32Array";
|
|
1469
|
+
if (types.isFloat64Array(value)) return "Float64Array";
|
|
1470
|
+
if (types.isBigUint64Array(value)) return "BigUint64Array";
|
|
1471
|
+
if (types.isBigInt64Array(value)) return "BigInt64Array";
|
|
1472
|
+
return "TypedArray";
|
|
1473
|
+
};
|
|
1474
|
+
var prototypeChainHasProxy = (value) => {
|
|
1475
|
+
let current = value;
|
|
1476
|
+
for (let depth = 0; depth < 8; depth++) {
|
|
1477
|
+
try {
|
|
1478
|
+
current = Object.getPrototypeOf(current);
|
|
1479
|
+
} catch {
|
|
1480
|
+
return true;
|
|
967
1481
|
}
|
|
968
|
-
|
|
1482
|
+
if (!current) return false;
|
|
1483
|
+
if (types.isProxy(current)) return true;
|
|
969
1484
|
}
|
|
970
|
-
return
|
|
1485
|
+
return true;
|
|
971
1486
|
};
|
|
972
|
-
var
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1487
|
+
var sampleBytes = (bytes, max) => {
|
|
1488
|
+
const length = Math.min(max, bytes.length);
|
|
1489
|
+
const sample = new Array(length);
|
|
1490
|
+
for (let index = 0; index < length; index++) sample[index] = bytes[index] ?? 0;
|
|
1491
|
+
return sample;
|
|
1492
|
+
};
|
|
1493
|
+
var RESERVED_USER_KEYS = /* @__PURE__ */ new Set([
|
|
1494
|
+
"__proto__",
|
|
1495
|
+
"__rasputin_type",
|
|
1496
|
+
"__rasputin_truncated",
|
|
1497
|
+
"__rasputin_fields",
|
|
1498
|
+
"__reason",
|
|
1499
|
+
"__original_length",
|
|
1500
|
+
"__serialized_bytes"
|
|
1501
|
+
]);
|
|
1502
|
+
var assignFrozenField = (fields, key, value) => {
|
|
1503
|
+
if (RESERVED_USER_KEYS.has(key) || key.startsWith("__rasputin_")) {
|
|
1504
|
+
const escaped = fields.__rasputin_fields ?? [];
|
|
1505
|
+
escaped.push({ name: key, value });
|
|
1506
|
+
fields.__rasputin_fields = escaped;
|
|
1507
|
+
return;
|
|
1508
|
+
}
|
|
1509
|
+
fields[key] = value;
|
|
1510
|
+
};
|
|
1511
|
+
var ownEnumerableKeys = (value, maxKeys) => {
|
|
1512
|
+
const keys = [];
|
|
1513
|
+
let proto = null;
|
|
1514
|
+
try {
|
|
1515
|
+
proto = Object.getPrototypeOf(value);
|
|
1516
|
+
} catch {
|
|
1517
|
+
proto = null;
|
|
1518
|
+
}
|
|
1519
|
+
const protoIsProxy = proto !== null && types.isProxy(proto);
|
|
1520
|
+
try {
|
|
1521
|
+
for (const key in value) {
|
|
1522
|
+
if (protoIsProxy && !Object.hasOwn(value, key)) break;
|
|
1523
|
+
if (!Object.hasOwn(value, key)) continue;
|
|
1524
|
+
if (keys.length >= maxKeys) return { keys, truncated: true };
|
|
1525
|
+
keys.push(key);
|
|
1002
1526
|
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1527
|
+
} catch {
|
|
1528
|
+
return { keys, truncated: keys.length >= maxKeys };
|
|
1005
1529
|
}
|
|
1530
|
+
return { keys, truncated: false };
|
|
1006
1531
|
};
|
|
1007
|
-
var
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
});
|
|
1014
|
-
var compileRedactKeys = (options) => {
|
|
1015
|
-
if (!options.redactKeys?.length) return new Set(DEFAULT_REDACT_KEYS);
|
|
1016
|
-
return /* @__PURE__ */ new Set([...DEFAULT_REDACT_KEYS, ...options.redactKeys.map((key) => key.toLowerCase())]);
|
|
1532
|
+
var bufferByteLength = (value) => {
|
|
1533
|
+
try {
|
|
1534
|
+
return Buffer2.byteLength(value);
|
|
1535
|
+
} catch {
|
|
1536
|
+
return 0;
|
|
1537
|
+
}
|
|
1017
1538
|
};
|
|
1018
|
-
var
|
|
1539
|
+
var stringEstimate = (value) => NODE + 2 + Buffer2.byteLength(value, "utf8");
|
|
1540
|
+
var URL_LIKE_PROPERTY_NAMES = /* @__PURE__ */ new Set([
|
|
1541
|
+
"url",
|
|
1542
|
+
"href",
|
|
1543
|
+
"originalurl",
|
|
1544
|
+
"path",
|
|
1545
|
+
"pathname",
|
|
1546
|
+
"search",
|
|
1547
|
+
"query",
|
|
1548
|
+
"requesturl",
|
|
1549
|
+
"requesturi",
|
|
1550
|
+
"location",
|
|
1551
|
+
"referer",
|
|
1552
|
+
"referrer",
|
|
1553
|
+
"uri",
|
|
1554
|
+
"connectionuri",
|
|
1555
|
+
"connectionurl",
|
|
1556
|
+
"databaseuri",
|
|
1557
|
+
"databaseurl",
|
|
1558
|
+
"mongouri",
|
|
1559
|
+
"mongourl",
|
|
1560
|
+
"redisuri",
|
|
1561
|
+
"redisurl",
|
|
1562
|
+
"postgresuri",
|
|
1563
|
+
"postgresurl"
|
|
1564
|
+
]);
|
|
1565
|
+
var compactPropertyName = (key) => {
|
|
1566
|
+
let compacted = "";
|
|
1019
1567
|
for (let index = 0; index < key.length; index++) {
|
|
1020
1568
|
const code = key.charCodeAt(index);
|
|
1021
|
-
if (code
|
|
1569
|
+
if (code === 45 || code === 46 || code === 95) continue;
|
|
1570
|
+
compacted += code >= 65 && code <= 90 ? String.fromCharCode(code + 32) : key[index];
|
|
1022
1571
|
}
|
|
1023
|
-
return
|
|
1572
|
+
return compacted;
|
|
1024
1573
|
};
|
|
1025
|
-
var
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1574
|
+
var propertyNameLooksLikeUrl = (key) => URL_LIKE_PROPERTY_NAMES.has(compactPropertyName(key));
|
|
1575
|
+
var looksLikeBareQueryString = (text) => {
|
|
1576
|
+
if (!text.includes("=") || /\s/.test(text)) return false;
|
|
1577
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(text) || text.startsWith("/")) return false;
|
|
1578
|
+
return /^[^\s=]+=[^\s]*(&[^\s=]+=[^\s]*)*$/.test(text);
|
|
1579
|
+
};
|
|
1580
|
+
var redactSensitiveQuery = (text, redactKeys) => {
|
|
1581
|
+
const queryAt = text.indexOf("?");
|
|
1582
|
+
let prefix = "";
|
|
1583
|
+
let query = "";
|
|
1584
|
+
let suffix = "";
|
|
1585
|
+
if (queryAt >= 0) {
|
|
1586
|
+
if (queryAt === text.length - 1) return text;
|
|
1587
|
+
const hashAt = text.indexOf("#", queryAt + 1);
|
|
1588
|
+
prefix = text.slice(0, queryAt + 1);
|
|
1589
|
+
query = hashAt < 0 ? text.slice(queryAt + 1) : text.slice(queryAt + 1, hashAt);
|
|
1590
|
+
suffix = hashAt < 0 ? "" : text.slice(hashAt);
|
|
1591
|
+
} else if (looksLikeBareQueryString(text)) {
|
|
1592
|
+
query = text;
|
|
1593
|
+
} else {
|
|
1594
|
+
return text;
|
|
1036
1595
|
}
|
|
1037
|
-
return
|
|
1596
|
+
if (!query.includes("=")) return text;
|
|
1597
|
+
let changed = false;
|
|
1598
|
+
const next = query.split("&").map((part) => {
|
|
1599
|
+
const equals = part.indexOf("=");
|
|
1600
|
+
const rawKey = equals < 0 ? part : part.slice(0, equals);
|
|
1601
|
+
if (!rawKey) return part;
|
|
1602
|
+
let decoded = rawKey;
|
|
1603
|
+
try {
|
|
1604
|
+
decoded = decodeURIComponent(rawKey.replace(/\+/g, " "));
|
|
1605
|
+
} catch {
|
|
1606
|
+
decoded = rawKey;
|
|
1607
|
+
}
|
|
1608
|
+
if (!keyIsRedacted(decoded, redactKeys) && !keyIsRedacted(rawKey, redactKeys)) return part;
|
|
1609
|
+
changed = true;
|
|
1610
|
+
return `${rawKey}=${REDACTED}`;
|
|
1611
|
+
});
|
|
1612
|
+
if (!changed) return text;
|
|
1613
|
+
return `${prefix}${next.join("&")}${suffix}`;
|
|
1038
1614
|
};
|
|
1039
|
-
var
|
|
1040
|
-
|
|
1041
|
-
if (
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
if (typeof value === "string") {
|
|
1048
|
-
if (value.length > maxStringLength || !isJsonSafeString(value)) return void 0;
|
|
1049
|
-
return { value, bytes: 2 + Buffer2.byteLength(value, "utf8"), visitedNodes: 1 };
|
|
1050
|
-
}
|
|
1051
|
-
if (typeof value === "undefined") {
|
|
1052
|
-
const serialized = typeMarker("undefined");
|
|
1053
|
-
return { value: serialized, bytes: jsonLiteralUtf8Bytes(serialized), visitedNodes: 1 };
|
|
1054
|
-
}
|
|
1055
|
-
if (typeof value === "bigint") {
|
|
1056
|
-
const serialized = typeMarker("bigint", value.toString());
|
|
1057
|
-
return { value: serialized, bytes: jsonLiteralUtf8Bytes(serialized), visitedNodes: 1 };
|
|
1058
|
-
}
|
|
1059
|
-
if (typeof value === "symbol") {
|
|
1060
|
-
const text = String(value);
|
|
1061
|
-
if (!isJsonSafeString(text)) return void 0;
|
|
1062
|
-
const serialized = typeMarker("symbol", text);
|
|
1063
|
-
return { value: serialized, bytes: jsonLiteralUtf8Bytes(serialized), visitedNodes: 1 };
|
|
1064
|
-
}
|
|
1065
|
-
if (typeof value === "function") {
|
|
1066
|
-
const name = value.name || "anonymous";
|
|
1067
|
-
if (!isJsonSafeString(name)) return void 0;
|
|
1068
|
-
const serialized = typeMarker("function", name);
|
|
1069
|
-
return { value: serialized, bytes: jsonLiteralUtf8Bytes(serialized), visitedNodes: 1 };
|
|
1615
|
+
var redactUrlUserinfo = (text) => {
|
|
1616
|
+
const schemeEnd = text.indexOf("://");
|
|
1617
|
+
if (schemeEnd <= 0) return text;
|
|
1618
|
+
const rest = text.slice(schemeEnd + 3);
|
|
1619
|
+
let authorityEnd = rest.length;
|
|
1620
|
+
for (const marker of ["/", "?", "#"]) {
|
|
1621
|
+
const at = rest.indexOf(marker);
|
|
1622
|
+
if (at >= 0 && at < authorityEnd) authorityEnd = at;
|
|
1070
1623
|
}
|
|
1071
|
-
|
|
1624
|
+
const authority = rest.slice(0, authorityEnd);
|
|
1625
|
+
const userinfoEnd = authority.lastIndexOf("@");
|
|
1626
|
+
if (userinfoEnd < 0) return text;
|
|
1627
|
+
return `${text.slice(0, schemeEnd + 3)}${REDACTED}@${authority.slice(userinfoEnd + 1)}${rest.slice(authorityEnd)}`;
|
|
1072
1628
|
};
|
|
1073
|
-
var
|
|
1074
|
-
|
|
1075
|
-
|
|
1629
|
+
var redactUrlLikeString = (text, redactKeys) => redactSensitiveQuery(redactUrlUserinfo(text), redactKeys);
|
|
1630
|
+
var isFrozenAtom = (value) => typeof value === "object" && value !== null && FROZEN in value;
|
|
1631
|
+
var createValueFreezer = (options = {}) => {
|
|
1632
|
+
const limits = compileFreezeLimits(options);
|
|
1633
|
+
const redactKeys = compileRedactKeys(options.redactKeys);
|
|
1076
1634
|
const sharedPath = /* @__PURE__ */ new Set();
|
|
1077
|
-
let
|
|
1078
|
-
const
|
|
1079
|
-
|
|
1080
|
-
if (
|
|
1081
|
-
return redactKeys.has(key.toLowerCase());
|
|
1082
|
-
};
|
|
1083
|
-
const addBytes = (metrics, count) => {
|
|
1084
|
-
metrics.bytes += count;
|
|
1085
|
-
if (metrics.bytes > limits.maxSerializedValueBytes) metrics.oversize = true;
|
|
1635
|
+
let freezing = false;
|
|
1636
|
+
const add = (metrics, count) => {
|
|
1637
|
+
metrics.estimatedBytes += count;
|
|
1638
|
+
if (metrics.estimatedBytes > limits.maxSerializedValueBytes) metrics.oversize = true;
|
|
1086
1639
|
};
|
|
1087
|
-
const
|
|
1088
|
-
|
|
1089
|
-
return { value: bounded, bytes: jsonLiteralUtf8Bytes(bounded), visitedNodes };
|
|
1090
|
-
};
|
|
1091
|
-
const openObject = (metrics, allocate) => {
|
|
1092
|
-
addBytes(metrics, 2);
|
|
1093
|
-
return {
|
|
1094
|
-
target: allocate && !metrics.oversize ? {} : void 0,
|
|
1095
|
-
first: true
|
|
1096
|
-
};
|
|
1097
|
-
};
|
|
1098
|
-
const openArray = (metrics, allocate) => {
|
|
1099
|
-
addBytes(metrics, 2);
|
|
1100
|
-
return {
|
|
1101
|
-
items: allocate && !metrics.oversize ? [] : void 0,
|
|
1102
|
-
first: true
|
|
1103
|
-
};
|
|
1104
|
-
};
|
|
1105
|
-
const beginField = (metrics, object, key) => {
|
|
1106
|
-
if (!object.first) addBytes(metrics, 1);
|
|
1107
|
-
object.first = false;
|
|
1108
|
-
addBytes(metrics, jsonStringUtf8Bytes(key) + 1);
|
|
1109
|
-
};
|
|
1110
|
-
const assignField = (object, key, fieldValue) => {
|
|
1111
|
-
if (object.target) object.target[key] = fieldValue;
|
|
1112
|
-
};
|
|
1113
|
-
const writeLiteralField = (metrics, object, key, jsonValue) => {
|
|
1114
|
-
beginField(metrics, object, key);
|
|
1115
|
-
addBytes(metrics, jsonLiteralUtf8Bytes(jsonValue));
|
|
1116
|
-
assignField(object, key, jsonValue);
|
|
1117
|
-
};
|
|
1118
|
-
const writeTypeMarker = (metrics, allocate, type, nestedValue) => {
|
|
1119
|
-
const object = openObject(metrics, allocate);
|
|
1120
|
-
writeLiteralField(metrics, object, "__rasputin_type", type);
|
|
1121
|
-
if (nestedValue !== void 0) writeLiteralField(metrics, object, "value", nestedValue);
|
|
1122
|
-
return object.target;
|
|
1123
|
-
};
|
|
1124
|
-
const writeTruncation = (metrics, allocate, reason, extra = {}) => {
|
|
1125
|
-
const object = openObject(metrics, allocate);
|
|
1126
|
-
writeLiteralField(metrics, object, "__rasputin_truncated", true);
|
|
1127
|
-
writeLiteralField(metrics, object, "__reason", reason);
|
|
1128
|
-
for (const key of Object.keys(extra)) writeLiteralField(metrics, object, key, extra[key]);
|
|
1129
|
-
return object.target;
|
|
1130
|
-
};
|
|
1131
|
-
const serializeInner = (value, depth, path, allocate, metrics) => {
|
|
1640
|
+
const freezeInner = (value, depth, path, metrics) => {
|
|
1641
|
+
if (metrics.oversize) return void 0;
|
|
1132
1642
|
metrics.visitedNodes++;
|
|
1133
|
-
const store = allocate && !metrics.oversize;
|
|
1134
1643
|
if (value === null) {
|
|
1135
|
-
|
|
1136
|
-
return
|
|
1644
|
+
add(metrics, 4);
|
|
1645
|
+
return null;
|
|
1137
1646
|
}
|
|
1138
1647
|
if (typeof value === "boolean") {
|
|
1139
|
-
|
|
1140
|
-
return
|
|
1648
|
+
add(metrics, value ? 4 : 5);
|
|
1649
|
+
return value;
|
|
1141
1650
|
}
|
|
1142
1651
|
if (typeof value === "number") {
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1652
|
+
const kind = taggedNumberKind(value);
|
|
1653
|
+
if (kind) {
|
|
1654
|
+
add(metrics, NODE + 16);
|
|
1655
|
+
return atom(kind);
|
|
1656
|
+
}
|
|
1657
|
+
add(metrics, NODE + String(value).length);
|
|
1658
|
+
return value;
|
|
1147
1659
|
}
|
|
1148
1660
|
if (typeof value === "string") {
|
|
1149
1661
|
if (value.length <= limits.maxStringLength) {
|
|
1150
|
-
|
|
1151
|
-
return
|
|
1662
|
+
add(metrics, stringEstimate(value));
|
|
1663
|
+
return value;
|
|
1152
1664
|
}
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1665
|
+
const sliced = value.slice(0, limits.maxStringLength);
|
|
1666
|
+
add(metrics, NODE + stringEstimate(sliced) + 48);
|
|
1667
|
+
return atom("truncated", {
|
|
1668
|
+
reason: "max_string_length",
|
|
1669
|
+
originalLength: value.length,
|
|
1670
|
+
value: sliced
|
|
1156
1671
|
});
|
|
1157
1672
|
}
|
|
1158
|
-
if (typeof value === "undefined")
|
|
1673
|
+
if (typeof value === "undefined") {
|
|
1674
|
+
add(metrics, NODE + 16);
|
|
1675
|
+
return atom("undefined");
|
|
1676
|
+
}
|
|
1159
1677
|
if (typeof value === "bigint") {
|
|
1160
|
-
|
|
1678
|
+
const text = value.toString();
|
|
1679
|
+
add(metrics, NODE + stringEstimate(text));
|
|
1680
|
+
return atom("bigint", { value: text });
|
|
1161
1681
|
}
|
|
1162
1682
|
if (typeof value === "symbol") {
|
|
1163
|
-
|
|
1683
|
+
const text = String(value);
|
|
1684
|
+
add(metrics, NODE + stringEstimate(text));
|
|
1685
|
+
return atom("symbol", { value: text });
|
|
1164
1686
|
}
|
|
1165
1687
|
if (typeof value === "function") {
|
|
1166
|
-
|
|
1688
|
+
if (types.isProxy(value)) {
|
|
1689
|
+
add(metrics, NODE + 16);
|
|
1690
|
+
return atom("Proxy");
|
|
1691
|
+
}
|
|
1692
|
+
const name = functionNameOf(value);
|
|
1693
|
+
add(metrics, NODE + stringEstimate(name));
|
|
1694
|
+
return atom("function", { value: name });
|
|
1695
|
+
}
|
|
1696
|
+
if (typeof value !== "object") {
|
|
1697
|
+
add(metrics, NODE + 16);
|
|
1698
|
+
return atom("unserializable");
|
|
1699
|
+
}
|
|
1700
|
+
if (path.has(value)) {
|
|
1701
|
+
add(metrics, NODE + 16);
|
|
1702
|
+
return atom("circular");
|
|
1167
1703
|
}
|
|
1168
|
-
if (depth >= limits.maxDepth) return writeTruncation(metrics, store, "max_depth");
|
|
1169
|
-
if (typeof value !== "object") return writeTypeMarker(metrics, store, typeof value);
|
|
1170
|
-
if (path.has(value)) return writeTypeMarker(metrics, store, "circular");
|
|
1171
1704
|
path.add(value);
|
|
1172
|
-
const bytesBefore = metrics.bytes;
|
|
1173
|
-
const oversizeBefore = metrics.oversize;
|
|
1174
1705
|
try {
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
writeLiteralField(metrics, object2, "__rasputin_type", "Error");
|
|
1179
|
-
writeLiteralField(metrics, object2, "name", value.name);
|
|
1180
|
-
beginField(metrics, object2, "message");
|
|
1181
|
-
assignField(
|
|
1182
|
-
object2,
|
|
1183
|
-
"message",
|
|
1184
|
-
serializeInner(value.message, depth + 1, path, childAllocate, metrics)
|
|
1185
|
-
);
|
|
1186
|
-
if (value.stack) {
|
|
1187
|
-
beginField(metrics, object2, "stack");
|
|
1188
|
-
assignField(
|
|
1189
|
-
object2,
|
|
1190
|
-
"stack",
|
|
1191
|
-
serializeInner(value.stack, depth + 1, path, childAllocate, metrics)
|
|
1192
|
-
);
|
|
1193
|
-
}
|
|
1194
|
-
return object2.target;
|
|
1706
|
+
if (types.isProxy(value) || prototypeChainHasProxy(value)) {
|
|
1707
|
+
add(metrics, NODE + 16);
|
|
1708
|
+
return atom("Proxy");
|
|
1195
1709
|
}
|
|
1196
|
-
if (value
|
|
1197
|
-
|
|
1710
|
+
if (types.isDate(value)) {
|
|
1711
|
+
const time = Date.prototype.getTime.call(value);
|
|
1712
|
+
const iso = Number.isFinite(time) ? new Date(time).toISOString() : "Invalid Date";
|
|
1713
|
+
add(metrics, NODE + stringEstimate(iso));
|
|
1714
|
+
return atom("Date", { value: iso });
|
|
1715
|
+
}
|
|
1716
|
+
if (depth >= limits.maxDepth) {
|
|
1717
|
+
add(metrics, NODE + 32);
|
|
1718
|
+
return atom("truncated", { reason: "max_depth" });
|
|
1719
|
+
}
|
|
1720
|
+
if (types.isNativeError(value) || isDomException(value)) {
|
|
1721
|
+
add(metrics, NODE + 32);
|
|
1722
|
+
const name = errorNameOf(value);
|
|
1723
|
+
add(metrics, stringEstimate(name));
|
|
1724
|
+
const message = freezeInner(errorMessageOf(value), depth + 1, path, metrics);
|
|
1725
|
+
const stack = errorStackOf(value);
|
|
1726
|
+
const extras = {};
|
|
1727
|
+
for (const key of ["code", "cause", "statusCode"]) {
|
|
1728
|
+
const slot = ownData(value, key);
|
|
1729
|
+
if (!slot) continue;
|
|
1730
|
+
extras[key] = freezeInner(slot.value, depth + 1, path, metrics);
|
|
1731
|
+
}
|
|
1732
|
+
return atom("Error", {
|
|
1733
|
+
name,
|
|
1734
|
+
message,
|
|
1735
|
+
...extras,
|
|
1736
|
+
...stack ? { stack: freezeInner(stack, depth + 1, path, metrics) } : {}
|
|
1737
|
+
});
|
|
1198
1738
|
}
|
|
1199
1739
|
if (Buffer2.isBuffer(value)) {
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1740
|
+
const byteLength = bufferByteLength(value);
|
|
1741
|
+
const slice = Buffer2.prototype.subarray.call(value, 0, limits.maxStringLength);
|
|
1742
|
+
const base64 = Buffer2.prototype.toString.call(slice, "base64");
|
|
1743
|
+
add(metrics, NODE + stringEstimate(base64) + 24);
|
|
1744
|
+
return atom("Buffer", {
|
|
1745
|
+
byteLength,
|
|
1746
|
+
base64,
|
|
1747
|
+
...byteLength > limits.maxStringLength ? { truncated: true } : {}
|
|
1204
1748
|
});
|
|
1205
1749
|
}
|
|
1206
|
-
if (value
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1750
|
+
if (types.isPromise(value)) {
|
|
1751
|
+
add(metrics, NODE + 16);
|
|
1752
|
+
return atom("Promise");
|
|
1753
|
+
}
|
|
1754
|
+
if (types.isMap(value)) {
|
|
1755
|
+
add(metrics, NODE + 16);
|
|
1756
|
+
const entries = [];
|
|
1212
1757
|
let counted2 = 0;
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1758
|
+
const mapSize = Object.getOwnPropertyDescriptor(Map.prototype, "size")?.get;
|
|
1759
|
+
const size = mapSize ? mapSize.call(value) : 0;
|
|
1760
|
+
for (const mapKey of Map.prototype.keys.call(value)) {
|
|
1761
|
+
if (counted2 >= limits.maxArrayElements || metrics.oversize) break;
|
|
1762
|
+
const key = freezeInner(mapKey, depth + 1, path, metrics);
|
|
1763
|
+
if (typeof mapKey === "string" && keyIsRedacted(mapKey, redactKeys)) {
|
|
1764
|
+
add(metrics, stringEstimate(REDACTED));
|
|
1765
|
+
entries.push([key, REDACTED]);
|
|
1766
|
+
} else {
|
|
1767
|
+
entries.push([
|
|
1768
|
+
key,
|
|
1769
|
+
freezeInner(Map.prototype.get.call(value, mapKey), depth + 1, path, metrics)
|
|
1770
|
+
]);
|
|
1771
|
+
}
|
|
1222
1772
|
counted2++;
|
|
1223
1773
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
writeLiteralField(metrics, object2, "__original_length", value.size);
|
|
1229
|
-
}
|
|
1230
|
-
return object2.target;
|
|
1774
|
+
return atom("Map", {
|
|
1775
|
+
entries,
|
|
1776
|
+
...size > limits.maxArrayElements ? { truncated: true, reason: "max_array_elements", originalLength: size } : {}
|
|
1777
|
+
});
|
|
1231
1778
|
}
|
|
1232
|
-
if (value
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
beginField(metrics, object2, "values");
|
|
1236
|
-
const items = openArray(metrics, childAllocate);
|
|
1779
|
+
if (types.isSet(value)) {
|
|
1780
|
+
add(metrics, NODE + 16);
|
|
1781
|
+
const values = [];
|
|
1237
1782
|
let counted2 = 0;
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
items.items?.push(serializedItem);
|
|
1783
|
+
const setSize = Object.getOwnPropertyDescriptor(Set.prototype, "size")?.get;
|
|
1784
|
+
const size = setSize ? setSize.call(value) : 0;
|
|
1785
|
+
for (const item of Set.prototype.values.call(value)) {
|
|
1786
|
+
if (counted2 >= limits.maxArrayElements || metrics.oversize) break;
|
|
1787
|
+
values.push(freezeInner(item, depth + 1, path, metrics));
|
|
1244
1788
|
counted2++;
|
|
1245
1789
|
}
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
writeLiteralField(metrics, object2, "__original_length", value.size);
|
|
1251
|
-
}
|
|
1252
|
-
return object2.target;
|
|
1790
|
+
return atom("Set", {
|
|
1791
|
+
values,
|
|
1792
|
+
...size > limits.maxArrayElements ? { truncated: true, reason: "max_array_elements", originalLength: size } : {}
|
|
1793
|
+
});
|
|
1253
1794
|
}
|
|
1254
1795
|
if (Array.isArray(value)) {
|
|
1255
|
-
|
|
1796
|
+
add(metrics, 2);
|
|
1797
|
+
const items = [];
|
|
1256
1798
|
const maxItems = value.length > limits.maxArrayElements ? limits.maxArrayElements - 1 : value.length;
|
|
1799
|
+
let redactNext = false;
|
|
1257
1800
|
for (let index = 0; index < maxItems; index++) {
|
|
1258
|
-
if (
|
|
1259
|
-
|
|
1260
|
-
|
|
1801
|
+
if (metrics.oversize) break;
|
|
1802
|
+
let descriptor;
|
|
1803
|
+
try {
|
|
1804
|
+
descriptor = Object.getOwnPropertyDescriptor(value, index);
|
|
1805
|
+
} catch {
|
|
1806
|
+
descriptor = void 0;
|
|
1807
|
+
}
|
|
1808
|
+
if (!descriptor) {
|
|
1809
|
+
add(metrics, NODE + 16);
|
|
1810
|
+
items.push(atom("hole"));
|
|
1811
|
+
redactNext = false;
|
|
1812
|
+
continue;
|
|
1813
|
+
}
|
|
1814
|
+
if (!("value" in descriptor)) {
|
|
1815
|
+
add(metrics, NODE + 16);
|
|
1816
|
+
items.push(atom("accessor"));
|
|
1817
|
+
redactNext = false;
|
|
1818
|
+
continue;
|
|
1819
|
+
}
|
|
1820
|
+
if (redactNext) {
|
|
1821
|
+
add(metrics, stringEstimate(REDACTED));
|
|
1822
|
+
items.push(REDACTED);
|
|
1823
|
+
redactNext = false;
|
|
1824
|
+
} else {
|
|
1825
|
+
items.push(freezeInner(descriptor.value, depth + 1, path, metrics));
|
|
1826
|
+
redactNext = typeof descriptor.value === "string" && keyIsRedacted(descriptor.value, redactKeys);
|
|
1827
|
+
}
|
|
1261
1828
|
}
|
|
1262
1829
|
if (value.length > limits.maxArrayElements) {
|
|
1263
|
-
|
|
1264
|
-
items.
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1830
|
+
add(metrics, NODE + 32);
|
|
1831
|
+
items.push(
|
|
1832
|
+
atom("truncated", {
|
|
1833
|
+
reason: "max_array_elements",
|
|
1834
|
+
originalLength: value.length
|
|
1268
1835
|
})
|
|
1269
1836
|
);
|
|
1270
1837
|
}
|
|
1271
|
-
|
|
1838
|
+
if (items[0] === RASPUTIN_WIRE_TAG) {
|
|
1839
|
+
return atom("instance", { type: "Array", value: { items } });
|
|
1840
|
+
}
|
|
1841
|
+
return items;
|
|
1842
|
+
}
|
|
1843
|
+
if (types.isTypedArray(value)) {
|
|
1844
|
+
const view = value;
|
|
1845
|
+
const byteLength = viewByteLength(view);
|
|
1846
|
+
const sampleLimit = Math.min(32, limits.maxStringLength);
|
|
1847
|
+
let sample = [];
|
|
1848
|
+
try {
|
|
1849
|
+
const buffer = typedArrayBufferGet?.call(view);
|
|
1850
|
+
const byteOffset = typedArrayByteOffsetGet?.call(view);
|
|
1851
|
+
if (buffer) {
|
|
1852
|
+
const bytes = new Uint8Array(
|
|
1853
|
+
buffer,
|
|
1854
|
+
byteOffset ?? 0,
|
|
1855
|
+
Math.min(sampleLimit, byteLength)
|
|
1856
|
+
);
|
|
1857
|
+
sample = sampleBytes(bytes, sampleLimit);
|
|
1858
|
+
}
|
|
1859
|
+
} catch {
|
|
1860
|
+
sample = [];
|
|
1861
|
+
}
|
|
1862
|
+
const typeName2 = typedArrayName(value);
|
|
1863
|
+
add(metrics, NODE + stringEstimate(typeName2) + 48);
|
|
1864
|
+
return atom("instance", {
|
|
1865
|
+
type: typeName2,
|
|
1866
|
+
value: {
|
|
1867
|
+
byteLength,
|
|
1868
|
+
...sample.length > 0 ? { sample } : {},
|
|
1869
|
+
...byteLength > sampleLimit ? { truncated: true } : {}
|
|
1870
|
+
}
|
|
1871
|
+
});
|
|
1872
|
+
}
|
|
1873
|
+
if (types.isDataView(value)) {
|
|
1874
|
+
const view = value;
|
|
1875
|
+
const byteLength = viewByteLength(view);
|
|
1876
|
+
add(metrics, NODE + 32);
|
|
1877
|
+
return atom("instance", {
|
|
1878
|
+
type: "DataView",
|
|
1879
|
+
value: { byteLength }
|
|
1880
|
+
});
|
|
1881
|
+
}
|
|
1882
|
+
if (types.isArrayBuffer(value) || types.isSharedArrayBuffer(value)) {
|
|
1883
|
+
const buffer = value;
|
|
1884
|
+
let byteLength = 0;
|
|
1885
|
+
try {
|
|
1886
|
+
byteLength = buffer.byteLength;
|
|
1887
|
+
} catch {
|
|
1888
|
+
byteLength = 0;
|
|
1889
|
+
}
|
|
1890
|
+
add(metrics, NODE + 32);
|
|
1891
|
+
return atom("instance", {
|
|
1892
|
+
type: types.isSharedArrayBuffer(value) ? "SharedArrayBuffer" : "ArrayBuffer",
|
|
1893
|
+
value: { byteLength }
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
if (types.isStringObject(value) || types.isNumberObject(value) || types.isBooleanObject(value)) {
|
|
1897
|
+
try {
|
|
1898
|
+
if (types.isStringObject(value)) {
|
|
1899
|
+
return freezeInner(String.prototype.valueOf.call(value), depth, path, metrics);
|
|
1900
|
+
}
|
|
1901
|
+
if (types.isNumberObject(value)) {
|
|
1902
|
+
return freezeInner(Number.prototype.valueOf.call(value), depth, path, metrics);
|
|
1903
|
+
}
|
|
1904
|
+
return freezeInner(Boolean.prototype.valueOf.call(value), depth, path, metrics);
|
|
1905
|
+
} catch {
|
|
1906
|
+
return atom("unserializable");
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
add(metrics, 2);
|
|
1910
|
+
const fields = /* @__PURE__ */ Object.create(null);
|
|
1911
|
+
let typeName;
|
|
1912
|
+
let prototype = null;
|
|
1913
|
+
try {
|
|
1914
|
+
prototype = Object.getPrototypeOf(value);
|
|
1915
|
+
} catch {
|
|
1916
|
+
prototype = null;
|
|
1917
|
+
}
|
|
1918
|
+
if (prototype && types.isProxy(prototype)) {
|
|
1919
|
+
add(metrics, NODE + 16);
|
|
1920
|
+
return atom("instance", { type: "Proxy", value: fields });
|
|
1272
1921
|
}
|
|
1273
|
-
const object = openObject(metrics, childAllocate);
|
|
1274
|
-
const prototype = Object.getPrototypeOf(value);
|
|
1275
1922
|
if (prototype && prototype !== Object.prototype) {
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
"
|
|
1280
|
-
|
|
1281
|
-
|
|
1923
|
+
typeName = "instance";
|
|
1924
|
+
if (!types.isProxy(prototype)) {
|
|
1925
|
+
const ctor = ownData(prototype, "constructor")?.value;
|
|
1926
|
+
if (typeof ctor === "function") {
|
|
1927
|
+
const name = functionNameOf(ctor);
|
|
1928
|
+
if (name && name !== "anonymous") typeName = name;
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
add(metrics, NODE + stringEstimate(typeName));
|
|
1282
1932
|
}
|
|
1283
|
-
const
|
|
1284
|
-
const
|
|
1933
|
+
const pairLabel = ownData(value, "name") ?? ownData(value, "key");
|
|
1934
|
+
const pairIsSensitive = pairLabel !== void 0 && typeof pairLabel.value === "string" && keyIsRedacted(pairLabel.value, redactKeys);
|
|
1935
|
+
const { keys, truncated } = ownEnumerableKeys(value, limits.maxObjectKeys);
|
|
1936
|
+
const maxKeys = truncated ? Math.max(0, limits.maxObjectKeys - 1) : keys.length;
|
|
1285
1937
|
for (let index = 0; index < maxKeys; index++) {
|
|
1286
1938
|
const key = keys[index];
|
|
1287
|
-
if (key === void 0) continue;
|
|
1288
|
-
|
|
1289
|
-
|
|
1939
|
+
if (key === void 0 || metrics.oversize) continue;
|
|
1940
|
+
add(metrics, stringEstimate(key));
|
|
1941
|
+
if (keyIsRedacted(key, redactKeys) || key === "value" && pairIsSensitive) {
|
|
1942
|
+
add(metrics, stringEstimate(REDACTED));
|
|
1943
|
+
assignFrozenField(fields, key, REDACTED);
|
|
1290
1944
|
continue;
|
|
1291
1945
|
}
|
|
1292
|
-
const
|
|
1293
|
-
if (
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
object,
|
|
1297
|
-
key,
|
|
1298
|
-
serializeInner(descriptor.value, depth + 1, path, childAllocate, metrics)
|
|
1299
|
-
);
|
|
1946
|
+
const slot = ownData(value, key);
|
|
1947
|
+
if (slot) {
|
|
1948
|
+
const field = typeof slot.value === "string" && propertyNameLooksLikeUrl(key) ? redactUrlLikeString(slot.value, redactKeys) : slot.value;
|
|
1949
|
+
assignFrozenField(fields, key, freezeInner(field, depth + 1, path, metrics));
|
|
1300
1950
|
} else {
|
|
1301
|
-
|
|
1302
|
-
|
|
1951
|
+
add(metrics, NODE + 16);
|
|
1952
|
+
assignFrozenField(fields, key, atom("accessor"));
|
|
1303
1953
|
}
|
|
1304
1954
|
}
|
|
1305
|
-
if (
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1955
|
+
if (truncated) {
|
|
1956
|
+
return atom("instance", {
|
|
1957
|
+
type: typeName,
|
|
1958
|
+
value: fields,
|
|
1959
|
+
truncated: true,
|
|
1960
|
+
reason: "max_object_keys"
|
|
1961
|
+
});
|
|
1309
1962
|
}
|
|
1310
|
-
return
|
|
1963
|
+
if (typeName) return atom("instance", { type: typeName, value: fields });
|
|
1964
|
+
return fields;
|
|
1311
1965
|
} catch (error) {
|
|
1312
|
-
metrics
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
allocate && !metrics.oversize,
|
|
1317
|
-
"unserializable",
|
|
1318
|
-
error instanceof Error ? error.message : void 0
|
|
1319
|
-
);
|
|
1966
|
+
add(metrics, NODE + 32);
|
|
1967
|
+
return atom("unserializable", {
|
|
1968
|
+
value: error instanceof Error ? error.message : void 0
|
|
1969
|
+
});
|
|
1320
1970
|
} finally {
|
|
1321
1971
|
path.delete(value);
|
|
1322
1972
|
}
|
|
1323
1973
|
};
|
|
1324
|
-
const
|
|
1325
|
-
const
|
|
1326
|
-
|
|
1327
|
-
return fast.bytes <= limits.maxSerializedValueBytes ? fast : boundedOversize(fast.bytes, fast.visitedNodes);
|
|
1328
|
-
}
|
|
1329
|
-
const metrics = { visitedNodes: 0, bytes: 0, oversize: false };
|
|
1330
|
-
const reentrant = serializing;
|
|
1974
|
+
const freeze = (value) => {
|
|
1975
|
+
const metrics = { visitedNodes: 0, estimatedBytes: 0, oversize: false };
|
|
1976
|
+
const reentrant = freezing;
|
|
1331
1977
|
const path = reentrant ? /* @__PURE__ */ new Set() : sharedPath;
|
|
1332
1978
|
if (!reentrant) {
|
|
1333
|
-
|
|
1979
|
+
freezing = true;
|
|
1334
1980
|
sharedPath.clear();
|
|
1335
1981
|
}
|
|
1336
1982
|
try {
|
|
1337
|
-
const
|
|
1338
|
-
if (metrics.
|
|
1339
|
-
return
|
|
1983
|
+
const frozen = freezeInner(value, 0, path, metrics);
|
|
1984
|
+
if (metrics.oversize) {
|
|
1985
|
+
return {
|
|
1986
|
+
value: atom("truncated", {
|
|
1987
|
+
reason: "max_serialized_value_bytes",
|
|
1988
|
+
serializedBytes: metrics.estimatedBytes
|
|
1989
|
+
}),
|
|
1990
|
+
estimatedBytes: metrics.estimatedBytes,
|
|
1991
|
+
visitedNodes: metrics.visitedNodes,
|
|
1992
|
+
oversize: true
|
|
1993
|
+
};
|
|
1340
1994
|
}
|
|
1341
|
-
return {
|
|
1995
|
+
return {
|
|
1996
|
+
value: frozen,
|
|
1997
|
+
estimatedBytes: metrics.estimatedBytes,
|
|
1998
|
+
visitedNodes: metrics.visitedNodes,
|
|
1999
|
+
oversize: false
|
|
2000
|
+
};
|
|
1342
2001
|
} catch {
|
|
1343
|
-
const failed = typeMarker("unserializable");
|
|
1344
2002
|
return {
|
|
1345
|
-
value:
|
|
1346
|
-
|
|
1347
|
-
visitedNodes: metrics.visitedNodes
|
|
2003
|
+
value: atom("unserializable"),
|
|
2004
|
+
estimatedBytes: NODE + 16,
|
|
2005
|
+
visitedNodes: Math.max(1, metrics.visitedNodes),
|
|
2006
|
+
oversize: false
|
|
1348
2007
|
};
|
|
1349
2008
|
} finally {
|
|
1350
2009
|
path.clear();
|
|
1351
|
-
if (!reentrant)
|
|
2010
|
+
if (!reentrant) freezing = false;
|
|
2011
|
+
}
|
|
2012
|
+
};
|
|
2013
|
+
return { freeze, limits };
|
|
2014
|
+
};
|
|
2015
|
+
|
|
2016
|
+
// src/execution-recorder/encode-frozen.ts
|
|
2017
|
+
var typeMarker = (type, value) => ({
|
|
2018
|
+
__rasputin_type: type,
|
|
2019
|
+
...value === void 0 ? {} : { value }
|
|
2020
|
+
});
|
|
2021
|
+
var truncation = (reason, extra = {}) => ({
|
|
2022
|
+
__rasputin_truncated: true,
|
|
2023
|
+
__reason: reason,
|
|
2024
|
+
...extra
|
|
2025
|
+
});
|
|
2026
|
+
var taggedNumber = (value) => {
|
|
2027
|
+
if (Number.isNaN(value)) return { __rasputin_type: "NaN" };
|
|
2028
|
+
if (value === Infinity) return { __rasputin_type: "Infinity" };
|
|
2029
|
+
if (value === -Infinity) return { __rasputin_type: "-Infinity" };
|
|
2030
|
+
if (Object.is(value, -0)) return { __rasputin_type: "-0" };
|
|
2031
|
+
return void 0;
|
|
2032
|
+
};
|
|
2033
|
+
var jsonStringUtf8Bytes = (value) => {
|
|
2034
|
+
let bytes = 2;
|
|
2035
|
+
for (let index = 0; index < value.length; index++) {
|
|
2036
|
+
const code = value.charCodeAt(index);
|
|
2037
|
+
if (code === 34 || code === 92) {
|
|
2038
|
+
bytes += 2;
|
|
2039
|
+
continue;
|
|
2040
|
+
}
|
|
2041
|
+
if (code === 8 || code === 9 || code === 10 || code === 12 || code === 13) {
|
|
2042
|
+
bytes += 2;
|
|
2043
|
+
continue;
|
|
2044
|
+
}
|
|
2045
|
+
if (code < 32) {
|
|
2046
|
+
bytes += 6;
|
|
2047
|
+
continue;
|
|
2048
|
+
}
|
|
2049
|
+
if (code < 128) {
|
|
2050
|
+
bytes += 1;
|
|
2051
|
+
continue;
|
|
2052
|
+
}
|
|
2053
|
+
if (code < 2048) {
|
|
2054
|
+
bytes += 2;
|
|
2055
|
+
continue;
|
|
2056
|
+
}
|
|
2057
|
+
if (code >= 55296 && code <= 56319) {
|
|
2058
|
+
const next = value.charCodeAt(index + 1);
|
|
2059
|
+
if (index + 1 < value.length && next >= 56320 && next <= 57343) {
|
|
2060
|
+
bytes += 4;
|
|
2061
|
+
index++;
|
|
2062
|
+
continue;
|
|
2063
|
+
}
|
|
2064
|
+
bytes += 6;
|
|
2065
|
+
continue;
|
|
2066
|
+
}
|
|
2067
|
+
if (code >= 56320 && code <= 57343) {
|
|
2068
|
+
bytes += 6;
|
|
2069
|
+
continue;
|
|
2070
|
+
}
|
|
2071
|
+
bytes += 3;
|
|
2072
|
+
}
|
|
2073
|
+
return bytes;
|
|
2074
|
+
};
|
|
2075
|
+
var ownData2 = (value, key) => {
|
|
2076
|
+
try {
|
|
2077
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
2078
|
+
if (descriptor && "value" in descriptor) return descriptor.value;
|
|
2079
|
+
return void 0;
|
|
2080
|
+
} catch {
|
|
2081
|
+
return void 0;
|
|
2082
|
+
}
|
|
2083
|
+
};
|
|
2084
|
+
var jsonLiteralUtf8Bytes = (value) => {
|
|
2085
|
+
if (value === null) return 4;
|
|
2086
|
+
switch (typeof value) {
|
|
2087
|
+
case "boolean":
|
|
2088
|
+
return value ? 4 : 5;
|
|
2089
|
+
case "number": {
|
|
2090
|
+
const tagged = taggedNumber(value);
|
|
2091
|
+
if (tagged) return jsonLiteralUtf8Bytes(tagged);
|
|
2092
|
+
return String(value).length;
|
|
2093
|
+
}
|
|
2094
|
+
case "string":
|
|
2095
|
+
return jsonStringUtf8Bytes(value);
|
|
2096
|
+
case "object": {
|
|
2097
|
+
if (Array.isArray(value)) {
|
|
2098
|
+
let bytes2 = 2;
|
|
2099
|
+
for (let index = 0; index < value.length; index++) {
|
|
2100
|
+
if (index > 0) bytes2 += 1;
|
|
2101
|
+
bytes2 += jsonLiteralUtf8Bytes(ownData2(value, index));
|
|
2102
|
+
}
|
|
2103
|
+
return bytes2;
|
|
2104
|
+
}
|
|
2105
|
+
const record = value;
|
|
2106
|
+
let bytes = 2;
|
|
2107
|
+
let first = true;
|
|
2108
|
+
for (const key of Object.keys(record)) {
|
|
2109
|
+
if (!first) bytes += 1;
|
|
2110
|
+
first = false;
|
|
2111
|
+
bytes += jsonStringUtf8Bytes(key) + 1;
|
|
2112
|
+
bytes += jsonLiteralUtf8Bytes(ownData2(record, key));
|
|
2113
|
+
}
|
|
2114
|
+
return bytes;
|
|
2115
|
+
}
|
|
2116
|
+
default:
|
|
2117
|
+
return Buffer3.byteLength(JSON.stringify(value) ?? "null", "utf8");
|
|
2118
|
+
}
|
|
2119
|
+
};
|
|
2120
|
+
var BUILTIN_INSTANCE_TYPES = /* @__PURE__ */ new Set([
|
|
2121
|
+
"Uint8Array",
|
|
2122
|
+
"Uint8ClampedArray",
|
|
2123
|
+
"Int8Array",
|
|
2124
|
+
"Uint16Array",
|
|
2125
|
+
"Int16Array",
|
|
2126
|
+
"Uint32Array",
|
|
2127
|
+
"Int32Array",
|
|
2128
|
+
"Float32Array",
|
|
2129
|
+
"Float64Array",
|
|
2130
|
+
"BigUint64Array",
|
|
2131
|
+
"BigInt64Array",
|
|
2132
|
+
"TypedArray",
|
|
2133
|
+
"ArrayBuffer",
|
|
2134
|
+
"SharedArrayBuffer",
|
|
2135
|
+
"DataView",
|
|
2136
|
+
"Proxy"
|
|
2137
|
+
]);
|
|
2138
|
+
var RESERVED_WIRE_KEYS = /* @__PURE__ */ new Set([
|
|
2139
|
+
"__proto__",
|
|
2140
|
+
"__rasputin_type",
|
|
2141
|
+
"__rasputin_truncated",
|
|
2142
|
+
"__rasputin_fields",
|
|
2143
|
+
"__reason",
|
|
2144
|
+
"__original_length",
|
|
2145
|
+
"__serialized_bytes"
|
|
2146
|
+
]);
|
|
2147
|
+
var encodePlainObject = (value) => {
|
|
2148
|
+
const record = value;
|
|
2149
|
+
if (typeof record.__rasputin_type === "string") {
|
|
2150
|
+
const encoded2 = /* @__PURE__ */ Object.create(null);
|
|
2151
|
+
for (const key of Object.keys(record)) {
|
|
2152
|
+
if (key === "__proto__") continue;
|
|
2153
|
+
encoded2[key] = encodeFrozen(record[key]);
|
|
2154
|
+
}
|
|
2155
|
+
encoded2.__rasputin_type = record.__rasputin_type;
|
|
2156
|
+
return encoded2;
|
|
2157
|
+
}
|
|
2158
|
+
const encoded = /* @__PURE__ */ Object.create(null);
|
|
2159
|
+
const escaped = [];
|
|
2160
|
+
for (const key of Object.keys(record)) {
|
|
2161
|
+
const encodedValue = encodeFrozen(record[key]);
|
|
2162
|
+
if (key === "__proto__" || RESERVED_WIRE_KEYS.has(key) || key.startsWith("__rasputin_")) {
|
|
2163
|
+
if (key === "__rasputin_fields") {
|
|
2164
|
+
encoded.__rasputin_fields = encodedValue;
|
|
2165
|
+
continue;
|
|
2166
|
+
}
|
|
2167
|
+
escaped.push({ name: key, value: encodedValue });
|
|
2168
|
+
} else {
|
|
2169
|
+
encoded[key] = encodedValue;
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
if (escaped.length > 0) {
|
|
2173
|
+
const existing = Array.isArray(encoded.__rasputin_fields) ? encoded.__rasputin_fields : [];
|
|
2174
|
+
encoded.__rasputin_fields = [...existing, ...escaped];
|
|
2175
|
+
}
|
|
2176
|
+
return encoded;
|
|
2177
|
+
};
|
|
2178
|
+
var encodeAtom = (frozen) => {
|
|
2179
|
+
const kind = frozen[FROZEN];
|
|
2180
|
+
switch (kind) {
|
|
2181
|
+
case "undefined":
|
|
2182
|
+
case "NaN":
|
|
2183
|
+
case "Infinity":
|
|
2184
|
+
case "-Infinity":
|
|
2185
|
+
case "-0":
|
|
2186
|
+
case "Proxy":
|
|
2187
|
+
case "circular":
|
|
2188
|
+
case "Promise":
|
|
2189
|
+
case "accessor":
|
|
2190
|
+
case "hole":
|
|
2191
|
+
return typeMarker(kind);
|
|
2192
|
+
case "bigint":
|
|
2193
|
+
case "symbol":
|
|
2194
|
+
case "function":
|
|
2195
|
+
case "Date":
|
|
2196
|
+
return typeMarker(kind, encodeFrozen(frozen.value));
|
|
2197
|
+
case "unserializable":
|
|
2198
|
+
return frozen.value === void 0 ? typeMarker("unserializable") : typeMarker("unserializable", encodeFrozen(frozen.value));
|
|
2199
|
+
case "Error": {
|
|
2200
|
+
const encoded = {
|
|
2201
|
+
__rasputin_type: "Error",
|
|
2202
|
+
name: frozen.name,
|
|
2203
|
+
message: encodeFrozen(frozen.message)
|
|
2204
|
+
};
|
|
2205
|
+
if (frozen.stack !== void 0) encoded.stack = encodeFrozen(frozen.stack);
|
|
2206
|
+
if (frozen.code !== void 0) encoded.code = encodeFrozen(frozen.code);
|
|
2207
|
+
if (frozen.cause !== void 0) encoded.cause = encodeFrozen(frozen.cause);
|
|
2208
|
+
if (frozen.statusCode !== void 0) encoded.statusCode = encodeFrozen(frozen.statusCode);
|
|
2209
|
+
return encoded;
|
|
1352
2210
|
}
|
|
2211
|
+
case "Buffer":
|
|
2212
|
+
return typeMarker("Buffer", {
|
|
2213
|
+
byteLength: frozen.byteLength,
|
|
2214
|
+
base64: frozen.base64,
|
|
2215
|
+
...frozen.truncated ? { __rasputin_truncated: true } : {}
|
|
2216
|
+
});
|
|
2217
|
+
case "Map": {
|
|
2218
|
+
const encoded = {
|
|
2219
|
+
__rasputin_type: "Map",
|
|
2220
|
+
entries: encodeFrozen(frozen.entries)
|
|
2221
|
+
};
|
|
2222
|
+
if (frozen.truncated) {
|
|
2223
|
+
encoded.__rasputin_truncated = true;
|
|
2224
|
+
encoded.__reason = frozen.reason;
|
|
2225
|
+
encoded.__original_length = frozen.originalLength;
|
|
2226
|
+
}
|
|
2227
|
+
return encoded;
|
|
2228
|
+
}
|
|
2229
|
+
case "Set": {
|
|
2230
|
+
const encoded = {
|
|
2231
|
+
__rasputin_type: "Set",
|
|
2232
|
+
values: encodeFrozen(frozen.values)
|
|
2233
|
+
};
|
|
2234
|
+
if (frozen.truncated) {
|
|
2235
|
+
encoded.__rasputin_truncated = true;
|
|
2236
|
+
encoded.__reason = frozen.reason;
|
|
2237
|
+
encoded.__original_length = frozen.originalLength;
|
|
2238
|
+
}
|
|
2239
|
+
return encoded;
|
|
2240
|
+
}
|
|
2241
|
+
case "truncated":
|
|
2242
|
+
return truncation(frozen.reason ?? "max_depth", {
|
|
2243
|
+
...frozen.originalLength === void 0 ? {} : { __original_length: frozen.originalLength },
|
|
2244
|
+
...frozen.serializedBytes === void 0 ? {} : { __serialized_bytes: frozen.serializedBytes },
|
|
2245
|
+
...frozen.value === void 0 ? {} : { value: encodeFrozen(frozen.value) }
|
|
2246
|
+
});
|
|
2247
|
+
case "instance": {
|
|
2248
|
+
const fields = typeof frozen.value === "object" && frozen.value !== null && !Array.isArray(frozen.value) ? encodePlainObject(frozen.value) : encodeFrozen(frozen.value);
|
|
2249
|
+
const encoded = /* @__PURE__ */ Object.create(null);
|
|
2250
|
+
if (typeof fields === "object" && fields !== null && !Array.isArray(fields)) {
|
|
2251
|
+
for (const key of Object.keys(fields)) {
|
|
2252
|
+
encoded[key] = fields[key];
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
if (frozen.type && BUILTIN_INSTANCE_TYPES.has(frozen.type)) {
|
|
2256
|
+
encoded.__rasputin_type = frozen.type;
|
|
2257
|
+
} else if (frozen.type) {
|
|
2258
|
+
encoded.__rasputin_type = "instance";
|
|
2259
|
+
encoded.__rasputin_class = frozen.type;
|
|
2260
|
+
} else if (!frozen.truncated) {
|
|
2261
|
+
encoded.__rasputin_type = "instance";
|
|
2262
|
+
}
|
|
2263
|
+
if (frozen.truncated) {
|
|
2264
|
+
encoded.__rasputin_truncated = true;
|
|
2265
|
+
encoded.__reason = frozen.reason;
|
|
2266
|
+
if (frozen.originalLength !== void 0) encoded.__original_length = frozen.originalLength;
|
|
2267
|
+
}
|
|
2268
|
+
return encoded;
|
|
2269
|
+
}
|
|
2270
|
+
default:
|
|
2271
|
+
return typeMarker("unserializable");
|
|
2272
|
+
}
|
|
2273
|
+
};
|
|
2274
|
+
var encodeFrozen = (value) => {
|
|
2275
|
+
if (value === REDACTED) return REDACTED;
|
|
2276
|
+
if (isFrozenAtom(value)) return encodeAtom(value);
|
|
2277
|
+
if (Array.isArray(value)) {
|
|
2278
|
+
const items = new Array(value.length);
|
|
2279
|
+
for (let index = 0; index < value.length; index++) {
|
|
2280
|
+
items[index] = encodeFrozen(value[index]);
|
|
2281
|
+
}
|
|
2282
|
+
return items;
|
|
2283
|
+
}
|
|
2284
|
+
if (typeof value === "object" && value !== null) {
|
|
2285
|
+
return encodePlainObject(value);
|
|
2286
|
+
}
|
|
2287
|
+
return value;
|
|
2288
|
+
};
|
|
2289
|
+
var encodeFrozenWithBytes = (frozen, visitedNodes, maxSerializedValueBytes) => {
|
|
2290
|
+
const encoded = encodeFrozen(frozen);
|
|
2291
|
+
if (typeof encoded === "object" && encoded !== null && !Array.isArray(encoded) && encoded.__reason === "max_serialized_value_bytes") {
|
|
2292
|
+
const bytes2 = jsonLiteralUtf8Bytes(encoded);
|
|
2293
|
+
return { value: encoded, bytes: bytes2, visitedNodes };
|
|
2294
|
+
}
|
|
2295
|
+
const bytes = jsonLiteralUtf8Bytes(encoded);
|
|
2296
|
+
if (bytes > maxSerializedValueBytes) {
|
|
2297
|
+
const bounded = truncation("max_serialized_value_bytes", { __serialized_bytes: bytes });
|
|
2298
|
+
return { value: bounded, bytes: jsonLiteralUtf8Bytes(bounded), visitedNodes };
|
|
2299
|
+
}
|
|
2300
|
+
return { value: encoded, bytes, visitedNodes };
|
|
2301
|
+
};
|
|
2302
|
+
|
|
2303
|
+
// src/execution-recorder/safe-serialize.ts
|
|
2304
|
+
var createSafeSerializer = (options = {}) => {
|
|
2305
|
+
const freezer = createValueFreezer(options);
|
|
2306
|
+
const serializeWithBytes = (value) => {
|
|
2307
|
+
const frozen = freezer.freeze(value);
|
|
2308
|
+
return encodeFrozenWithBytes(
|
|
2309
|
+
frozen.value,
|
|
2310
|
+
frozen.visitedNodes,
|
|
2311
|
+
freezer.limits.maxSerializedValueBytes
|
|
2312
|
+
);
|
|
1353
2313
|
};
|
|
1354
2314
|
return {
|
|
2315
|
+
freeze: freezer.freeze,
|
|
2316
|
+
encode: encodeFrozen,
|
|
1355
2317
|
serialize: (value) => serializeWithBytes(value).value,
|
|
1356
2318
|
serializeWithBytes
|
|
1357
2319
|
};
|
|
@@ -1422,9 +2384,40 @@ var createSourceExclusionMatcher = (exclusions) => {
|
|
|
1422
2384
|
return matchers.length === 0 ? () => false : (definition) => matchers.some((matcher) => matcher(definition));
|
|
1423
2385
|
};
|
|
1424
2386
|
|
|
2387
|
+
// src/execution-recorder/warn-missing-async-context-frame.ts
|
|
2388
|
+
var ASYNC_CONTEXT_FRAME_FLAG = "--experimental-async-context-frame";
|
|
2389
|
+
var ASYNC_CONTEXT_FRAME_WARNING_SUPPRESS_ENV = "RASPUTIN_SUPPRESS_ASYNC_CONTEXT_FRAME_WARNING";
|
|
2390
|
+
var warnedSymbol = Symbol.for("rasputin.asyncContextFrameWarning");
|
|
2391
|
+
var hasFlag = (execArgv, nodeOptions) => {
|
|
2392
|
+
if (execArgv.includes(ASYNC_CONTEXT_FRAME_FLAG)) return true;
|
|
2393
|
+
if (!nodeOptions) return false;
|
|
2394
|
+
return nodeOptions.split(/\s+/).includes(ASYNC_CONTEXT_FRAME_FLAG);
|
|
2395
|
+
};
|
|
2396
|
+
var missingAsyncContextFrameWarning = (runtime) => {
|
|
2397
|
+
if (runtime.bun || !runtime.node) return void 0;
|
|
2398
|
+
const major = Number(runtime.node.split(".")[0]);
|
|
2399
|
+
if (!Number.isInteger(major) || major >= 24) return void 0;
|
|
2400
|
+
if (hasFlag(runtime.execArgv, runtime.nodeOptions)) return void 0;
|
|
2401
|
+
return `[rasputin] Node.js ${major} is running without ${ASYNC_CONTEXT_FRAME_FLAG}. AsyncLocalStorage is faster with that flag, which is the default on Node.js 24+. Start Node with ${ASYNC_CONTEXT_FRAME_FLAG}, or use Node.js 24 or newer. Set ${ASYNC_CONTEXT_FRAME_WARNING_SUPPRESS_ENV}=1 to hide this warning.`;
|
|
2402
|
+
};
|
|
2403
|
+
var warnIfMissingAsyncContextFrame = () => {
|
|
2404
|
+
if (process.env[ASYNC_CONTEXT_FRAME_WARNING_SUPPRESS_ENV] === "1") return;
|
|
2405
|
+
if (Reflect.get(globalThis, warnedSymbol)) return;
|
|
2406
|
+
const message = missingAsyncContextFrameWarning({
|
|
2407
|
+
bun: process.versions.bun,
|
|
2408
|
+
node: process.versions.node,
|
|
2409
|
+
execArgv: process.execArgv,
|
|
2410
|
+
nodeOptions: process.env.NODE_OPTIONS
|
|
2411
|
+
});
|
|
2412
|
+
if (!message) return;
|
|
2413
|
+
Reflect.set(globalThis, warnedSymbol, true);
|
|
2414
|
+
console.warn(message);
|
|
2415
|
+
};
|
|
2416
|
+
|
|
1425
2417
|
// src/execution-recorder/execution-recorder.ts
|
|
1426
2418
|
var DEFAULT_MAX_ACTIVE_MEMORY_BYTES = 64 * 1024 * 1024;
|
|
1427
|
-
var
|
|
2419
|
+
var DEFAULT_MAX_EXECUTION_HOLD_MS = 6e4;
|
|
2420
|
+
var DEFAULT_MAX_RETAINED_ERROR_RECORDINGS = 32;
|
|
1428
2421
|
var phaseTimingEnabled = process.env.RASPUTIN_RECORDER_PHASE_TIMING === "1";
|
|
1429
2422
|
var manualFunctionDefinition = (value) => {
|
|
1430
2423
|
const located = /^(.+):([^:@]+)@(\d+):(\d+)$/.exec(value);
|
|
@@ -1443,72 +2436,39 @@ var normalizeFunctionDefinition = (value) => typeof value === "string" ? manualF
|
|
|
1443
2436
|
var elapsedMs2 = (startedAtNs, endedAtNs = process.hrtime.bigint()) => Number(endedAtNs - startedAtNs) / 1e6;
|
|
1444
2437
|
var roundedMilliseconds2 = (nanoseconds) => Math.round(Number(nanoseconds) / 1e6 * 1e4) / 1e4;
|
|
1445
2438
|
var addRecorderTime = (recording, nanoseconds) => {
|
|
1446
|
-
if (nanoseconds
|
|
2439
|
+
if (process.env.RASPUTIN_RECORDER_PHASE_TIMING !== "1" || nanoseconds <= 0n) return;
|
|
2440
|
+
recording.inlineRecorderTimeNs += nanoseconds;
|
|
2441
|
+
};
|
|
2442
|
+
var mapArrayLike = (args, map) => {
|
|
2443
|
+
const mapped = new Array(args.length);
|
|
2444
|
+
for (let index = 0; index < args.length; index++) {
|
|
2445
|
+
mapped[index] = map(args[index], index);
|
|
2446
|
+
}
|
|
2447
|
+
return mapped;
|
|
1447
2448
|
};
|
|
1448
|
-
var isPromiseLike = (value) => Boolean(value) && typeof value.then === "function";
|
|
1449
2449
|
var notifyObserver = (observer, value) => {
|
|
1450
2450
|
try {
|
|
1451
2451
|
observer(value);
|
|
1452
2452
|
} catch {
|
|
1453
2453
|
}
|
|
1454
2454
|
};
|
|
1455
|
-
var
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
} catch (error) {
|
|
1460
|
-
notifyObserver(onThrow, error);
|
|
1461
|
-
throw error;
|
|
1462
|
-
}
|
|
1463
|
-
if (isPromiseLike(result)) {
|
|
1464
|
-
return result.then(
|
|
1465
|
-
(value) => {
|
|
1466
|
-
notifyObserver(onReturn, value);
|
|
1467
|
-
return value;
|
|
1468
|
-
},
|
|
1469
|
-
(error) => {
|
|
1470
|
-
notifyObserver(onThrow, error);
|
|
1471
|
-
throw error;
|
|
1472
|
-
}
|
|
1473
|
-
);
|
|
1474
|
-
}
|
|
1475
|
-
notifyObserver(onReturn, result);
|
|
1476
|
-
return result;
|
|
1477
|
-
};
|
|
1478
|
-
var observeRecordedCallback = (recording, recorderStartedAtNs, callback, onReturn, onThrow) => {
|
|
1479
|
-
const callbackStartedAtNs = process.hrtime.bigint();
|
|
1480
|
-
const recordExitWork = (callbackEndedAtNs2) => {
|
|
2455
|
+
var observeRecordedCallback = function __rasputinHandleRun__2(recording, recorderStartedAtNs, callback, onReturn, onThrow) {
|
|
2456
|
+
const callbackStartedAtNs = phaseTimingEnabled ? process.hrtime.bigint() : recorderStartedAtNs;
|
|
2457
|
+
const recordExitWork = (callbackEndedAtNs) => {
|
|
2458
|
+
if (!phaseTimingEnabled) return;
|
|
1481
2459
|
addRecorderTime(recording, callbackStartedAtNs - recorderStartedAtNs);
|
|
1482
|
-
addRecorderTime(recording, process.hrtime.bigint() -
|
|
2460
|
+
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs);
|
|
1483
2461
|
};
|
|
1484
2462
|
let result;
|
|
1485
2463
|
try {
|
|
1486
2464
|
result = callback();
|
|
1487
2465
|
} catch (error) {
|
|
1488
|
-
const callbackEndedAtNs2 = process.hrtime.bigint();
|
|
1489
2466
|
notifyObserver(onThrow, error);
|
|
1490
|
-
recordExitWork(
|
|
2467
|
+
recordExitWork(phaseTimingEnabled ? process.hrtime.bigint() : recorderStartedAtNs);
|
|
1491
2468
|
throw error;
|
|
1492
2469
|
}
|
|
1493
|
-
if (isPromiseLike(result)) {
|
|
1494
|
-
return result.then(
|
|
1495
|
-
(value) => {
|
|
1496
|
-
const callbackEndedAtNs2 = process.hrtime.bigint();
|
|
1497
|
-
notifyObserver(onReturn, value);
|
|
1498
|
-
recordExitWork(callbackEndedAtNs2);
|
|
1499
|
-
return value;
|
|
1500
|
-
},
|
|
1501
|
-
(error) => {
|
|
1502
|
-
const callbackEndedAtNs2 = process.hrtime.bigint();
|
|
1503
|
-
notifyObserver(onThrow, error);
|
|
1504
|
-
recordExitWork(callbackEndedAtNs2);
|
|
1505
|
-
throw error;
|
|
1506
|
-
}
|
|
1507
|
-
);
|
|
1508
|
-
}
|
|
1509
|
-
const callbackEndedAtNs = process.hrtime.bigint();
|
|
1510
2470
|
notifyObserver(onReturn, result);
|
|
1511
|
-
recordExitWork(
|
|
2471
|
+
recordExitWork(phaseTimingEnabled ? process.hrtime.bigint() : recorderStartedAtNs);
|
|
1512
2472
|
return result;
|
|
1513
2473
|
};
|
|
1514
2474
|
var emptyStats = {
|
|
@@ -1538,32 +2498,34 @@ var emptyStats = {
|
|
|
1538
2498
|
journalPoolMisses: 0,
|
|
1539
2499
|
journalPoolSize: 0,
|
|
1540
2500
|
journalAllocatedCapacity: 0,
|
|
1541
|
-
|
|
1542
|
-
derivationElidedFunctionCalls: 0,
|
|
1543
|
-
derivationRootsCaptured: 0,
|
|
1544
|
-
derivationControlFactsCaptured: 0,
|
|
1545
|
-
derivationValuesAvoided: 0,
|
|
1546
|
-
derivationFallbackFunctions: 0,
|
|
1547
|
-
derivationFallbackExpressions: 0,
|
|
1548
|
-
derivationFallbackReasons: {},
|
|
1549
|
-
derivationRootBytes: 0
|
|
2501
|
+
attributionDegradations: 0
|
|
1550
2502
|
};
|
|
1551
2503
|
var noOpExecution = {
|
|
1552
2504
|
createScope: () => ({
|
|
1553
2505
|
run: (callback) => callback(),
|
|
1554
2506
|
getErrorState: () => void 0,
|
|
2507
|
+
associateError: () => {
|
|
2508
|
+
},
|
|
1555
2509
|
finish: () => {
|
|
1556
2510
|
}
|
|
1557
2511
|
}),
|
|
1558
|
-
run: (_metadata, callback) => callback(),
|
|
1559
2512
|
getErrorState: () => void 0,
|
|
1560
2513
|
runFunction: (_functionId, _args, callback) => callback(),
|
|
1561
2514
|
runFunctionPlans: (_plans, _planIndex, _args, callback) => callback(),
|
|
1562
2515
|
prepareFunctionPlans: () => [],
|
|
1563
2516
|
runPreparedFunction: (_plan, _args, callback) => callback(),
|
|
2517
|
+
enterPreparedFunction: () => ({
|
|
2518
|
+
leave: (value) => value,
|
|
2519
|
+
fail: () => {
|
|
2520
|
+
},
|
|
2521
|
+
end: () => {
|
|
2522
|
+
},
|
|
2523
|
+
run: (callback) => callback(),
|
|
2524
|
+
suspend: (value) => value,
|
|
2525
|
+
resume: (value) => value
|
|
2526
|
+
}),
|
|
1564
2527
|
trace: (_functionId, fn) => fn,
|
|
1565
|
-
getStats: () => ({ ...emptyStats
|
|
1566
|
-
captureDerivationRoot: (_rootId, value) => value
|
|
2528
|
+
getStats: () => ({ ...emptyStats })
|
|
1567
2529
|
};
|
|
1568
2530
|
var mergeExecutionMetadata = (target, metadata) => {
|
|
1569
2531
|
if (metadata.kind) target.kind = metadata.kind;
|
|
@@ -1588,7 +2550,41 @@ var newSuppression = (group, parentCallId, startedAtNs, endedAtNs) => ({
|
|
|
1588
2550
|
});
|
|
1589
2551
|
var createExecutionRecorder = (options) => {
|
|
1590
2552
|
if (!options?.enabled) return noOpExecution;
|
|
2553
|
+
warnIfMissingAsyncContextFrame();
|
|
1591
2554
|
const storage = new AsyncLocalStorage();
|
|
2555
|
+
const currentStore = () => {
|
|
2556
|
+
try {
|
|
2557
|
+
return storage.getStore();
|
|
2558
|
+
} catch {
|
|
2559
|
+
return void 0;
|
|
2560
|
+
}
|
|
2561
|
+
};
|
|
2562
|
+
const degradeAttribution = (recording, plan) => {
|
|
2563
|
+
if (!recording.attributionDegraded) {
|
|
2564
|
+
recording.attributionDegraded = true;
|
|
2565
|
+
stats.attributionDegradations++;
|
|
2566
|
+
const eventsDropped = Math.max(
|
|
2567
|
+
1,
|
|
2568
|
+
recording.journal?.dropped ?? recording.memory.eventsDropped
|
|
2569
|
+
);
|
|
2570
|
+
recording.cachedState = {
|
|
2571
|
+
events: [],
|
|
2572
|
+
functions: [],
|
|
2573
|
+
truncated: { eventsDropped },
|
|
2574
|
+
capture: {
|
|
2575
|
+
completeness: "unavailable",
|
|
2576
|
+
reason: "attribution_invariant",
|
|
2577
|
+
valuesDropped: recording.memory.valuesDropped,
|
|
2578
|
+
eventsDropped
|
|
2579
|
+
}
|
|
2580
|
+
};
|
|
2581
|
+
}
|
|
2582
|
+
if (plan) plan.disabled = true;
|
|
2583
|
+
};
|
|
2584
|
+
const noteDisabledPlan = (recording) => {
|
|
2585
|
+
if (recording.finished || recording.evicted || recording.attributionDegraded) return;
|
|
2586
|
+
recording.disabledPlanEncountered = true;
|
|
2587
|
+
};
|
|
1592
2588
|
const maxEventsPerExecution = sanitizeJournalCapacity(options.maxEventsPerExecution);
|
|
1593
2589
|
const maxCapturedCallsPerFunction = Math.max(
|
|
1594
2590
|
1,
|
|
@@ -1598,6 +2594,14 @@ var createExecutionRecorder = (options) => {
|
|
|
1598
2594
|
0,
|
|
1599
2595
|
Math.floor(options.maxActiveMemoryBytes ?? DEFAULT_MAX_ACTIVE_MEMORY_BYTES)
|
|
1600
2596
|
);
|
|
2597
|
+
const maxExecutionHoldNs = BigInt(Math.max(1, Math.floor(options.maxExecutionHoldMs ?? DEFAULT_MAX_EXECUTION_HOLD_MS))) * 1000000n;
|
|
2598
|
+
const maxRetainedErrorRecordings = Math.max(
|
|
2599
|
+
1,
|
|
2600
|
+
Math.floor(options.maxRetainedErrorRecordings ?? DEFAULT_MAX_RETAINED_ERROR_RECORDINGS)
|
|
2601
|
+
);
|
|
2602
|
+
const liveRecordings = [];
|
|
2603
|
+
let lastSweepNs = 0n;
|
|
2604
|
+
const sweepIntervalNs = maxExecutionHoldNs / 4n < 50000000n ? maxExecutionHoldNs / 4n : 50000000n;
|
|
1601
2605
|
const memoryBudget = new RecorderMemoryBudget(
|
|
1602
2606
|
maxActiveMemoryBytes,
|
|
1603
2607
|
options.maxSerializedValueBytes ?? 8 * 1024
|
|
@@ -1605,12 +2609,17 @@ var createExecutionRecorder = (options) => {
|
|
|
1605
2609
|
const serializer = createSafeSerializer(options);
|
|
1606
2610
|
const excludesSource = createSourceExclusionMatcher(options.excludeSources);
|
|
1607
2611
|
const journalPool = new ExecutionJournalPool(maxEventsPerExecution);
|
|
2612
|
+
const runtimeStateSizeBudget = {
|
|
2613
|
+
targetBytes: options.runtimeStateTargetBytes,
|
|
2614
|
+
maximumBytes: options.maxRuntimeStateBytes
|
|
2615
|
+
};
|
|
1608
2616
|
const plansByRuntimeId = [];
|
|
1609
2617
|
let executionCounter = 0;
|
|
1610
2618
|
let nextRuntimePlanId = 1;
|
|
1611
2619
|
const internedPlans = /* @__PURE__ */ new Map();
|
|
1612
2620
|
const preparedModules = /* @__PURE__ */ new WeakMap();
|
|
1613
2621
|
const errorExecutions = /* @__PURE__ */ new WeakMap();
|
|
2622
|
+
const retainedErrorRecordings = [];
|
|
1614
2623
|
const phases = phaseTimingEnabled ? { alsNs: 0n, materializeNs: 0n } : void 0;
|
|
1615
2624
|
const stats = {
|
|
1616
2625
|
functionCallsObserved: 0,
|
|
@@ -1629,15 +2638,7 @@ var createExecutionRecorder = (options) => {
|
|
|
1629
2638
|
measuredExecutions: 0,
|
|
1630
2639
|
totalInlineWallTimeMs: 0,
|
|
1631
2640
|
maxInlineWallTimeMs: 0,
|
|
1632
|
-
|
|
1633
|
-
derivationElidedFunctionCalls: 0,
|
|
1634
|
-
derivationRootsCaptured: 0,
|
|
1635
|
-
derivationControlFactsCaptured: 0,
|
|
1636
|
-
derivationValuesAvoided: 0,
|
|
1637
|
-
derivationFallbackFunctions: 0,
|
|
1638
|
-
derivationFallbackExpressions: 0,
|
|
1639
|
-
derivationFallbackReasons: {},
|
|
1640
|
-
derivationRootBytes: 0
|
|
2641
|
+
attributionDegradations: 0
|
|
1641
2642
|
};
|
|
1642
2643
|
const addPhase = (key, nanoseconds) => {
|
|
1643
2644
|
if (phases && nanoseconds > 0n) phases[key] += nanoseconds;
|
|
@@ -1648,14 +2649,36 @@ var createExecutionRecorder = (options) => {
|
|
|
1648
2649
|
stats.totalInlineWallTimeMs = Math.round((stats.totalInlineWallTimeMs + inlineWallTimeMs) * 1e4) / 1e4;
|
|
1649
2650
|
stats.maxInlineWallTimeMs = Math.max(stats.maxInlineWallTimeMs, inlineWallTimeMs);
|
|
1650
2651
|
};
|
|
1651
|
-
const
|
|
1652
|
-
const
|
|
2652
|
+
const freezeAndCount = (value) => {
|
|
2653
|
+
const frozen = serializer.freeze(value);
|
|
1653
2654
|
stats.serializedValues++;
|
|
1654
|
-
stats.serializedValueNodes +=
|
|
1655
|
-
stats.serializedValueBytes +=
|
|
1656
|
-
return
|
|
2655
|
+
stats.serializedValueNodes += frozen.visitedNodes;
|
|
2656
|
+
stats.serializedValueBytes += frozen.estimatedBytes;
|
|
2657
|
+
return {
|
|
2658
|
+
value: frozen.value,
|
|
2659
|
+
bytes: frozen.estimatedBytes,
|
|
2660
|
+
visitedNodes: frozen.visitedNodes
|
|
2661
|
+
};
|
|
2662
|
+
};
|
|
2663
|
+
const captureValue = (recording, value) => {
|
|
2664
|
+
try {
|
|
2665
|
+
return memoryBudget.captureValue(recording.memory, () => freezeAndCount(value));
|
|
2666
|
+
} catch {
|
|
2667
|
+
return { __rasputin_type: "unserializable" };
|
|
2668
|
+
}
|
|
1657
2669
|
};
|
|
1658
|
-
const
|
|
2670
|
+
const encodeEventValues = (events) => events.map((event) => {
|
|
2671
|
+
if (event.type === "function_enter") {
|
|
2672
|
+
return { ...event, args: event.args.map((argument) => serializer.encode(argument)) };
|
|
2673
|
+
}
|
|
2674
|
+
if (event.type === "function_exit") {
|
|
2675
|
+
return { ...event, returnValue: serializer.encode(event.returnValue) };
|
|
2676
|
+
}
|
|
2677
|
+
if (event.type === "function_throw") {
|
|
2678
|
+
return { ...event, error: serializer.encode(event.error) };
|
|
2679
|
+
}
|
|
2680
|
+
return event;
|
|
2681
|
+
});
|
|
1659
2682
|
const storePlan = (plan) => {
|
|
1660
2683
|
plansByRuntimeId[plan.runtimePlanId] = plan;
|
|
1661
2684
|
return plan;
|
|
@@ -1668,7 +2691,8 @@ var createExecutionRecorder = (options) => {
|
|
|
1668
2691
|
definition,
|
|
1669
2692
|
functionId: definition.functionId,
|
|
1670
2693
|
excluded: excludesSource(definition),
|
|
1671
|
-
estimatedCallBytes: estimatedCallBytesFor(definition.functionId)
|
|
2694
|
+
estimatedCallBytes: estimatedCallBytesFor(definition.functionId),
|
|
2695
|
+
omitCallValues: false
|
|
1672
2696
|
});
|
|
1673
2697
|
internedPlans.set(definition.functionId, plan);
|
|
1674
2698
|
return plan;
|
|
@@ -1683,28 +2707,13 @@ var createExecutionRecorder = (options) => {
|
|
|
1683
2707
|
definition,
|
|
1684
2708
|
functionId: definition.functionId,
|
|
1685
2709
|
excluded: excludesSource(definition),
|
|
1686
|
-
estimatedCallBytes: estimatedCallBytesFor(definition.functionId)
|
|
2710
|
+
estimatedCallBytes: estimatedCallBytesFor(definition.functionId),
|
|
2711
|
+
omitCallValues: encodedPlanOmitsCallValues(encoded)
|
|
1687
2712
|
});
|
|
1688
2713
|
});
|
|
1689
2714
|
preparedModules.set(plans, prepared);
|
|
1690
2715
|
return prepared;
|
|
1691
2716
|
};
|
|
1692
|
-
const derivationMetrics = (recording) => {
|
|
1693
|
-
const manifest = snapshotInstrumentationManifest();
|
|
1694
|
-
const plans = manifest?.derivationPlans ?? [];
|
|
1695
|
-
const reasons = { ...stats.derivationFallbackReasons };
|
|
1696
|
-
return {
|
|
1697
|
-
derivationCandidateFunctions: plans.filter((plan) => !plan.fallbackReason).length,
|
|
1698
|
-
derivationElidedFunctionCalls: stats.derivationElidedFunctionCalls,
|
|
1699
|
-
derivationRootsCaptured: recording.derivationRoots.length,
|
|
1700
|
-
derivationControlFactsCaptured: stats.derivationControlFactsCaptured,
|
|
1701
|
-
derivationValuesAvoided: stats.derivationValuesAvoided,
|
|
1702
|
-
derivationFallbackFunctions: plans.filter((plan) => plan.fallbackReason).length,
|
|
1703
|
-
derivationFallbackExpressions: recording.derivationRoots.length,
|
|
1704
|
-
derivationFallbackReasons: reasons,
|
|
1705
|
-
derivationRootBytes: recording.derivationRootBytes
|
|
1706
|
-
};
|
|
1707
|
-
};
|
|
1708
2717
|
const eventsHaveOmittedValues = (events) => {
|
|
1709
2718
|
for (const event of events) {
|
|
1710
2719
|
if (event.type === "function_enter" && event.args.some((arg) => rasputinTagKind(arg) === "omitted")) {
|
|
@@ -1716,37 +2725,46 @@ var createExecutionRecorder = (options) => {
|
|
|
1716
2725
|
}
|
|
1717
2726
|
return false;
|
|
1718
2727
|
};
|
|
1719
|
-
const resolveCaptureProfile = (recording, events, truncated, capture
|
|
2728
|
+
const resolveCaptureProfile = (recording, events, truncated, capture) => {
|
|
1720
2729
|
const source = recording.sawAutomatic ? "automatic" : recording.sawManual ? "manual" : "scope-only";
|
|
1721
2730
|
if (source === "scope-only") {
|
|
1722
2731
|
return {
|
|
1723
2732
|
source,
|
|
1724
2733
|
functionBoundaries: "none",
|
|
1725
2734
|
functionValues: "none",
|
|
1726
|
-
timings: "none"
|
|
1727
|
-
derivation: derivation ? "available" : "none"
|
|
2735
|
+
timings: "none"
|
|
1728
2736
|
};
|
|
1729
2737
|
}
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
}
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
2738
|
+
if (recording.evicted || capture?.completeness === "unavailable") {
|
|
2739
|
+
return {
|
|
2740
|
+
source,
|
|
2741
|
+
functionBoundaries: "none",
|
|
2742
|
+
functionValues: "none",
|
|
2743
|
+
timings: "none"
|
|
2744
|
+
};
|
|
2745
|
+
}
|
|
2746
|
+
if (recording.budgetExpired || capture?.reason === "long_lived_execution_budget") {
|
|
2747
|
+
return {
|
|
2748
|
+
source,
|
|
2749
|
+
functionBoundaries: events.length > 0 ? "partial" : "none",
|
|
2750
|
+
functionValues: events.length > 0 ? "selective" : "none",
|
|
2751
|
+
timings: events.length > 0 ? "partial" : "none"
|
|
2752
|
+
};
|
|
2753
|
+
}
|
|
2754
|
+
if (capture?.reason === "plan_disabled_after_attribution_invariant") {
|
|
2755
|
+
return {
|
|
2756
|
+
source,
|
|
2757
|
+
functionBoundaries: events.length > 0 ? "partial" : "none",
|
|
2758
|
+
functionValues: eventsHaveOmittedValues(events) ? "selective" : events.length > 0 ? "full" : "none",
|
|
2759
|
+
timings: events.length > 0 ? "partial" : "none"
|
|
2760
|
+
};
|
|
1745
2761
|
}
|
|
2762
|
+
const droppedEvents = Boolean(truncated?.eventsDropped || capture?.eventsDropped);
|
|
1746
2763
|
return {
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
2764
|
+
source,
|
|
2765
|
+
functionBoundaries: droppedEvents ? "partial" : "full",
|
|
2766
|
+
functionValues: eventsHaveOmittedValues(events) ? "selective" : "full",
|
|
2767
|
+
timings: droppedEvents ? "partial" : "full"
|
|
1750
2768
|
};
|
|
1751
2769
|
};
|
|
1752
2770
|
const stateFrom = (recording, endedAtNs = process.hrtime.bigint()) => {
|
|
@@ -1755,40 +2773,58 @@ var createExecutionRecorder = (options) => {
|
|
|
1755
2773
|
let functions = [];
|
|
1756
2774
|
let truncated;
|
|
1757
2775
|
let capture;
|
|
1758
|
-
let derivation;
|
|
1759
2776
|
if (recording.cachedState) {
|
|
1760
2777
|
events = recording.cachedState.events;
|
|
1761
2778
|
functions = recording.cachedState.functions;
|
|
1762
2779
|
truncated = recording.cachedState.truncated;
|
|
1763
2780
|
capture = recording.cachedState.capture;
|
|
1764
|
-
derivation = recording.cachedState.derivation;
|
|
1765
2781
|
} else {
|
|
1766
2782
|
if (recording.journal) {
|
|
1767
2783
|
const materialized = recording.journal.materialize(plansByRuntimeId, recording.startedAtNs);
|
|
1768
|
-
events = materialized.events;
|
|
2784
|
+
events = encodeEventValues(materialized.events);
|
|
2785
|
+
if (recording.lateCapturedCallIds && recording.lateCapturedCallIds.size > 0) {
|
|
2786
|
+
events = events.map(
|
|
2787
|
+
(event) => event.type === "function_enter" && recording.lateCapturedCallIds?.has(event.callId) ? { ...event, capturedAt: "throw" } : event
|
|
2788
|
+
);
|
|
2789
|
+
}
|
|
1769
2790
|
functions = materialized.functions;
|
|
1770
2791
|
truncated = recording.journal.dropped > 0 ? { eventsDropped: recording.journal.dropped } : void 0;
|
|
1771
2792
|
}
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
2793
|
+
if (recording.budgetExpired) {
|
|
2794
|
+
capture = {
|
|
2795
|
+
completeness: "partial",
|
|
2796
|
+
reason: "long_lived_execution_budget",
|
|
2797
|
+
valuesDropped: recording.memory.valuesDropped,
|
|
2798
|
+
eventsDropped: recording.memory.eventsDropped
|
|
2799
|
+
};
|
|
2800
|
+
} else if (recording.disabledPlanEncountered) {
|
|
2801
|
+
capture = {
|
|
2802
|
+
completeness: "partial",
|
|
2803
|
+
reason: "plan_disabled_after_attribution_invariant",
|
|
2804
|
+
valuesDropped: recording.memory.valuesDropped,
|
|
2805
|
+
eventsDropped: recording.memory.eventsDropped
|
|
2806
|
+
};
|
|
2807
|
+
} else if (recording.memory.underPressure) {
|
|
2808
|
+
capture = {
|
|
2809
|
+
completeness: "partial",
|
|
2810
|
+
reason: "process_memory_budget",
|
|
2811
|
+
valuesDropped: recording.memory.valuesDropped,
|
|
2812
|
+
eventsDropped: recording.memory.eventsDropped
|
|
2813
|
+
};
|
|
2814
|
+
}
|
|
1779
2815
|
if (recording.finished && recording.inFlightCalls === 0 && recording.journal) {
|
|
1780
|
-
recording.cachedState = { events, functions, truncated, capture
|
|
2816
|
+
recording.cachedState = { events, functions, truncated, capture };
|
|
1781
2817
|
journalPool.release(recording.journal);
|
|
1782
2818
|
recording.journal = void 0;
|
|
1783
2819
|
}
|
|
1784
2820
|
}
|
|
1785
2821
|
const state = {
|
|
1786
2822
|
version: 4,
|
|
1787
|
-
captureProfile: resolveCaptureProfile(recording, events, truncated, capture
|
|
2823
|
+
captureProfile: resolveCaptureProfile(recording, events, truncated, capture),
|
|
1788
2824
|
executionId: recording.executionId,
|
|
1789
2825
|
startedAt: recording.startedAt,
|
|
1790
2826
|
durationMs: elapsedMs2(recording.startedAtNs, endedAtNs),
|
|
1791
|
-
recorder: { inlineWallTimeMs: 0
|
|
2827
|
+
recorder: { inlineWallTimeMs: 0 },
|
|
1792
2828
|
execution: {
|
|
1793
2829
|
...recording.execution,
|
|
1794
2830
|
...recording.execution.request ? { request: { ...recording.execution.request } } : {}
|
|
@@ -1796,29 +2832,153 @@ var createExecutionRecorder = (options) => {
|
|
|
1796
2832
|
functions: functions.slice(),
|
|
1797
2833
|
events: events.slice(),
|
|
1798
2834
|
...truncated ? { truncated: { ...truncated } } : {},
|
|
1799
|
-
...capture ? { capture: { ...capture } } : {}
|
|
1800
|
-
...derivation ? { derivation: { ...derivation, roots: derivation.roots.slice() } } : {}
|
|
2835
|
+
...capture ? { capture: { ...capture } } : {}
|
|
1801
2836
|
};
|
|
1802
2837
|
if (phaseTimingEnabled)
|
|
1803
2838
|
addPhase("materializeNs", process.hrtime.bigint() - recorderStartedAtNs);
|
|
1804
|
-
|
|
2839
|
+
const sizeBudgetStartedAtNs = process.hrtime.bigint();
|
|
2840
|
+
addRecorderTime(recording, sizeBudgetStartedAtNs - recorderStartedAtNs);
|
|
1805
2841
|
state.recorder = {
|
|
1806
|
-
inlineWallTimeMs: roundedMilliseconds2(recording.inlineRecorderTimeNs)
|
|
1807
|
-
|
|
2842
|
+
inlineWallTimeMs: roundedMilliseconds2(recording.inlineRecorderTimeNs)
|
|
2843
|
+
};
|
|
2844
|
+
const boundedState = enforceRuntimeStateSizeBudget(state, runtimeStateSizeBudget);
|
|
2845
|
+
addRecorderTime(recording, process.hrtime.bigint() - sizeBudgetStartedAtNs);
|
|
2846
|
+
boundedState.recorder = {
|
|
2847
|
+
inlineWallTimeMs: roundedMilliseconds2(recording.inlineRecorderTimeNs)
|
|
2848
|
+
};
|
|
2849
|
+
return boundedState.truncated?.size ? enforceRuntimeStateSizeBudget(boundedState, runtimeStateSizeBudget) : boundedState;
|
|
2850
|
+
};
|
|
2851
|
+
const evictRetainedRecording = (recording) => {
|
|
2852
|
+
const eventCount = recording.cachedState?.events.length ?? recording.journal?.eventCount ?? 0;
|
|
2853
|
+
const dropped = (recording.cachedState?.truncated?.eventsDropped ?? recording.journal?.dropped ?? 0) + eventCount;
|
|
2854
|
+
try {
|
|
2855
|
+
memoryBudget.release(recording.memory);
|
|
2856
|
+
} catch {
|
|
2857
|
+
}
|
|
2858
|
+
if (recording.journal) {
|
|
2859
|
+
journalPool.release(recording.journal);
|
|
2860
|
+
recording.journal = void 0;
|
|
2861
|
+
}
|
|
2862
|
+
recording.evicted = true;
|
|
2863
|
+
detachLiveRecording(recording);
|
|
2864
|
+
recording.cachedState = {
|
|
2865
|
+
events: [],
|
|
2866
|
+
functions: [],
|
|
2867
|
+
truncated: { eventsDropped: Math.max(1, dropped) },
|
|
2868
|
+
capture: {
|
|
2869
|
+
completeness: "unavailable",
|
|
2870
|
+
reason: "retained_state_evicted",
|
|
2871
|
+
valuesDropped: 0,
|
|
2872
|
+
eventsDropped: Math.max(1, dropped)
|
|
2873
|
+
}
|
|
2874
|
+
};
|
|
2875
|
+
};
|
|
2876
|
+
const trimFinishedRetainedRecordings = (keep) => {
|
|
2877
|
+
while (retainedErrorRecordings.length > maxRetainedErrorRecordings) {
|
|
2878
|
+
const evictIndex = retainedErrorRecordings.findIndex(
|
|
2879
|
+
(candidate) => candidate !== keep && candidate.finished
|
|
2880
|
+
);
|
|
2881
|
+
if (evictIndex < 0) break;
|
|
2882
|
+
const [evicted] = retainedErrorRecordings.splice(evictIndex, 1);
|
|
2883
|
+
if (evicted) evictRetainedRecording(evicted);
|
|
2884
|
+
}
|
|
2885
|
+
};
|
|
2886
|
+
const retainErrorRecording = (recording) => {
|
|
2887
|
+
if (recording.retainedForError) return;
|
|
2888
|
+
recording.retainedForError = true;
|
|
2889
|
+
retainedErrorRecordings.push(recording);
|
|
2890
|
+
trimFinishedRetainedRecordings(recording);
|
|
2891
|
+
};
|
|
2892
|
+
const detachLiveRecording = (recording) => {
|
|
2893
|
+
const index = liveRecordings.indexOf(recording);
|
|
2894
|
+
if (index >= 0) liveRecordings.splice(index, 1);
|
|
2895
|
+
};
|
|
2896
|
+
const expireLongLivedRecording = (recording, nowNs) => {
|
|
2897
|
+
if (recording.evicted || recording.budgetExpired) return;
|
|
2898
|
+
recording.budgetExpired = true;
|
|
2899
|
+
recording.memory.underPressure = true;
|
|
2900
|
+
const journalEvents = recording.journal?.eventCount ?? 0;
|
|
2901
|
+
const cachedEvents = recording.cachedState?.events.length ?? 0;
|
|
2902
|
+
const eventsDropped = Math.max(
|
|
2903
|
+
1,
|
|
2904
|
+
recording.memory.eventsDropped + journalEvents + cachedEvents
|
|
2905
|
+
);
|
|
2906
|
+
try {
|
|
2907
|
+
memoryBudget.release(recording.memory);
|
|
2908
|
+
} catch {
|
|
2909
|
+
}
|
|
2910
|
+
if (recording.journal) {
|
|
2911
|
+
journalPool.release(recording.journal);
|
|
2912
|
+
recording.journal = void 0;
|
|
2913
|
+
}
|
|
2914
|
+
recording.cachedState = {
|
|
2915
|
+
events: [],
|
|
2916
|
+
functions: [],
|
|
2917
|
+
truncated: { eventsDropped },
|
|
2918
|
+
capture: {
|
|
2919
|
+
completeness: "partial",
|
|
2920
|
+
reason: "long_lived_execution_budget",
|
|
2921
|
+
valuesDropped: recording.memory.valuesDropped,
|
|
2922
|
+
eventsDropped
|
|
2923
|
+
}
|
|
1808
2924
|
};
|
|
1809
|
-
|
|
2925
|
+
if (!recording.finished) {
|
|
2926
|
+
recording.finished = true;
|
|
2927
|
+
stats.activeExecutions = Math.max(0, stats.activeExecutions - 1);
|
|
2928
|
+
recording.finishedAtNs = nowNs;
|
|
2929
|
+
if (!recording.hasError) {
|
|
2930
|
+
stats.successfulExecutionsDiscarded++;
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
detachLiveRecording(recording);
|
|
2934
|
+
};
|
|
2935
|
+
const sweepLongLivedExecutions = (nowNs) => {
|
|
2936
|
+
if (nowNs - lastSweepNs < sweepIntervalNs && liveRecordings.length < 256) return;
|
|
2937
|
+
lastSweepNs = nowNs;
|
|
2938
|
+
for (let index = liveRecordings.length - 1; index >= 0; index--) {
|
|
2939
|
+
const recording = liveRecordings[index];
|
|
2940
|
+
if (!recording) continue;
|
|
2941
|
+
if (recording.evicted || recording.memory.released || recording.budgetExpired) {
|
|
2942
|
+
liveRecordings.splice(index, 1);
|
|
2943
|
+
continue;
|
|
2944
|
+
}
|
|
2945
|
+
if (nowNs - recording.startedAtNs < maxExecutionHoldNs) continue;
|
|
2946
|
+
try {
|
|
2947
|
+
expireLongLivedRecording(recording, nowNs);
|
|
2948
|
+
} catch {
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
1810
2951
|
};
|
|
1811
2952
|
const rememberError = (error, recording) => {
|
|
1812
2953
|
recording.hasError = true;
|
|
1813
|
-
|
|
1814
|
-
if (!errorExecutions.has(
|
|
2954
|
+
const key = (typeof error === "object" || typeof error === "function") && error !== null ? error : void 0;
|
|
2955
|
+
if (recording.budgetExpired && !(key && errorExecutions.has(key))) {
|
|
2956
|
+
const eventsDropped = Math.max(
|
|
2957
|
+
1,
|
|
2958
|
+
recording.cachedState?.capture?.eventsDropped ?? recording.cachedState?.truncated?.eventsDropped ?? recording.memory.eventsDropped
|
|
2959
|
+
);
|
|
2960
|
+
recording.cachedState = {
|
|
2961
|
+
events: [],
|
|
2962
|
+
functions: [],
|
|
2963
|
+
truncated: { eventsDropped },
|
|
2964
|
+
capture: {
|
|
2965
|
+
completeness: "unavailable",
|
|
2966
|
+
reason: "long_lived_execution_budget",
|
|
2967
|
+
valuesDropped: recording.memory.valuesDropped,
|
|
2968
|
+
eventsDropped
|
|
2969
|
+
}
|
|
2970
|
+
};
|
|
2971
|
+
}
|
|
2972
|
+
retainErrorRecording(recording);
|
|
2973
|
+
if (!key) return;
|
|
2974
|
+
if (!errorExecutions.has(key)) {
|
|
1815
2975
|
stats.errorSnapshots++;
|
|
1816
2976
|
if (recording.memory.underPressure && !recording.partialSnapshotCounted) {
|
|
1817
2977
|
recording.partialSnapshotCounted = true;
|
|
1818
2978
|
stats.partialErrorSnapshots++;
|
|
1819
2979
|
}
|
|
1820
2980
|
}
|
|
1821
|
-
errorExecutions.set(
|
|
2981
|
+
errorExecutions.set(key, recording);
|
|
1822
2982
|
};
|
|
1823
2983
|
const countDroppedEvents = (recording, droppedBefore) => {
|
|
1824
2984
|
const dropped = recording.journal?.dropped ?? droppedBefore;
|
|
@@ -1868,13 +3028,19 @@ var createExecutionRecorder = (options) => {
|
|
|
1868
3028
|
return {
|
|
1869
3029
|
// Keep the bounded thrown value even after surrounding capture degrades. A partial
|
|
1870
3030
|
// snapshot without the exception itself would not be useful for investigation.
|
|
1871
|
-
value:
|
|
3031
|
+
value: (() => {
|
|
3032
|
+
try {
|
|
3033
|
+
return freezeAndCount(error).value;
|
|
3034
|
+
} catch {
|
|
3035
|
+
return { __rasputin_type: "unserializable" };
|
|
3036
|
+
}
|
|
3037
|
+
})(),
|
|
1872
3038
|
commit: () => {
|
|
1873
3039
|
if (key) recording.capturedErrors.set(key, callId);
|
|
1874
3040
|
}
|
|
1875
3041
|
};
|
|
1876
3042
|
};
|
|
1877
|
-
const captureCompletedThrow = (recording, plan, args, parentCallId, startedAtNs, error) => {
|
|
3043
|
+
const captureCompletedThrow = (recording, plan, args, parentCallId, startedAtNs, error, capturedArgs) => {
|
|
1878
3044
|
if (!recording.journal) {
|
|
1879
3045
|
rememberError(error, recording);
|
|
1880
3046
|
return;
|
|
@@ -1885,7 +3051,7 @@ var createExecutionRecorder = (options) => {
|
|
|
1885
3051
|
}
|
|
1886
3052
|
const callId = ++recording.nextCallId;
|
|
1887
3053
|
const capturedError = serializedError(recording, error, callId);
|
|
1888
|
-
const
|
|
3054
|
+
const recordedArgs = capturedArgs ?? mapArrayLike(args, (argument) => captureValue(recording, argument));
|
|
1889
3055
|
const endedAtNs = process.hrtime.bigint();
|
|
1890
3056
|
const droppedBefore = recording.journal.dropped;
|
|
1891
3057
|
const retained = recording.journal.forceCompletedCall(
|
|
@@ -1893,13 +3059,15 @@ var createExecutionRecorder = (options) => {
|
|
|
1893
3059
|
callId,
|
|
1894
3060
|
parentCallId,
|
|
1895
3061
|
startedAtNs - recording.startedAtNs,
|
|
1896
|
-
|
|
3062
|
+
recordedArgs,
|
|
1897
3063
|
KIND_THROW,
|
|
1898
3064
|
endedAtNs - recording.startedAtNs,
|
|
1899
3065
|
endedAtNs - startedAtNs,
|
|
1900
3066
|
capturedError.value
|
|
1901
3067
|
);
|
|
1902
3068
|
if (retained) {
|
|
3069
|
+
recording.lateCapturedCallIds ??= /* @__PURE__ */ new Set();
|
|
3070
|
+
recording.lateCapturedCallIds.add(callId);
|
|
1903
3071
|
stats.functionCallsCaptured++;
|
|
1904
3072
|
capturedError.commit();
|
|
1905
3073
|
}
|
|
@@ -1944,35 +3112,47 @@ var createExecutionRecorder = (options) => {
|
|
|
1944
3112
|
};
|
|
1945
3113
|
const settleInFlight = (recording) => {
|
|
1946
3114
|
if (recording.inFlightCalls > 0) recording.inFlightCalls--;
|
|
1947
|
-
|
|
3115
|
+
releaseWhenIdle(recording);
|
|
1948
3116
|
};
|
|
1949
|
-
const
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
recording.finished = true;
|
|
1954
|
-
if (metadata) mergeExecutionMetadata(recording.execution, metadata);
|
|
1955
|
-
memoryBudget.release(recording.memory);
|
|
1956
|
-
stats.activeExecutions = Math.max(0, stats.activeExecutions - 1);
|
|
1957
|
-
if (!recording.hasError) {
|
|
1958
|
-
stats.successfulExecutionsDiscarded++;
|
|
3117
|
+
const releaseWhenIdle = (recording) => {
|
|
3118
|
+
try {
|
|
3119
|
+
if (!recording.finished || recording.inFlightCalls > 0) return;
|
|
3120
|
+
memoryBudget.release(recording.memory);
|
|
1959
3121
|
releaseJournalIfIdle(recording);
|
|
3122
|
+
} catch {
|
|
1960
3123
|
}
|
|
1961
|
-
recording.finishedAtNs = process.hrtime.bigint();
|
|
1962
|
-
addRecorderTime(recording, recording.finishedAtNs - recorderStartedAtNs);
|
|
1963
|
-
recordInlineTiming(recording);
|
|
1964
3124
|
};
|
|
1965
|
-
const
|
|
3125
|
+
const finish = (store, metadata) => {
|
|
3126
|
+
try {
|
|
3127
|
+
const { recording } = store;
|
|
3128
|
+
if (recording.finished) return;
|
|
3129
|
+
const recorderStartedAtNs = process.hrtime.bigint();
|
|
3130
|
+
recording.finished = true;
|
|
3131
|
+
if (metadata) mergeExecutionMetadata(recording.execution, metadata);
|
|
3132
|
+
stats.activeExecutions = Math.max(0, stats.activeExecutions - 1);
|
|
3133
|
+
if (!recording.hasError) {
|
|
3134
|
+
stats.successfulExecutionsDiscarded++;
|
|
3135
|
+
}
|
|
3136
|
+
recording.finishedAtNs = process.hrtime.bigint();
|
|
3137
|
+
addRecorderTime(recording, recording.finishedAtNs - recorderStartedAtNs);
|
|
3138
|
+
recordInlineTiming(recording);
|
|
3139
|
+
releaseWhenIdle(recording);
|
|
3140
|
+
if (recording.inFlightCalls === 0) detachLiveRecording(recording);
|
|
3141
|
+
} catch {
|
|
3142
|
+
}
|
|
3143
|
+
};
|
|
3144
|
+
const runStore = function __rasputinHandleRun__3(store, callback) {
|
|
1966
3145
|
if (!phaseTimingEnabled) return storage.run(store, callback);
|
|
1967
3146
|
const alsStartedAtNs = process.hrtime.bigint();
|
|
1968
|
-
return storage.run(store, ()
|
|
3147
|
+
return storage.run(store, function __rasputinHandleRun__4() {
|
|
1969
3148
|
addPhase("alsNs", process.hrtime.bigint() - alsStartedAtNs);
|
|
1970
3149
|
return callback();
|
|
1971
3150
|
});
|
|
1972
3151
|
};
|
|
1973
3152
|
const createScope = (metadata) => {
|
|
1974
|
-
const recorderStartedAtNs = process.hrtime.bigint();
|
|
1975
3153
|
try {
|
|
3154
|
+
const recorderStartedAtNs = process.hrtime.bigint();
|
|
3155
|
+
sweepLongLivedExecutions(recorderStartedAtNs);
|
|
1976
3156
|
const recording = {
|
|
1977
3157
|
executionId: `${Date.now()}-${process.pid}-${++executionCounter}`,
|
|
1978
3158
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -1991,30 +3171,52 @@ var createExecutionRecorder = (options) => {
|
|
|
1991
3171
|
hasError: false,
|
|
1992
3172
|
memory: memoryBudget.startExecution(),
|
|
1993
3173
|
partialSnapshotCounted: false,
|
|
1994
|
-
derivationRoots: [],
|
|
1995
|
-
derivationRootBytes: 0,
|
|
1996
3174
|
sawAutomatic: false,
|
|
1997
|
-
sawManual: false
|
|
1998
|
-
executedFunctionIds: /* @__PURE__ */ new Set()
|
|
3175
|
+
sawManual: false
|
|
1999
3176
|
};
|
|
2000
3177
|
stats.activeExecutions++;
|
|
2001
3178
|
stats.peakActiveExecutions = Math.max(stats.peakActiveExecutions, stats.activeExecutions);
|
|
3179
|
+
liveRecordings.push(recording);
|
|
2002
3180
|
addRecorderTime(recording, process.hrtime.bigint() - recorderStartedAtNs);
|
|
2003
3181
|
const store = { recording };
|
|
2004
3182
|
return {
|
|
2005
|
-
run: (callback)
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
3183
|
+
run: function __rasputinHandleRun__3(callback) {
|
|
3184
|
+
let startedCallback = false;
|
|
3185
|
+
try {
|
|
3186
|
+
const runStartedAtNs = process.hrtime.bigint();
|
|
3187
|
+
return runStore(store, function __rasputinHandleRun__4() {
|
|
3188
|
+
startedCallback = true;
|
|
3189
|
+
addRecorderTime(recording, process.hrtime.bigint() - runStartedAtNs);
|
|
3190
|
+
try {
|
|
3191
|
+
return callback();
|
|
3192
|
+
} catch (error) {
|
|
3193
|
+
if (recording.budgetExpired || recording.evicted) {
|
|
3194
|
+
rememberError(error, recording);
|
|
3195
|
+
}
|
|
3196
|
+
throw error;
|
|
3197
|
+
}
|
|
3198
|
+
});
|
|
3199
|
+
} catch (error) {
|
|
3200
|
+
if (startedCallback) throw error;
|
|
2009
3201
|
return callback();
|
|
2010
|
-
}
|
|
3202
|
+
}
|
|
2011
3203
|
},
|
|
2012
3204
|
getErrorState: (error, errorMetadata) => {
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
3205
|
+
try {
|
|
3206
|
+
const getStateStartedAtNs = process.hrtime.bigint();
|
|
3207
|
+
if (errorMetadata) mergeExecutionMetadata(recording.execution, errorMetadata);
|
|
3208
|
+
rememberError(error, recording);
|
|
3209
|
+
addRecorderTime(recording, process.hrtime.bigint() - getStateStartedAtNs);
|
|
3210
|
+
return stateFrom(recording, recording.finishedAtNs);
|
|
3211
|
+
} catch {
|
|
3212
|
+
return void 0;
|
|
3213
|
+
}
|
|
3214
|
+
},
|
|
3215
|
+
associateError: (error) => {
|
|
3216
|
+
try {
|
|
3217
|
+
rememberError(error, recording);
|
|
3218
|
+
} catch {
|
|
3219
|
+
}
|
|
2018
3220
|
},
|
|
2019
3221
|
finish: (finishMetadata) => finish(store, finishMetadata)
|
|
2020
3222
|
};
|
|
@@ -2022,32 +3224,11 @@ var createExecutionRecorder = (options) => {
|
|
|
2022
3224
|
return noOpExecution.createScope(metadata);
|
|
2023
3225
|
}
|
|
2024
3226
|
};
|
|
2025
|
-
const run = (metadata, callback) => {
|
|
2026
|
-
const scope = createScope(metadata);
|
|
2027
|
-
return scope.run(
|
|
2028
|
-
() => observeCallback(
|
|
2029
|
-
callback,
|
|
2030
|
-
() => scope.finish(),
|
|
2031
|
-
(error) => {
|
|
2032
|
-
try {
|
|
2033
|
-
const store = storage.getStore();
|
|
2034
|
-
if (store) {
|
|
2035
|
-
const recorderStartedAtNs = process.hrtime.bigint();
|
|
2036
|
-
rememberError(error, store.recording);
|
|
2037
|
-
addRecorderTime(store.recording, process.hrtime.bigint() - recorderStartedAtNs);
|
|
2038
|
-
}
|
|
2039
|
-
} finally {
|
|
2040
|
-
scope.finish();
|
|
2041
|
-
}
|
|
2042
|
-
}
|
|
2043
|
-
)
|
|
2044
|
-
);
|
|
2045
|
-
};
|
|
2046
3227
|
const getErrorState = (error, metadata) => {
|
|
2047
3228
|
const getStateStartedAtNs = process.hrtime.bigint();
|
|
2048
3229
|
try {
|
|
2049
3230
|
const weakKey = (typeof error === "object" || typeof error === "function") && error !== null ? error : void 0;
|
|
2050
|
-
const recording = (weakKey ? errorExecutions.get(weakKey) : void 0) ??
|
|
3231
|
+
const recording = (weakKey ? errorExecutions.get(weakKey) : void 0) ?? currentStore()?.recording;
|
|
2051
3232
|
if (!recording) return void 0;
|
|
2052
3233
|
if (metadata) mergeExecutionMetadata(recording.execution, metadata);
|
|
2053
3234
|
rememberError(error, recording);
|
|
@@ -2057,14 +3238,46 @@ var createExecutionRecorder = (options) => {
|
|
|
2057
3238
|
return void 0;
|
|
2058
3239
|
}
|
|
2059
3240
|
};
|
|
2060
|
-
const
|
|
2061
|
-
|
|
2062
|
-
|
|
3241
|
+
const runPreparedFunctionFromStore = function __rasputinHandleRun__3(store, plan, args, callback, omitValues) {
|
|
3242
|
+
let startedCallback = false;
|
|
3243
|
+
try {
|
|
3244
|
+
return runPreparedFunctionFromStoreInner(
|
|
3245
|
+
store,
|
|
3246
|
+
plan,
|
|
3247
|
+
args,
|
|
3248
|
+
function __rasputinHandleRun__4() {
|
|
3249
|
+
startedCallback = true;
|
|
3250
|
+
return callback();
|
|
3251
|
+
},
|
|
3252
|
+
omitValues
|
|
3253
|
+
);
|
|
3254
|
+
} catch (error) {
|
|
3255
|
+
if (startedCallback) throw error;
|
|
3256
|
+
return callback();
|
|
3257
|
+
}
|
|
3258
|
+
};
|
|
3259
|
+
const runPreparedFunctionFromStoreInner = function __rasputinHandleRun__3(store, plan, args, callback, omitValues) {
|
|
3260
|
+
const omitCallValues = omitValues === true || plan.omitCallValues;
|
|
3261
|
+
if (!store) return callback();
|
|
3262
|
+
if (plan.disabled) {
|
|
3263
|
+
noteDisabledPlan(store.recording);
|
|
3264
|
+
return callback();
|
|
3265
|
+
}
|
|
3266
|
+
if (store.recording.finished) {
|
|
3267
|
+
try {
|
|
3268
|
+
return callback();
|
|
3269
|
+
} catch (error) {
|
|
3270
|
+
if (store.recording.budgetExpired || store.recording.evicted) {
|
|
3271
|
+
rememberError(error, store.recording);
|
|
3272
|
+
}
|
|
3273
|
+
throw error;
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
2063
3276
|
stats.functionCallsObserved++;
|
|
2064
3277
|
const recorderStartedAtNs = process.hrtime.bigint();
|
|
2065
3278
|
if (store.suppressCapture || plan.excluded) {
|
|
2066
3279
|
stats.functionCallsExcluded++;
|
|
2067
|
-
return runStore({ ...store, suppressCapture: true }, ()
|
|
3280
|
+
return runStore({ ...store, suppressCapture: true }, function __rasputinHandleRun__4() {
|
|
2068
3281
|
addRecorderTime(store.recording, process.hrtime.bigint() - recorderStartedAtNs);
|
|
2069
3282
|
return callback();
|
|
2070
3283
|
});
|
|
@@ -2075,41 +3288,21 @@ var createExecutionRecorder = (options) => {
|
|
|
2075
3288
|
const group = repeatedCallGroup(recording, plan, parentCallId);
|
|
2076
3289
|
group.observedCalls++;
|
|
2077
3290
|
const journal = acquireJournal(recording);
|
|
2078
|
-
|
|
3291
|
+
try {
|
|
3292
|
+
if (group.observedCalls === 1) journal?.notePlan(plan.runtimePlanId);
|
|
3293
|
+
} catch {
|
|
3294
|
+
}
|
|
2079
3295
|
if (group.observedCalls > maxCapturedCallsPerFunction) {
|
|
2080
3296
|
const startedAtNs2 = process.hrtime.bigint();
|
|
2081
3297
|
try {
|
|
2082
|
-
const result =
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
(value) => {
|
|
2087
|
-
const callbackEndedAtNs2 = process.hrtime.bigint();
|
|
2088
|
-
recordSuppressedCall(recording, group, parentCallId, startedAtNs2, callbackEndedAtNs2);
|
|
2089
|
-
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs2);
|
|
2090
|
-
settleInFlight(recording);
|
|
2091
|
-
return value;
|
|
2092
|
-
},
|
|
2093
|
-
(error) => {
|
|
2094
|
-
const callbackEndedAtNs2 = process.hrtime.bigint();
|
|
2095
|
-
captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs2, error);
|
|
2096
|
-
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs2);
|
|
2097
|
-
settleInFlight(recording);
|
|
2098
|
-
throw error;
|
|
2099
|
-
}
|
|
2100
|
-
);
|
|
2101
|
-
}
|
|
2102
|
-
const callbackEndedAtNs = process.hrtime.bigint();
|
|
2103
|
-
recordSuppressedCall(recording, group, parentCallId, startedAtNs2, callbackEndedAtNs);
|
|
2104
|
-
addRecorderTime(recording, startedAtNs2 - recorderStartedAtNs);
|
|
2105
|
-
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs);
|
|
3298
|
+
const result = runStore(store, function __rasputinHandleRun__4() {
|
|
3299
|
+
return callback();
|
|
3300
|
+
});
|
|
3301
|
+
recordSuppressedCall(recording, group, parentCallId, startedAtNs2, process.hrtime.bigint());
|
|
2106
3302
|
settleInFlight(recording);
|
|
2107
3303
|
return result;
|
|
2108
3304
|
} catch (error) {
|
|
2109
|
-
const callbackEndedAtNs = process.hrtime.bigint();
|
|
2110
3305
|
captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs2, error);
|
|
2111
|
-
addRecorderTime(recording, startedAtNs2 - recorderStartedAtNs);
|
|
2112
|
-
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs);
|
|
2113
3306
|
settleInFlight(recording);
|
|
2114
3307
|
throw error;
|
|
2115
3308
|
}
|
|
@@ -2117,9 +3310,8 @@ var createExecutionRecorder = (options) => {
|
|
|
2117
3310
|
const startedAtNs = process.hrtime.bigint();
|
|
2118
3311
|
if (!journal) {
|
|
2119
3312
|
memoryBudget.reserveCall(recording.memory, plan.estimatedCallBytes);
|
|
2120
|
-
return runStore(
|
|
2121
|
-
|
|
2122
|
-
() => observeRecordedCallback(
|
|
3313
|
+
return runStore(store, function __rasputinHandleRun__4() {
|
|
3314
|
+
return observeRecordedCallback(
|
|
2123
3315
|
recording,
|
|
2124
3316
|
recorderStartedAtNs,
|
|
2125
3317
|
callback,
|
|
@@ -2128,8 +3320,8 @@ var createExecutionRecorder = (options) => {
|
|
|
2128
3320
|
rememberError(error, recording);
|
|
2129
3321
|
settleInFlight(recording);
|
|
2130
3322
|
}
|
|
2131
|
-
)
|
|
2132
|
-
);
|
|
3323
|
+
);
|
|
3324
|
+
});
|
|
2133
3325
|
}
|
|
2134
3326
|
if (!journal.canStartCall()) {
|
|
2135
3327
|
const captureSuccess = () => {
|
|
@@ -2138,9 +3330,8 @@ var createExecutionRecorder = (options) => {
|
|
|
2138
3330
|
countDroppedEvents(recording, droppedBefore);
|
|
2139
3331
|
settleInFlight(recording);
|
|
2140
3332
|
};
|
|
2141
|
-
return runStore(
|
|
2142
|
-
|
|
2143
|
-
() => observeRecordedCallback(
|
|
3333
|
+
return runStore(store, function __rasputinHandleRun__4() {
|
|
3334
|
+
return observeRecordedCallback(
|
|
2144
3335
|
recording,
|
|
2145
3336
|
recorderStartedAtNs,
|
|
2146
3337
|
callback,
|
|
@@ -2149,8 +3340,8 @@ var createExecutionRecorder = (options) => {
|
|
|
2149
3340
|
captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs, error);
|
|
2150
3341
|
settleInFlight(recording);
|
|
2151
3342
|
}
|
|
2152
|
-
)
|
|
2153
|
-
);
|
|
3343
|
+
);
|
|
3344
|
+
});
|
|
2154
3345
|
}
|
|
2155
3346
|
if (!memoryBudget.reserveCall(recording.memory, plan.estimatedCallBytes)) {
|
|
2156
3347
|
return observeRecordedCallback(
|
|
@@ -2166,12 +3357,27 @@ var createExecutionRecorder = (options) => {
|
|
|
2166
3357
|
}
|
|
2167
3358
|
const callId = ++recording.nextCallId;
|
|
2168
3359
|
const enterTimestampNs = process.hrtime.bigint() - recording.startedAtNs;
|
|
2169
|
-
const capturedArgs =
|
|
2170
|
-
|
|
3360
|
+
const capturedArgs = omitCallValues ? mapArrayLike(args, () => rasputinOmitted()) : mapArrayLike(args, (argument) => captureValue(recording, argument));
|
|
3361
|
+
try {
|
|
3362
|
+
journal.startCall(plan.runtimePlanId, callId, parentCallId, enterTimestampNs, capturedArgs);
|
|
3363
|
+
} catch {
|
|
3364
|
+
journal.dropCall();
|
|
3365
|
+
return runStore(store, function __rasputinHandleRun__4() {
|
|
3366
|
+
return observeRecordedCallback(
|
|
3367
|
+
recording,
|
|
3368
|
+
recorderStartedAtNs,
|
|
3369
|
+
callback,
|
|
3370
|
+
() => settleInFlight(recording),
|
|
3371
|
+
(error) => {
|
|
3372
|
+
rememberError(error, recording);
|
|
3373
|
+
settleInFlight(recording);
|
|
3374
|
+
}
|
|
3375
|
+
);
|
|
3376
|
+
});
|
|
3377
|
+
}
|
|
2171
3378
|
const callStore = { recording, currentCallId: callId };
|
|
2172
|
-
return runStore(
|
|
2173
|
-
|
|
2174
|
-
() => observeRecordedCallback(
|
|
3379
|
+
return runStore(callStore, function __rasputinHandleRun__4() {
|
|
3380
|
+
return observeRecordedCallback(
|
|
2175
3381
|
recording,
|
|
2176
3382
|
recorderStartedAtNs,
|
|
2177
3383
|
callback,
|
|
@@ -2179,7 +3385,7 @@ var createExecutionRecorder = (options) => {
|
|
|
2179
3385
|
if (recording.journal) {
|
|
2180
3386
|
const timestampNs = process.hrtime.bigint() - recording.startedAtNs;
|
|
2181
3387
|
const durationNs = process.hrtime.bigint() - startedAtNs;
|
|
2182
|
-
const returnValue =
|
|
3388
|
+
const returnValue = omitCallValues ? rasputinOmitted() : captureValue(recording, value);
|
|
2183
3389
|
recording.journal.finishCall(KIND_EXIT, callId, timestampNs, durationNs, returnValue);
|
|
2184
3390
|
stats.functionCallsCaptured++;
|
|
2185
3391
|
}
|
|
@@ -2204,113 +3410,519 @@ var createExecutionRecorder = (options) => {
|
|
|
2204
3410
|
rememberError(error, recording);
|
|
2205
3411
|
settleInFlight(recording);
|
|
2206
3412
|
}
|
|
2207
|
-
)
|
|
2208
|
-
);
|
|
3413
|
+
);
|
|
3414
|
+
});
|
|
3415
|
+
};
|
|
3416
|
+
const noopHandle2 = {
|
|
3417
|
+
leave: (value) => value,
|
|
3418
|
+
fail: () => {
|
|
3419
|
+
},
|
|
3420
|
+
end: () => {
|
|
3421
|
+
},
|
|
3422
|
+
run: function __rasputinHandleRun__3(callback) {
|
|
3423
|
+
return runExactlyOnce((invoke) => invoke(), callback);
|
|
3424
|
+
},
|
|
3425
|
+
suspend: (value) => value,
|
|
3426
|
+
resume: (value) => value
|
|
3427
|
+
};
|
|
3428
|
+
const bindStoreTransitions = (active, parent, recording, plan) => {
|
|
3429
|
+
let suspended = false;
|
|
3430
|
+
const enter = (next) => {
|
|
3431
|
+
try {
|
|
3432
|
+
storage.enterWith(next);
|
|
3433
|
+
} catch {
|
|
3434
|
+
degradeAttribution(recording, plan);
|
|
3435
|
+
}
|
|
3436
|
+
};
|
|
3437
|
+
const expectStore = (expected) => {
|
|
3438
|
+
if (currentStore() !== expected) degradeAttribution(recording, plan);
|
|
3439
|
+
};
|
|
3440
|
+
return {
|
|
3441
|
+
enterActive: () => enter(active),
|
|
3442
|
+
run: function __rasputinHandleRun__3(callback) {
|
|
3443
|
+
return runExactlyOnce((invoke) => {
|
|
3444
|
+
try {
|
|
3445
|
+
enter(parent);
|
|
3446
|
+
} catch {
|
|
3447
|
+
}
|
|
3448
|
+
return storage.run(active, invoke);
|
|
3449
|
+
}, callback);
|
|
3450
|
+
},
|
|
3451
|
+
suspend: (value) => {
|
|
3452
|
+
expectStore(active);
|
|
3453
|
+
suspended = true;
|
|
3454
|
+
enter(parent);
|
|
3455
|
+
return value;
|
|
3456
|
+
},
|
|
3457
|
+
resume: (value) => {
|
|
3458
|
+
if (suspended) {
|
|
3459
|
+
expectStore(parent);
|
|
3460
|
+
suspended = false;
|
|
3461
|
+
enter(active);
|
|
3462
|
+
} else {
|
|
3463
|
+
expectStore(active);
|
|
3464
|
+
}
|
|
3465
|
+
return value;
|
|
3466
|
+
},
|
|
3467
|
+
restore: () => {
|
|
3468
|
+
expectStore(active);
|
|
3469
|
+
enter(parent);
|
|
3470
|
+
}
|
|
3471
|
+
};
|
|
3472
|
+
};
|
|
3473
|
+
const enterPreparedFunctionFromStore = (store, plan, args, omitValues) => {
|
|
3474
|
+
if (!store) return noopHandle2;
|
|
3475
|
+
if (plan.disabled) {
|
|
3476
|
+
noteDisabledPlan(store.recording);
|
|
3477
|
+
return noopHandle2;
|
|
3478
|
+
}
|
|
3479
|
+
if (store.recording.finished) {
|
|
3480
|
+
if (!store.recording.budgetExpired && !store.recording.evicted) return noopHandle2;
|
|
3481
|
+
const expired = store.recording;
|
|
3482
|
+
const expiredStore = { recording: expired };
|
|
3483
|
+
return {
|
|
3484
|
+
leave: (value) => value,
|
|
3485
|
+
fail: (error) => {
|
|
3486
|
+
rememberError(error, expired);
|
|
3487
|
+
},
|
|
3488
|
+
end: () => {
|
|
3489
|
+
},
|
|
3490
|
+
run: function __rasputinHandleRun__3(callback) {
|
|
3491
|
+
return runExactlyOnce((invoke) => storage.run(expiredStore, invoke), callback);
|
|
3492
|
+
},
|
|
3493
|
+
suspend: (value) => value,
|
|
3494
|
+
resume: (value) => value
|
|
3495
|
+
};
|
|
3496
|
+
}
|
|
3497
|
+
stats.functionCallsObserved++;
|
|
3498
|
+
const recording = store.recording;
|
|
3499
|
+
const omitCallValues = omitValues === true || plan.omitCallValues;
|
|
3500
|
+
const parentCallId = store.currentCallId;
|
|
3501
|
+
if (store.suppressCapture || plan.excluded) {
|
|
3502
|
+
stats.functionCallsExcluded++;
|
|
3503
|
+
const excludedStore = { ...store, suppressCapture: true };
|
|
3504
|
+
const excluded = bindStoreTransitions(excludedStore, store, recording, plan);
|
|
3505
|
+
excluded.enterActive();
|
|
3506
|
+
let ended2 = false;
|
|
3507
|
+
return {
|
|
3508
|
+
leave: (value) => value,
|
|
3509
|
+
fail: () => {
|
|
3510
|
+
},
|
|
3511
|
+
end: () => {
|
|
3512
|
+
if (ended2) return;
|
|
3513
|
+
ended2 = true;
|
|
3514
|
+
excluded.restore();
|
|
3515
|
+
},
|
|
3516
|
+
run: excluded.run,
|
|
3517
|
+
suspend: excluded.suspend,
|
|
3518
|
+
resume: excluded.resume
|
|
3519
|
+
};
|
|
3520
|
+
}
|
|
3521
|
+
recording.inFlightCalls++;
|
|
3522
|
+
const group = repeatedCallGroup(recording, plan, parentCallId);
|
|
3523
|
+
group.observedCalls++;
|
|
3524
|
+
const journal = acquireJournal(recording);
|
|
3525
|
+
try {
|
|
3526
|
+
if (group.observedCalls === 1) journal?.notePlan(plan.runtimePlanId);
|
|
3527
|
+
} catch {
|
|
3528
|
+
}
|
|
3529
|
+
let status = "open";
|
|
3530
|
+
let pendingReturn;
|
|
3531
|
+
let ended = false;
|
|
3532
|
+
const startedAtNs = process.hrtime.bigint();
|
|
3533
|
+
const parentStore = store;
|
|
3534
|
+
const uncaptured = bindStoreTransitions(parentStore, parentStore, recording, plan);
|
|
3535
|
+
const finishEnd = () => {
|
|
3536
|
+
if (ended) return;
|
|
3537
|
+
ended = true;
|
|
3538
|
+
settleInFlight(recording);
|
|
3539
|
+
uncaptured.restore();
|
|
3540
|
+
};
|
|
3541
|
+
const context = {
|
|
3542
|
+
run: uncaptured.run,
|
|
3543
|
+
suspend: uncaptured.suspend,
|
|
3544
|
+
resume: uncaptured.resume
|
|
3545
|
+
};
|
|
3546
|
+
if (group.observedCalls > maxCapturedCallsPerFunction) {
|
|
3547
|
+
uncaptured.enterActive();
|
|
3548
|
+
return {
|
|
3549
|
+
leave: (value) => {
|
|
3550
|
+
if (status !== "failed") {
|
|
3551
|
+
status = "left";
|
|
3552
|
+
pendingReturn = value;
|
|
3553
|
+
}
|
|
3554
|
+
return value;
|
|
3555
|
+
},
|
|
3556
|
+
fail: (error, liveArgs) => {
|
|
3557
|
+
if (status === "failed") return;
|
|
3558
|
+
status = "failed";
|
|
3559
|
+
captureCompletedThrow(
|
|
3560
|
+
recording,
|
|
3561
|
+
plan,
|
|
3562
|
+
liveArgs ?? args,
|
|
3563
|
+
parentCallId,
|
|
3564
|
+
startedAtNs,
|
|
3565
|
+
error
|
|
3566
|
+
);
|
|
3567
|
+
},
|
|
3568
|
+
end: () => {
|
|
3569
|
+
if (status !== "failed") {
|
|
3570
|
+
recordSuppressedCall(
|
|
3571
|
+
recording,
|
|
3572
|
+
group,
|
|
3573
|
+
parentCallId,
|
|
3574
|
+
startedAtNs,
|
|
3575
|
+
process.hrtime.bigint()
|
|
3576
|
+
);
|
|
3577
|
+
}
|
|
3578
|
+
finishEnd();
|
|
3579
|
+
},
|
|
3580
|
+
...context
|
|
3581
|
+
};
|
|
3582
|
+
}
|
|
3583
|
+
const dropWithoutCapture = (onThrow) => {
|
|
3584
|
+
uncaptured.enterActive();
|
|
3585
|
+
return {
|
|
3586
|
+
leave: (value) => {
|
|
3587
|
+
if (status !== "failed") {
|
|
3588
|
+
status = "left";
|
|
3589
|
+
pendingReturn = value;
|
|
3590
|
+
}
|
|
3591
|
+
return value;
|
|
3592
|
+
},
|
|
3593
|
+
fail: (error) => {
|
|
3594
|
+
if (status === "failed") return;
|
|
3595
|
+
status = "failed";
|
|
3596
|
+
onThrow(error);
|
|
3597
|
+
},
|
|
3598
|
+
end: () => {
|
|
3599
|
+
if (status !== "failed") {
|
|
3600
|
+
const droppedBefore = recording.journal?.dropped ?? 0;
|
|
3601
|
+
recording.journal?.dropCall();
|
|
3602
|
+
countDroppedEvents(recording, droppedBefore);
|
|
3603
|
+
}
|
|
3604
|
+
finishEnd();
|
|
3605
|
+
},
|
|
3606
|
+
...context
|
|
3607
|
+
};
|
|
3608
|
+
};
|
|
3609
|
+
if (!journal) {
|
|
3610
|
+
memoryBudget.reserveCall(recording.memory, plan.estimatedCallBytes);
|
|
3611
|
+
uncaptured.enterActive();
|
|
3612
|
+
return {
|
|
3613
|
+
leave: (value) => {
|
|
3614
|
+
if (status !== "failed") {
|
|
3615
|
+
status = "left";
|
|
3616
|
+
pendingReturn = value;
|
|
3617
|
+
}
|
|
3618
|
+
return value;
|
|
3619
|
+
},
|
|
3620
|
+
fail: (error) => {
|
|
3621
|
+
if (status === "failed") return;
|
|
3622
|
+
status = "failed";
|
|
3623
|
+
rememberError(error, recording);
|
|
3624
|
+
},
|
|
3625
|
+
end: finishEnd,
|
|
3626
|
+
...context
|
|
3627
|
+
};
|
|
3628
|
+
}
|
|
3629
|
+
if (!journal.canStartCall()) {
|
|
3630
|
+
return dropWithoutCapture((error) => {
|
|
3631
|
+
captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs, error);
|
|
3632
|
+
});
|
|
3633
|
+
}
|
|
3634
|
+
if (!memoryBudget.reserveCall(recording.memory, plan.estimatedCallBytes)) {
|
|
3635
|
+
uncaptured.enterActive();
|
|
3636
|
+
return {
|
|
3637
|
+
leave: (value) => {
|
|
3638
|
+
if (status !== "failed") {
|
|
3639
|
+
status = "left";
|
|
3640
|
+
pendingReturn = value;
|
|
3641
|
+
}
|
|
3642
|
+
return value;
|
|
3643
|
+
},
|
|
3644
|
+
fail: (error) => {
|
|
3645
|
+
if (status === "failed") return;
|
|
3646
|
+
status = "failed";
|
|
3647
|
+
rememberError(error, recording);
|
|
3648
|
+
},
|
|
3649
|
+
end: finishEnd,
|
|
3650
|
+
...context
|
|
3651
|
+
};
|
|
3652
|
+
}
|
|
3653
|
+
const callId = ++recording.nextCallId;
|
|
3654
|
+
const enterTimestampNs = process.hrtime.bigint() - recording.startedAtNs;
|
|
3655
|
+
const capturedArgs = omitCallValues ? mapArrayLike(args, () => rasputinOmitted()) : mapArrayLike(args, (argument) => captureValue(recording, argument));
|
|
3656
|
+
try {
|
|
3657
|
+
journal.startCall(plan.runtimePlanId, callId, parentCallId, enterTimestampNs, capturedArgs);
|
|
3658
|
+
} catch {
|
|
3659
|
+
journal.dropCall();
|
|
3660
|
+
return dropWithoutCapture((error) => rememberError(error, recording));
|
|
3661
|
+
}
|
|
3662
|
+
const callStore = { recording, currentCallId: callId };
|
|
3663
|
+
const captured = bindStoreTransitions(callStore, parentStore, recording, plan);
|
|
3664
|
+
captured.enterActive();
|
|
3665
|
+
const writeExit = (value) => {
|
|
3666
|
+
if (!recording.journal) return;
|
|
3667
|
+
const timestampNs = process.hrtime.bigint() - recording.startedAtNs;
|
|
3668
|
+
const durationNs = process.hrtime.bigint() - startedAtNs;
|
|
3669
|
+
const returnValue = omitCallValues ? rasputinOmitted() : captureValue(recording, value);
|
|
3670
|
+
recording.journal.finishCall(KIND_EXIT, callId, timestampNs, durationNs, returnValue);
|
|
3671
|
+
stats.functionCallsCaptured++;
|
|
3672
|
+
};
|
|
3673
|
+
const writeThrow = (error) => {
|
|
3674
|
+
if (!recording.journal) {
|
|
3675
|
+
rememberError(error, recording);
|
|
3676
|
+
return;
|
|
3677
|
+
}
|
|
3678
|
+
const capturedError = serializedError(recording, error, callId);
|
|
3679
|
+
recording.journal.finishCall(
|
|
3680
|
+
KIND_THROW,
|
|
3681
|
+
callId,
|
|
3682
|
+
process.hrtime.bigint() - recording.startedAtNs,
|
|
3683
|
+
process.hrtime.bigint() - startedAtNs,
|
|
3684
|
+
capturedError.value
|
|
3685
|
+
);
|
|
3686
|
+
stats.functionCallsCaptured++;
|
|
3687
|
+
capturedError.commit();
|
|
3688
|
+
rememberError(error, recording);
|
|
3689
|
+
};
|
|
3690
|
+
return {
|
|
3691
|
+
leave: (value) => {
|
|
3692
|
+
if (status !== "failed") {
|
|
3693
|
+
status = "left";
|
|
3694
|
+
pendingReturn = value;
|
|
3695
|
+
}
|
|
3696
|
+
return value;
|
|
3697
|
+
},
|
|
3698
|
+
fail: (error) => {
|
|
3699
|
+
if (status === "failed") return;
|
|
3700
|
+
status = "failed";
|
|
3701
|
+
try {
|
|
3702
|
+
writeThrow(error);
|
|
3703
|
+
} catch {
|
|
3704
|
+
rememberError(error, recording);
|
|
3705
|
+
}
|
|
3706
|
+
},
|
|
3707
|
+
end: () => {
|
|
3708
|
+
try {
|
|
3709
|
+
if (status !== "failed") writeExit(status === "left" ? pendingReturn : void 0);
|
|
3710
|
+
} catch {
|
|
3711
|
+
}
|
|
3712
|
+
if (ended) return;
|
|
3713
|
+
ended = true;
|
|
3714
|
+
settleInFlight(recording);
|
|
3715
|
+
captured.restore();
|
|
3716
|
+
},
|
|
3717
|
+
run: captured.run,
|
|
3718
|
+
suspend: captured.suspend,
|
|
3719
|
+
resume: captured.resume
|
|
3720
|
+
};
|
|
3721
|
+
};
|
|
3722
|
+
const runPreparedFunction = (plan, args, callback, omitValues) => {
|
|
3723
|
+
const store = currentStore();
|
|
3724
|
+
if (store && !store.recording.finished && !store.recording.sawAutomatic) {
|
|
3725
|
+
store.recording.sawAutomatic = true;
|
|
3726
|
+
}
|
|
3727
|
+
return runPreparedFunctionFromStore(store, plan, args, callback, omitValues);
|
|
3728
|
+
};
|
|
3729
|
+
const isolateHandle2 = (handle) => ({
|
|
3730
|
+
leave: (value) => {
|
|
3731
|
+
try {
|
|
3732
|
+
return handle.leave(value);
|
|
3733
|
+
} catch {
|
|
3734
|
+
return value;
|
|
3735
|
+
}
|
|
3736
|
+
},
|
|
3737
|
+
fail: (error, liveArgs) => {
|
|
3738
|
+
try {
|
|
3739
|
+
handle.fail(error, liveArgs);
|
|
3740
|
+
} catch {
|
|
3741
|
+
}
|
|
3742
|
+
},
|
|
3743
|
+
end: () => {
|
|
3744
|
+
try {
|
|
3745
|
+
handle.end();
|
|
3746
|
+
} catch {
|
|
3747
|
+
}
|
|
3748
|
+
},
|
|
3749
|
+
run: function __rasputinHandleRun__3(callback) {
|
|
3750
|
+
return runExactlyOnce((invoke) => handle.run(invoke), callback);
|
|
3751
|
+
},
|
|
3752
|
+
suspend: (value) => {
|
|
3753
|
+
try {
|
|
3754
|
+
return handle.suspend(value);
|
|
3755
|
+
} catch {
|
|
3756
|
+
return value;
|
|
3757
|
+
}
|
|
3758
|
+
},
|
|
3759
|
+
resume: (value) => {
|
|
3760
|
+
try {
|
|
3761
|
+
return handle.resume(value);
|
|
3762
|
+
} catch {
|
|
3763
|
+
return value;
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
3766
|
+
});
|
|
3767
|
+
const enterPreparedFunction = (plan, args, omitValues) => {
|
|
3768
|
+
try {
|
|
3769
|
+
const store = currentStore();
|
|
3770
|
+
if (store && !store.recording.finished && !store.recording.sawAutomatic) {
|
|
3771
|
+
store.recording.sawAutomatic = true;
|
|
3772
|
+
}
|
|
3773
|
+
return isolateHandle2(enterPreparedFunctionFromStore(store, plan, args, omitValues));
|
|
3774
|
+
} catch {
|
|
3775
|
+
return noopHandle2;
|
|
3776
|
+
}
|
|
2209
3777
|
};
|
|
2210
3778
|
const runFunction = (input, args, callback) => {
|
|
2211
|
-
const store =
|
|
3779
|
+
const store = currentStore();
|
|
2212
3780
|
if (store && !store.recording.finished) store.recording.sawManual = true;
|
|
2213
|
-
return
|
|
3781
|
+
return runPreparedFunctionFromStore(
|
|
3782
|
+
store,
|
|
3783
|
+
preparePlan(normalizeFunctionDefinition(input)),
|
|
3784
|
+
args,
|
|
3785
|
+
callback
|
|
3786
|
+
);
|
|
2214
3787
|
};
|
|
2215
3788
|
const runFunctionPlans = (plans, planIndex, args, callback, omitValues) => {
|
|
2216
|
-
const store =
|
|
3789
|
+
const store = currentStore();
|
|
2217
3790
|
const plan = preparedPlansFor(plans)[planIndex];
|
|
2218
|
-
if (store && !store.recording.finished) {
|
|
3791
|
+
if (store && !store.recording.finished && !store.recording.sawAutomatic) {
|
|
2219
3792
|
store.recording.sawAutomatic = true;
|
|
2220
|
-
if (plan) store.recording.executedFunctionIds.add(plan.functionId);
|
|
2221
3793
|
}
|
|
2222
|
-
return plan ?
|
|
3794
|
+
return plan ? runPreparedFunctionFromStore(store, plan, args, callback, omitValues) : callback();
|
|
2223
3795
|
};
|
|
2224
3796
|
const prepareFunctionPlans = (plans) => preparedPlansFor(plans);
|
|
2225
3797
|
function trace(input, fn) {
|
|
2226
3798
|
const definition = typeof input === "string" ? manualFunctionDefinition(input) : { ...input, functionId: runtimeFunctionId2(input) };
|
|
2227
3799
|
const plan = preparePlan(definition);
|
|
2228
|
-
return function
|
|
2229
|
-
|
|
3800
|
+
return function __rasputinHandleRun__3(...args) {
|
|
3801
|
+
if (new.target) {
|
|
3802
|
+
throw new TypeError("execution.trace() wraps function calls, not constructors");
|
|
3803
|
+
}
|
|
3804
|
+
const receiver = this;
|
|
3805
|
+
const store = currentStore();
|
|
2230
3806
|
if (store && !store.recording.finished) store.recording.sawManual = true;
|
|
2231
|
-
return
|
|
3807
|
+
return runPreparedFunctionFromStore(store, plan, args, function __rasputinHandleRun__4() {
|
|
3808
|
+
return fn.apply(receiver, args);
|
|
3809
|
+
});
|
|
2232
3810
|
};
|
|
2233
3811
|
}
|
|
2234
|
-
const captureDerivationRoot = (rootId, value) => {
|
|
2235
|
-
const store = storage.getStore();
|
|
2236
|
-
if (!store || store.recording.finished || store.suppressCapture) return value;
|
|
2237
|
-
const recording = store.recording;
|
|
2238
|
-
if (recording.memory.mode !== "full") return value;
|
|
2239
|
-
if (recording.derivationRoots.length >= maxEventsPerExecution) return value;
|
|
2240
|
-
const recorderStartedAtNs = process.hrtime.bigint();
|
|
2241
|
-
try {
|
|
2242
|
-
const serialized = captureValue(recording, value);
|
|
2243
|
-
if (recording.memory.mode !== "full") return value;
|
|
2244
|
-
if (!memoryBudget.reserveStorage(recording.memory, DERIVATION_ROOT_RECORD_BYTES)) {
|
|
2245
|
-
return value;
|
|
2246
|
-
}
|
|
2247
|
-
const completeness = capturedValueCompleteness(serialized);
|
|
2248
|
-
const bytes = jsonLiteralUtf8Bytes(serialized);
|
|
2249
|
-
recording.derivationRoots.push({
|
|
2250
|
-
rootId,
|
|
2251
|
-
callId: store.currentCallId ?? 0,
|
|
2252
|
-
value: serialized,
|
|
2253
|
-
completeness
|
|
2254
|
-
});
|
|
2255
|
-
recording.derivationRootBytes += bytes;
|
|
2256
|
-
stats.derivationRootsCaptured++;
|
|
2257
|
-
stats.derivationRootBytes += bytes;
|
|
2258
|
-
stats.derivationFallbackExpressions++;
|
|
2259
|
-
return value;
|
|
2260
|
-
} finally {
|
|
2261
|
-
addRecorderTime(recording, process.hrtime.bigint() - recorderStartedAtNs);
|
|
2262
|
-
}
|
|
2263
|
-
};
|
|
2264
3812
|
return {
|
|
2265
3813
|
createScope,
|
|
2266
|
-
run,
|
|
2267
3814
|
getErrorState,
|
|
2268
3815
|
runFunction,
|
|
2269
3816
|
runFunctionPlans,
|
|
2270
3817
|
prepareFunctionPlans,
|
|
2271
3818
|
runPreparedFunction,
|
|
3819
|
+
enterPreparedFunction,
|
|
2272
3820
|
trace,
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
derivationFallbackFunctions: plans.filter((plan) => plan.fallbackReason).length,
|
|
2283
|
-
derivationFallbackReasons: { ...stats.derivationFallbackReasons },
|
|
2284
|
-
...phases ? {
|
|
2285
|
-
phaseAlsNs: Number(phases.alsNs),
|
|
2286
|
-
phaseMaterializeNs: Number(phases.materializeNs)
|
|
2287
|
-
} : {}
|
|
2288
|
-
};
|
|
2289
|
-
}
|
|
3821
|
+
getStats: () => ({
|
|
3822
|
+
...stats,
|
|
3823
|
+
...memoryBudget.getStats(),
|
|
3824
|
+
...journalPool.stats(),
|
|
3825
|
+
...phases ? {
|
|
3826
|
+
phaseAlsNs: Number(phases.alsNs),
|
|
3827
|
+
phaseMaterializeNs: Number(phases.materializeNs)
|
|
3828
|
+
} : {}
|
|
3829
|
+
})
|
|
2290
3830
|
};
|
|
2291
3831
|
};
|
|
2292
3832
|
|
|
2293
3833
|
// src/execution-recorder/automatic-runtime.ts
|
|
2294
|
-
var AUTOMATIC_RUNTIME_SYMBOL = "rasputin.execution.runtime.
|
|
3834
|
+
var AUTOMATIC_RUNTIME_SYMBOL = "rasputin.execution.runtime.v3";
|
|
2295
3835
|
var runtimeSymbol = Symbol.for(AUTOMATIC_RUNTIME_SYMBOL);
|
|
2296
|
-
var
|
|
2297
|
-
|
|
3836
|
+
var passthroughHandle = () => ({
|
|
3837
|
+
leave: (value) => value,
|
|
3838
|
+
fail: () => {
|
|
3839
|
+
},
|
|
3840
|
+
end: () => {
|
|
3841
|
+
},
|
|
3842
|
+
run: function __rasputinHandleRun__3(callback) {
|
|
3843
|
+
return runExactlyOnce((invoke) => invoke(), callback);
|
|
3844
|
+
},
|
|
3845
|
+
suspend: (value) => value,
|
|
3846
|
+
resume: (value) => value
|
|
3847
|
+
});
|
|
3848
|
+
var isolateHandle = (handle) => ({
|
|
3849
|
+
leave: (value) => {
|
|
3850
|
+
try {
|
|
3851
|
+
return handle.leave(value);
|
|
3852
|
+
} catch {
|
|
3853
|
+
return value;
|
|
3854
|
+
}
|
|
3855
|
+
},
|
|
3856
|
+
fail: (error, liveArgs) => {
|
|
3857
|
+
try {
|
|
3858
|
+
handle.fail(error, liveArgs);
|
|
3859
|
+
} catch {
|
|
3860
|
+
}
|
|
3861
|
+
},
|
|
3862
|
+
end: () => {
|
|
3863
|
+
try {
|
|
3864
|
+
handle.end();
|
|
3865
|
+
} catch {
|
|
3866
|
+
}
|
|
3867
|
+
},
|
|
3868
|
+
run: function __rasputinHandleRun__3(callback) {
|
|
3869
|
+
return runExactlyOnce((invoke) => handle.run(invoke), callback);
|
|
3870
|
+
},
|
|
3871
|
+
suspend: (value) => {
|
|
3872
|
+
try {
|
|
3873
|
+
return handle.suspend(value);
|
|
3874
|
+
} catch {
|
|
3875
|
+
return value;
|
|
3876
|
+
}
|
|
3877
|
+
},
|
|
3878
|
+
resume: (value) => {
|
|
3879
|
+
try {
|
|
3880
|
+
return handle.resume(value);
|
|
3881
|
+
} catch {
|
|
3882
|
+
return value;
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
3885
|
+
});
|
|
3886
|
+
var passthroughRun = (_planIndex, _args, callback) => callback();
|
|
3887
|
+
var passthroughEnter = () => passthroughHandle();
|
|
2298
3888
|
var bindPassthrough = (module) => {
|
|
2299
|
-
module.cell.run =
|
|
3889
|
+
module.cell.run = passthroughRun;
|
|
3890
|
+
module.cell.enter = passthroughEnter;
|
|
3891
|
+
};
|
|
3892
|
+
var attachRunner = (cell) => {
|
|
3893
|
+
const run = ((planIndex, args, callback, omitValues) => cell.run(planIndex, args, callback, omitValues));
|
|
3894
|
+
run.enter = (planIndex, args, omitValues) => cell.enter(planIndex, args, omitValues);
|
|
3895
|
+
return run;
|
|
3896
|
+
};
|
|
3897
|
+
var bindExecution = (execution, module) => {
|
|
3898
|
+
const prepared = execution.prepareFunctionPlans(module.plans);
|
|
3899
|
+
module.cell.run = (planIndex, args, callback, omitValues) => {
|
|
3900
|
+
const plan = prepared[planIndex];
|
|
3901
|
+
return plan ? execution.runPreparedFunction(plan, args, callback, omitValues) : callback();
|
|
3902
|
+
};
|
|
3903
|
+
module.cell.enter = (planIndex, args, omitValues) => {
|
|
3904
|
+
try {
|
|
3905
|
+
const plan = prepared[planIndex];
|
|
3906
|
+
return isolateHandle(
|
|
3907
|
+
plan ? execution.enterPreparedFunction(plan, args, omitValues) : passthroughEnter(planIndex, args, omitValues)
|
|
3908
|
+
);
|
|
3909
|
+
} catch {
|
|
3910
|
+
return passthroughHandle();
|
|
3911
|
+
}
|
|
3912
|
+
};
|
|
2300
3913
|
};
|
|
2301
3914
|
var isRegistry = (value) => Array.isArray(Reflect.get(value, "runtimes")) && Array.isArray(Reflect.get(value, "modules")) && typeof Reflect.get(value, "register") === "function";
|
|
2302
3915
|
var registerModule = (registry, plans) => {
|
|
2303
|
-
const cell = { run:
|
|
3916
|
+
const cell = { run: passthroughRun, enter: passthroughEnter };
|
|
2304
3917
|
const module = { plans, cell };
|
|
2305
3918
|
registry.modules.push(module);
|
|
2306
3919
|
registry.runtimes.at(-1)?.bind(module);
|
|
2307
|
-
return (
|
|
3920
|
+
return attachRunner(cell);
|
|
2308
3921
|
};
|
|
2309
3922
|
var createRegistry = () => {
|
|
2310
3923
|
const registry = {
|
|
2311
3924
|
runtimes: [],
|
|
2312
3925
|
modules: [],
|
|
2313
|
-
captureRoot: passthroughCapture,
|
|
2314
3926
|
register(plans) {
|
|
2315
3927
|
return registerModule(registry, plans);
|
|
2316
3928
|
}
|
|
@@ -2320,9 +3932,6 @@ var createRegistry = () => {
|
|
|
2320
3932
|
var getAutomaticRuntimeRegistry = () => {
|
|
2321
3933
|
const existing = Reflect.get(globalThis, runtimeSymbol);
|
|
2322
3934
|
if (existing && typeof existing === "object" && isRegistry(existing)) {
|
|
2323
|
-
if (typeof existing.captureRoot !== "function") {
|
|
2324
|
-
existing.captureRoot = passthroughCapture;
|
|
2325
|
-
}
|
|
2326
3935
|
return existing;
|
|
2327
3936
|
}
|
|
2328
3937
|
const registry = createRegistry();
|
|
@@ -2333,18 +3942,15 @@ var installAutomaticExecutionRuntime = (execution) => {
|
|
|
2333
3942
|
const registry = getAutomaticRuntimeRegistry();
|
|
2334
3943
|
const runtime = {
|
|
2335
3944
|
bind(module) {
|
|
2336
|
-
|
|
2337
|
-
}
|
|
2338
|
-
captureRoot: (rootId, value) => execution.captureDerivationRoot(rootId, value)
|
|
3945
|
+
bindExecution(execution, module);
|
|
3946
|
+
}
|
|
2339
3947
|
};
|
|
2340
3948
|
registry.runtimes.push(runtime);
|
|
2341
|
-
registry.captureRoot = runtime.captureRoot;
|
|
2342
3949
|
for (const module of registry.modules) runtime.bind(module);
|
|
2343
3950
|
return () => {
|
|
2344
3951
|
const index = registry.runtimes.lastIndexOf(runtime);
|
|
2345
3952
|
if (index >= 0) registry.runtimes.splice(index, 1);
|
|
2346
3953
|
const current = registry.runtimes.at(-1);
|
|
2347
|
-
registry.captureRoot = current?.captureRoot ?? passthroughCapture;
|
|
2348
3954
|
for (const module of registry.modules) {
|
|
2349
3955
|
if (current) current.bind(module);
|
|
2350
3956
|
else bindPassthrough(module);
|
|
@@ -2353,117 +3959,234 @@ var installAutomaticExecutionRuntime = (execution) => {
|
|
|
2353
3959
|
};
|
|
2354
3960
|
|
|
2355
3961
|
// src/install-global-handlers.ts
|
|
3962
|
+
var RASPUTIN_PROCESS_LISTENER = Symbol.for("rasputin.process.listener.v1");
|
|
3963
|
+
var unhandledRejectionMode = () => {
|
|
3964
|
+
const tokens = [
|
|
3965
|
+
...process.execArgv,
|
|
3966
|
+
...(process.env.NODE_OPTIONS?.match(/(?:[^\s"]+|"[^"]*")+/g) ?? []).map(
|
|
3967
|
+
(token) => token.replace(/^"|"$/g, "")
|
|
3968
|
+
)
|
|
3969
|
+
];
|
|
3970
|
+
for (let index = tokens.length - 1; index >= 0; index--) {
|
|
3971
|
+
const token = tokens[index];
|
|
3972
|
+
if (!token) continue;
|
|
3973
|
+
if (token.startsWith("--unhandled-rejections="))
|
|
3974
|
+
return token.slice("--unhandled-rejections=".length);
|
|
3975
|
+
if (token === "--unhandled-rejections") return tokens[index + 1] ?? "";
|
|
3976
|
+
}
|
|
3977
|
+
return "throw";
|
|
3978
|
+
};
|
|
3979
|
+
var isBun = typeof process.versions.bun === "string";
|
|
3980
|
+
var unhandledRejectionIsFatal = () => {
|
|
3981
|
+
const mode = unhandledRejectionMode();
|
|
3982
|
+
return mode === "throw" || mode === "strict";
|
|
3983
|
+
};
|
|
3984
|
+
var printDiagnostic = (error) => {
|
|
3985
|
+
if (error instanceof Error) {
|
|
3986
|
+
console.error(error.stack ?? `${error.name}: ${error.message}`);
|
|
3987
|
+
return;
|
|
3988
|
+
}
|
|
3989
|
+
console.error(error);
|
|
3990
|
+
};
|
|
2356
3991
|
var removeProcessListener = process.off.bind(process);
|
|
2357
|
-
var
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
3992
|
+
var tagListener = (listener) => {
|
|
3993
|
+
Object.defineProperty(listener, RASPUTIN_PROCESS_LISTENER, { value: true });
|
|
3994
|
+
return listener;
|
|
3995
|
+
};
|
|
3996
|
+
var hostListenerCount = (event) => {
|
|
3997
|
+
const listeners = event === "uncaughtException" ? process.listeners("uncaughtException") : process.listeners("unhandledRejection");
|
|
3998
|
+
return listeners.filter((listener) => !(RASPUTIN_PROCESS_LISTENER in listener)).length;
|
|
3999
|
+
};
|
|
4000
|
+
var registered = [];
|
|
4001
|
+
var uninstallProcess;
|
|
4002
|
+
var handlingUncaught = false;
|
|
4003
|
+
var captureOnAll = (error) => {
|
|
4004
|
+
for (const entry of registered) {
|
|
2362
4005
|
try {
|
|
2363
|
-
client.captureException(
|
|
4006
|
+
entry.client.captureException(error);
|
|
2364
4007
|
} catch {
|
|
2365
4008
|
}
|
|
2366
|
-
}
|
|
2367
|
-
|
|
4009
|
+
}
|
|
4010
|
+
};
|
|
4011
|
+
var flushAll = async (timeoutMs) => {
|
|
4012
|
+
await Promise.all(
|
|
4013
|
+
registered.map(
|
|
4014
|
+
(entry) => entry.client.flush(timeoutMs).catch(() => {
|
|
4015
|
+
})
|
|
4016
|
+
)
|
|
4017
|
+
);
|
|
4018
|
+
};
|
|
4019
|
+
var installSharedListeners = () => {
|
|
4020
|
+
if (uninstallProcess) return;
|
|
4021
|
+
const onUnhandledRejection = tagListener((reason) => {
|
|
4022
|
+
captureOnAll(reason);
|
|
4023
|
+
if (hostListenerCount("unhandledRejection") > 0) return;
|
|
4024
|
+
const mode = unhandledRejectionMode();
|
|
4025
|
+
if (mode !== "none") printDiagnostic(reason);
|
|
4026
|
+
if (mode === "warn-with-error-code") process.exitCode = 1;
|
|
4027
|
+
});
|
|
4028
|
+
const onUncaughtException = tagListener((error, origin) => {
|
|
4029
|
+
const exitOnUncaught = registered.some((entry) => entry.exitOnUncaught);
|
|
4030
|
+
const flushTimeoutMs = registered.reduce(
|
|
4031
|
+
(max, entry) => Math.max(max, entry.flushTimeoutMs),
|
|
4032
|
+
2e3
|
|
4033
|
+
);
|
|
2368
4034
|
if (handlingUncaught) {
|
|
2369
|
-
|
|
4035
|
+
if (exitOnUncaught && hostListenerCount("uncaughtException") === 0) {
|
|
4036
|
+
process.exit(1);
|
|
4037
|
+
}
|
|
2370
4038
|
return;
|
|
2371
4039
|
}
|
|
2372
4040
|
handlingUncaught = true;
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
4041
|
+
captureOnAll(error);
|
|
4042
|
+
const hostOwns = hostListenerCount("uncaughtException") > 0;
|
|
4043
|
+
const shouldExit = exitOnUncaught && !hostOwns && !(isBun && origin === "unhandledRejection");
|
|
4044
|
+
if (!hostOwns) printDiagnostic(error);
|
|
4045
|
+
if (shouldExit) process.exitCode = 1;
|
|
2378
4046
|
const shutdown = async () => {
|
|
2379
4047
|
try {
|
|
2380
|
-
await
|
|
4048
|
+
await flushAll(flushTimeoutMs);
|
|
2381
4049
|
} catch {
|
|
2382
4050
|
}
|
|
2383
|
-
if (
|
|
4051
|
+
if (shouldExit) {
|
|
4052
|
+
process.exit(1);
|
|
4053
|
+
return;
|
|
4054
|
+
}
|
|
4055
|
+
handlingUncaught = false;
|
|
2384
4056
|
};
|
|
4057
|
+
if (shouldExit) {
|
|
4058
|
+
const watchdog = setTimeout(() => process.exit(1), flushTimeoutMs + 50);
|
|
4059
|
+
void shutdown().finally(() => clearTimeout(watchdog));
|
|
4060
|
+
return;
|
|
4061
|
+
}
|
|
2385
4062
|
void shutdown();
|
|
2386
|
-
};
|
|
4063
|
+
});
|
|
2387
4064
|
try {
|
|
2388
4065
|
process.on("uncaughtException", onUncaughtException);
|
|
2389
|
-
|
|
4066
|
+
if (!unhandledRejectionIsFatal()) {
|
|
4067
|
+
process.on("unhandledRejection", onUnhandledRejection);
|
|
4068
|
+
}
|
|
2390
4069
|
} catch {
|
|
2391
|
-
return
|
|
2392
|
-
};
|
|
4070
|
+
return;
|
|
2393
4071
|
}
|
|
2394
|
-
|
|
4072
|
+
uninstallProcess = () => {
|
|
2395
4073
|
try {
|
|
2396
4074
|
removeProcessListener("uncaughtException", onUncaughtException);
|
|
2397
4075
|
removeProcessListener("unhandledRejection", onUnhandledRejection);
|
|
2398
4076
|
} catch {
|
|
2399
4077
|
}
|
|
4078
|
+
uninstallProcess = void 0;
|
|
4079
|
+
handlingUncaught = false;
|
|
4080
|
+
};
|
|
4081
|
+
};
|
|
4082
|
+
var installGlobalHandlers = (client, options = {}) => {
|
|
4083
|
+
const entry = {
|
|
4084
|
+
client,
|
|
4085
|
+
exitOnUncaught: options.exitOnUncaughtException ?? true,
|
|
4086
|
+
flushTimeoutMs: options.flushTimeoutMs ?? 2e3
|
|
4087
|
+
};
|
|
4088
|
+
registered.push(entry);
|
|
4089
|
+
installSharedListeners();
|
|
4090
|
+
return () => {
|
|
4091
|
+
const index = registered.indexOf(entry);
|
|
4092
|
+
if (index >= 0) registered.splice(index, 1);
|
|
4093
|
+
if (registered.length === 0) uninstallProcess?.();
|
|
2400
4094
|
};
|
|
2401
4095
|
};
|
|
2402
|
-
|
|
2403
|
-
// src/rasputin-init.ts
|
|
2404
|
-
import { join } from "node:path";
|
|
2405
|
-
import {
|
|
2406
|
-
createClient,
|
|
2407
|
-
isClientEnabled
|
|
2408
|
-
} from "@rasputin-ai/core";
|
|
2409
4096
|
|
|
2410
4097
|
// src/sdk-meta.ts
|
|
2411
4098
|
var SDK_NAME = "@rasputin-ai/node";
|
|
2412
|
-
var SDK_VERSION = "0.5.0
|
|
4099
|
+
var SDK_VERSION = "0.5.0";
|
|
2413
4100
|
|
|
2414
4101
|
// src/rasputin-init.ts
|
|
2415
|
-
var
|
|
2416
|
-
|
|
4102
|
+
var publicExecution = (runtime) => ({
|
|
4103
|
+
createScope: (metadata) => {
|
|
4104
|
+
const scope = runtime.createScope(metadata);
|
|
4105
|
+
return {
|
|
4106
|
+
run: scope.run,
|
|
4107
|
+
associateError: scope.associateError,
|
|
4108
|
+
finish: scope.finish
|
|
4109
|
+
};
|
|
4110
|
+
},
|
|
4111
|
+
trace: runtime.trace,
|
|
4112
|
+
getStats: runtime.getStats
|
|
4113
|
+
});
|
|
4114
|
+
var withExecution = (client, runtime, installRuntime, manifest, uninstallHandlers = () => {
|
|
4115
|
+
}) => {
|
|
4116
|
+
const uninstallRuntime = installRuntime ? installAutomaticExecutionRuntime(runtime) : () => {
|
|
2417
4117
|
};
|
|
2418
4118
|
const manifestUpload = scheduleInstrumentationManifestUpload(manifest);
|
|
4119
|
+
const execution = publicExecution(runtime);
|
|
2419
4120
|
return {
|
|
2420
4121
|
...client,
|
|
2421
4122
|
execution,
|
|
2422
4123
|
getStats: () => ({ ...client.getStats(), recorder: execution.getStats() }),
|
|
2423
4124
|
verifyConfiguration: manifestUpload.verify,
|
|
2424
4125
|
captureException: (error, context) => {
|
|
2425
|
-
const
|
|
2426
|
-
error,
|
|
2427
|
-
context?.request ? { kind: "http", request: context.request } : void 0
|
|
2428
|
-
);
|
|
2429
|
-
const result = client.captureException(error, { ...context, runtimeState });
|
|
4126
|
+
const result = client.captureException(error, context);
|
|
2430
4127
|
manifestUpload.flushSoon();
|
|
2431
4128
|
return result;
|
|
2432
4129
|
},
|
|
2433
4130
|
flush: async (timeoutMs) => {
|
|
4131
|
+
const startedAt = Date.now();
|
|
2434
4132
|
await client.flush(timeoutMs);
|
|
2435
|
-
|
|
4133
|
+
if (timeoutMs === void 0) {
|
|
4134
|
+
await manifestUpload.wait();
|
|
4135
|
+
return;
|
|
4136
|
+
}
|
|
4137
|
+
await manifestUpload.wait(Math.max(0, timeoutMs - (Date.now() - startedAt)));
|
|
2436
4138
|
},
|
|
2437
4139
|
close: async () => {
|
|
4140
|
+
uninstallHandlers();
|
|
2438
4141
|
uninstallRuntime();
|
|
2439
4142
|
manifestUpload.disconnect();
|
|
4143
|
+
const startedAt = Date.now();
|
|
2440
4144
|
await client.close();
|
|
2441
|
-
await manifestUpload.wait();
|
|
4145
|
+
await manifestUpload.wait(Math.max(0, 2e3 - (Date.now() - startedAt)));
|
|
2442
4146
|
}
|
|
2443
4147
|
};
|
|
2444
4148
|
};
|
|
2445
4149
|
var RasputinInit = (options) => {
|
|
2446
4150
|
try {
|
|
2447
|
-
const
|
|
2448
|
-
const recorderEnabled =
|
|
2449
|
-
const
|
|
4151
|
+
const enabled = isClientEnabled(options);
|
|
4152
|
+
const recorderEnabled = enabled && options.executionRecorder?.enabled !== false;
|
|
4153
|
+
const runtime = createExecutionRecorder({
|
|
2450
4154
|
...options.executionRecorder,
|
|
2451
4155
|
enabled: recorderEnabled
|
|
2452
4156
|
});
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
sourceRoot: options.sourceRoot,
|
|
2462
|
-
sourceRoots: options.sourceRoots,
|
|
2463
|
-
logSuccess: options.logSuccess
|
|
4157
|
+
const client = createClient(options, {
|
|
4158
|
+
sdkVersion: SDK_VERSION,
|
|
4159
|
+
sdkName: SDK_NAME,
|
|
4160
|
+
installTransportSignalHandlers: options.installTransportSignalHandlers,
|
|
4161
|
+
resolveRuntimeState: (error, context) => runtime.getErrorState(
|
|
4162
|
+
error,
|
|
4163
|
+
context?.request ? { kind: "http", request: context.request } : void 0
|
|
4164
|
+
)
|
|
2464
4165
|
});
|
|
2465
|
-
if (
|
|
2466
|
-
|
|
4166
|
+
if (enabled) {
|
|
4167
|
+
loadInstrumentationManifestIfPresent(
|
|
4168
|
+
options.instrumentationManifestPath ?? process.env.RASPUTIN_INSTRUMENTATION_MANIFEST ?? join(process.cwd(), ".rasputin", "instrumentation-manifest.json")
|
|
4169
|
+
);
|
|
4170
|
+
}
|
|
4171
|
+
let uninstallHandlers = () => {
|
|
4172
|
+
};
|
|
4173
|
+
const wrappedClient = withExecution(
|
|
4174
|
+
client,
|
|
4175
|
+
runtime,
|
|
4176
|
+
recorderEnabled,
|
|
4177
|
+
{
|
|
4178
|
+
projectApiKey: options.projectApiKey ?? "",
|
|
4179
|
+
release: options.release,
|
|
4180
|
+
apiUrl: options.apiUrl,
|
|
4181
|
+
enabled,
|
|
4182
|
+
sourceRoot: options.sourceRoot,
|
|
4183
|
+
sourceRoots: options.sourceRoots,
|
|
4184
|
+
logSuccess: options.logSuccess
|
|
4185
|
+
},
|
|
4186
|
+
() => uninstallHandlers()
|
|
4187
|
+
);
|
|
4188
|
+
if (enabled && options.installGlobalHandlers !== false) {
|
|
4189
|
+
uninstallHandlers = installGlobalHandlers(wrappedClient);
|
|
2467
4190
|
}
|
|
2468
4191
|
return wrappedClient;
|
|
2469
4192
|
} catch {
|
|
@@ -2472,7 +4195,7 @@ var RasputinInit = (options) => {
|
|
|
2472
4195
|
createExecutionRecorder({ enabled: false }),
|
|
2473
4196
|
false,
|
|
2474
4197
|
{
|
|
2475
|
-
projectApiKey: options.projectApiKey,
|
|
4198
|
+
projectApiKey: options.projectApiKey ?? "",
|
|
2476
4199
|
release: options.release,
|
|
2477
4200
|
apiUrl: options.apiUrl,
|
|
2478
4201
|
enabled: false,
|
|
@@ -2484,9 +4207,5 @@ var RasputinInit = (options) => {
|
|
|
2484
4207
|
}
|
|
2485
4208
|
};
|
|
2486
4209
|
export {
|
|
2487
|
-
RasputinInit
|
|
2488
|
-
createExecutionRecorder,
|
|
2489
|
-
installAutomaticExecutionRuntime,
|
|
2490
|
-
installGlobalHandlers,
|
|
2491
|
-
scheduleInstrumentationManifestUpload
|
|
4210
|
+
RasputinInit
|
|
2492
4211
|
};
|