@rasputin-ai/node 0.1.4 → 0.3.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 +129 -14
- package/dist/auto-instrumentation/bun-plugin.d.ts +23 -0
- package/dist/auto-instrumentation/bun-plugin.d.ts.map +1 -0
- package/dist/auto-instrumentation/collect-instrumentation-delta.d.ts +58 -0
- package/dist/auto-instrumentation/collect-instrumentation-delta.d.ts.map +1 -0
- package/dist/auto-instrumentation/instrumentation-manifest-registry.d.ts +11 -0
- package/dist/auto-instrumentation/instrumentation-manifest-registry.d.ts.map +1 -0
- package/dist/auto-instrumentation/node-hooks.d.ts +6 -0
- package/dist/auto-instrumentation/node-hooks.d.ts.map +1 -0
- package/dist/auto-instrumentation/schedule-instrumentation-manifest-upload.d.ts +16 -0
- package/dist/auto-instrumentation/schedule-instrumentation-manifest-upload.d.ts.map +1 -0
- package/dist/auto-instrumentation/sdk-source-boundary.d.ts +7 -0
- package/dist/auto-instrumentation/sdk-source-boundary.d.ts.map +1 -0
- package/dist/auto-instrumentation/source-classification.d.ts +10 -0
- package/dist/auto-instrumentation/source-classification.d.ts.map +1 -0
- package/dist/auto-instrumentation/source-map-locations.d.ts +3 -0
- package/dist/auto-instrumentation/source-map-locations.d.ts.map +1 -0
- package/dist/auto-instrumentation/transform-source.d.ts +18 -0
- package/dist/auto-instrumentation/transform-source.d.ts.map +1 -0
- package/dist/execution-recorder/automatic-runtime.d.ts +18 -0
- package/dist/execution-recorder/automatic-runtime.d.ts.map +1 -0
- package/dist/execution-recorder/call-aware-event-buffer.d.ts +23 -0
- package/dist/execution-recorder/call-aware-event-buffer.d.ts.map +1 -0
- package/dist/execution-recorder/execution-recorder-types.d.ts +71 -0
- package/dist/execution-recorder/execution-recorder-types.d.ts.map +1 -0
- package/dist/execution-recorder/execution-recorder.d.ts +4 -0
- package/dist/execution-recorder/execution-recorder.d.ts.map +1 -0
- package/dist/execution-recorder/index.d.ts +3 -0
- package/dist/execution-recorder/index.d.ts.map +1 -0
- package/dist/execution-recorder/recorder-memory-budget.d.ts +37 -0
- package/dist/execution-recorder/recorder-memory-budget.d.ts.map +1 -0
- package/dist/execution-recorder/safe-serialize.d.ts +10 -0
- package/dist/execution-recorder/safe-serialize.d.ts.map +1 -0
- package/dist/execution-recorder/source-exclusions.d.ts +9 -0
- package/dist/execution-recorder/source-exclusions.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1201 -8
- package/dist/install-global-handlers.d.ts.map +1 -1
- package/dist/instrument/bun.d.ts +2 -0
- package/dist/instrument/bun.d.ts.map +1 -0
- package/dist/instrument/bun.js +477 -0
- package/dist/instrument/node.d.ts +2 -0
- package/dist/instrument/node.d.ts.map +1 -0
- package/dist/instrument/node.js +532 -0
- package/dist/rasputin-init.d.ts +29 -2
- package/dist/rasputin-init.d.ts.map +1 -1
- package/dist/sdk-meta.d.ts +1 -1
- package/package.json +15 -4
package/dist/index.js
CHANGED
|
@@ -1,4 +1,1133 @@
|
|
|
1
|
+
// src/auto-instrumentation/schedule-instrumentation-manifest-upload.ts
|
|
2
|
+
import {
|
|
3
|
+
detectRelease,
|
|
4
|
+
resolveEndpointUrls,
|
|
5
|
+
uploadInstrumentationManifest
|
|
6
|
+
} from "@rasputin-ai/core";
|
|
7
|
+
|
|
8
|
+
// src/auto-instrumentation/instrumentation-manifest-registry.ts
|
|
9
|
+
import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
|
|
10
|
+
|
|
11
|
+
// src/execution-recorder/automatic-runtime.ts
|
|
12
|
+
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
13
|
+
var AUTOMATIC_RUNTIME_SYMBOL = "rasputin.execution.runtime.v1";
|
|
14
|
+
var AUTOMATIC_SOURCE_SEPARATOR = "\0";
|
|
15
|
+
var runtimeSymbol = Symbol.for(AUTOMATIC_RUNTIME_SYMBOL);
|
|
16
|
+
var normalizeAutomaticFunctionId = (sourceToken, repoRoot) => {
|
|
17
|
+
if (!sourceToken.includes(AUTOMATIC_SOURCE_SEPARATOR)) return sourceToken;
|
|
18
|
+
const [filePath, name, line, column] = sourceToken.split(AUTOMATIC_SOURCE_SEPARATOR);
|
|
19
|
+
if (!filePath || !name || !line || !column) return void 0;
|
|
20
|
+
const fromRoot = relative(repoRoot, resolve(filePath));
|
|
21
|
+
if (!fromRoot || fromRoot === ".." || fromRoot.startsWith(`..${sep}`) || isAbsolute(fromRoot)) {
|
|
22
|
+
return void 0;
|
|
23
|
+
}
|
|
24
|
+
return `${fromRoot.replaceAll("\\", "/")}:${name}@${line}:${column}`;
|
|
25
|
+
};
|
|
26
|
+
var getRegistry = () => {
|
|
27
|
+
const existing = Reflect.get(globalThis, runtimeSymbol);
|
|
28
|
+
if (existing?.__rasputinRuntimeRegistry && Array.isArray(existing.runtimes)) {
|
|
29
|
+
return existing;
|
|
30
|
+
}
|
|
31
|
+
const runtimes = [];
|
|
32
|
+
const registry = {
|
|
33
|
+
__rasputinRuntimeRegistry: true,
|
|
34
|
+
runtimes,
|
|
35
|
+
run: (functionId, args, callback) => {
|
|
36
|
+
const runtime = runtimes.at(-1);
|
|
37
|
+
return runtime ? runtime.run(functionId, args, callback) : callback();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
Reflect.set(globalThis, runtimeSymbol, registry);
|
|
41
|
+
return registry;
|
|
42
|
+
};
|
|
43
|
+
var installAutomaticExecutionRuntime = (execution, options = {}) => {
|
|
44
|
+
const registry = getRegistry();
|
|
45
|
+
const repoRoot = options.repoRoot ? resolve(options.repoRoot) : void 0;
|
|
46
|
+
const normalizedIds = /* @__PURE__ */ new Map();
|
|
47
|
+
const runtime = {
|
|
48
|
+
run: (sourceToken, args, callback) => {
|
|
49
|
+
if (!sourceToken.includes(AUTOMATIC_SOURCE_SEPARATOR)) {
|
|
50
|
+
return execution.runFunction(sourceToken, args, callback);
|
|
51
|
+
}
|
|
52
|
+
if (!repoRoot) return callback();
|
|
53
|
+
let functionId = normalizedIds.get(sourceToken);
|
|
54
|
+
if (!normalizedIds.has(sourceToken)) {
|
|
55
|
+
functionId = normalizeAutomaticFunctionId(sourceToken, repoRoot);
|
|
56
|
+
normalizedIds.set(sourceToken, functionId);
|
|
57
|
+
}
|
|
58
|
+
return functionId ? execution.runFunction(functionId, args, callback) : callback();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
registry.runtimes.push(runtime);
|
|
62
|
+
return () => {
|
|
63
|
+
const index = registry.runtimes.lastIndexOf(runtime);
|
|
64
|
+
if (index >= 0) registry.runtimes.splice(index, 1);
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// src/auto-instrumentation/instrumentation-manifest-registry.ts
|
|
69
|
+
var INSTRUMENTATION_MANIFEST_SYMBOL = "rasputin.instrumentation.manifest.v1";
|
|
70
|
+
var registrySymbol = Symbol.for(INSTRUMENTATION_MANIFEST_SYMBOL);
|
|
71
|
+
var getRegistry2 = () => {
|
|
72
|
+
const existing = Reflect.get(globalThis, registrySymbol);
|
|
73
|
+
if (existing?.__rasputinManifestRegistry && existing.files instanceof Map && typeof existing.generation === "number" && typeof existing.uploadedGeneration === "number") {
|
|
74
|
+
return existing;
|
|
75
|
+
}
|
|
76
|
+
const registry = {
|
|
77
|
+
__rasputinManifestRegistry: true,
|
|
78
|
+
files: /* @__PURE__ */ new Map(),
|
|
79
|
+
generation: 0,
|
|
80
|
+
uploadedGeneration: 0
|
|
81
|
+
};
|
|
82
|
+
Reflect.set(globalThis, registrySymbol, registry);
|
|
83
|
+
return registry;
|
|
84
|
+
};
|
|
85
|
+
var repoRelativePath = (filePath, repoRoot) => {
|
|
86
|
+
const fromRoot = relative2(repoRoot, resolve2(filePath));
|
|
87
|
+
if (!fromRoot || fromRoot === ".." || fromRoot.startsWith(`..${sep2}`) || isAbsolute2(fromRoot)) {
|
|
88
|
+
return void 0;
|
|
89
|
+
}
|
|
90
|
+
return fromRoot.replaceAll("\\", "/");
|
|
91
|
+
};
|
|
92
|
+
var isInstrumentationManifestDirty = () => {
|
|
93
|
+
const registry = getRegistry2();
|
|
94
|
+
return registry.generation !== registry.uploadedGeneration && registry.files.size > 0;
|
|
95
|
+
};
|
|
96
|
+
var instrumentationManifestGeneration = () => getRegistry2().generation;
|
|
97
|
+
var snapshotInstrumentationManifest = (repoRoot) => {
|
|
98
|
+
const functions = [];
|
|
99
|
+
const callSites = [];
|
|
100
|
+
const destructures = [];
|
|
101
|
+
const root = resolve2(repoRoot);
|
|
102
|
+
for (const delta of getRegistry2().files.values()) {
|
|
103
|
+
for (const fn of delta.functions) {
|
|
104
|
+
const functionId = normalizeAutomaticFunctionId(fn.sourceToken, root);
|
|
105
|
+
const path = repoRelativePath(fn.filePath, root);
|
|
106
|
+
if (!functionId || !path) continue;
|
|
107
|
+
functions.push({
|
|
108
|
+
functionId,
|
|
109
|
+
path,
|
|
110
|
+
name: fn.name,
|
|
111
|
+
startLine: fn.startLine,
|
|
112
|
+
startColumn: fn.startColumn,
|
|
113
|
+
endLine: fn.endLine,
|
|
114
|
+
endColumn: fn.endColumn,
|
|
115
|
+
params: fn.params
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
for (const site of delta.callSites) {
|
|
119
|
+
const callerFunctionId = normalizeAutomaticFunctionId(site.callerSourceToken, root);
|
|
120
|
+
const path = repoRelativePath(site.filePath, root);
|
|
121
|
+
if (!callerFunctionId || !path) continue;
|
|
122
|
+
callSites.push({
|
|
123
|
+
id: `${path}:${site.line}:${site.column}`,
|
|
124
|
+
callerFunctionId,
|
|
125
|
+
calleeName: site.calleeName,
|
|
126
|
+
calleeText: site.calleeText,
|
|
127
|
+
path,
|
|
128
|
+
line: site.line,
|
|
129
|
+
column: site.column,
|
|
130
|
+
endLine: site.endLine,
|
|
131
|
+
endColumn: site.endColumn,
|
|
132
|
+
resultBinding: site.resultBinding,
|
|
133
|
+
argIdentifiers: site.argIdentifiers
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
for (const destructure of delta.destructures) {
|
|
137
|
+
const callerFunctionId = normalizeAutomaticFunctionId(destructure.callerSourceToken, root);
|
|
138
|
+
const path = repoRelativePath(destructure.filePath, root);
|
|
139
|
+
if (!callerFunctionId || !path) continue;
|
|
140
|
+
destructures.push({
|
|
141
|
+
callerFunctionId,
|
|
142
|
+
sourceParam: destructure.sourceParam,
|
|
143
|
+
path,
|
|
144
|
+
line: destructure.line,
|
|
145
|
+
column: destructure.column,
|
|
146
|
+
binding: destructure.binding
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (functions.length === 0 && callSites.length === 0 && destructures.length === 0) {
|
|
151
|
+
return void 0;
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
schema_version: 1,
|
|
155
|
+
functions,
|
|
156
|
+
callSites,
|
|
157
|
+
destructures
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
var markInstrumentationManifestUploaded = (generation) => {
|
|
161
|
+
const registry = getRegistry2();
|
|
162
|
+
if (registry.generation === generation) {
|
|
163
|
+
registry.uploadedGeneration = generation;
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
var setInstrumentationManifestOnDirty = (onDirty) => {
|
|
167
|
+
getRegistry2().onDirty = onDirty;
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// src/auto-instrumentation/schedule-instrumentation-manifest-upload.ts
|
|
171
|
+
var noopHandle = {
|
|
172
|
+
flushSoon() {
|
|
173
|
+
},
|
|
174
|
+
async wait() {
|
|
175
|
+
},
|
|
176
|
+
disconnect() {
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
var scheduleInstrumentationManifestUpload = (options) => {
|
|
180
|
+
const release = detectRelease({ release: options.release });
|
|
181
|
+
const repoRoot = options.repoRoot;
|
|
182
|
+
if (!options.enabled || !release || !repoRoot || !options.projectApiKey.trim()) {
|
|
183
|
+
return noopHandle;
|
|
184
|
+
}
|
|
185
|
+
const { instrumentationManifestUrl } = resolveEndpointUrls(options.apiUrl);
|
|
186
|
+
let inflight;
|
|
187
|
+
const flushSoon = () => {
|
|
188
|
+
if (!isInstrumentationManifestDirty()) return;
|
|
189
|
+
const generation = instrumentationManifestGeneration();
|
|
190
|
+
const manifest = snapshotInstrumentationManifest(repoRoot);
|
|
191
|
+
if (!manifest) {
|
|
192
|
+
markInstrumentationManifestUploaded(generation);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const work = uploadInstrumentationManifest({
|
|
196
|
+
url: instrumentationManifestUrl,
|
|
197
|
+
projectApiKey: options.projectApiKey,
|
|
198
|
+
release,
|
|
199
|
+
manifest,
|
|
200
|
+
fetch: options.fetch
|
|
201
|
+
}).then((result) => {
|
|
202
|
+
if (result === "ok") markInstrumentationManifestUploaded(generation);
|
|
203
|
+
});
|
|
204
|
+
inflight = inflight ? inflight.then(() => work) : work;
|
|
205
|
+
};
|
|
206
|
+
setInstrumentationManifestOnDirty(flushSoon);
|
|
207
|
+
flushSoon();
|
|
208
|
+
return {
|
|
209
|
+
flushSoon,
|
|
210
|
+
wait: async () => {
|
|
211
|
+
await inflight;
|
|
212
|
+
},
|
|
213
|
+
disconnect: () => {
|
|
214
|
+
setInstrumentationManifestOnDirty(void 0);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// src/execution-recorder/execution-recorder.ts
|
|
220
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
221
|
+
|
|
222
|
+
// src/execution-recorder/call-aware-event-buffer.ts
|
|
223
|
+
var CallAwareEventBuffer = class {
|
|
224
|
+
constructor(capacity) {
|
|
225
|
+
this.capacity = capacity;
|
|
226
|
+
}
|
|
227
|
+
items = [];
|
|
228
|
+
openCallIds = /* @__PURE__ */ new Set();
|
|
229
|
+
dropped = 0;
|
|
230
|
+
canStartCall() {
|
|
231
|
+
return this.items.length + this.openCallIds.size + 2 <= this.capacity;
|
|
232
|
+
}
|
|
233
|
+
startCall(event) {
|
|
234
|
+
this.items.push(event);
|
|
235
|
+
this.openCallIds.add(event.callId);
|
|
236
|
+
}
|
|
237
|
+
finishCall(event) {
|
|
238
|
+
if (event.type !== "function_exit" && event.type !== "function_throw") return;
|
|
239
|
+
if (!this.openCallIds.delete(event.callId)) return;
|
|
240
|
+
this.items.push(event);
|
|
241
|
+
}
|
|
242
|
+
dropCall() {
|
|
243
|
+
this.dropped += 2;
|
|
244
|
+
}
|
|
245
|
+
append(event) {
|
|
246
|
+
if (this.items.length + this.openCallIds.size + 1 > this.capacity) {
|
|
247
|
+
this.dropped++;
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
this.items.push(event);
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
forceCompletedCall(enter, terminal) {
|
|
254
|
+
while (this.items.length + this.openCallIds.size + 2 > this.capacity) {
|
|
255
|
+
if (!this.evictCompletedLeafOrSummary()) {
|
|
256
|
+
this.dropCall();
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
this.items.push(enter, terminal);
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
values() {
|
|
264
|
+
return [...this.items];
|
|
265
|
+
}
|
|
266
|
+
contains(target) {
|
|
267
|
+
return this.items.includes(target);
|
|
268
|
+
}
|
|
269
|
+
evictCompletedLeafOrSummary() {
|
|
270
|
+
const summaryIndex = this.items.findIndex(
|
|
271
|
+
(event) => event.type === "function_calls_suppressed"
|
|
272
|
+
);
|
|
273
|
+
if (summaryIndex >= 0) {
|
|
274
|
+
this.items.splice(summaryIndex, 1);
|
|
275
|
+
this.dropped++;
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
const parentCallIds = /* @__PURE__ */ new Set();
|
|
279
|
+
for (const event of this.items) {
|
|
280
|
+
if ((event.type === "function_enter" || event.type === "function_calls_suppressed") && event.parentCallId !== void 0) {
|
|
281
|
+
parentCallIds.add(event.parentCallId);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
for (let index = 0; index < this.items.length; index++) {
|
|
285
|
+
const event = this.items[index];
|
|
286
|
+
if (event?.type !== "function_enter" || this.openCallIds.has(event.callId) || parentCallIds.has(event.callId)) {
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
const terminalIndex = this.items.findIndex(
|
|
290
|
+
(candidate) => (candidate.type === "function_exit" || candidate.type === "function_throw") && candidate.callId === event.callId
|
|
291
|
+
);
|
|
292
|
+
if (terminalIndex < 0) continue;
|
|
293
|
+
this.items.splice(Math.max(index, terminalIndex), 1);
|
|
294
|
+
this.items.splice(Math.min(index, terminalIndex), 1);
|
|
295
|
+
this.dropped += 2;
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
// src/execution-recorder/recorder-memory-budget.ts
|
|
303
|
+
import { Buffer } from "node:buffer";
|
|
304
|
+
var EXECUTION_BASE_ESTIMATED_BYTES = 1024;
|
|
305
|
+
var EVENT_PAIR_BASE_ESTIMATED_BYTES = 512;
|
|
306
|
+
var SUMMARY_EVENT_BASE_ESTIMATED_BYTES = 256;
|
|
307
|
+
var VALUE_HEAP_ESTIMATE_MULTIPLIER = 2;
|
|
308
|
+
var MEMORY_BUDGET_VALUE_MARKER = {
|
|
309
|
+
__rasputin_type: "omitted",
|
|
310
|
+
__reason: "process_memory_budget"
|
|
311
|
+
};
|
|
312
|
+
var RecorderMemoryBudget = class {
|
|
313
|
+
constructor(maximumBytes, maximumSerializedValueBytes) {
|
|
314
|
+
this.maximumBytes = maximumBytes;
|
|
315
|
+
this.maximumSerializedValueBytes = maximumSerializedValueBytes;
|
|
316
|
+
}
|
|
317
|
+
activeEstimatedBytes = 0;
|
|
318
|
+
stats = {
|
|
319
|
+
activeEstimatedBytes: 0,
|
|
320
|
+
peakActiveEstimatedBytes: 0,
|
|
321
|
+
memoryPressureExecutions: 0,
|
|
322
|
+
memoryPressureDegradations: 0,
|
|
323
|
+
valuesDroppedByMemoryBudget: 0,
|
|
324
|
+
eventsDroppedByMemoryBudget: 0
|
|
325
|
+
};
|
|
326
|
+
startExecution() {
|
|
327
|
+
const allocation = {
|
|
328
|
+
mode: "full",
|
|
329
|
+
estimatedBytes: 0,
|
|
330
|
+
released: false,
|
|
331
|
+
underPressure: false,
|
|
332
|
+
valuesDropped: 0,
|
|
333
|
+
eventsDropped: 0
|
|
334
|
+
};
|
|
335
|
+
if (!this.reserve(allocation, EXECUTION_BASE_ESTIMATED_BYTES)) {
|
|
336
|
+
this.markPressure(allocation, "metadata-only");
|
|
337
|
+
}
|
|
338
|
+
return allocation;
|
|
339
|
+
}
|
|
340
|
+
captureValue(allocation, serialize) {
|
|
341
|
+
if (allocation.mode !== "full") {
|
|
342
|
+
this.dropValues(allocation, 1);
|
|
343
|
+
return MEMORY_BUDGET_VALUE_MARKER;
|
|
344
|
+
}
|
|
345
|
+
const maximumEstimate = this.maximumSerializedValueBytes * VALUE_HEAP_ESTIMATE_MULTIPLIER;
|
|
346
|
+
if (this.activeEstimatedBytes + maximumEstimate > this.maximumBytes) {
|
|
347
|
+
this.markPressure(allocation, "structure-only");
|
|
348
|
+
this.dropValues(allocation, 1);
|
|
349
|
+
return MEMORY_BUDGET_VALUE_MARKER;
|
|
350
|
+
}
|
|
351
|
+
const serialized = serialize();
|
|
352
|
+
if (!this.reserve(allocation, serialized.bytes * VALUE_HEAP_ESTIMATE_MULTIPLIER)) {
|
|
353
|
+
this.markPressure(allocation, "structure-only");
|
|
354
|
+
this.dropValues(allocation, 1);
|
|
355
|
+
return MEMORY_BUDGET_VALUE_MARKER;
|
|
356
|
+
}
|
|
357
|
+
return serialized.value;
|
|
358
|
+
}
|
|
359
|
+
reserveCall(allocation, functionId) {
|
|
360
|
+
if (allocation.mode === "metadata-only") {
|
|
361
|
+
this.dropEvents(allocation, 2);
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
const estimatedBytes = EVENT_PAIR_BASE_ESTIMATED_BYTES + Buffer.byteLength(functionId, "utf8") * 2;
|
|
365
|
+
if (this.reserve(allocation, estimatedBytes)) return true;
|
|
366
|
+
this.markPressure(allocation, "metadata-only");
|
|
367
|
+
this.dropEvents(allocation, 2);
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
reserveStandaloneEvent(allocation) {
|
|
371
|
+
if (allocation.mode === "metadata-only") {
|
|
372
|
+
this.dropEvents(allocation, 1);
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
if (this.reserve(allocation, SUMMARY_EVENT_BASE_ESTIMATED_BYTES)) return true;
|
|
376
|
+
this.markPressure(allocation, "metadata-only");
|
|
377
|
+
this.dropEvents(allocation, 1);
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
release(allocation) {
|
|
381
|
+
if (allocation.released) return;
|
|
382
|
+
allocation.released = true;
|
|
383
|
+
this.activeEstimatedBytes = Math.max(0, this.activeEstimatedBytes - allocation.estimatedBytes);
|
|
384
|
+
this.stats.activeEstimatedBytes = this.activeEstimatedBytes;
|
|
385
|
+
}
|
|
386
|
+
getStats() {
|
|
387
|
+
return { ...this.stats };
|
|
388
|
+
}
|
|
389
|
+
reserve(allocation, bytes) {
|
|
390
|
+
const boundedBytes = Math.max(0, Math.ceil(bytes));
|
|
391
|
+
if (this.activeEstimatedBytes + boundedBytes > this.maximumBytes) return false;
|
|
392
|
+
this.activeEstimatedBytes += boundedBytes;
|
|
393
|
+
allocation.estimatedBytes += boundedBytes;
|
|
394
|
+
this.stats.activeEstimatedBytes = this.activeEstimatedBytes;
|
|
395
|
+
this.stats.peakActiveEstimatedBytes = Math.max(
|
|
396
|
+
this.stats.peakActiveEstimatedBytes,
|
|
397
|
+
this.activeEstimatedBytes
|
|
398
|
+
);
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
markPressure(allocation, mode) {
|
|
402
|
+
if (!allocation.underPressure) {
|
|
403
|
+
allocation.underPressure = true;
|
|
404
|
+
this.stats.memoryPressureExecutions++;
|
|
405
|
+
}
|
|
406
|
+
if (allocation.mode === mode || allocation.mode === "metadata-only" && mode === "structure-only") {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
allocation.mode = mode;
|
|
410
|
+
this.stats.memoryPressureDegradations++;
|
|
411
|
+
}
|
|
412
|
+
dropValues(allocation, count) {
|
|
413
|
+
allocation.valuesDropped += count;
|
|
414
|
+
this.stats.valuesDroppedByMemoryBudget += count;
|
|
415
|
+
}
|
|
416
|
+
dropEvents(allocation, count) {
|
|
417
|
+
allocation.eventsDropped += count;
|
|
418
|
+
this.stats.eventsDroppedByMemoryBudget += count;
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
// src/execution-recorder/safe-serialize.ts
|
|
423
|
+
import { Buffer as Buffer2 } from "node:buffer";
|
|
424
|
+
var DEFAULT_REDACT_KEYS = /* @__PURE__ */ new Set([
|
|
425
|
+
"password",
|
|
426
|
+
"token",
|
|
427
|
+
"authorization",
|
|
428
|
+
"cookie",
|
|
429
|
+
"secret",
|
|
430
|
+
"apikey",
|
|
431
|
+
"creditcard"
|
|
432
|
+
]);
|
|
433
|
+
var defaults = {
|
|
434
|
+
maxDepth: 3,
|
|
435
|
+
maxObjectKeys: 30,
|
|
436
|
+
maxArrayElements: 20,
|
|
437
|
+
maxStringLength: 500,
|
|
438
|
+
maxSerializedValueBytes: 8 * 1024
|
|
439
|
+
};
|
|
440
|
+
var truncation = (reason, extra = {}) => ({
|
|
441
|
+
__rasputin_truncated: true,
|
|
442
|
+
__reason: reason,
|
|
443
|
+
...extra
|
|
444
|
+
});
|
|
445
|
+
var typeMarker = (type, value) => ({
|
|
446
|
+
__rasputin_type: type,
|
|
447
|
+
...value === void 0 ? {} : { value }
|
|
448
|
+
});
|
|
449
|
+
var redact = (item, redactKeys, seen) => {
|
|
450
|
+
if (!item || typeof item !== "object") return item;
|
|
451
|
+
if (seen.has(item)) return item;
|
|
452
|
+
seen.add(item);
|
|
453
|
+
if (Array.isArray(item)) {
|
|
454
|
+
return item.map((entry) => redact(entry, redactKeys, seen));
|
|
455
|
+
}
|
|
456
|
+
for (const [key, child] of Object.entries(item)) {
|
|
457
|
+
item[key] = redactKeys.has(key.toLowerCase()) ? "[RASPUTIN_REDACTED]" : redact(child, redactKeys, seen);
|
|
458
|
+
}
|
|
459
|
+
return item;
|
|
460
|
+
};
|
|
461
|
+
var errorValue = (error, depth, seen, limits) => ({
|
|
462
|
+
__rasputin_type: "Error",
|
|
463
|
+
name: error.name,
|
|
464
|
+
message: serializeInner(error.message, depth + 1, seen, limits),
|
|
465
|
+
...error.stack ? { stack: serializeInner(error.stack, depth + 1, seen, limits) } : {}
|
|
466
|
+
});
|
|
467
|
+
var serializeInner = (value, depth, seen, limits) => {
|
|
468
|
+
if (value === null || typeof value === "boolean" || typeof value === "number") return value;
|
|
469
|
+
if (typeof value === "string") {
|
|
470
|
+
if (value.length <= limits.maxStringLength) return value;
|
|
471
|
+
return truncation("max_string_length", {
|
|
472
|
+
__original_length: value.length,
|
|
473
|
+
value: value.slice(0, limits.maxStringLength)
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
if (typeof value === "undefined") return typeMarker("undefined");
|
|
477
|
+
if (typeof value === "bigint") return typeMarker("bigint", value.toString());
|
|
478
|
+
if (typeof value === "symbol") return typeMarker("symbol", String(value));
|
|
479
|
+
if (typeof value === "function") return typeMarker("function", value.name || "anonymous");
|
|
480
|
+
if (depth >= limits.maxDepth) return truncation("max_depth");
|
|
481
|
+
if (typeof value !== "object") return typeMarker(typeof value);
|
|
482
|
+
if (seen.has(value)) return typeMarker("circular");
|
|
483
|
+
seen.add(value);
|
|
484
|
+
try {
|
|
485
|
+
if (value instanceof Error) return errorValue(value, depth, seen, limits);
|
|
486
|
+
if (value instanceof Date) return typeMarker("Date", value.toISOString());
|
|
487
|
+
if (Buffer2.isBuffer(value)) {
|
|
488
|
+
return typeMarker("Buffer", {
|
|
489
|
+
byteLength: value.byteLength,
|
|
490
|
+
base64: value.subarray(0, limits.maxStringLength).toString("base64"),
|
|
491
|
+
...value.byteLength > limits.maxStringLength ? { __rasputin_truncated: true } : {}
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
if (value instanceof Promise) return typeMarker("Promise");
|
|
495
|
+
if (value instanceof Map) {
|
|
496
|
+
const entries = [];
|
|
497
|
+
for (const entry of value.entries()) {
|
|
498
|
+
if (entries.length >= limits.maxArrayElements) break;
|
|
499
|
+
entries.push([
|
|
500
|
+
serializeInner(entry[0], depth + 1, seen, limits),
|
|
501
|
+
serializeInner(entry[1], depth + 1, seen, limits)
|
|
502
|
+
]);
|
|
503
|
+
}
|
|
504
|
+
return {
|
|
505
|
+
__rasputin_type: "Map",
|
|
506
|
+
entries,
|
|
507
|
+
...value.size > limits.maxArrayElements ? truncation("max_array_elements", { __original_length: value.size }) : {}
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
if (value instanceof Set) {
|
|
511
|
+
const items = [];
|
|
512
|
+
for (const item of value.values()) {
|
|
513
|
+
if (items.length >= limits.maxArrayElements) break;
|
|
514
|
+
items.push(serializeInner(item, depth + 1, seen, limits));
|
|
515
|
+
}
|
|
516
|
+
return {
|
|
517
|
+
__rasputin_type: "Set",
|
|
518
|
+
values: items,
|
|
519
|
+
...value.size > limits.maxArrayElements ? truncation("max_array_elements", { __original_length: value.size }) : {}
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
if (Array.isArray(value)) {
|
|
523
|
+
const maxItems = value.length > limits.maxArrayElements ? limits.maxArrayElements - 1 : value.length;
|
|
524
|
+
const items = value.slice(0, maxItems).map((item) => serializeInner(item, depth + 1, seen, limits));
|
|
525
|
+
if (value.length > limits.maxArrayElements) {
|
|
526
|
+
items.push(truncation("max_array_elements", { __original_length: value.length }));
|
|
527
|
+
}
|
|
528
|
+
return items;
|
|
529
|
+
}
|
|
530
|
+
const prototype = Object.getPrototypeOf(value);
|
|
531
|
+
const serialized = {};
|
|
532
|
+
if (prototype && prototype !== Object.prototype) {
|
|
533
|
+
serialized.__rasputin_type = prototype.constructor?.name ?? "instance";
|
|
534
|
+
}
|
|
535
|
+
const keys = Object.keys(value);
|
|
536
|
+
const maxKeys = keys.length > limits.maxObjectKeys ? limits.maxObjectKeys - 1 : keys.length;
|
|
537
|
+
for (const key of keys.slice(0, maxKeys)) {
|
|
538
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
539
|
+
serialized[key] = descriptor && "value" in descriptor ? serializeInner(descriptor.value, depth + 1, seen, limits) : typeMarker("accessor");
|
|
540
|
+
}
|
|
541
|
+
if (keys.length > limits.maxObjectKeys) {
|
|
542
|
+
Object.assign(serialized, truncation("max_object_keys", { __original_length: keys.length }));
|
|
543
|
+
}
|
|
544
|
+
return serialized;
|
|
545
|
+
} catch (error) {
|
|
546
|
+
return typeMarker("unserializable", error instanceof Error ? error.message : void 0);
|
|
547
|
+
} finally {
|
|
548
|
+
seen.delete(value);
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
var safeSerializeWithBytes = (value, options = {}) => {
|
|
552
|
+
const limits = {
|
|
553
|
+
maxDepth: options.maxDepth ?? defaults.maxDepth,
|
|
554
|
+
maxObjectKeys: options.maxObjectKeys ?? defaults.maxObjectKeys,
|
|
555
|
+
maxArrayElements: options.maxArrayElements ?? defaults.maxArrayElements,
|
|
556
|
+
maxStringLength: options.maxStringLength ?? defaults.maxStringLength,
|
|
557
|
+
maxSerializedValueBytes: options.maxSerializedValueBytes ?? defaults.maxSerializedValueBytes
|
|
558
|
+
};
|
|
559
|
+
try {
|
|
560
|
+
const redactKeys = /* @__PURE__ */ new Set([
|
|
561
|
+
...DEFAULT_REDACT_KEYS,
|
|
562
|
+
...(options.redactKeys ?? []).map((key) => key.toLowerCase())
|
|
563
|
+
]);
|
|
564
|
+
const serialized = serializeInner(value, 0, /* @__PURE__ */ new WeakSet(), limits);
|
|
565
|
+
const redacted = redact(serialized, redactKeys, /* @__PURE__ */ new WeakSet());
|
|
566
|
+
const bytes = Buffer2.byteLength(JSON.stringify(redacted), "utf8");
|
|
567
|
+
const bounded = bytes <= limits.maxSerializedValueBytes ? redacted : truncation("max_serialized_value_bytes", { __serialized_bytes: bytes });
|
|
568
|
+
return {
|
|
569
|
+
value: bounded,
|
|
570
|
+
bytes: bounded === redacted ? bytes : Buffer2.byteLength(JSON.stringify(bounded), "utf8")
|
|
571
|
+
};
|
|
572
|
+
} catch {
|
|
573
|
+
const value2 = typeMarker("unserializable");
|
|
574
|
+
return { value: value2, bytes: Buffer2.byteLength(JSON.stringify(value2), "utf8") };
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
var safeSerialize = (value, options = {}) => safeSerializeWithBytes(value, options).value;
|
|
578
|
+
|
|
579
|
+
// src/execution-recorder/source-exclusions.ts
|
|
580
|
+
var sourcePathFrom = (functionId) => {
|
|
581
|
+
const separator = functionId.indexOf(":");
|
|
582
|
+
return (separator < 0 ? functionId : functionId.slice(0, separator)).replaceAll("\\", "/");
|
|
583
|
+
};
|
|
584
|
+
var normalizePattern = (pattern) => pattern.trim().replaceAll("\\", "/").replace(/^\.\//, "").replace(/\/$/, "");
|
|
585
|
+
var globRegex = (pattern) => {
|
|
586
|
+
let expression = "";
|
|
587
|
+
for (let index = 0; index < pattern.length; index++) {
|
|
588
|
+
const character = pattern[index];
|
|
589
|
+
const next = pattern[index + 1];
|
|
590
|
+
if (character === "*" && next === "*") {
|
|
591
|
+
if (pattern[index + 2] === "/") {
|
|
592
|
+
expression += "(?:.*/)?";
|
|
593
|
+
index += 2;
|
|
594
|
+
} else {
|
|
595
|
+
expression += ".*";
|
|
596
|
+
index++;
|
|
597
|
+
}
|
|
598
|
+
continue;
|
|
599
|
+
}
|
|
600
|
+
if (character === "*") {
|
|
601
|
+
expression += "[^/]*";
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
if (character === "?") {
|
|
605
|
+
expression += "[^/]";
|
|
606
|
+
continue;
|
|
607
|
+
}
|
|
608
|
+
expression += character?.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") ?? "";
|
|
609
|
+
}
|
|
610
|
+
return new RegExp(`^${expression}$`);
|
|
611
|
+
};
|
|
612
|
+
var createSourceExclusionMatcher = (exclusions) => {
|
|
613
|
+
const matchers = (exclusions ?? []).flatMap((exclusion) => {
|
|
614
|
+
if (exclusion instanceof RegExp) {
|
|
615
|
+
return [
|
|
616
|
+
(functionId) => {
|
|
617
|
+
exclusion.lastIndex = 0;
|
|
618
|
+
const matched = exclusion.test(functionId);
|
|
619
|
+
exclusion.lastIndex = 0;
|
|
620
|
+
return matched;
|
|
621
|
+
}
|
|
622
|
+
];
|
|
623
|
+
}
|
|
624
|
+
const pattern = normalizePattern(exclusion);
|
|
625
|
+
if (!pattern) return [];
|
|
626
|
+
if (pattern.includes("*") || pattern.includes("?")) {
|
|
627
|
+
const regex = globRegex(pattern);
|
|
628
|
+
return [(functionId) => regex.test(sourcePathFrom(functionId))];
|
|
629
|
+
}
|
|
630
|
+
return [
|
|
631
|
+
(functionId) => {
|
|
632
|
+
const sourcePath = sourcePathFrom(functionId);
|
|
633
|
+
return sourcePath === pattern || sourcePath.startsWith(`${pattern}/`);
|
|
634
|
+
}
|
|
635
|
+
];
|
|
636
|
+
});
|
|
637
|
+
return matchers.length === 0 ? () => false : (functionId) => matchers.some((matcher) => matcher(functionId));
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
// src/execution-recorder/execution-recorder.ts
|
|
641
|
+
var DEFAULT_MAX_ACTIVE_MEMORY_BYTES = 64 * 1024 * 1024;
|
|
642
|
+
var elapsedMs = (startedAtNs, endedAtNs = process.hrtime.bigint()) => Number(endedAtNs - startedAtNs) / 1e6;
|
|
643
|
+
var roundedMilliseconds = (nanoseconds) => Math.round(Number(nanoseconds) / 1e6 * 1e4) / 1e4;
|
|
644
|
+
var addRecorderTime = (recording, nanoseconds) => {
|
|
645
|
+
if (nanoseconds > 0n) recording.inlineRecorderTimeNs += nanoseconds;
|
|
646
|
+
};
|
|
647
|
+
var isPromiseLike = (value) => Boolean(value) && typeof value.then === "function";
|
|
648
|
+
var notifyObserver = (observer, value) => {
|
|
649
|
+
try {
|
|
650
|
+
observer(value);
|
|
651
|
+
} catch {
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
var observeCallback = (callback, onReturn, onThrow) => {
|
|
655
|
+
let result;
|
|
656
|
+
try {
|
|
657
|
+
result = callback();
|
|
658
|
+
} catch (error) {
|
|
659
|
+
notifyObserver(onThrow, error);
|
|
660
|
+
throw error;
|
|
661
|
+
}
|
|
662
|
+
if (isPromiseLike(result)) {
|
|
663
|
+
return result.then(
|
|
664
|
+
(value) => {
|
|
665
|
+
notifyObserver(onReturn, value);
|
|
666
|
+
return value;
|
|
667
|
+
},
|
|
668
|
+
(error) => {
|
|
669
|
+
notifyObserver(onThrow, error);
|
|
670
|
+
throw error;
|
|
671
|
+
}
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
notifyObserver(onReturn, result);
|
|
675
|
+
return result;
|
|
676
|
+
};
|
|
677
|
+
var observeRecordedCallback = (recording, recorderStartedAtNs, callback, onReturn, onThrow) => {
|
|
678
|
+
const callbackStartedAtNs = process.hrtime.bigint();
|
|
679
|
+
const recordExitWork = (callbackEndedAtNs2) => {
|
|
680
|
+
addRecorderTime(recording, callbackStartedAtNs - recorderStartedAtNs);
|
|
681
|
+
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs2);
|
|
682
|
+
};
|
|
683
|
+
let result;
|
|
684
|
+
try {
|
|
685
|
+
result = callback();
|
|
686
|
+
} catch (error) {
|
|
687
|
+
const callbackEndedAtNs2 = process.hrtime.bigint();
|
|
688
|
+
notifyObserver(onThrow, error);
|
|
689
|
+
recordExitWork(callbackEndedAtNs2);
|
|
690
|
+
throw error;
|
|
691
|
+
}
|
|
692
|
+
if (isPromiseLike(result)) {
|
|
693
|
+
return result.then(
|
|
694
|
+
(value) => {
|
|
695
|
+
const callbackEndedAtNs2 = process.hrtime.bigint();
|
|
696
|
+
notifyObserver(onReturn, value);
|
|
697
|
+
recordExitWork(callbackEndedAtNs2);
|
|
698
|
+
return value;
|
|
699
|
+
},
|
|
700
|
+
(error) => {
|
|
701
|
+
const callbackEndedAtNs2 = process.hrtime.bigint();
|
|
702
|
+
notifyObserver(onThrow, error);
|
|
703
|
+
recordExitWork(callbackEndedAtNs2);
|
|
704
|
+
throw error;
|
|
705
|
+
}
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
const callbackEndedAtNs = process.hrtime.bigint();
|
|
709
|
+
notifyObserver(onReturn, result);
|
|
710
|
+
recordExitWork(callbackEndedAtNs);
|
|
711
|
+
return result;
|
|
712
|
+
};
|
|
713
|
+
var noOpExecution = {
|
|
714
|
+
createScope: () => ({
|
|
715
|
+
run: (callback) => callback(),
|
|
716
|
+
getErrorState: () => void 0,
|
|
717
|
+
finish: () => {
|
|
718
|
+
}
|
|
719
|
+
}),
|
|
720
|
+
run: (_metadata, callback) => callback(),
|
|
721
|
+
getErrorState: () => void 0,
|
|
722
|
+
runFunction: (_functionId, _args, callback) => callback(),
|
|
723
|
+
trace: (_functionId, fn) => fn,
|
|
724
|
+
getStats: () => ({
|
|
725
|
+
errorSnapshots: 0,
|
|
726
|
+
successfulExecutionsDiscarded: 0,
|
|
727
|
+
truncatedEvents: 0,
|
|
728
|
+
repeatedCallsSuppressed: 0,
|
|
729
|
+
activeExecutions: 0,
|
|
730
|
+
peakActiveExecutions: 0,
|
|
731
|
+
activeEstimatedBytes: 0,
|
|
732
|
+
peakActiveEstimatedBytes: 0,
|
|
733
|
+
memoryPressureExecutions: 0,
|
|
734
|
+
memoryPressureDegradations: 0,
|
|
735
|
+
valuesDroppedByMemoryBudget: 0,
|
|
736
|
+
eventsDroppedByMemoryBudget: 0,
|
|
737
|
+
partialErrorSnapshots: 0
|
|
738
|
+
})
|
|
739
|
+
};
|
|
740
|
+
var mergeExecutionMetadata = (target, metadata) => {
|
|
741
|
+
if (metadata.kind) target.kind = metadata.kind;
|
|
742
|
+
if (metadata.name !== void 0) target.name = metadata.name;
|
|
743
|
+
if (metadata.request) target.request = { ...target.request, ...metadata.request };
|
|
744
|
+
};
|
|
745
|
+
var createExecutionRecorder = (options) => {
|
|
746
|
+
if (!options?.enabled) return noOpExecution;
|
|
747
|
+
const storage = new AsyncLocalStorage();
|
|
748
|
+
const maxEventsPerExecution = Math.max(2, Math.floor(options.maxEventsPerExecution ?? 500));
|
|
749
|
+
const maxCapturedCallsPerFunction = Math.max(
|
|
750
|
+
1,
|
|
751
|
+
Math.floor(options.maxCapturedCallsPerFunction ?? 3)
|
|
752
|
+
);
|
|
753
|
+
const maxActiveMemoryBytes = Math.max(
|
|
754
|
+
0,
|
|
755
|
+
Math.floor(options.maxActiveMemoryBytes ?? DEFAULT_MAX_ACTIVE_MEMORY_BYTES)
|
|
756
|
+
);
|
|
757
|
+
const memoryBudget = new RecorderMemoryBudget(
|
|
758
|
+
maxActiveMemoryBytes,
|
|
759
|
+
options.maxSerializedValueBytes ?? 8 * 1024
|
|
760
|
+
);
|
|
761
|
+
const excludesSource = createSourceExclusionMatcher(options.excludeSources);
|
|
762
|
+
let executionCounter = 0;
|
|
763
|
+
const errorExecutions = /* @__PURE__ */ new WeakMap();
|
|
764
|
+
const stats = {
|
|
765
|
+
errorSnapshots: 0,
|
|
766
|
+
successfulExecutionsDiscarded: 0,
|
|
767
|
+
truncatedEvents: 0,
|
|
768
|
+
repeatedCallsSuppressed: 0,
|
|
769
|
+
activeExecutions: 0,
|
|
770
|
+
peakActiveExecutions: 0,
|
|
771
|
+
partialErrorSnapshots: 0
|
|
772
|
+
};
|
|
773
|
+
const captureValue = (recording, value) => memoryBudget.captureValue(recording.memory, () => safeSerializeWithBytes(value, options));
|
|
774
|
+
const stateFrom = (recording, endedAtNs = process.hrtime.bigint()) => {
|
|
775
|
+
const recorderStartedAtNs = process.hrtime.bigint();
|
|
776
|
+
const state = {
|
|
777
|
+
version: 1,
|
|
778
|
+
executionId: recording.executionId,
|
|
779
|
+
startedAt: recording.startedAt,
|
|
780
|
+
durationMs: elapsedMs(recording.startedAtNs, endedAtNs),
|
|
781
|
+
recorder: { inlineWallTimeMs: 0 },
|
|
782
|
+
execution: {
|
|
783
|
+
...recording.execution,
|
|
784
|
+
...recording.execution.request ? { request: { ...recording.execution.request } } : {}
|
|
785
|
+
},
|
|
786
|
+
events: recording.events.values().map((event) => event.type === "function_calls_suppressed" ? { ...event } : event),
|
|
787
|
+
...recording.events.dropped > 0 ? { truncated: { eventsDropped: recording.events.dropped } } : {},
|
|
788
|
+
...recording.memory.underPressure ? {
|
|
789
|
+
capture: {
|
|
790
|
+
completeness: "partial",
|
|
791
|
+
reason: "process_memory_budget",
|
|
792
|
+
valuesDropped: recording.memory.valuesDropped,
|
|
793
|
+
eventsDropped: recording.memory.eventsDropped
|
|
794
|
+
}
|
|
795
|
+
} : {}
|
|
796
|
+
};
|
|
797
|
+
addRecorderTime(recording, process.hrtime.bigint() - recorderStartedAtNs);
|
|
798
|
+
state.recorder = { inlineWallTimeMs: roundedMilliseconds(recording.inlineRecorderTimeNs) };
|
|
799
|
+
return state;
|
|
800
|
+
};
|
|
801
|
+
const rememberError = (error, recording) => {
|
|
802
|
+
recording.hasError = true;
|
|
803
|
+
if (typeof error !== "object" && typeof error !== "function" || error === null) return;
|
|
804
|
+
if (!errorExecutions.has(error)) {
|
|
805
|
+
stats.errorSnapshots++;
|
|
806
|
+
if (recording.memory.underPressure && !recording.partialSnapshotCounted) {
|
|
807
|
+
recording.partialSnapshotCounted = true;
|
|
808
|
+
stats.partialErrorSnapshots++;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
errorExecutions.set(error, recording);
|
|
812
|
+
};
|
|
813
|
+
const countDroppedEvents = (recording, droppedBefore) => {
|
|
814
|
+
stats.truncatedEvents += recording.events.dropped - droppedBefore;
|
|
815
|
+
};
|
|
816
|
+
const appendStandaloneEvent = (recording, event) => {
|
|
817
|
+
if (!memoryBudget.reserveStandaloneEvent(recording.memory)) return;
|
|
818
|
+
const droppedBefore = recording.events.dropped;
|
|
819
|
+
recording.events.append(event);
|
|
820
|
+
countDroppedEvents(recording, droppedBefore);
|
|
821
|
+
};
|
|
822
|
+
const repeatedCallGroup = (recording, functionId, parentCallId) => {
|
|
823
|
+
let byParent = recording.repeatedCalls.get(functionId);
|
|
824
|
+
if (!byParent) {
|
|
825
|
+
byParent = /* @__PURE__ */ new Map();
|
|
826
|
+
recording.repeatedCalls.set(functionId, byParent);
|
|
827
|
+
}
|
|
828
|
+
let group = byParent.get(parentCallId);
|
|
829
|
+
if (!group) {
|
|
830
|
+
group = { observedCalls: 0 };
|
|
831
|
+
byParent.set(parentCallId, group);
|
|
832
|
+
}
|
|
833
|
+
return group;
|
|
834
|
+
};
|
|
835
|
+
const serializedError = (recording, error, callId) => {
|
|
836
|
+
const key = (typeof error === "object" || typeof error === "function") && error !== null ? error : void 0;
|
|
837
|
+
const referencedCallId = key ? recording.capturedErrors.get(key) : void 0;
|
|
838
|
+
if (referencedCallId !== void 0) {
|
|
839
|
+
return {
|
|
840
|
+
value: { __rasputin_type: "ErrorReference", callId: referencedCallId },
|
|
841
|
+
commit: () => {
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
return {
|
|
846
|
+
// Keep the bounded thrown value even after surrounding capture degrades. A partial
|
|
847
|
+
// snapshot without the exception itself would not be useful for investigation.
|
|
848
|
+
value: safeSerialize(error, options),
|
|
849
|
+
commit: () => {
|
|
850
|
+
if (key) recording.capturedErrors.set(key, callId);
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
};
|
|
854
|
+
const captureCompletedThrow = (recording, functionId, args, parentCallId, startedAtNs, startedAtMs, error) => {
|
|
855
|
+
if (!memoryBudget.reserveCall(recording.memory, functionId)) {
|
|
856
|
+
rememberError(error, recording);
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
const callId = ++recording.nextCallId;
|
|
860
|
+
const capturedError = serializedError(recording, error, callId);
|
|
861
|
+
const enter = {
|
|
862
|
+
type: "function_enter",
|
|
863
|
+
callId,
|
|
864
|
+
functionId,
|
|
865
|
+
timestampMs: startedAtMs,
|
|
866
|
+
args: Array.from(args, (argument) => captureValue(recording, argument)),
|
|
867
|
+
...parentCallId === void 0 ? {} : { parentCallId }
|
|
868
|
+
};
|
|
869
|
+
const terminal = {
|
|
870
|
+
type: "function_throw",
|
|
871
|
+
callId,
|
|
872
|
+
timestampMs: elapsedMs(recording.startedAtNs),
|
|
873
|
+
durationMs: elapsedMs(startedAtNs),
|
|
874
|
+
error: capturedError.value
|
|
875
|
+
};
|
|
876
|
+
const droppedBefore = recording.events.dropped;
|
|
877
|
+
const retained = recording.events.forceCompletedCall(enter, terminal);
|
|
878
|
+
if (retained) capturedError.commit();
|
|
879
|
+
countDroppedEvents(recording, droppedBefore);
|
|
880
|
+
rememberError(error, recording);
|
|
881
|
+
};
|
|
882
|
+
const recordSuppressedCall = (recording, group, functionId, parentCallId, startedAtMs, durationMs) => {
|
|
883
|
+
stats.repeatedCallsSuppressed++;
|
|
884
|
+
const endedAtMs = startedAtMs + durationMs;
|
|
885
|
+
if (!group.summary) {
|
|
886
|
+
group.summary = {
|
|
887
|
+
type: "function_calls_suppressed",
|
|
888
|
+
functionId,
|
|
889
|
+
timestampMs: startedAtMs,
|
|
890
|
+
lastTimestampMs: endedAtMs,
|
|
891
|
+
suppressedCallCount: 1,
|
|
892
|
+
totalDurationMs: durationMs,
|
|
893
|
+
...parentCallId === void 0 ? {} : { parentCallId }
|
|
894
|
+
};
|
|
895
|
+
appendStandaloneEvent(recording, group.summary);
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
group.summary.lastTimestampMs = endedAtMs;
|
|
899
|
+
group.summary.suppressedCallCount++;
|
|
900
|
+
group.summary.totalDurationMs = Math.round((group.summary.totalDurationMs + durationMs) * 1e4) / 1e4;
|
|
901
|
+
if (!recording.events.contains(group.summary)) appendStandaloneEvent(recording, group.summary);
|
|
902
|
+
};
|
|
903
|
+
const finish = (store, metadata) => {
|
|
904
|
+
const { recording } = store;
|
|
905
|
+
if (recording.finished) return;
|
|
906
|
+
const recorderStartedAtNs = process.hrtime.bigint();
|
|
907
|
+
recording.finished = true;
|
|
908
|
+
if (metadata) mergeExecutionMetadata(recording.execution, metadata);
|
|
909
|
+
memoryBudget.release(recording.memory);
|
|
910
|
+
stats.activeExecutions = Math.max(0, stats.activeExecutions - 1);
|
|
911
|
+
if (!recording.hasError) stats.successfulExecutionsDiscarded++;
|
|
912
|
+
recording.finishedAtNs = process.hrtime.bigint();
|
|
913
|
+
addRecorderTime(recording, recording.finishedAtNs - recorderStartedAtNs);
|
|
914
|
+
};
|
|
915
|
+
const createScope = (metadata) => {
|
|
916
|
+
const recorderStartedAtNs = process.hrtime.bigint();
|
|
917
|
+
try {
|
|
918
|
+
const recording = {
|
|
919
|
+
executionId: `${Date.now()}-${process.pid}-${++executionCounter}`,
|
|
920
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
921
|
+
startedAtNs: recorderStartedAtNs,
|
|
922
|
+
inlineRecorderTimeNs: 0n,
|
|
923
|
+
execution: {
|
|
924
|
+
...metadata,
|
|
925
|
+
...metadata.request ? { request: { ...metadata.request } } : {}
|
|
926
|
+
},
|
|
927
|
+
events: new CallAwareEventBuffer(maxEventsPerExecution),
|
|
928
|
+
repeatedCalls: /* @__PURE__ */ new Map(),
|
|
929
|
+
capturedErrors: /* @__PURE__ */ new WeakMap(),
|
|
930
|
+
nextCallId: 0,
|
|
931
|
+
finished: false,
|
|
932
|
+
hasError: false,
|
|
933
|
+
memory: memoryBudget.startExecution(),
|
|
934
|
+
partialSnapshotCounted: false
|
|
935
|
+
};
|
|
936
|
+
stats.activeExecutions++;
|
|
937
|
+
stats.peakActiveExecutions = Math.max(stats.peakActiveExecutions, stats.activeExecutions);
|
|
938
|
+
addRecorderTime(recording, process.hrtime.bigint() - recorderStartedAtNs);
|
|
939
|
+
const store = { recording };
|
|
940
|
+
return {
|
|
941
|
+
run: (callback) => {
|
|
942
|
+
const runStartedAtNs = process.hrtime.bigint();
|
|
943
|
+
return storage.run(store, () => {
|
|
944
|
+
addRecorderTime(recording, process.hrtime.bigint() - runStartedAtNs);
|
|
945
|
+
return callback();
|
|
946
|
+
});
|
|
947
|
+
},
|
|
948
|
+
getErrorState: (error, errorMetadata) => {
|
|
949
|
+
const getStateStartedAtNs = process.hrtime.bigint();
|
|
950
|
+
if (errorMetadata) mergeExecutionMetadata(recording.execution, errorMetadata);
|
|
951
|
+
rememberError(error, recording);
|
|
952
|
+
addRecorderTime(recording, process.hrtime.bigint() - getStateStartedAtNs);
|
|
953
|
+
return stateFrom(recording, recording.finishedAtNs);
|
|
954
|
+
},
|
|
955
|
+
finish: (finishMetadata) => finish(store, finishMetadata)
|
|
956
|
+
};
|
|
957
|
+
} catch {
|
|
958
|
+
return noOpExecution.createScope(metadata);
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
const run = (metadata, callback) => {
|
|
962
|
+
const scope = createScope(metadata);
|
|
963
|
+
return scope.run(
|
|
964
|
+
() => observeCallback(
|
|
965
|
+
callback,
|
|
966
|
+
() => scope.finish(),
|
|
967
|
+
(error) => {
|
|
968
|
+
try {
|
|
969
|
+
const store = storage.getStore();
|
|
970
|
+
if (store) {
|
|
971
|
+
const recorderStartedAtNs = process.hrtime.bigint();
|
|
972
|
+
rememberError(error, store.recording);
|
|
973
|
+
addRecorderTime(store.recording, process.hrtime.bigint() - recorderStartedAtNs);
|
|
974
|
+
}
|
|
975
|
+
} finally {
|
|
976
|
+
scope.finish();
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
)
|
|
980
|
+
);
|
|
981
|
+
};
|
|
982
|
+
const getErrorState = (error, metadata) => {
|
|
983
|
+
const getStateStartedAtNs = process.hrtime.bigint();
|
|
984
|
+
try {
|
|
985
|
+
const weakKey = (typeof error === "object" || typeof error === "function") && error !== null ? error : void 0;
|
|
986
|
+
const recording = (weakKey ? errorExecutions.get(weakKey) : void 0) ?? storage.getStore()?.recording;
|
|
987
|
+
if (!recording) return void 0;
|
|
988
|
+
if (metadata) mergeExecutionMetadata(recording.execution, metadata);
|
|
989
|
+
rememberError(error, recording);
|
|
990
|
+
addRecorderTime(recording, process.hrtime.bigint() - getStateStartedAtNs);
|
|
991
|
+
return stateFrom(recording, recording.finishedAtNs);
|
|
992
|
+
} catch {
|
|
993
|
+
return void 0;
|
|
994
|
+
}
|
|
995
|
+
};
|
|
996
|
+
const runFunction = (functionId, args, callback) => {
|
|
997
|
+
const store = storage.getStore();
|
|
998
|
+
if (!store || store.recording.finished) return callback();
|
|
999
|
+
const recorderStartedAtNs = process.hrtime.bigint();
|
|
1000
|
+
if (store.suppressCapture || excludesSource(functionId)) {
|
|
1001
|
+
return storage.run({ ...store, suppressCapture: true }, () => {
|
|
1002
|
+
addRecorderTime(store.recording, process.hrtime.bigint() - recorderStartedAtNs);
|
|
1003
|
+
return callback();
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
const parentCallId = store.currentCallId;
|
|
1007
|
+
const group = repeatedCallGroup(store.recording, functionId, parentCallId);
|
|
1008
|
+
group.observedCalls++;
|
|
1009
|
+
if (group.observedCalls > maxCapturedCallsPerFunction) {
|
|
1010
|
+
const startedAtNs2 = process.hrtime.bigint();
|
|
1011
|
+
const startedAtMs = elapsedMs(store.recording.startedAtNs, startedAtNs2);
|
|
1012
|
+
const captureSuccess = () => recordSuppressedCall(
|
|
1013
|
+
store.recording,
|
|
1014
|
+
group,
|
|
1015
|
+
functionId,
|
|
1016
|
+
parentCallId,
|
|
1017
|
+
startedAtMs,
|
|
1018
|
+
elapsedMs(startedAtNs2)
|
|
1019
|
+
);
|
|
1020
|
+
return observeRecordedCallback(
|
|
1021
|
+
store.recording,
|
|
1022
|
+
recorderStartedAtNs,
|
|
1023
|
+
callback,
|
|
1024
|
+
captureSuccess,
|
|
1025
|
+
(error) => captureCompletedThrow(
|
|
1026
|
+
store.recording,
|
|
1027
|
+
functionId,
|
|
1028
|
+
args,
|
|
1029
|
+
parentCallId,
|
|
1030
|
+
startedAtNs2,
|
|
1031
|
+
startedAtMs,
|
|
1032
|
+
error
|
|
1033
|
+
)
|
|
1034
|
+
);
|
|
1035
|
+
}
|
|
1036
|
+
const startedAtNs = process.hrtime.bigint();
|
|
1037
|
+
if (!store.recording.events.canStartCall()) {
|
|
1038
|
+
const startedAtMs = elapsedMs(store.recording.startedAtNs, startedAtNs);
|
|
1039
|
+
const captureSuccess = () => {
|
|
1040
|
+
const droppedBefore = store.recording.events.dropped;
|
|
1041
|
+
store.recording.events.dropCall();
|
|
1042
|
+
countDroppedEvents(store.recording, droppedBefore);
|
|
1043
|
+
};
|
|
1044
|
+
return storage.run(
|
|
1045
|
+
store,
|
|
1046
|
+
() => observeRecordedCallback(
|
|
1047
|
+
store.recording,
|
|
1048
|
+
recorderStartedAtNs,
|
|
1049
|
+
callback,
|
|
1050
|
+
captureSuccess,
|
|
1051
|
+
(error) => captureCompletedThrow(
|
|
1052
|
+
store.recording,
|
|
1053
|
+
functionId,
|
|
1054
|
+
args,
|
|
1055
|
+
parentCallId,
|
|
1056
|
+
startedAtNs,
|
|
1057
|
+
startedAtMs,
|
|
1058
|
+
error
|
|
1059
|
+
)
|
|
1060
|
+
)
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1063
|
+
if (!memoryBudget.reserveCall(store.recording.memory, functionId)) {
|
|
1064
|
+
return observeRecordedCallback(
|
|
1065
|
+
store.recording,
|
|
1066
|
+
recorderStartedAtNs,
|
|
1067
|
+
callback,
|
|
1068
|
+
() => {
|
|
1069
|
+
},
|
|
1070
|
+
(error) => rememberError(error, store.recording)
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
const callId = ++store.recording.nextCallId;
|
|
1074
|
+
const enter = {
|
|
1075
|
+
type: "function_enter",
|
|
1076
|
+
callId,
|
|
1077
|
+
functionId,
|
|
1078
|
+
timestampMs: elapsedMs(store.recording.startedAtNs),
|
|
1079
|
+
args: Array.from(args, (argument) => captureValue(store.recording, argument)),
|
|
1080
|
+
...parentCallId === void 0 ? {} : { parentCallId }
|
|
1081
|
+
};
|
|
1082
|
+
store.recording.events.startCall(enter);
|
|
1083
|
+
const callStore = { recording: store.recording, currentCallId: callId };
|
|
1084
|
+
return storage.run(
|
|
1085
|
+
callStore,
|
|
1086
|
+
() => observeRecordedCallback(
|
|
1087
|
+
store.recording,
|
|
1088
|
+
recorderStartedAtNs,
|
|
1089
|
+
callback,
|
|
1090
|
+
(value) => {
|
|
1091
|
+
store.recording.events.finishCall({
|
|
1092
|
+
type: "function_exit",
|
|
1093
|
+
callId,
|
|
1094
|
+
timestampMs: elapsedMs(store.recording.startedAtNs),
|
|
1095
|
+
durationMs: elapsedMs(startedAtNs),
|
|
1096
|
+
returnValue: captureValue(store.recording, value)
|
|
1097
|
+
});
|
|
1098
|
+
},
|
|
1099
|
+
(error) => {
|
|
1100
|
+
const capturedError = serializedError(store.recording, error, callId);
|
|
1101
|
+
store.recording.events.finishCall({
|
|
1102
|
+
type: "function_throw",
|
|
1103
|
+
callId,
|
|
1104
|
+
timestampMs: elapsedMs(store.recording.startedAtNs),
|
|
1105
|
+
durationMs: elapsedMs(startedAtNs),
|
|
1106
|
+
error: capturedError.value
|
|
1107
|
+
});
|
|
1108
|
+
capturedError.commit();
|
|
1109
|
+
rememberError(error, store.recording);
|
|
1110
|
+
}
|
|
1111
|
+
)
|
|
1112
|
+
);
|
|
1113
|
+
};
|
|
1114
|
+
function trace(functionId, fn) {
|
|
1115
|
+
return function traced(...args) {
|
|
1116
|
+
return runFunction(functionId, args, () => fn.apply(this, args));
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
return {
|
|
1120
|
+
createScope,
|
|
1121
|
+
run,
|
|
1122
|
+
getErrorState,
|
|
1123
|
+
runFunction,
|
|
1124
|
+
trace,
|
|
1125
|
+
getStats: () => ({ ...stats, ...memoryBudget.getStats() })
|
|
1126
|
+
};
|
|
1127
|
+
};
|
|
1128
|
+
|
|
1
1129
|
// src/install-global-handlers.ts
|
|
1130
|
+
var removeProcessListener = process.off.bind(process);
|
|
2
1131
|
var installGlobalHandlers = (client, options = {}) => {
|
|
3
1132
|
const exitOnUncaught = options.exitOnUncaughtException ?? true;
|
|
4
1133
|
const flushTimeoutMs = options.flushTimeoutMs ?? 2e3;
|
|
@@ -38,8 +1167,8 @@ var installGlobalHandlers = (client, options = {}) => {
|
|
|
38
1167
|
}
|
|
39
1168
|
return () => {
|
|
40
1169
|
try {
|
|
41
|
-
|
|
42
|
-
|
|
1170
|
+
removeProcessListener("uncaughtException", onUncaughtException);
|
|
1171
|
+
removeProcessListener("unhandledRejection", onUnhandledRejection);
|
|
43
1172
|
} catch {
|
|
44
1173
|
}
|
|
45
1174
|
};
|
|
@@ -48,26 +1177,90 @@ var installGlobalHandlers = (client, options = {}) => {
|
|
|
48
1177
|
// src/rasputin-init.ts
|
|
49
1178
|
import {
|
|
50
1179
|
createClient,
|
|
51
|
-
isClientEnabled
|
|
1180
|
+
isClientEnabled,
|
|
1181
|
+
resolveRepoRoot
|
|
52
1182
|
} from "@rasputin-ai/core";
|
|
53
1183
|
|
|
54
1184
|
// src/sdk-meta.ts
|
|
55
1185
|
var SDK_NAME = "@rasputin-ai/node";
|
|
56
|
-
var SDK_VERSION = "0.
|
|
1186
|
+
var SDK_VERSION = "0.3.0";
|
|
57
1187
|
|
|
58
1188
|
// src/rasputin-init.ts
|
|
1189
|
+
var withExecution = (client, execution, installRuntime, repoRoot, manifest) => {
|
|
1190
|
+
const uninstallRuntime = installRuntime ? installAutomaticExecutionRuntime(execution, { repoRoot }) : () => {
|
|
1191
|
+
};
|
|
1192
|
+
const manifestUpload = scheduleInstrumentationManifestUpload({
|
|
1193
|
+
...manifest,
|
|
1194
|
+
repoRoot
|
|
1195
|
+
});
|
|
1196
|
+
return {
|
|
1197
|
+
...client,
|
|
1198
|
+
execution,
|
|
1199
|
+
getStats: () => ({ ...client.getStats(), recorder: execution.getStats() }),
|
|
1200
|
+
captureException: (error, context) => {
|
|
1201
|
+
const runtimeState = context?.runtimeState ?? execution.getErrorState(
|
|
1202
|
+
error,
|
|
1203
|
+
context?.request ? { kind: "http", request: context.request } : void 0
|
|
1204
|
+
);
|
|
1205
|
+
const result = client.captureException(error, { ...context, runtimeState });
|
|
1206
|
+
manifestUpload.flushSoon();
|
|
1207
|
+
return result;
|
|
1208
|
+
},
|
|
1209
|
+
flush: async (timeoutMs) => {
|
|
1210
|
+
await client.flush(timeoutMs);
|
|
1211
|
+
await manifestUpload.wait();
|
|
1212
|
+
},
|
|
1213
|
+
close: async () => {
|
|
1214
|
+
uninstallRuntime();
|
|
1215
|
+
manifestUpload.disconnect();
|
|
1216
|
+
await client.close();
|
|
1217
|
+
await manifestUpload.wait();
|
|
1218
|
+
}
|
|
1219
|
+
};
|
|
1220
|
+
};
|
|
59
1221
|
var RasputinInit = (options) => {
|
|
60
1222
|
try {
|
|
61
1223
|
const client = createClient(options, { sdkVersion: SDK_VERSION, sdkName: SDK_NAME });
|
|
1224
|
+
const recorderEnabled = isClientEnabled(options) && options.executionRecorder?.enabled !== false;
|
|
1225
|
+
const execution = createExecutionRecorder({
|
|
1226
|
+
...options.executionRecorder,
|
|
1227
|
+
enabled: recorderEnabled
|
|
1228
|
+
});
|
|
1229
|
+
const wrappedClient = withExecution(
|
|
1230
|
+
client,
|
|
1231
|
+
execution,
|
|
1232
|
+
recorderEnabled,
|
|
1233
|
+
resolveRepoRoot(options),
|
|
1234
|
+
{
|
|
1235
|
+
projectApiKey: options.projectApiKey,
|
|
1236
|
+
release: options.release,
|
|
1237
|
+
apiUrl: options.apiUrl,
|
|
1238
|
+
enabled: isClientEnabled(options)
|
|
1239
|
+
}
|
|
1240
|
+
);
|
|
62
1241
|
if (isClientEnabled(options)) {
|
|
63
|
-
installGlobalHandlers(
|
|
1242
|
+
installGlobalHandlers(wrappedClient);
|
|
64
1243
|
}
|
|
65
|
-
return
|
|
1244
|
+
return wrappedClient;
|
|
66
1245
|
} catch {
|
|
67
|
-
return
|
|
1246
|
+
return withExecution(
|
|
1247
|
+
createClient({ ...options, enabled: false }),
|
|
1248
|
+
createExecutionRecorder({ enabled: false }),
|
|
1249
|
+
false,
|
|
1250
|
+
void 0,
|
|
1251
|
+
{
|
|
1252
|
+
projectApiKey: options.projectApiKey,
|
|
1253
|
+
release: options.release,
|
|
1254
|
+
apiUrl: options.apiUrl,
|
|
1255
|
+
enabled: false
|
|
1256
|
+
}
|
|
1257
|
+
);
|
|
68
1258
|
}
|
|
69
1259
|
};
|
|
70
1260
|
export {
|
|
71
1261
|
RasputinInit,
|
|
72
|
-
|
|
1262
|
+
createExecutionRecorder,
|
|
1263
|
+
installAutomaticExecutionRuntime,
|
|
1264
|
+
installGlobalHandlers,
|
|
1265
|
+
scheduleInstrumentationManifestUpload
|
|
73
1266
|
};
|