@rasputin-ai/node 0.5.0-alpha.5 → 0.5.0-alpha.7
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/dist/auto-instrumentation/instrument-compiled-esm.d.ts +2 -0
- package/dist/auto-instrumentation/instrument-compiled-esm.d.ts.map +1 -1
- package/dist/auto-instrumentation/instrumentation-manifest-delta.d.ts +2 -1
- package/dist/auto-instrumentation/instrumentation-manifest-delta.d.ts.map +1 -1
- package/dist/auto-instrumentation/instrumentation-manifest-registry.d.ts +1 -1
- package/dist/auto-instrumentation/instrumentation-manifest-registry.d.ts.map +1 -1
- package/dist/auto-instrumentation/transform-source.d.ts +6 -0
- package/dist/auto-instrumentation/transform-source.d.ts.map +1 -1
- package/dist/derivation/analyze-function.d.ts +40 -0
- package/dist/derivation/analyze-function.d.ts.map +1 -0
- package/dist/derivation/build-dependency-graph.d.ts +21 -0
- package/dist/derivation/build-dependency-graph.d.ts.map +1 -0
- package/dist/derivation/derivation-ir.d.ts +33 -0
- package/dist/derivation/derivation-ir.d.ts.map +1 -0
- package/dist/derivation/derivation-proof.d.ts +14 -0
- package/dist/derivation/derivation-proof.d.ts.map +1 -0
- package/dist/derivation/emit-capture-plan.d.ts +8 -0
- package/dist/derivation/emit-capture-plan.d.ts.map +1 -0
- package/dist/execution-recorder/automatic-runtime.d.ts +3 -1
- package/dist/execution-recorder/automatic-runtime.d.ts.map +1 -1
- package/dist/execution-recorder/execution-journal.d.ts +84 -0
- package/dist/execution-recorder/execution-journal.d.ts.map +1 -0
- package/dist/execution-recorder/execution-recorder-types.d.ts +19 -2
- package/dist/execution-recorder/execution-recorder-types.d.ts.map +1 -1
- package/dist/execution-recorder/execution-recorder.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/safe-serialize.d.ts +1 -0
- package/dist/execution-recorder/safe-serialize.d.ts.map +1 -1
- package/dist/index.js +1058 -317
- package/dist/instrument/build.js +761 -71
- package/dist/instrument/bun.js +742 -66
- package/dist/instrument/node.js +742 -66
- package/dist/sdk-meta.d.ts +1 -1
- package/package.json +2 -2
- package/dist/execution-recorder/call-aware-event-buffer.d.ts +0 -37
- package/dist/execution-recorder/call-aware-event-buffer.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -133,7 +133,7 @@ var definitionFromEncodedPlan = (plan) => {
|
|
|
133
133
|
var estimatedCallBytesFor = (functionId) => EVENT_PAIR_BASE_ESTIMATED_BYTES + Buffer.byteLength(functionId, "utf8") * 2;
|
|
134
134
|
|
|
135
135
|
// src/auto-instrumentation/instrumentation-manifest-registry.ts
|
|
136
|
-
var INSTRUMENTATION_MANIFEST_SYMBOL = "rasputin.instrumentation.manifest.
|
|
136
|
+
var INSTRUMENTATION_MANIFEST_SYMBOL = "rasputin.instrumentation.manifest.v3";
|
|
137
137
|
var registrySymbol = Symbol.for(INSTRUMENTATION_MANIFEST_SYMBOL);
|
|
138
138
|
var getRegistry = () => {
|
|
139
139
|
const existing = Reflect.get(globalThis, registrySymbol);
|
|
@@ -190,6 +190,7 @@ var snapshotInstrumentationManifest = (options = {}) => {
|
|
|
190
190
|
const functions = [];
|
|
191
191
|
const callSites = [];
|
|
192
192
|
const destructures = [];
|
|
193
|
+
const derivationPlans = [];
|
|
193
194
|
for (const delta of getRegistry().files.values()) {
|
|
194
195
|
for (const fn of delta.functions) {
|
|
195
196
|
const definition = definitionFromEncodedPlan(fn.plan);
|
|
@@ -241,6 +242,7 @@ var snapshotInstrumentationManifest = (options = {}) => {
|
|
|
241
242
|
binding: destructure.binding
|
|
242
243
|
});
|
|
243
244
|
}
|
|
245
|
+
derivationPlans.push(...delta.derivationPlans ?? []);
|
|
244
246
|
}
|
|
245
247
|
const registry = getRegistry();
|
|
246
248
|
if (registry.prebuilt && registry.files.size === 0) {
|
|
@@ -268,7 +270,8 @@ var snapshotInstrumentationManifest = (options = {}) => {
|
|
|
268
270
|
} : {},
|
|
269
271
|
functions,
|
|
270
272
|
callSites,
|
|
271
|
-
destructures
|
|
273
|
+
destructures,
|
|
274
|
+
derivationPlans
|
|
272
275
|
};
|
|
273
276
|
};
|
|
274
277
|
var markInstrumentationManifestUploaded = (generation) => {
|
|
@@ -384,85 +387,392 @@ var scheduleInstrumentationManifestUpload = (options) => {
|
|
|
384
387
|
|
|
385
388
|
// src/execution-recorder/execution-recorder.ts
|
|
386
389
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
387
|
-
import {
|
|
390
|
+
import {
|
|
391
|
+
capturedValueCompleteness,
|
|
392
|
+
hashInstrumentationManifest,
|
|
393
|
+
rasputinOmitted,
|
|
394
|
+
runtimeFunctionId as runtimeFunctionId2
|
|
395
|
+
} from "@rasputin-ai/core";
|
|
388
396
|
|
|
389
|
-
// src/execution-recorder/
|
|
390
|
-
var
|
|
391
|
-
var
|
|
397
|
+
// src/execution-recorder/execution-journal.ts
|
|
398
|
+
var KIND_ENTER = 1;
|
|
399
|
+
var KIND_EXIT = 2;
|
|
400
|
+
var KIND_THROW = 3;
|
|
401
|
+
var KIND_SUPPRESSED = 4;
|
|
402
|
+
var NO_PARENT = 4294967295;
|
|
403
|
+
var NO_SUPPRESSION = 4294967295;
|
|
404
|
+
var MAX_POOLED_JOURNALS = 8;
|
|
405
|
+
var MAX_POOLED_JOURNAL_CAPACITY = 4096;
|
|
406
|
+
var INITIAL_JOURNAL_STORAGE = 32;
|
|
407
|
+
var BYTES_PER_EVENT = Uint8Array.BYTES_PER_ELEMENT + Uint32Array.BYTES_PER_ELEMENT * 4 + BigInt64Array.BYTES_PER_ELEMENT * 2;
|
|
408
|
+
var DEFAULT_MAX_EVENTS_PER_EXECUTION = 500;
|
|
409
|
+
var MAX_JOURNAL_EVENTS = 16384;
|
|
410
|
+
var elapsedMs = (startedAtNs, endedAtNs) => Number(endedAtNs - startedAtNs) / 1e6;
|
|
411
|
+
var roundedMilliseconds = (nanoseconds) => Math.round(Number(nanoseconds) / 1e6 * 1e4) / 1e4;
|
|
412
|
+
var relativeMs = (relativeNs) => Number(relativeNs) / 1e6;
|
|
413
|
+
var sanitizeJournalCapacity = (value) => {
|
|
414
|
+
const requested = value ?? DEFAULT_MAX_EVENTS_PER_EXECUTION;
|
|
415
|
+
if (!Number.isFinite(requested)) return DEFAULT_MAX_EVENTS_PER_EXECUTION;
|
|
416
|
+
return Math.min(MAX_JOURNAL_EVENTS, Math.max(2, Math.floor(requested)));
|
|
417
|
+
};
|
|
418
|
+
var ExecutionJournal = class {
|
|
419
|
+
dropped = 0;
|
|
420
|
+
allocatedBytes = 0;
|
|
421
|
+
onGrow;
|
|
422
|
+
length = 0;
|
|
423
|
+
kind = new Uint8Array(0);
|
|
424
|
+
planId = new Uint32Array(0);
|
|
425
|
+
callId = new Uint32Array(0);
|
|
426
|
+
parentCallId = new Uint32Array(0);
|
|
427
|
+
timestampNs = new BigInt64Array(0);
|
|
428
|
+
durationNs = new BigInt64Array(0);
|
|
429
|
+
suppressionIndex = new Uint32Array(0);
|
|
430
|
+
payloads = [];
|
|
431
|
+
suppressions = [];
|
|
432
|
+
openCallIds = /* @__PURE__ */ new Set();
|
|
433
|
+
notedPlanIds = [];
|
|
434
|
+
notedPlanSet = /* @__PURE__ */ new Set();
|
|
435
|
+
maxCapacity;
|
|
392
436
|
constructor(capacity) {
|
|
393
|
-
this.
|
|
437
|
+
this.maxCapacity = sanitizeJournalCapacity(capacity);
|
|
438
|
+
this.reallocate(Math.min(this.maxCapacity, INITIAL_JOURNAL_STORAGE));
|
|
439
|
+
}
|
|
440
|
+
get capacity() {
|
|
441
|
+
return this.maxCapacity;
|
|
442
|
+
}
|
|
443
|
+
get hasOpenCalls() {
|
|
444
|
+
return this.openCallIds.size > 0;
|
|
445
|
+
}
|
|
446
|
+
get eventCount() {
|
|
447
|
+
return this.length;
|
|
448
|
+
}
|
|
449
|
+
get payloadSlotCount() {
|
|
450
|
+
return this.payloads.length;
|
|
394
451
|
}
|
|
395
|
-
items = [];
|
|
396
|
-
openCallIds = /* @__PURE__ */ new Set();
|
|
397
|
-
dropped = 0;
|
|
398
452
|
canStartCall() {
|
|
399
|
-
|
|
453
|
+
if (this.length + this.openCallIds.size + 2 > this.maxCapacity) return false;
|
|
454
|
+
return this.ensureCapacity(this.length + 2);
|
|
400
455
|
}
|
|
401
|
-
|
|
402
|
-
this.
|
|
403
|
-
this.
|
|
456
|
+
notePlan(runtimePlanId) {
|
|
457
|
+
if (this.notedPlanSet.has(runtimePlanId)) return;
|
|
458
|
+
this.notedPlanSet.add(runtimePlanId);
|
|
459
|
+
this.notedPlanIds.push(runtimePlanId);
|
|
404
460
|
}
|
|
405
|
-
|
|
406
|
-
if (
|
|
407
|
-
|
|
408
|
-
this.
|
|
461
|
+
registerSuppression(group) {
|
|
462
|
+
if (group.storageIndex >= 0) return group;
|
|
463
|
+
group.storageIndex = this.suppressions.length;
|
|
464
|
+
this.suppressions.push(group);
|
|
465
|
+
return group;
|
|
466
|
+
}
|
|
467
|
+
startCall(runtimePlanId, callId, parentCallId, timestampNs, args) {
|
|
468
|
+
if (!this.write(
|
|
469
|
+
KIND_ENTER,
|
|
470
|
+
runtimePlanId,
|
|
471
|
+
callId,
|
|
472
|
+
parentCallId,
|
|
473
|
+
timestampNs,
|
|
474
|
+
0n,
|
|
475
|
+
args,
|
|
476
|
+
NO_SUPPRESSION
|
|
477
|
+
)) {
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
this.openCallIds.add(callId);
|
|
481
|
+
}
|
|
482
|
+
finishCall(kind, callId, timestampNs, durationNs, payload) {
|
|
483
|
+
if (!this.openCallIds.delete(callId)) return;
|
|
484
|
+
this.write(kind, 0, callId, void 0, timestampNs, durationNs, payload, NO_SUPPRESSION);
|
|
409
485
|
}
|
|
410
486
|
dropCall() {
|
|
411
487
|
this.dropped += 2;
|
|
412
488
|
}
|
|
413
489
|
appendSuppressed(group) {
|
|
414
|
-
if (this.
|
|
490
|
+
if (this.length + this.openCallIds.size + 1 > this.maxCapacity) {
|
|
491
|
+
this.dropped++;
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
this.registerSuppression(group);
|
|
495
|
+
group.retainedIndex = this.length;
|
|
496
|
+
if (!this.write(
|
|
497
|
+
KIND_SUPPRESSED,
|
|
498
|
+
group.runtimePlanId,
|
|
499
|
+
0,
|
|
500
|
+
group.parentCallId,
|
|
501
|
+
0n,
|
|
502
|
+
0n,
|
|
503
|
+
void 0,
|
|
504
|
+
group.storageIndex
|
|
505
|
+
)) {
|
|
506
|
+
group.retainedIndex = -1;
|
|
415
507
|
this.dropped++;
|
|
416
508
|
return false;
|
|
417
509
|
}
|
|
418
|
-
const placeholder = { kind: "suppressed", group };
|
|
419
|
-
this.items.push(placeholder);
|
|
420
|
-
group.retainedSlot = placeholder;
|
|
421
510
|
return true;
|
|
422
511
|
}
|
|
423
|
-
forceCompletedCall(
|
|
424
|
-
while (this.
|
|
512
|
+
forceCompletedCall(runtimePlanId, callId, parentCallId, enterTimestampNs, args, terminalKind, terminalTimestampNs, durationNs, payload) {
|
|
513
|
+
while (this.length + this.openCallIds.size + 2 > this.maxCapacity) {
|
|
425
514
|
if (!this.evictCompletedLeafOrSummary()) {
|
|
426
515
|
this.dropCall();
|
|
427
516
|
return false;
|
|
428
517
|
}
|
|
429
518
|
}
|
|
430
|
-
this.
|
|
519
|
+
if (!this.ensureCapacity(this.length + 2)) {
|
|
520
|
+
this.dropCall();
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
this.write(
|
|
524
|
+
KIND_ENTER,
|
|
525
|
+
runtimePlanId,
|
|
526
|
+
callId,
|
|
527
|
+
parentCallId,
|
|
528
|
+
enterTimestampNs,
|
|
529
|
+
0n,
|
|
530
|
+
args,
|
|
531
|
+
NO_SUPPRESSION
|
|
532
|
+
);
|
|
533
|
+
this.write(
|
|
534
|
+
terminalKind,
|
|
535
|
+
0,
|
|
536
|
+
callId,
|
|
537
|
+
void 0,
|
|
538
|
+
terminalTimestampNs,
|
|
539
|
+
durationNs,
|
|
540
|
+
payload,
|
|
541
|
+
NO_SUPPRESSION
|
|
542
|
+
);
|
|
431
543
|
return true;
|
|
432
544
|
}
|
|
433
|
-
|
|
434
|
-
|
|
545
|
+
materialize(plansByRuntimeId, executionStartedAtNs) {
|
|
546
|
+
const events = [];
|
|
547
|
+
const referencedFunctionIds = /* @__PURE__ */ new Set();
|
|
548
|
+
for (let index = 0; index < this.length; index++) {
|
|
549
|
+
const event = this.eventAt(index, plansByRuntimeId, executionStartedAtNs);
|
|
550
|
+
if (!event) continue;
|
|
551
|
+
events.push(event);
|
|
552
|
+
if (event.type === "function_enter" || event.type === "function_calls_suppressed") {
|
|
553
|
+
referencedFunctionIds.add(event.functionId);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
const functions = [];
|
|
557
|
+
const seenFunctionIds = /* @__PURE__ */ new Set();
|
|
558
|
+
for (const runtimePlanId of this.notedPlanIds) {
|
|
559
|
+
const definition = plansByRuntimeId[runtimePlanId]?.definition;
|
|
560
|
+
if (!definition || !referencedFunctionIds.has(definition.functionId)) continue;
|
|
561
|
+
if (seenFunctionIds.has(definition.functionId)) continue;
|
|
562
|
+
seenFunctionIds.add(definition.functionId);
|
|
563
|
+
functions.push(definition);
|
|
564
|
+
}
|
|
565
|
+
return { events, functions };
|
|
566
|
+
}
|
|
567
|
+
clear() {
|
|
568
|
+
this.length = 0;
|
|
569
|
+
this.dropped = 0;
|
|
570
|
+
this.onGrow = void 0;
|
|
571
|
+
this.openCallIds.clear();
|
|
572
|
+
this.notedPlanIds.length = 0;
|
|
573
|
+
this.notedPlanSet.clear();
|
|
574
|
+
for (let index = 0; index < this.payloads.length; index++) this.payloads[index] = void 0;
|
|
575
|
+
this.payloads.length = 0;
|
|
576
|
+
for (const group of this.suppressions) {
|
|
577
|
+
group.retainedIndex = -1;
|
|
578
|
+
group.storageIndex = -1;
|
|
579
|
+
}
|
|
580
|
+
this.suppressions.length = 0;
|
|
581
|
+
}
|
|
582
|
+
eventAt(index, plansByRuntimeId, executionStartedAtNs) {
|
|
583
|
+
const kind = this.kind[index];
|
|
584
|
+
if (kind === KIND_ENTER) {
|
|
585
|
+
const functionId = plansByRuntimeId[this.planId[index] ?? 0]?.functionId;
|
|
586
|
+
if (!functionId) return void 0;
|
|
587
|
+
const parentCallId = this.parentCallId[index] ?? NO_PARENT;
|
|
588
|
+
const payload = this.payloads[index];
|
|
589
|
+
return {
|
|
590
|
+
type: "function_enter",
|
|
591
|
+
callId: this.callId[index] ?? 0,
|
|
592
|
+
functionId,
|
|
593
|
+
timestampMs: relativeMs(this.timestampNs[index] ?? 0n),
|
|
594
|
+
args: Array.isArray(payload) ? payload : [],
|
|
595
|
+
...parentCallId === NO_PARENT ? {} : { parentCallId }
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
if (kind === KIND_EXIT) {
|
|
599
|
+
return {
|
|
600
|
+
type: "function_exit",
|
|
601
|
+
callId: this.callId[index] ?? 0,
|
|
602
|
+
timestampMs: relativeMs(this.timestampNs[index] ?? 0n),
|
|
603
|
+
durationMs: relativeMs(this.durationNs[index] ?? 0n),
|
|
604
|
+
returnValue: this.payloads[index]
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
if (kind === KIND_THROW) {
|
|
608
|
+
return {
|
|
609
|
+
type: "function_throw",
|
|
610
|
+
callId: this.callId[index] ?? 0,
|
|
611
|
+
timestampMs: relativeMs(this.timestampNs[index] ?? 0n),
|
|
612
|
+
durationMs: relativeMs(this.durationNs[index] ?? 0n),
|
|
613
|
+
error: this.payloads[index]
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
if (kind === KIND_SUPPRESSED) {
|
|
617
|
+
const group = this.suppressions[this.suppressionIndex[index] ?? 0];
|
|
618
|
+
if (!group) return void 0;
|
|
619
|
+
return {
|
|
620
|
+
type: "function_calls_suppressed",
|
|
621
|
+
functionId: group.functionId,
|
|
622
|
+
timestampMs: elapsedMs(executionStartedAtNs, group.firstTimestampNs),
|
|
623
|
+
lastTimestampMs: elapsedMs(executionStartedAtNs, group.lastTimestampNs),
|
|
624
|
+
suppressedCallCount: group.count,
|
|
625
|
+
totalDurationMs: roundedMilliseconds(group.totalDurationNs),
|
|
626
|
+
...group.parentCallId === void 0 ? {} : { parentCallId: group.parentCallId }
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
return void 0;
|
|
630
|
+
}
|
|
631
|
+
write(kind, runtimePlanId, callId, parentCallId, timestampNs, durationNs, payload, suppressionIndex) {
|
|
632
|
+
if (!this.ensureCapacity(this.length + 1)) return false;
|
|
633
|
+
const index = this.length;
|
|
634
|
+
this.kind[index] = kind;
|
|
635
|
+
this.planId[index] = runtimePlanId;
|
|
636
|
+
this.callId[index] = callId;
|
|
637
|
+
this.parentCallId[index] = parentCallId === void 0 ? NO_PARENT : parentCallId;
|
|
638
|
+
this.timestampNs[index] = timestampNs;
|
|
639
|
+
this.durationNs[index] = durationNs;
|
|
640
|
+
this.payloads[index] = payload;
|
|
641
|
+
this.suppressionIndex[index] = suppressionIndex;
|
|
642
|
+
this.length++;
|
|
643
|
+
return true;
|
|
644
|
+
}
|
|
645
|
+
ensureCapacity(needed) {
|
|
646
|
+
if (needed <= this.kind.length) return true;
|
|
647
|
+
if (needed > this.maxCapacity) return false;
|
|
648
|
+
let next = this.kind.length === 0 ? Math.min(INITIAL_JOURNAL_STORAGE, this.maxCapacity) : this.kind.length;
|
|
649
|
+
while (next < needed) {
|
|
650
|
+
const grown = Math.min(this.maxCapacity, next * 2);
|
|
651
|
+
if (grown <= next) return false;
|
|
652
|
+
next = grown;
|
|
653
|
+
}
|
|
654
|
+
const extraBytes = (next - this.kind.length) * BYTES_PER_EVENT;
|
|
655
|
+
if (this.onGrow && extraBytes > 0 && !this.onGrow(extraBytes)) return false;
|
|
656
|
+
this.reallocate(next);
|
|
657
|
+
return true;
|
|
658
|
+
}
|
|
659
|
+
reallocate(size) {
|
|
660
|
+
const nextKind = new Uint8Array(size);
|
|
661
|
+
const nextPlanId = new Uint32Array(size);
|
|
662
|
+
const nextCallId = new Uint32Array(size);
|
|
663
|
+
const nextParentCallId = new Uint32Array(size);
|
|
664
|
+
const nextTimestampNs = new BigInt64Array(size);
|
|
665
|
+
const nextDurationNs = new BigInt64Array(size);
|
|
666
|
+
const nextSuppressionIndex = new Uint32Array(size);
|
|
667
|
+
if (this.length > 0) {
|
|
668
|
+
nextKind.set(this.kind.subarray(0, this.length));
|
|
669
|
+
nextPlanId.set(this.planId.subarray(0, this.length));
|
|
670
|
+
nextCallId.set(this.callId.subarray(0, this.length));
|
|
671
|
+
nextParentCallId.set(this.parentCallId.subarray(0, this.length));
|
|
672
|
+
nextTimestampNs.set(this.timestampNs.subarray(0, this.length));
|
|
673
|
+
nextDurationNs.set(this.durationNs.subarray(0, this.length));
|
|
674
|
+
nextSuppressionIndex.set(this.suppressionIndex.subarray(0, this.length));
|
|
675
|
+
}
|
|
676
|
+
this.kind = nextKind;
|
|
677
|
+
this.planId = nextPlanId;
|
|
678
|
+
this.callId = nextCallId;
|
|
679
|
+
this.parentCallId = nextParentCallId;
|
|
680
|
+
this.timestampNs = nextTimestampNs;
|
|
681
|
+
this.durationNs = nextDurationNs;
|
|
682
|
+
this.suppressionIndex = nextSuppressionIndex;
|
|
683
|
+
this.allocatedBytes = size * BYTES_PER_EVENT;
|
|
435
684
|
}
|
|
436
685
|
evictCompletedLeafOrSummary() {
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
const
|
|
440
|
-
if (
|
|
441
|
-
this.
|
|
686
|
+
for (let index = 0; index < this.length; index++) {
|
|
687
|
+
if (this.kind[index] !== KIND_SUPPRESSED) continue;
|
|
688
|
+
const group = this.suppressions[this.suppressionIndex[index] ?? 0];
|
|
689
|
+
if (group) group.retainedIndex = -1;
|
|
690
|
+
this.removeAt(index);
|
|
442
691
|
this.dropped++;
|
|
443
692
|
return true;
|
|
444
693
|
}
|
|
445
694
|
const parentCallIds = /* @__PURE__ */ new Set();
|
|
446
|
-
for (
|
|
447
|
-
const
|
|
448
|
-
if (
|
|
695
|
+
for (let index = 0; index < this.length; index++) {
|
|
696
|
+
const kind = this.kind[index];
|
|
697
|
+
if (kind !== KIND_ENTER && kind !== KIND_SUPPRESSED) continue;
|
|
698
|
+
const parentCallId = this.parentCallId[index] ?? NO_PARENT;
|
|
699
|
+
if (parentCallId !== NO_PARENT) parentCallIds.add(parentCallId);
|
|
449
700
|
}
|
|
450
|
-
for (let index = 0; index < this.
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
701
|
+
for (let index = 0; index < this.length; index++) {
|
|
702
|
+
if (this.kind[index] !== KIND_ENTER) continue;
|
|
703
|
+
const eventCallId = this.callId[index] ?? 0;
|
|
704
|
+
if (this.openCallIds.has(eventCallId) || parentCallIds.has(eventCallId)) continue;
|
|
705
|
+
let terminalIndex = -1;
|
|
706
|
+
for (let candidate = 0; candidate < this.length; candidate++) {
|
|
707
|
+
const kind = this.kind[candidate];
|
|
708
|
+
if ((kind === KIND_EXIT || kind === KIND_THROW) && this.callId[candidate] === eventCallId) {
|
|
709
|
+
terminalIndex = candidate;
|
|
710
|
+
break;
|
|
711
|
+
}
|
|
454
712
|
}
|
|
455
|
-
const terminalIndex = this.items.findIndex(
|
|
456
|
-
(candidate) => !isSuppressionPlaceholder(candidate) && (candidate.type === "function_exit" || candidate.type === "function_throw") && candidate.callId === event.callId
|
|
457
|
-
);
|
|
458
713
|
if (terminalIndex < 0) continue;
|
|
459
|
-
|
|
460
|
-
|
|
714
|
+
const later = Math.max(index, terminalIndex);
|
|
715
|
+
const earlier = Math.min(index, terminalIndex);
|
|
716
|
+
this.removeAt(later);
|
|
717
|
+
this.removeAt(earlier);
|
|
461
718
|
this.dropped += 2;
|
|
462
719
|
return true;
|
|
463
720
|
}
|
|
464
721
|
return false;
|
|
465
722
|
}
|
|
723
|
+
removeAt(index) {
|
|
724
|
+
this.payloads[index] = void 0;
|
|
725
|
+
const next = index + 1;
|
|
726
|
+
if (next < this.length) {
|
|
727
|
+
this.kind.copyWithin(index, next, this.length);
|
|
728
|
+
this.planId.copyWithin(index, next, this.length);
|
|
729
|
+
this.callId.copyWithin(index, next, this.length);
|
|
730
|
+
this.parentCallId.copyWithin(index, next, this.length);
|
|
731
|
+
this.timestampNs.copyWithin(index, next, this.length);
|
|
732
|
+
this.durationNs.copyWithin(index, next, this.length);
|
|
733
|
+
this.suppressionIndex.copyWithin(index, next, this.length);
|
|
734
|
+
this.payloads.copyWithin(index, next, this.length);
|
|
735
|
+
}
|
|
736
|
+
this.payloads[this.length - 1] = void 0;
|
|
737
|
+
this.length--;
|
|
738
|
+
this.payloads.length = this.length;
|
|
739
|
+
for (const group of this.suppressions) {
|
|
740
|
+
if (group.retainedIndex > index) group.retainedIndex--;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
var ExecutionJournalPool = class {
|
|
745
|
+
constructor(capacity, maxPooled = MAX_POOLED_JOURNALS) {
|
|
746
|
+
this.capacity = capacity;
|
|
747
|
+
this.maxPooled = maxPooled;
|
|
748
|
+
}
|
|
749
|
+
hits = 0;
|
|
750
|
+
misses = 0;
|
|
751
|
+
available = [];
|
|
752
|
+
acquire() {
|
|
753
|
+
const pooled = this.available.pop();
|
|
754
|
+
if (pooled) {
|
|
755
|
+
this.hits++;
|
|
756
|
+
return pooled;
|
|
757
|
+
}
|
|
758
|
+
this.misses++;
|
|
759
|
+
return new ExecutionJournal(this.capacity);
|
|
760
|
+
}
|
|
761
|
+
release(journal) {
|
|
762
|
+
journal.clear();
|
|
763
|
+
if (this.available.length >= this.maxPooled || journal.capacity > MAX_POOLED_JOURNAL_CAPACITY || journal.capacity !== this.capacity) {
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
this.available.push(journal);
|
|
767
|
+
}
|
|
768
|
+
stats() {
|
|
769
|
+
return {
|
|
770
|
+
journalPoolHits: this.hits,
|
|
771
|
+
journalPoolMisses: this.misses,
|
|
772
|
+
journalPoolSize: this.available.length,
|
|
773
|
+
journalAllocatedCapacity: this.capacity
|
|
774
|
+
};
|
|
775
|
+
}
|
|
466
776
|
};
|
|
467
777
|
|
|
468
778
|
// src/execution-recorder/recorder-memory-budget.ts
|
|
@@ -540,6 +850,12 @@ var RecorderMemoryBudget = class {
|
|
|
540
850
|
this.dropEvents(allocation, 1);
|
|
541
851
|
return false;
|
|
542
852
|
}
|
|
853
|
+
reserveStorage(allocation, bytes) {
|
|
854
|
+
if (allocation.released || allocation.mode === "metadata-only") return false;
|
|
855
|
+
if (this.reserve(allocation, bytes)) return true;
|
|
856
|
+
this.markPressure(allocation, "metadata-only");
|
|
857
|
+
return false;
|
|
858
|
+
}
|
|
543
859
|
release(allocation) {
|
|
544
860
|
if (allocation.released) return;
|
|
545
861
|
allocation.released = true;
|
|
@@ -600,10 +916,7 @@ var defaults = {
|
|
|
600
916
|
maxStringLength: 500,
|
|
601
917
|
maxSerializedValueBytes: 8 * 1024
|
|
602
918
|
};
|
|
603
|
-
var
|
|
604
|
-
var TYPE_MARKER_VALUE_MID = '","value":"';
|
|
605
|
-
var TYPE_MARKER_CLOSE = '"}';
|
|
606
|
-
var UNDEFINED_MARKER_BYTES = TYPE_MARKER_OPEN.length + "undefined".length + TYPE_MARKER_CLOSE.length;
|
|
919
|
+
var REDACTED = "[RASPUTIN_REDACTED]";
|
|
607
920
|
var truncation = (reason, extra = {}) => ({
|
|
608
921
|
__rasputin_truncated: true,
|
|
609
922
|
__reason: reason,
|
|
@@ -613,7 +926,83 @@ var typeMarker = (type, value) => ({
|
|
|
613
926
|
__rasputin_type: type,
|
|
614
927
|
...value === void 0 ? {} : { value }
|
|
615
928
|
});
|
|
616
|
-
var
|
|
929
|
+
var jsonStringUtf8Bytes = (value) => {
|
|
930
|
+
let bytes = 2;
|
|
931
|
+
for (let index = 0; index < value.length; index++) {
|
|
932
|
+
const code = value.charCodeAt(index);
|
|
933
|
+
if (code === 34 || code === 92) {
|
|
934
|
+
bytes += 2;
|
|
935
|
+
continue;
|
|
936
|
+
}
|
|
937
|
+
if (code === 8 || code === 9 || code === 10 || code === 12 || code === 13) {
|
|
938
|
+
bytes += 2;
|
|
939
|
+
continue;
|
|
940
|
+
}
|
|
941
|
+
if (code < 32) {
|
|
942
|
+
bytes += 6;
|
|
943
|
+
continue;
|
|
944
|
+
}
|
|
945
|
+
if (code < 128) {
|
|
946
|
+
bytes += 1;
|
|
947
|
+
continue;
|
|
948
|
+
}
|
|
949
|
+
if (code < 2048) {
|
|
950
|
+
bytes += 2;
|
|
951
|
+
continue;
|
|
952
|
+
}
|
|
953
|
+
if (code >= 55296 && code <= 56319) {
|
|
954
|
+
const next = value.charCodeAt(index + 1);
|
|
955
|
+
if (index + 1 < value.length && next >= 56320 && next <= 57343) {
|
|
956
|
+
bytes += 4;
|
|
957
|
+
index++;
|
|
958
|
+
continue;
|
|
959
|
+
}
|
|
960
|
+
bytes += 6;
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
963
|
+
if (code >= 56320 && code <= 57343) {
|
|
964
|
+
bytes += 6;
|
|
965
|
+
continue;
|
|
966
|
+
}
|
|
967
|
+
bytes += 3;
|
|
968
|
+
}
|
|
969
|
+
return bytes;
|
|
970
|
+
};
|
|
971
|
+
var jsonLiteralUtf8Bytes = (value) => {
|
|
972
|
+
if (value === null) return 4;
|
|
973
|
+
switch (typeof value) {
|
|
974
|
+
case "boolean":
|
|
975
|
+
return value ? 4 : 5;
|
|
976
|
+
case "number":
|
|
977
|
+
if (!Number.isFinite(value)) return 4;
|
|
978
|
+
if (Object.is(value, -0)) return 1;
|
|
979
|
+
return String(value).length;
|
|
980
|
+
case "string":
|
|
981
|
+
return jsonStringUtf8Bytes(value);
|
|
982
|
+
case "object": {
|
|
983
|
+
if (Array.isArray(value)) {
|
|
984
|
+
let bytes2 = 2;
|
|
985
|
+
for (let index = 0; index < value.length; index++) {
|
|
986
|
+
if (index > 0) bytes2 += 1;
|
|
987
|
+
bytes2 += jsonLiteralUtf8Bytes(value[index]);
|
|
988
|
+
}
|
|
989
|
+
return bytes2;
|
|
990
|
+
}
|
|
991
|
+
const record = value;
|
|
992
|
+
let bytes = 2;
|
|
993
|
+
let first = true;
|
|
994
|
+
for (const key of Object.keys(record)) {
|
|
995
|
+
if (!first) bytes += 1;
|
|
996
|
+
first = false;
|
|
997
|
+
bytes += jsonStringUtf8Bytes(key) + 1;
|
|
998
|
+
bytes += jsonLiteralUtf8Bytes(record[key]);
|
|
999
|
+
}
|
|
1000
|
+
return bytes;
|
|
1001
|
+
}
|
|
1002
|
+
default:
|
|
1003
|
+
return Buffer2.byteLength(JSON.stringify(value) ?? "null", "utf8");
|
|
1004
|
+
}
|
|
1005
|
+
};
|
|
617
1006
|
var compileLimits = (options) => ({
|
|
618
1007
|
maxDepth: options.maxDepth ?? defaults.maxDepth,
|
|
619
1008
|
maxObjectKeys: options.maxObjectKeys ?? defaults.maxObjectKeys,
|
|
@@ -625,6 +1014,13 @@ var compileRedactKeys = (options) => {
|
|
|
625
1014
|
if (!options.redactKeys?.length) return new Set(DEFAULT_REDACT_KEYS);
|
|
626
1015
|
return /* @__PURE__ */ new Set([...DEFAULT_REDACT_KEYS, ...options.redactKeys.map((key) => key.toLowerCase())]);
|
|
627
1016
|
};
|
|
1017
|
+
var keyNeedsCaseFold = (key) => {
|
|
1018
|
+
for (let index = 0; index < key.length; index++) {
|
|
1019
|
+
const code = key.charCodeAt(index);
|
|
1020
|
+
if (code > 127 || code >= 65 && code <= 90) return true;
|
|
1021
|
+
}
|
|
1022
|
+
return false;
|
|
1023
|
+
};
|
|
628
1024
|
var isJsonSafeString = (value) => {
|
|
629
1025
|
for (let index = 0; index < value.length; index++) {
|
|
630
1026
|
const code = value.charCodeAt(index);
|
|
@@ -639,7 +1035,6 @@ var isJsonSafeString = (value) => {
|
|
|
639
1035
|
}
|
|
640
1036
|
return true;
|
|
641
1037
|
};
|
|
642
|
-
var typeMarkerWithValueBytes = (type, jsonSafeValue) => TYPE_MARKER_OPEN.length + type.length + TYPE_MARKER_VALUE_MID.length + Buffer2.byteLength(jsonSafeValue, "utf8") + TYPE_MARKER_CLOSE.length;
|
|
643
1038
|
var primitiveFastPath = (value, maxStringLength) => {
|
|
644
1039
|
if (value === null) return { value: null, bytes: 4, visitedNodes: 1 };
|
|
645
1040
|
if (typeof value === "boolean") return { value, bytes: value ? 4 : 5, visitedNodes: 1 };
|
|
@@ -653,176 +1048,306 @@ var primitiveFastPath = (value, maxStringLength) => {
|
|
|
653
1048
|
return { value, bytes: 2 + Buffer2.byteLength(value, "utf8"), visitedNodes: 1 };
|
|
654
1049
|
}
|
|
655
1050
|
if (typeof value === "undefined") {
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
bytes: UNDEFINED_MARKER_BYTES,
|
|
659
|
-
visitedNodes: 1
|
|
660
|
-
};
|
|
1051
|
+
const serialized = typeMarker("undefined");
|
|
1052
|
+
return { value: serialized, bytes: jsonLiteralUtf8Bytes(serialized), visitedNodes: 1 };
|
|
661
1053
|
}
|
|
662
1054
|
if (typeof value === "bigint") {
|
|
663
|
-
const
|
|
664
|
-
return {
|
|
665
|
-
value: { __rasputin_type: "bigint", value: digits },
|
|
666
|
-
bytes: typeMarkerWithValueBytes("bigint", digits),
|
|
667
|
-
visitedNodes: 1
|
|
668
|
-
};
|
|
1055
|
+
const serialized = typeMarker("bigint", value.toString());
|
|
1056
|
+
return { value: serialized, bytes: jsonLiteralUtf8Bytes(serialized), visitedNodes: 1 };
|
|
669
1057
|
}
|
|
670
1058
|
if (typeof value === "symbol") {
|
|
671
1059
|
const text = String(value);
|
|
672
1060
|
if (!isJsonSafeString(text)) return void 0;
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
bytes: typeMarkerWithValueBytes("symbol", text),
|
|
676
|
-
visitedNodes: 1
|
|
677
|
-
};
|
|
1061
|
+
const serialized = typeMarker("symbol", text);
|
|
1062
|
+
return { value: serialized, bytes: jsonLiteralUtf8Bytes(serialized), visitedNodes: 1 };
|
|
678
1063
|
}
|
|
679
1064
|
if (typeof value === "function") {
|
|
680
1065
|
const name = value.name || "anonymous";
|
|
681
1066
|
if (!isJsonSafeString(name)) return void 0;
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
bytes: typeMarkerWithValueBytes("function", name),
|
|
685
|
-
visitedNodes: 1
|
|
686
|
-
};
|
|
1067
|
+
const serialized = typeMarker("function", name);
|
|
1068
|
+
return { value: serialized, bytes: jsonLiteralUtf8Bytes(serialized), visitedNodes: 1 };
|
|
687
1069
|
}
|
|
688
1070
|
return void 0;
|
|
689
1071
|
};
|
|
690
1072
|
var createSafeSerializer = (options = {}) => {
|
|
691
1073
|
const limits = compileLimits(options);
|
|
692
1074
|
const redactKeys = compileRedactKeys(options);
|
|
693
|
-
const
|
|
1075
|
+
const sharedPath = /* @__PURE__ */ new Set();
|
|
1076
|
+
let serializing = false;
|
|
1077
|
+
const isRedactedKey = (key) => {
|
|
1078
|
+
if (redactKeys.has(key)) return true;
|
|
1079
|
+
if (!keyNeedsCaseFold(key)) return false;
|
|
1080
|
+
return redactKeys.has(key.toLowerCase());
|
|
1081
|
+
};
|
|
1082
|
+
const addBytes = (metrics, count) => {
|
|
1083
|
+
metrics.bytes += count;
|
|
1084
|
+
if (metrics.bytes > limits.maxSerializedValueBytes) metrics.oversize = true;
|
|
1085
|
+
};
|
|
1086
|
+
const boundedOversize = (bytes, visitedNodes) => {
|
|
1087
|
+
const bounded = truncation("max_serialized_value_bytes", { __serialized_bytes: bytes });
|
|
1088
|
+
return { value: bounded, bytes: jsonLiteralUtf8Bytes(bounded), visitedNodes };
|
|
1089
|
+
};
|
|
1090
|
+
const openObject = (metrics, allocate) => {
|
|
1091
|
+
addBytes(metrics, 2);
|
|
1092
|
+
return {
|
|
1093
|
+
target: allocate && !metrics.oversize ? {} : void 0,
|
|
1094
|
+
first: true
|
|
1095
|
+
};
|
|
1096
|
+
};
|
|
1097
|
+
const openArray = (metrics, allocate) => {
|
|
1098
|
+
addBytes(metrics, 2);
|
|
1099
|
+
return {
|
|
1100
|
+
items: allocate && !metrics.oversize ? [] : void 0,
|
|
1101
|
+
first: true
|
|
1102
|
+
};
|
|
1103
|
+
};
|
|
1104
|
+
const beginField = (metrics, object, key) => {
|
|
1105
|
+
if (!object.first) addBytes(metrics, 1);
|
|
1106
|
+
object.first = false;
|
|
1107
|
+
addBytes(metrics, jsonStringUtf8Bytes(key) + 1);
|
|
1108
|
+
};
|
|
1109
|
+
const assignField = (object, key, fieldValue) => {
|
|
1110
|
+
if (object.target) object.target[key] = fieldValue;
|
|
1111
|
+
};
|
|
1112
|
+
const writeLiteralField = (metrics, object, key, jsonValue) => {
|
|
1113
|
+
beginField(metrics, object, key);
|
|
1114
|
+
addBytes(metrics, jsonLiteralUtf8Bytes(jsonValue));
|
|
1115
|
+
assignField(object, key, jsonValue);
|
|
1116
|
+
};
|
|
1117
|
+
const writeTypeMarker = (metrics, allocate, type, nestedValue) => {
|
|
1118
|
+
const object = openObject(metrics, allocate);
|
|
1119
|
+
writeLiteralField(metrics, object, "__rasputin_type", type);
|
|
1120
|
+
if (nestedValue !== void 0) writeLiteralField(metrics, object, "value", nestedValue);
|
|
1121
|
+
return object.target;
|
|
1122
|
+
};
|
|
1123
|
+
const writeTruncation = (metrics, allocate, reason, extra = {}) => {
|
|
1124
|
+
const object = openObject(metrics, allocate);
|
|
1125
|
+
writeLiteralField(metrics, object, "__rasputin_truncated", true);
|
|
1126
|
+
writeLiteralField(metrics, object, "__reason", reason);
|
|
1127
|
+
for (const key of Object.keys(extra)) writeLiteralField(metrics, object, key, extra[key]);
|
|
1128
|
+
return object.target;
|
|
1129
|
+
};
|
|
1130
|
+
const serializeInner = (value, depth, path, allocate, metrics) => {
|
|
694
1131
|
metrics.visitedNodes++;
|
|
695
|
-
|
|
1132
|
+
const store = allocate && !metrics.oversize;
|
|
1133
|
+
if (value === null) {
|
|
1134
|
+
addBytes(metrics, 4);
|
|
1135
|
+
return store ? null : void 0;
|
|
1136
|
+
}
|
|
1137
|
+
if (typeof value === "boolean") {
|
|
1138
|
+
addBytes(metrics, value ? 4 : 5);
|
|
1139
|
+
return store ? value : void 0;
|
|
1140
|
+
}
|
|
1141
|
+
if (typeof value === "number") {
|
|
1142
|
+
if (!Number.isFinite(value)) addBytes(metrics, 4);
|
|
1143
|
+
else if (Object.is(value, -0)) addBytes(metrics, 1);
|
|
1144
|
+
else addBytes(metrics, String(value).length);
|
|
1145
|
+
return store ? value : void 0;
|
|
1146
|
+
}
|
|
696
1147
|
if (typeof value === "string") {
|
|
697
|
-
if (value.length <= limits.maxStringLength)
|
|
698
|
-
|
|
1148
|
+
if (value.length <= limits.maxStringLength) {
|
|
1149
|
+
addBytes(metrics, jsonStringUtf8Bytes(value));
|
|
1150
|
+
return store ? value : void 0;
|
|
1151
|
+
}
|
|
1152
|
+
return writeTruncation(metrics, store, "max_string_length", {
|
|
699
1153
|
__original_length: value.length,
|
|
700
1154
|
value: value.slice(0, limits.maxStringLength)
|
|
701
1155
|
});
|
|
702
1156
|
}
|
|
703
|
-
if (typeof value === "undefined") return
|
|
704
|
-
if (typeof value === "bigint")
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
if (
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
if (
|
|
711
|
-
|
|
1157
|
+
if (typeof value === "undefined") return writeTypeMarker(metrics, store, "undefined");
|
|
1158
|
+
if (typeof value === "bigint") {
|
|
1159
|
+
return writeTypeMarker(metrics, store, "bigint", value.toString());
|
|
1160
|
+
}
|
|
1161
|
+
if (typeof value === "symbol") {
|
|
1162
|
+
return writeTypeMarker(metrics, store, "symbol", String(value));
|
|
1163
|
+
}
|
|
1164
|
+
if (typeof value === "function") {
|
|
1165
|
+
return writeTypeMarker(metrics, store, "function", value.name || "anonymous");
|
|
1166
|
+
}
|
|
1167
|
+
if (depth >= limits.maxDepth) return writeTruncation(metrics, store, "max_depth");
|
|
1168
|
+
if (typeof value !== "object") return writeTypeMarker(metrics, store, typeof value);
|
|
1169
|
+
if (path.has(value)) return writeTypeMarker(metrics, store, "circular");
|
|
1170
|
+
path.add(value);
|
|
1171
|
+
const bytesBefore = metrics.bytes;
|
|
1172
|
+
const oversizeBefore = metrics.oversize;
|
|
712
1173
|
try {
|
|
1174
|
+
const childAllocate = allocate && !metrics.oversize;
|
|
713
1175
|
if (value instanceof Error) {
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
1176
|
+
const object2 = openObject(metrics, childAllocate);
|
|
1177
|
+
writeLiteralField(metrics, object2, "__rasputin_type", "Error");
|
|
1178
|
+
writeLiteralField(metrics, object2, "name", value.name);
|
|
1179
|
+
beginField(metrics, object2, "message");
|
|
1180
|
+
assignField(
|
|
1181
|
+
object2,
|
|
1182
|
+
"message",
|
|
1183
|
+
serializeInner(value.message, depth + 1, path, childAllocate, metrics)
|
|
1184
|
+
);
|
|
1185
|
+
if (value.stack) {
|
|
1186
|
+
beginField(metrics, object2, "stack");
|
|
1187
|
+
assignField(
|
|
1188
|
+
object2,
|
|
1189
|
+
"stack",
|
|
1190
|
+
serializeInner(value.stack, depth + 1, path, childAllocate, metrics)
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
return object2.target;
|
|
1194
|
+
}
|
|
1195
|
+
if (value instanceof Date) {
|
|
1196
|
+
return writeTypeMarker(metrics, childAllocate, "Date", value.toISOString());
|
|
720
1197
|
}
|
|
721
|
-
if (value instanceof Date) return typeMarker("Date", value.toISOString());
|
|
722
1198
|
if (Buffer2.isBuffer(value)) {
|
|
723
|
-
return
|
|
1199
|
+
return writeTypeMarker(metrics, childAllocate, "Buffer", {
|
|
724
1200
|
byteLength: value.byteLength,
|
|
725
1201
|
base64: value.subarray(0, limits.maxStringLength).toString("base64"),
|
|
726
1202
|
...value.byteLength > limits.maxStringLength ? { __rasputin_truncated: true } : {}
|
|
727
1203
|
});
|
|
728
1204
|
}
|
|
729
|
-
if (value instanceof Promise) return
|
|
1205
|
+
if (value instanceof Promise) return writeTypeMarker(metrics, childAllocate, "Promise");
|
|
730
1206
|
if (value instanceof Map) {
|
|
731
|
-
const
|
|
1207
|
+
const object2 = openObject(metrics, childAllocate);
|
|
1208
|
+
writeLiteralField(metrics, object2, "__rasputin_type", "Map");
|
|
1209
|
+
beginField(metrics, object2, "entries");
|
|
1210
|
+
const entries = openArray(metrics, childAllocate);
|
|
1211
|
+
let counted2 = 0;
|
|
732
1212
|
for (const entry of value.entries()) {
|
|
733
|
-
if (
|
|
734
|
-
entries.
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
]);
|
|
1213
|
+
if (counted2 >= limits.maxArrayElements) break;
|
|
1214
|
+
if (!entries.first) addBytes(metrics, 1);
|
|
1215
|
+
entries.first = false;
|
|
1216
|
+
addBytes(metrics, 2);
|
|
1217
|
+
const key = serializeInner(entry[0], depth + 1, path, childAllocate, metrics);
|
|
1218
|
+
addBytes(metrics, 1);
|
|
1219
|
+
const mapped = serializeInner(entry[1], depth + 1, path, childAllocate, metrics);
|
|
1220
|
+
entries.items?.push([key, mapped]);
|
|
1221
|
+
counted2++;
|
|
1222
|
+
}
|
|
1223
|
+
assignField(object2, "entries", entries.items ?? []);
|
|
1224
|
+
if (value.size > limits.maxArrayElements) {
|
|
1225
|
+
writeLiteralField(metrics, object2, "__rasputin_truncated", true);
|
|
1226
|
+
writeLiteralField(metrics, object2, "__reason", "max_array_elements");
|
|
1227
|
+
writeLiteralField(metrics, object2, "__original_length", value.size);
|
|
738
1228
|
}
|
|
739
|
-
return
|
|
740
|
-
__rasputin_type: "Map",
|
|
741
|
-
entries,
|
|
742
|
-
...value.size > limits.maxArrayElements ? truncation("max_array_elements", { __original_length: value.size }) : {}
|
|
743
|
-
};
|
|
1229
|
+
return object2.target;
|
|
744
1230
|
}
|
|
745
1231
|
if (value instanceof Set) {
|
|
746
|
-
const
|
|
1232
|
+
const object2 = openObject(metrics, childAllocate);
|
|
1233
|
+
writeLiteralField(metrics, object2, "__rasputin_type", "Set");
|
|
1234
|
+
beginField(metrics, object2, "values");
|
|
1235
|
+
const items = openArray(metrics, childAllocate);
|
|
1236
|
+
let counted2 = 0;
|
|
747
1237
|
for (const item of value.values()) {
|
|
748
|
-
if (
|
|
749
|
-
items.
|
|
1238
|
+
if (counted2 >= limits.maxArrayElements) break;
|
|
1239
|
+
if (!items.first) addBytes(metrics, 1);
|
|
1240
|
+
items.first = false;
|
|
1241
|
+
const serializedItem = serializeInner(item, depth + 1, path, childAllocate, metrics);
|
|
1242
|
+
items.items?.push(serializedItem);
|
|
1243
|
+
counted2++;
|
|
750
1244
|
}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
1245
|
+
assignField(object2, "values", items.items ?? []);
|
|
1246
|
+
if (value.size > limits.maxArrayElements) {
|
|
1247
|
+
writeLiteralField(metrics, object2, "__rasputin_truncated", true);
|
|
1248
|
+
writeLiteralField(metrics, object2, "__reason", "max_array_elements");
|
|
1249
|
+
writeLiteralField(metrics, object2, "__original_length", value.size);
|
|
1250
|
+
}
|
|
1251
|
+
return object2.target;
|
|
756
1252
|
}
|
|
757
1253
|
if (Array.isArray(value)) {
|
|
1254
|
+
const items = openArray(metrics, childAllocate);
|
|
758
1255
|
const maxItems = value.length > limits.maxArrayElements ? limits.maxArrayElements - 1 : value.length;
|
|
759
|
-
const items = [];
|
|
760
1256
|
for (let index = 0; index < maxItems; index++) {
|
|
761
|
-
items.
|
|
1257
|
+
if (!items.first) addBytes(metrics, 1);
|
|
1258
|
+
items.first = false;
|
|
1259
|
+
items.items?.push(serializeInner(value[index], depth + 1, path, childAllocate, metrics));
|
|
762
1260
|
}
|
|
763
1261
|
if (value.length > limits.maxArrayElements) {
|
|
764
|
-
items.
|
|
1262
|
+
if (!items.first) addBytes(metrics, 1);
|
|
1263
|
+
items.first = false;
|
|
1264
|
+
items.items?.push(
|
|
1265
|
+
writeTruncation(metrics, childAllocate, "max_array_elements", {
|
|
1266
|
+
__original_length: value.length
|
|
1267
|
+
})
|
|
1268
|
+
);
|
|
765
1269
|
}
|
|
766
|
-
return items;
|
|
1270
|
+
return items.items;
|
|
767
1271
|
}
|
|
1272
|
+
const object = openObject(metrics, childAllocate);
|
|
768
1273
|
const prototype = Object.getPrototypeOf(value);
|
|
769
|
-
const serialized = {};
|
|
770
1274
|
if (prototype && prototype !== Object.prototype) {
|
|
771
|
-
|
|
1275
|
+
writeLiteralField(
|
|
1276
|
+
metrics,
|
|
1277
|
+
object,
|
|
1278
|
+
"__rasputin_type",
|
|
1279
|
+
prototype.constructor?.name ?? "instance"
|
|
1280
|
+
);
|
|
772
1281
|
}
|
|
773
1282
|
const keys = Object.keys(value);
|
|
774
1283
|
const maxKeys = keys.length > limits.maxObjectKeys ? limits.maxObjectKeys - 1 : keys.length;
|
|
775
1284
|
for (let index = 0; index < maxKeys; index++) {
|
|
776
1285
|
const key = keys[index];
|
|
777
1286
|
if (key === void 0) continue;
|
|
778
|
-
if (
|
|
779
|
-
|
|
1287
|
+
if (isRedactedKey(key)) {
|
|
1288
|
+
writeLiteralField(metrics, object, key, REDACTED);
|
|
780
1289
|
continue;
|
|
781
1290
|
}
|
|
782
1291
|
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
783
|
-
|
|
1292
|
+
if (descriptor && "value" in descriptor) {
|
|
1293
|
+
beginField(metrics, object, key);
|
|
1294
|
+
assignField(
|
|
1295
|
+
object,
|
|
1296
|
+
key,
|
|
1297
|
+
serializeInner(descriptor.value, depth + 1, path, childAllocate, metrics)
|
|
1298
|
+
);
|
|
1299
|
+
} else {
|
|
1300
|
+
beginField(metrics, object, key);
|
|
1301
|
+
assignField(object, key, writeTypeMarker(metrics, childAllocate, "accessor"));
|
|
1302
|
+
}
|
|
784
1303
|
}
|
|
785
1304
|
if (keys.length > limits.maxObjectKeys) {
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
);
|
|
1305
|
+
writeLiteralField(metrics, object, "__rasputin_truncated", true);
|
|
1306
|
+
writeLiteralField(metrics, object, "__reason", "max_object_keys");
|
|
1307
|
+
writeLiteralField(metrics, object, "__original_length", keys.length);
|
|
790
1308
|
}
|
|
791
|
-
return
|
|
1309
|
+
return object.target;
|
|
792
1310
|
} catch (error) {
|
|
793
|
-
|
|
1311
|
+
metrics.bytes = bytesBefore;
|
|
1312
|
+
metrics.oversize = oversizeBefore;
|
|
1313
|
+
return writeTypeMarker(
|
|
1314
|
+
metrics,
|
|
1315
|
+
allocate && !metrics.oversize,
|
|
1316
|
+
"unserializable",
|
|
1317
|
+
error instanceof Error ? error.message : void 0
|
|
1318
|
+
);
|
|
794
1319
|
} finally {
|
|
795
|
-
|
|
1320
|
+
path.delete(value);
|
|
796
1321
|
}
|
|
797
1322
|
};
|
|
798
|
-
const boundedOversize = (bytes, visitedNodes) => {
|
|
799
|
-
const bounded = truncation("max_serialized_value_bytes", { __serialized_bytes: bytes });
|
|
800
|
-
return {
|
|
801
|
-
value: bounded,
|
|
802
|
-
bytes: Buffer2.byteLength(JSON.stringify(bounded), "utf8"),
|
|
803
|
-
visitedNodes
|
|
804
|
-
};
|
|
805
|
-
};
|
|
806
1323
|
const serializeWithBytes = (value) => {
|
|
807
1324
|
const fast = primitiveFastPath(value, limits.maxStringLength);
|
|
808
1325
|
if (fast) {
|
|
809
1326
|
return fast.bytes <= limits.maxSerializedValueBytes ? fast : boundedOversize(fast.bytes, fast.visitedNodes);
|
|
810
1327
|
}
|
|
811
|
-
const metrics = { visitedNodes: 0 };
|
|
1328
|
+
const metrics = { visitedNodes: 0, bytes: 0, oversize: false };
|
|
1329
|
+
const reentrant = serializing;
|
|
1330
|
+
const path = reentrant ? /* @__PURE__ */ new Set() : sharedPath;
|
|
1331
|
+
if (!reentrant) {
|
|
1332
|
+
serializing = true;
|
|
1333
|
+
sharedPath.clear();
|
|
1334
|
+
}
|
|
812
1335
|
try {
|
|
813
|
-
const serialized = serializeInner(value, 0,
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
return { value: serialized, bytes, visitedNodes: metrics.visitedNodes };
|
|
1336
|
+
const serialized = serializeInner(value, 0, path, true, metrics);
|
|
1337
|
+
if (metrics.bytes > limits.maxSerializedValueBytes) {
|
|
1338
|
+
return boundedOversize(metrics.bytes, metrics.visitedNodes);
|
|
817
1339
|
}
|
|
818
|
-
return
|
|
1340
|
+
return { value: serialized, bytes: metrics.bytes, visitedNodes: metrics.visitedNodes };
|
|
819
1341
|
} catch {
|
|
820
1342
|
const failed = typeMarker("unserializable");
|
|
821
1343
|
return {
|
|
822
1344
|
value: failed,
|
|
823
|
-
bytes:
|
|
1345
|
+
bytes: jsonLiteralUtf8Bytes(failed),
|
|
824
1346
|
visitedNodes: metrics.visitedNodes
|
|
825
1347
|
};
|
|
1348
|
+
} finally {
|
|
1349
|
+
path.clear();
|
|
1350
|
+
if (!reentrant) serializing = false;
|
|
826
1351
|
}
|
|
827
1352
|
};
|
|
828
1353
|
return {
|
|
@@ -898,6 +1423,8 @@ var createSourceExclusionMatcher = (exclusions) => {
|
|
|
898
1423
|
|
|
899
1424
|
// src/execution-recorder/execution-recorder.ts
|
|
900
1425
|
var DEFAULT_MAX_ACTIVE_MEMORY_BYTES = 64 * 1024 * 1024;
|
|
1426
|
+
var DERIVATION_ROOT_RECORD_BYTES = 64;
|
|
1427
|
+
var phaseTimingEnabled = process.env.RASPUTIN_RECORDER_PHASE_TIMING === "1";
|
|
901
1428
|
var manualFunctionDefinition = (value) => {
|
|
902
1429
|
const located = /^(.+):([^:@]+)@(\d+):(\d+)$/.exec(value);
|
|
903
1430
|
const named = located ? void 0 : /^(.+):([^:@]+)$/.exec(value);
|
|
@@ -912,8 +1439,8 @@ var manualFunctionDefinition = (value) => {
|
|
|
912
1439
|
return { ...definition, functionId: runtimeFunctionId2(definition) };
|
|
913
1440
|
};
|
|
914
1441
|
var normalizeFunctionDefinition = (value) => typeof value === "string" ? manualFunctionDefinition(value) : value;
|
|
915
|
-
var
|
|
916
|
-
var
|
|
1442
|
+
var elapsedMs2 = (startedAtNs, endedAtNs = process.hrtime.bigint()) => Number(endedAtNs - startedAtNs) / 1e6;
|
|
1443
|
+
var roundedMilliseconds2 = (nanoseconds) => Math.round(Number(nanoseconds) / 1e6 * 1e4) / 1e4;
|
|
917
1444
|
var addRecorderTime = (recording, nanoseconds) => {
|
|
918
1445
|
if (nanoseconds > 0n) recording.inlineRecorderTimeNs += nanoseconds;
|
|
919
1446
|
};
|
|
@@ -1005,7 +1532,20 @@ var emptyStats = {
|
|
|
1005
1532
|
totalInlineWallTimeMs: 0,
|
|
1006
1533
|
maxInlineWallTimeMs: 0,
|
|
1007
1534
|
activeEstimatedBytes: 0,
|
|
1008
|
-
peakActiveEstimatedBytes: 0
|
|
1535
|
+
peakActiveEstimatedBytes: 0,
|
|
1536
|
+
journalPoolHits: 0,
|
|
1537
|
+
journalPoolMisses: 0,
|
|
1538
|
+
journalPoolSize: 0,
|
|
1539
|
+
journalAllocatedCapacity: 0,
|
|
1540
|
+
derivationCandidateFunctions: 0,
|
|
1541
|
+
derivationElidedFunctionCalls: 0,
|
|
1542
|
+
derivationRootsCaptured: 0,
|
|
1543
|
+
derivationControlFactsCaptured: 0,
|
|
1544
|
+
derivationValuesAvoided: 0,
|
|
1545
|
+
derivationFallbackFunctions: 0,
|
|
1546
|
+
derivationFallbackExpressions: 0,
|
|
1547
|
+
derivationFallbackReasons: {},
|
|
1548
|
+
derivationRootBytes: 0
|
|
1009
1549
|
};
|
|
1010
1550
|
var noOpExecution = {
|
|
1011
1551
|
createScope: () => ({
|
|
@@ -1021,17 +1561,34 @@ var noOpExecution = {
|
|
|
1021
1561
|
prepareFunctionPlans: () => [],
|
|
1022
1562
|
runPreparedFunction: (_plan, _args, callback) => callback(),
|
|
1023
1563
|
trace: (_functionId, fn) => fn,
|
|
1024
|
-
getStats: () => ({ ...emptyStats })
|
|
1564
|
+
getStats: () => ({ ...emptyStats, derivationFallbackReasons: {} }),
|
|
1565
|
+
captureDerivationRoot: (_rootId, value) => value
|
|
1025
1566
|
};
|
|
1026
1567
|
var mergeExecutionMetadata = (target, metadata) => {
|
|
1027
1568
|
if (metadata.kind) target.kind = metadata.kind;
|
|
1028
1569
|
if (metadata.name !== void 0) target.name = metadata.name;
|
|
1029
1570
|
if (metadata.request) target.request = { ...target.request, ...metadata.request };
|
|
1030
1571
|
};
|
|
1572
|
+
var newRepeatedGroup = (plan) => ({
|
|
1573
|
+
observedCalls: 0,
|
|
1574
|
+
functionId: plan.functionId,
|
|
1575
|
+
runtimePlanId: plan.runtimePlanId
|
|
1576
|
+
});
|
|
1577
|
+
var newSuppression = (group, parentCallId, startedAtNs, endedAtNs) => ({
|
|
1578
|
+
count: 1,
|
|
1579
|
+
firstTimestampNs: startedAtNs,
|
|
1580
|
+
lastTimestampNs: endedAtNs,
|
|
1581
|
+
totalDurationNs: endedAtNs - startedAtNs,
|
|
1582
|
+
functionId: group.functionId,
|
|
1583
|
+
runtimePlanId: group.runtimePlanId,
|
|
1584
|
+
...parentCallId === void 0 ? {} : { parentCallId },
|
|
1585
|
+
storageIndex: -1,
|
|
1586
|
+
retainedIndex: -1
|
|
1587
|
+
});
|
|
1031
1588
|
var createExecutionRecorder = (options) => {
|
|
1032
1589
|
if (!options?.enabled) return noOpExecution;
|
|
1033
1590
|
const storage = new AsyncLocalStorage();
|
|
1034
|
-
const maxEventsPerExecution =
|
|
1591
|
+
const maxEventsPerExecution = sanitizeJournalCapacity(options.maxEventsPerExecution);
|
|
1035
1592
|
const maxCapturedCallsPerFunction = Math.max(
|
|
1036
1593
|
1,
|
|
1037
1594
|
Math.floor(options.maxCapturedCallsPerFunction ?? 3)
|
|
@@ -1046,11 +1603,14 @@ var createExecutionRecorder = (options) => {
|
|
|
1046
1603
|
);
|
|
1047
1604
|
const serializer = createSafeSerializer(options);
|
|
1048
1605
|
const excludesSource = createSourceExclusionMatcher(options.excludeSources);
|
|
1606
|
+
const journalPool = new ExecutionJournalPool(maxEventsPerExecution);
|
|
1607
|
+
const plansByRuntimeId = [];
|
|
1049
1608
|
let executionCounter = 0;
|
|
1050
1609
|
let nextRuntimePlanId = 1;
|
|
1051
1610
|
const internedPlans = /* @__PURE__ */ new Map();
|
|
1052
1611
|
const preparedModules = /* @__PURE__ */ new WeakMap();
|
|
1053
1612
|
const errorExecutions = /* @__PURE__ */ new WeakMap();
|
|
1613
|
+
const phases = phaseTimingEnabled ? { alsNs: 0n, materializeNs: 0n } : void 0;
|
|
1054
1614
|
const stats = {
|
|
1055
1615
|
functionCallsObserved: 0,
|
|
1056
1616
|
functionCallsCaptured: 0,
|
|
@@ -1067,10 +1627,22 @@ var createExecutionRecorder = (options) => {
|
|
|
1067
1627
|
partialErrorSnapshots: 0,
|
|
1068
1628
|
measuredExecutions: 0,
|
|
1069
1629
|
totalInlineWallTimeMs: 0,
|
|
1070
|
-
maxInlineWallTimeMs: 0
|
|
1630
|
+
maxInlineWallTimeMs: 0,
|
|
1631
|
+
derivationCandidateFunctions: 0,
|
|
1632
|
+
derivationElidedFunctionCalls: 0,
|
|
1633
|
+
derivationRootsCaptured: 0,
|
|
1634
|
+
derivationControlFactsCaptured: 0,
|
|
1635
|
+
derivationValuesAvoided: 0,
|
|
1636
|
+
derivationFallbackFunctions: 0,
|
|
1637
|
+
derivationFallbackExpressions: 0,
|
|
1638
|
+
derivationFallbackReasons: {},
|
|
1639
|
+
derivationRootBytes: 0
|
|
1640
|
+
};
|
|
1641
|
+
const addPhase = (key, nanoseconds) => {
|
|
1642
|
+
if (phases && nanoseconds > 0n) phases[key] += nanoseconds;
|
|
1071
1643
|
};
|
|
1072
1644
|
const recordInlineTiming = (recording) => {
|
|
1073
|
-
const inlineWallTimeMs =
|
|
1645
|
+
const inlineWallTimeMs = roundedMilliseconds2(recording.inlineRecorderTimeNs);
|
|
1074
1646
|
stats.measuredExecutions++;
|
|
1075
1647
|
stats.totalInlineWallTimeMs = Math.round((stats.totalInlineWallTimeMs + inlineWallTimeMs) * 1e4) / 1e4;
|
|
1076
1648
|
stats.maxInlineWallTimeMs = Math.max(stats.maxInlineWallTimeMs, inlineWallTimeMs);
|
|
@@ -1083,16 +1655,20 @@ var createExecutionRecorder = (options) => {
|
|
|
1083
1655
|
return serialized;
|
|
1084
1656
|
};
|
|
1085
1657
|
const captureValue = (recording, value) => memoryBudget.captureValue(recording.memory, () => serializeAndCount(value));
|
|
1658
|
+
const storePlan = (plan) => {
|
|
1659
|
+
plansByRuntimeId[plan.runtimePlanId] = plan;
|
|
1660
|
+
return plan;
|
|
1661
|
+
};
|
|
1086
1662
|
const preparePlan = (definition) => {
|
|
1087
1663
|
const existing = internedPlans.get(definition.functionId);
|
|
1088
1664
|
if (existing) return existing;
|
|
1089
|
-
const plan = {
|
|
1665
|
+
const plan = storePlan({
|
|
1090
1666
|
runtimePlanId: nextRuntimePlanId++,
|
|
1091
1667
|
definition,
|
|
1092
1668
|
functionId: definition.functionId,
|
|
1093
1669
|
excluded: excludesSource(definition),
|
|
1094
1670
|
estimatedCallBytes: estimatedCallBytesFor(definition.functionId)
|
|
1095
|
-
};
|
|
1671
|
+
});
|
|
1096
1672
|
internedPlans.set(definition.functionId, plan);
|
|
1097
1673
|
return plan;
|
|
1098
1674
|
};
|
|
@@ -1101,62 +1677,111 @@ var createExecutionRecorder = (options) => {
|
|
|
1101
1677
|
if (cached) return cached;
|
|
1102
1678
|
const prepared = plans.map((encoded) => {
|
|
1103
1679
|
const definition = definitionFromEncodedPlan(encoded);
|
|
1104
|
-
return {
|
|
1680
|
+
return storePlan({
|
|
1105
1681
|
runtimePlanId: nextRuntimePlanId++,
|
|
1106
1682
|
definition,
|
|
1107
1683
|
functionId: definition.functionId,
|
|
1108
1684
|
excluded: excludesSource(definition),
|
|
1109
1685
|
estimatedCallBytes: estimatedCallBytesFor(definition.functionId)
|
|
1110
|
-
};
|
|
1686
|
+
});
|
|
1111
1687
|
});
|
|
1112
1688
|
preparedModules.set(plans, prepared);
|
|
1113
1689
|
return prepared;
|
|
1114
1690
|
};
|
|
1115
|
-
const
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1691
|
+
const derivationMetrics = (recording) => {
|
|
1692
|
+
const manifest = snapshotInstrumentationManifest();
|
|
1693
|
+
const plans = manifest?.derivationPlans ?? [];
|
|
1694
|
+
const reasons = { ...stats.derivationFallbackReasons };
|
|
1695
|
+
return {
|
|
1696
|
+
derivationCandidateFunctions: plans.filter((plan) => !plan.fallbackReason).length,
|
|
1697
|
+
derivationElidedFunctionCalls: stats.derivationElidedFunctionCalls,
|
|
1698
|
+
derivationRootsCaptured: recording.derivationRoots.length,
|
|
1699
|
+
derivationControlFactsCaptured: stats.derivationControlFactsCaptured,
|
|
1700
|
+
derivationValuesAvoided: stats.derivationValuesAvoided,
|
|
1701
|
+
derivationFallbackFunctions: plans.filter((plan) => plan.fallbackReason).length,
|
|
1702
|
+
derivationFallbackExpressions: recording.derivationRoots.length,
|
|
1703
|
+
derivationFallbackReasons: reasons,
|
|
1704
|
+
derivationRootBytes: recording.derivationRootBytes
|
|
1705
|
+
};
|
|
1706
|
+
};
|
|
1707
|
+
const resolveCaptureMode = (recording) => {
|
|
1708
|
+
if (recording.derivationRoots.length > 0) return "derivation";
|
|
1709
|
+
const plans = snapshotInstrumentationManifest()?.derivationPlans ?? [];
|
|
1710
|
+
if (recording.sawAutomatic && plans.some(
|
|
1711
|
+
(plan) => !plan.fallbackReason && recording.executedFunctionIds.has(plan.functionId)
|
|
1712
|
+
)) {
|
|
1713
|
+
return "derivation";
|
|
1714
|
+
}
|
|
1715
|
+
if (recording.sawAutomatic) return "automatic-full";
|
|
1716
|
+
if (recording.sawManual) return "manual";
|
|
1717
|
+
return "scope-only";
|
|
1718
|
+
};
|
|
1719
|
+
const derivationCapture = (recording) => {
|
|
1720
|
+
const manifest = snapshotInstrumentationManifest();
|
|
1721
|
+
if (!manifest) return void 0;
|
|
1722
|
+
return {
|
|
1723
|
+
manifestHash: hashInstrumentationManifest(manifest),
|
|
1724
|
+
roots: recording.derivationRoots.slice(),
|
|
1725
|
+
controlFacts: []
|
|
1726
|
+
};
|
|
1727
|
+
};
|
|
1124
1728
|
const stateFrom = (recording, endedAtNs = process.hrtime.bigint()) => {
|
|
1125
1729
|
const recorderStartedAtNs = process.hrtime.bigint();
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1730
|
+
let events = [];
|
|
1731
|
+
let functions = [];
|
|
1732
|
+
let truncated;
|
|
1733
|
+
let capture;
|
|
1734
|
+
let derivation;
|
|
1735
|
+
if (recording.cachedState) {
|
|
1736
|
+
events = recording.cachedState.events;
|
|
1737
|
+
functions = recording.cachedState.functions;
|
|
1738
|
+
truncated = recording.cachedState.truncated;
|
|
1739
|
+
capture = recording.cachedState.capture;
|
|
1740
|
+
derivation = recording.cachedState.derivation;
|
|
1741
|
+
} else {
|
|
1742
|
+
if (recording.journal) {
|
|
1743
|
+
const materialized = recording.journal.materialize(plansByRuntimeId, recording.startedAtNs);
|
|
1744
|
+
events = materialized.events;
|
|
1745
|
+
functions = materialized.functions;
|
|
1746
|
+
truncated = recording.journal.dropped > 0 ? { eventsDropped: recording.journal.dropped } : void 0;
|
|
1747
|
+
}
|
|
1748
|
+
capture = recording.memory.underPressure ? {
|
|
1749
|
+
completeness: "partial",
|
|
1750
|
+
reason: "process_memory_budget",
|
|
1751
|
+
valuesDropped: recording.memory.valuesDropped,
|
|
1752
|
+
eventsDropped: recording.memory.eventsDropped
|
|
1753
|
+
} : void 0;
|
|
1754
|
+
derivation = derivationCapture(recording);
|
|
1755
|
+
if (recording.finished && recording.inFlightCalls === 0 && recording.journal) {
|
|
1756
|
+
recording.cachedState = { events, functions, truncated, capture, derivation };
|
|
1757
|
+
journalPool.release(recording.journal);
|
|
1758
|
+
recording.journal = void 0;
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1134
1761
|
const state = {
|
|
1135
|
-
version:
|
|
1762
|
+
version: 3,
|
|
1763
|
+
captureMode: resolveCaptureMode(recording),
|
|
1136
1764
|
executionId: recording.executionId,
|
|
1137
1765
|
startedAt: recording.startedAt,
|
|
1138
|
-
durationMs:
|
|
1139
|
-
recorder: { inlineWallTimeMs: 0 },
|
|
1766
|
+
durationMs: elapsedMs2(recording.startedAtNs, endedAtNs),
|
|
1767
|
+
recorder: { inlineWallTimeMs: 0, derivation: derivationMetrics(recording) },
|
|
1140
1768
|
execution: {
|
|
1141
1769
|
...recording.execution,
|
|
1142
1770
|
...recording.execution.request ? { request: { ...recording.execution.request } } : {}
|
|
1143
1771
|
},
|
|
1144
|
-
functions:
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
...
|
|
1149
|
-
...recording.memory.underPressure ? {
|
|
1150
|
-
capture: {
|
|
1151
|
-
completeness: "partial",
|
|
1152
|
-
reason: "process_memory_budget",
|
|
1153
|
-
valuesDropped: recording.memory.valuesDropped,
|
|
1154
|
-
eventsDropped: recording.memory.eventsDropped
|
|
1155
|
-
}
|
|
1156
|
-
} : {}
|
|
1772
|
+
functions: functions.slice(),
|
|
1773
|
+
events: events.slice(),
|
|
1774
|
+
...truncated ? { truncated: { ...truncated } } : {},
|
|
1775
|
+
...capture ? { capture: { ...capture } } : {},
|
|
1776
|
+
...derivation ? { derivation: { ...derivation, roots: derivation.roots.slice() } } : {}
|
|
1157
1777
|
};
|
|
1778
|
+
if (phaseTimingEnabled)
|
|
1779
|
+
addPhase("materializeNs", process.hrtime.bigint() - recorderStartedAtNs);
|
|
1158
1780
|
addRecorderTime(recording, process.hrtime.bigint() - recorderStartedAtNs);
|
|
1159
|
-
state.recorder = {
|
|
1781
|
+
state.recorder = {
|
|
1782
|
+
inlineWallTimeMs: roundedMilliseconds2(recording.inlineRecorderTimeNs),
|
|
1783
|
+
derivation: derivationMetrics(recording)
|
|
1784
|
+
};
|
|
1160
1785
|
return state;
|
|
1161
1786
|
};
|
|
1162
1787
|
const rememberError = (error, recording) => {
|
|
@@ -1172,32 +1797,38 @@ var createExecutionRecorder = (options) => {
|
|
|
1172
1797
|
errorExecutions.set(error, recording);
|
|
1173
1798
|
};
|
|
1174
1799
|
const countDroppedEvents = (recording, droppedBefore) => {
|
|
1175
|
-
|
|
1800
|
+
const dropped = recording.journal?.dropped ?? droppedBefore;
|
|
1801
|
+
stats.truncatedEvents += dropped - droppedBefore;
|
|
1176
1802
|
};
|
|
1177
1803
|
const appendSuppressedPlaceholder = (recording, group) => {
|
|
1804
|
+
if (!recording.journal) return;
|
|
1178
1805
|
if (!memoryBudget.reserveStandaloneEvent(recording.memory)) return;
|
|
1179
|
-
const droppedBefore = recording.
|
|
1180
|
-
recording.
|
|
1806
|
+
const droppedBefore = recording.journal.dropped;
|
|
1807
|
+
recording.journal.appendSuppressed(group);
|
|
1181
1808
|
countDroppedEvents(recording, droppedBefore);
|
|
1182
1809
|
};
|
|
1183
|
-
const repeatedCallGroup = (recording,
|
|
1810
|
+
const repeatedCallGroup = (recording, plan, parentCallId) => {
|
|
1184
1811
|
const slots = recording.repeatedCalls;
|
|
1185
|
-
let slot = slots[runtimePlanId];
|
|
1812
|
+
let slot = slots[plan.runtimePlanId];
|
|
1186
1813
|
if (!slot) {
|
|
1187
1814
|
slot = {};
|
|
1188
|
-
slots[runtimePlanId] = slot;
|
|
1815
|
+
slots[plan.runtimePlanId] = slot;
|
|
1189
1816
|
}
|
|
1190
1817
|
if (parentCallId === void 0) {
|
|
1191
|
-
if (!slot.root) slot.root =
|
|
1818
|
+
if (!slot.root) slot.root = newRepeatedGroup(plan);
|
|
1192
1819
|
return slot.root;
|
|
1193
1820
|
}
|
|
1821
|
+
if (slot.lastParentGroup && slot.lastParentCallId === parentCallId) {
|
|
1822
|
+
return slot.lastParentGroup;
|
|
1823
|
+
}
|
|
1194
1824
|
if (!slot.byParent) slot.byParent = /* @__PURE__ */ new Map();
|
|
1195
|
-
|
|
1196
|
-
let group = byParent.get(parentCallId);
|
|
1825
|
+
let group = slot.byParent.get(parentCallId);
|
|
1197
1826
|
if (!group) {
|
|
1198
|
-
group =
|
|
1199
|
-
byParent.set(parentCallId, group);
|
|
1827
|
+
group = newRepeatedGroup(plan);
|
|
1828
|
+
slot.byParent.set(parentCallId, group);
|
|
1200
1829
|
}
|
|
1830
|
+
slot.lastParentCallId = parentCallId;
|
|
1831
|
+
slot.lastParentGroup = group;
|
|
1201
1832
|
return group;
|
|
1202
1833
|
};
|
|
1203
1834
|
const serializedError = (recording, error, callId) => {
|
|
@@ -1220,29 +1851,30 @@ var createExecutionRecorder = (options) => {
|
|
|
1220
1851
|
};
|
|
1221
1852
|
};
|
|
1222
1853
|
const captureCompletedThrow = (recording, plan, args, parentCallId, startedAtNs, error) => {
|
|
1854
|
+
if (!recording.journal) {
|
|
1855
|
+
rememberError(error, recording);
|
|
1856
|
+
return;
|
|
1857
|
+
}
|
|
1223
1858
|
if (!memoryBudget.reserveCall(recording.memory, plan.estimatedCallBytes)) {
|
|
1224
1859
|
rememberError(error, recording);
|
|
1225
1860
|
return;
|
|
1226
1861
|
}
|
|
1227
1862
|
const callId = ++recording.nextCallId;
|
|
1228
1863
|
const capturedError = serializedError(recording, error, callId);
|
|
1229
|
-
const
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
args: Array.from(args, (argument) => captureValue(recording, argument)),
|
|
1235
|
-
...parentCallId === void 0 ? {} : { parentCallId }
|
|
1236
|
-
};
|
|
1237
|
-
const terminal = {
|
|
1238
|
-
type: "function_throw",
|
|
1864
|
+
const capturedArgs = Array.from(args, (argument) => captureValue(recording, argument));
|
|
1865
|
+
const endedAtNs = process.hrtime.bigint();
|
|
1866
|
+
const droppedBefore = recording.journal.dropped;
|
|
1867
|
+
const retained = recording.journal.forceCompletedCall(
|
|
1868
|
+
plan.runtimePlanId,
|
|
1239
1869
|
callId,
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1870
|
+
parentCallId,
|
|
1871
|
+
startedAtNs - recording.startedAtNs,
|
|
1872
|
+
capturedArgs,
|
|
1873
|
+
KIND_THROW,
|
|
1874
|
+
endedAtNs - recording.startedAtNs,
|
|
1875
|
+
endedAtNs - startedAtNs,
|
|
1876
|
+
capturedError.value
|
|
1877
|
+
);
|
|
1246
1878
|
if (retained) {
|
|
1247
1879
|
stats.functionCallsCaptured++;
|
|
1248
1880
|
capturedError.commit();
|
|
@@ -1250,29 +1882,46 @@ var createExecutionRecorder = (options) => {
|
|
|
1250
1882
|
countDroppedEvents(recording, droppedBefore);
|
|
1251
1883
|
rememberError(error, recording);
|
|
1252
1884
|
};
|
|
1253
|
-
const recordSuppressedCall = (recording, group,
|
|
1885
|
+
const recordSuppressedCall = (recording, group, parentCallId, startedAtNs, endedAtNs) => {
|
|
1254
1886
|
stats.repeatedCallsSuppressed++;
|
|
1255
|
-
const durationNs = endedAtNs - startedAtNs;
|
|
1256
1887
|
if (!group.suppressed) {
|
|
1257
|
-
group.suppressed =
|
|
1258
|
-
count: 1,
|
|
1259
|
-
firstTimestampNs: startedAtNs,
|
|
1260
|
-
lastTimestampNs: endedAtNs,
|
|
1261
|
-
totalDurationNs: durationNs,
|
|
1262
|
-
functionId,
|
|
1263
|
-
...parentCallId === void 0 ? {} : { parentCallId }
|
|
1264
|
-
};
|
|
1888
|
+
group.suppressed = newSuppression(group, parentCallId, startedAtNs, endedAtNs);
|
|
1265
1889
|
appendSuppressedPlaceholder(recording, group.suppressed);
|
|
1266
1890
|
return;
|
|
1267
1891
|
}
|
|
1268
1892
|
const suppressed = group.suppressed;
|
|
1269
1893
|
suppressed.count++;
|
|
1270
1894
|
suppressed.lastTimestampNs = endedAtNs;
|
|
1271
|
-
suppressed.totalDurationNs +=
|
|
1272
|
-
if (
|
|
1895
|
+
suppressed.totalDurationNs += endedAtNs - startedAtNs;
|
|
1896
|
+
if (suppressed.retainedIndex < 0) {
|
|
1273
1897
|
appendSuppressedPlaceholder(recording, suppressed);
|
|
1274
1898
|
}
|
|
1275
1899
|
};
|
|
1900
|
+
const releaseJournalIfIdle = (recording) => {
|
|
1901
|
+
if (!recording.finished || recording.hasError || recording.inFlightCalls > 0) return;
|
|
1902
|
+
if (!recording.journal) return;
|
|
1903
|
+
journalPool.release(recording.journal);
|
|
1904
|
+
recording.journal = void 0;
|
|
1905
|
+
};
|
|
1906
|
+
const acquireJournal = (recording) => {
|
|
1907
|
+
if (recording.journal) return recording.journal;
|
|
1908
|
+
try {
|
|
1909
|
+
const journal = journalPool.acquire();
|
|
1910
|
+
if (!memoryBudget.reserveStorage(recording.memory, journal.allocatedBytes)) {
|
|
1911
|
+
journalPool.release(journal);
|
|
1912
|
+
return void 0;
|
|
1913
|
+
}
|
|
1914
|
+
journal.onGrow = (deltaBytes) => memoryBudget.reserveStorage(recording.memory, deltaBytes);
|
|
1915
|
+
recording.journal = journal;
|
|
1916
|
+
return journal;
|
|
1917
|
+
} catch {
|
|
1918
|
+
return void 0;
|
|
1919
|
+
}
|
|
1920
|
+
};
|
|
1921
|
+
const settleInFlight = (recording) => {
|
|
1922
|
+
if (recording.inFlightCalls > 0) recording.inFlightCalls--;
|
|
1923
|
+
releaseJournalIfIdle(recording);
|
|
1924
|
+
};
|
|
1276
1925
|
const finish = (store, metadata) => {
|
|
1277
1926
|
const { recording } = store;
|
|
1278
1927
|
if (recording.finished) return;
|
|
@@ -1281,11 +1930,22 @@ var createExecutionRecorder = (options) => {
|
|
|
1281
1930
|
if (metadata) mergeExecutionMetadata(recording.execution, metadata);
|
|
1282
1931
|
memoryBudget.release(recording.memory);
|
|
1283
1932
|
stats.activeExecutions = Math.max(0, stats.activeExecutions - 1);
|
|
1284
|
-
if (!recording.hasError)
|
|
1933
|
+
if (!recording.hasError) {
|
|
1934
|
+
stats.successfulExecutionsDiscarded++;
|
|
1935
|
+
releaseJournalIfIdle(recording);
|
|
1936
|
+
}
|
|
1285
1937
|
recording.finishedAtNs = process.hrtime.bigint();
|
|
1286
1938
|
addRecorderTime(recording, recording.finishedAtNs - recorderStartedAtNs);
|
|
1287
1939
|
recordInlineTiming(recording);
|
|
1288
1940
|
};
|
|
1941
|
+
const runStore = (store, callback) => {
|
|
1942
|
+
if (!phaseTimingEnabled) return storage.run(store, callback);
|
|
1943
|
+
const alsStartedAtNs = process.hrtime.bigint();
|
|
1944
|
+
return storage.run(store, () => {
|
|
1945
|
+
addPhase("alsNs", process.hrtime.bigint() - alsStartedAtNs);
|
|
1946
|
+
return callback();
|
|
1947
|
+
});
|
|
1948
|
+
};
|
|
1289
1949
|
const createScope = (metadata) => {
|
|
1290
1950
|
const recorderStartedAtNs = process.hrtime.bigint();
|
|
1291
1951
|
try {
|
|
@@ -1298,15 +1958,20 @@ var createExecutionRecorder = (options) => {
|
|
|
1298
1958
|
...metadata,
|
|
1299
1959
|
...metadata.request ? { request: { ...metadata.request } } : {}
|
|
1300
1960
|
},
|
|
1301
|
-
|
|
1302
|
-
functions: /* @__PURE__ */ new Map(),
|
|
1961
|
+
journal: void 0,
|
|
1303
1962
|
repeatedCalls: [],
|
|
1304
1963
|
capturedErrors: /* @__PURE__ */ new WeakMap(),
|
|
1305
1964
|
nextCallId: 0,
|
|
1965
|
+
inFlightCalls: 0,
|
|
1306
1966
|
finished: false,
|
|
1307
1967
|
hasError: false,
|
|
1308
1968
|
memory: memoryBudget.startExecution(),
|
|
1309
|
-
partialSnapshotCounted: false
|
|
1969
|
+
partialSnapshotCounted: false,
|
|
1970
|
+
derivationRoots: [],
|
|
1971
|
+
derivationRootBytes: 0,
|
|
1972
|
+
sawAutomatic: false,
|
|
1973
|
+
sawManual: false,
|
|
1974
|
+
executedFunctionIds: /* @__PURE__ */ new Set()
|
|
1310
1975
|
};
|
|
1311
1976
|
stats.activeExecutions++;
|
|
1312
1977
|
stats.peakActiveExecutions = Math.max(stats.peakActiveExecutions, stats.activeExecutions);
|
|
@@ -1315,7 +1980,7 @@ var createExecutionRecorder = (options) => {
|
|
|
1315
1980
|
return {
|
|
1316
1981
|
run: (callback) => {
|
|
1317
1982
|
const runStartedAtNs = process.hrtime.bigint();
|
|
1318
|
-
return
|
|
1983
|
+
return runStore(store, () => {
|
|
1319
1984
|
addRecorderTime(recording, process.hrtime.bigint() - runStartedAtNs);
|
|
1320
1985
|
return callback();
|
|
1321
1986
|
});
|
|
@@ -1368,156 +2033,210 @@ var createExecutionRecorder = (options) => {
|
|
|
1368
2033
|
return void 0;
|
|
1369
2034
|
}
|
|
1370
2035
|
};
|
|
1371
|
-
const runPreparedFunction = (plan, args, callback) => {
|
|
2036
|
+
const runPreparedFunction = (plan, args, callback, omitValues) => {
|
|
1372
2037
|
const store = storage.getStore();
|
|
1373
2038
|
if (!store || store.recording.finished) return callback();
|
|
1374
2039
|
stats.functionCallsObserved++;
|
|
1375
2040
|
const recorderStartedAtNs = process.hrtime.bigint();
|
|
1376
2041
|
if (store.suppressCapture || plan.excluded) {
|
|
1377
2042
|
stats.functionCallsExcluded++;
|
|
1378
|
-
return
|
|
2043
|
+
return runStore({ ...store, suppressCapture: true }, () => {
|
|
1379
2044
|
addRecorderTime(store.recording, process.hrtime.bigint() - recorderStartedAtNs);
|
|
1380
2045
|
return callback();
|
|
1381
2046
|
});
|
|
1382
2047
|
}
|
|
2048
|
+
const recording = store.recording;
|
|
2049
|
+
recording.inFlightCalls++;
|
|
1383
2050
|
const parentCallId = store.currentCallId;
|
|
1384
|
-
const group = repeatedCallGroup(
|
|
2051
|
+
const group = repeatedCallGroup(recording, plan, parentCallId);
|
|
1385
2052
|
group.observedCalls++;
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
}
|
|
2053
|
+
const journal = acquireJournal(recording);
|
|
2054
|
+
if (group.observedCalls === 1) journal?.notePlan(plan.runtimePlanId);
|
|
1389
2055
|
if (group.observedCalls > maxCapturedCallsPerFunction) {
|
|
1390
2056
|
const startedAtNs2 = process.hrtime.bigint();
|
|
1391
2057
|
try {
|
|
1392
2058
|
const result = callback();
|
|
1393
2059
|
if (isPromiseLike(result)) {
|
|
1394
|
-
addRecorderTime(
|
|
2060
|
+
addRecorderTime(recording, startedAtNs2 - recorderStartedAtNs);
|
|
1395
2061
|
return result.then(
|
|
1396
2062
|
(value) => {
|
|
1397
2063
|
const callbackEndedAtNs2 = process.hrtime.bigint();
|
|
1398
|
-
recordSuppressedCall(
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
plan.functionId,
|
|
1402
|
-
parentCallId,
|
|
1403
|
-
startedAtNs2,
|
|
1404
|
-
callbackEndedAtNs2
|
|
1405
|
-
);
|
|
1406
|
-
addRecorderTime(store.recording, process.hrtime.bigint() - callbackEndedAtNs2);
|
|
2064
|
+
recordSuppressedCall(recording, group, parentCallId, startedAtNs2, callbackEndedAtNs2);
|
|
2065
|
+
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs2);
|
|
2066
|
+
settleInFlight(recording);
|
|
1407
2067
|
return value;
|
|
1408
2068
|
},
|
|
1409
2069
|
(error) => {
|
|
1410
2070
|
const callbackEndedAtNs2 = process.hrtime.bigint();
|
|
1411
|
-
captureCompletedThrow(
|
|
1412
|
-
addRecorderTime(
|
|
2071
|
+
captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs2, error);
|
|
2072
|
+
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs2);
|
|
2073
|
+
settleInFlight(recording);
|
|
1413
2074
|
throw error;
|
|
1414
2075
|
}
|
|
1415
2076
|
);
|
|
1416
2077
|
}
|
|
1417
2078
|
const callbackEndedAtNs = process.hrtime.bigint();
|
|
1418
|
-
recordSuppressedCall(
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
parentCallId,
|
|
1423
|
-
startedAtNs2,
|
|
1424
|
-
callbackEndedAtNs
|
|
1425
|
-
);
|
|
1426
|
-
addRecorderTime(store.recording, startedAtNs2 - recorderStartedAtNs);
|
|
1427
|
-
addRecorderTime(store.recording, process.hrtime.bigint() - callbackEndedAtNs);
|
|
2079
|
+
recordSuppressedCall(recording, group, parentCallId, startedAtNs2, callbackEndedAtNs);
|
|
2080
|
+
addRecorderTime(recording, startedAtNs2 - recorderStartedAtNs);
|
|
2081
|
+
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs);
|
|
2082
|
+
settleInFlight(recording);
|
|
1428
2083
|
return result;
|
|
1429
2084
|
} catch (error) {
|
|
1430
2085
|
const callbackEndedAtNs = process.hrtime.bigint();
|
|
1431
|
-
captureCompletedThrow(
|
|
1432
|
-
addRecorderTime(
|
|
1433
|
-
addRecorderTime(
|
|
2086
|
+
captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs2, error);
|
|
2087
|
+
addRecorderTime(recording, startedAtNs2 - recorderStartedAtNs);
|
|
2088
|
+
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs);
|
|
2089
|
+
settleInFlight(recording);
|
|
1434
2090
|
throw error;
|
|
1435
2091
|
}
|
|
1436
2092
|
}
|
|
1437
2093
|
const startedAtNs = process.hrtime.bigint();
|
|
1438
|
-
if (!
|
|
2094
|
+
if (!journal) {
|
|
2095
|
+
memoryBudget.reserveCall(recording.memory, plan.estimatedCallBytes);
|
|
2096
|
+
return runStore(
|
|
2097
|
+
store,
|
|
2098
|
+
() => observeRecordedCallback(
|
|
2099
|
+
recording,
|
|
2100
|
+
recorderStartedAtNs,
|
|
2101
|
+
callback,
|
|
2102
|
+
() => settleInFlight(recording),
|
|
2103
|
+
(error) => {
|
|
2104
|
+
rememberError(error, recording);
|
|
2105
|
+
settleInFlight(recording);
|
|
2106
|
+
}
|
|
2107
|
+
)
|
|
2108
|
+
);
|
|
2109
|
+
}
|
|
2110
|
+
if (!journal.canStartCall()) {
|
|
1439
2111
|
const captureSuccess = () => {
|
|
1440
|
-
const droppedBefore =
|
|
1441
|
-
|
|
1442
|
-
countDroppedEvents(
|
|
2112
|
+
const droppedBefore = recording.journal?.dropped ?? 0;
|
|
2113
|
+
recording.journal?.dropCall();
|
|
2114
|
+
countDroppedEvents(recording, droppedBefore);
|
|
2115
|
+
settleInFlight(recording);
|
|
1443
2116
|
};
|
|
1444
|
-
return
|
|
2117
|
+
return runStore(
|
|
1445
2118
|
store,
|
|
1446
2119
|
() => observeRecordedCallback(
|
|
1447
|
-
|
|
2120
|
+
recording,
|
|
1448
2121
|
recorderStartedAtNs,
|
|
1449
2122
|
callback,
|
|
1450
2123
|
captureSuccess,
|
|
1451
|
-
(error) =>
|
|
2124
|
+
(error) => {
|
|
2125
|
+
captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs, error);
|
|
2126
|
+
settleInFlight(recording);
|
|
2127
|
+
}
|
|
1452
2128
|
)
|
|
1453
2129
|
);
|
|
1454
2130
|
}
|
|
1455
|
-
if (!memoryBudget.reserveCall(
|
|
2131
|
+
if (!memoryBudget.reserveCall(recording.memory, plan.estimatedCallBytes)) {
|
|
1456
2132
|
return observeRecordedCallback(
|
|
1457
|
-
|
|
2133
|
+
recording,
|
|
1458
2134
|
recorderStartedAtNs,
|
|
1459
2135
|
callback,
|
|
1460
|
-
() =>
|
|
1461
|
-
|
|
1462
|
-
|
|
2136
|
+
() => settleInFlight(recording),
|
|
2137
|
+
(error) => {
|
|
2138
|
+
rememberError(error, recording);
|
|
2139
|
+
settleInFlight(recording);
|
|
2140
|
+
}
|
|
1463
2141
|
);
|
|
1464
2142
|
}
|
|
1465
|
-
const callId = ++
|
|
1466
|
-
const
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
args: Array.from(args, (argument) => captureValue(store.recording, argument)),
|
|
1472
|
-
...parentCallId === void 0 ? {} : { parentCallId }
|
|
1473
|
-
};
|
|
1474
|
-
store.recording.events.startCall(enter);
|
|
1475
|
-
const callStore = { recording: store.recording, currentCallId: callId };
|
|
1476
|
-
return storage.run(
|
|
2143
|
+
const callId = ++recording.nextCallId;
|
|
2144
|
+
const enterTimestampNs = process.hrtime.bigint() - recording.startedAtNs;
|
|
2145
|
+
const capturedArgs = omitValues ? Array.from(args, () => rasputinOmitted()) : Array.from(args, (argument) => captureValue(recording, argument));
|
|
2146
|
+
journal.startCall(plan.runtimePlanId, callId, parentCallId, enterTimestampNs, capturedArgs);
|
|
2147
|
+
const callStore = { recording, currentCallId: callId };
|
|
2148
|
+
return runStore(
|
|
1477
2149
|
callStore,
|
|
1478
2150
|
() => observeRecordedCallback(
|
|
1479
|
-
|
|
2151
|
+
recording,
|
|
1480
2152
|
recorderStartedAtNs,
|
|
1481
2153
|
callback,
|
|
1482
2154
|
(value) => {
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
}
|
|
1490
|
-
|
|
2155
|
+
if (recording.journal) {
|
|
2156
|
+
const timestampNs = process.hrtime.bigint() - recording.startedAtNs;
|
|
2157
|
+
const durationNs = process.hrtime.bigint() - startedAtNs;
|
|
2158
|
+
const returnValue = omitValues ? rasputinOmitted() : captureValue(recording, value);
|
|
2159
|
+
recording.journal.finishCall(KIND_EXIT, callId, timestampNs, durationNs, returnValue);
|
|
2160
|
+
stats.functionCallsCaptured++;
|
|
2161
|
+
}
|
|
2162
|
+
settleInFlight(recording);
|
|
1491
2163
|
},
|
|
1492
2164
|
(error) => {
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
2165
|
+
if (!recording.journal) {
|
|
2166
|
+
rememberError(error, recording);
|
|
2167
|
+
settleInFlight(recording);
|
|
2168
|
+
return;
|
|
2169
|
+
}
|
|
2170
|
+
const capturedError = serializedError(recording, error, callId);
|
|
2171
|
+
recording.journal.finishCall(
|
|
2172
|
+
KIND_THROW,
|
|
1496
2173
|
callId,
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
2174
|
+
process.hrtime.bigint() - recording.startedAtNs,
|
|
2175
|
+
process.hrtime.bigint() - startedAtNs,
|
|
2176
|
+
capturedError.value
|
|
2177
|
+
);
|
|
1501
2178
|
stats.functionCallsCaptured++;
|
|
1502
2179
|
capturedError.commit();
|
|
1503
|
-
rememberError(error,
|
|
2180
|
+
rememberError(error, recording);
|
|
2181
|
+
settleInFlight(recording);
|
|
1504
2182
|
}
|
|
1505
2183
|
)
|
|
1506
2184
|
);
|
|
1507
2185
|
};
|
|
1508
|
-
const runFunction = (input, args, callback) =>
|
|
1509
|
-
|
|
2186
|
+
const runFunction = (input, args, callback) => {
|
|
2187
|
+
const store = storage.getStore();
|
|
2188
|
+
if (store && !store.recording.finished) store.recording.sawManual = true;
|
|
2189
|
+
return runPreparedFunction(preparePlan(normalizeFunctionDefinition(input)), args, callback);
|
|
2190
|
+
};
|
|
2191
|
+
const runFunctionPlans = (plans, planIndex, args, callback, omitValues) => {
|
|
2192
|
+
const store = storage.getStore();
|
|
1510
2193
|
const plan = preparedPlansFor(plans)[planIndex];
|
|
1511
|
-
|
|
2194
|
+
if (store && !store.recording.finished) {
|
|
2195
|
+
store.recording.sawAutomatic = true;
|
|
2196
|
+
if (plan) store.recording.executedFunctionIds.add(plan.functionId);
|
|
2197
|
+
}
|
|
2198
|
+
return plan ? runPreparedFunction(plan, args, callback, omitValues) : callback();
|
|
1512
2199
|
};
|
|
1513
2200
|
const prepareFunctionPlans = (plans) => preparedPlansFor(plans);
|
|
1514
2201
|
function trace(input, fn) {
|
|
1515
2202
|
const definition = typeof input === "string" ? manualFunctionDefinition(input) : { ...input, functionId: runtimeFunctionId2(input) };
|
|
1516
2203
|
const plan = preparePlan(definition);
|
|
1517
2204
|
return function traced(...args) {
|
|
2205
|
+
const store = storage.getStore();
|
|
2206
|
+
if (store && !store.recording.finished) store.recording.sawManual = true;
|
|
1518
2207
|
return runPreparedFunction(plan, args, () => fn.apply(this, args));
|
|
1519
2208
|
};
|
|
1520
2209
|
}
|
|
2210
|
+
const captureDerivationRoot = (rootId, value) => {
|
|
2211
|
+
const store = storage.getStore();
|
|
2212
|
+
if (!store || store.recording.finished || store.suppressCapture) return value;
|
|
2213
|
+
const recording = store.recording;
|
|
2214
|
+
if (recording.memory.mode !== "full") return value;
|
|
2215
|
+
if (recording.derivationRoots.length >= maxEventsPerExecution) return value;
|
|
2216
|
+
const recorderStartedAtNs = process.hrtime.bigint();
|
|
2217
|
+
try {
|
|
2218
|
+
const serialized = captureValue(recording, value);
|
|
2219
|
+
if (recording.memory.mode !== "full") return value;
|
|
2220
|
+
if (!memoryBudget.reserveStorage(recording.memory, DERIVATION_ROOT_RECORD_BYTES)) {
|
|
2221
|
+
return value;
|
|
2222
|
+
}
|
|
2223
|
+
const completeness = capturedValueCompleteness(serialized);
|
|
2224
|
+
const bytes = jsonLiteralUtf8Bytes(serialized);
|
|
2225
|
+
recording.derivationRoots.push({
|
|
2226
|
+
rootId,
|
|
2227
|
+
callId: store.currentCallId ?? 0,
|
|
2228
|
+
value: serialized,
|
|
2229
|
+
completeness
|
|
2230
|
+
});
|
|
2231
|
+
recording.derivationRootBytes += bytes;
|
|
2232
|
+
stats.derivationRootsCaptured++;
|
|
2233
|
+
stats.derivationRootBytes += bytes;
|
|
2234
|
+
stats.derivationFallbackExpressions++;
|
|
2235
|
+
return value;
|
|
2236
|
+
} finally {
|
|
2237
|
+
addRecorderTime(recording, process.hrtime.bigint() - recorderStartedAtNs);
|
|
2238
|
+
}
|
|
2239
|
+
};
|
|
1521
2240
|
return {
|
|
1522
2241
|
createScope,
|
|
1523
2242
|
run,
|
|
@@ -1527,13 +2246,30 @@ var createExecutionRecorder = (options) => {
|
|
|
1527
2246
|
prepareFunctionPlans,
|
|
1528
2247
|
runPreparedFunction,
|
|
1529
2248
|
trace,
|
|
1530
|
-
|
|
2249
|
+
captureDerivationRoot,
|
|
2250
|
+
getStats: () => {
|
|
2251
|
+
const manifest = snapshotInstrumentationManifest();
|
|
2252
|
+
const plans = manifest?.derivationPlans ?? [];
|
|
2253
|
+
return {
|
|
2254
|
+
...stats,
|
|
2255
|
+
...memoryBudget.getStats(),
|
|
2256
|
+
...journalPool.stats(),
|
|
2257
|
+
derivationCandidateFunctions: plans.filter((plan) => !plan.fallbackReason).length,
|
|
2258
|
+
derivationFallbackFunctions: plans.filter((plan) => plan.fallbackReason).length,
|
|
2259
|
+
derivationFallbackReasons: { ...stats.derivationFallbackReasons },
|
|
2260
|
+
...phases ? {
|
|
2261
|
+
phaseAlsNs: Number(phases.alsNs),
|
|
2262
|
+
phaseMaterializeNs: Number(phases.materializeNs)
|
|
2263
|
+
} : {}
|
|
2264
|
+
};
|
|
2265
|
+
}
|
|
1531
2266
|
};
|
|
1532
2267
|
};
|
|
1533
2268
|
|
|
1534
2269
|
// src/execution-recorder/automatic-runtime.ts
|
|
1535
2270
|
var AUTOMATIC_RUNTIME_SYMBOL = "rasputin.execution.runtime.v2";
|
|
1536
2271
|
var runtimeSymbol = Symbol.for(AUTOMATIC_RUNTIME_SYMBOL);
|
|
2272
|
+
var passthroughCapture = (_rootId, value) => value;
|
|
1537
2273
|
var passthrough = (_planIndex, _args, callback) => callback();
|
|
1538
2274
|
var bindPassthrough = (module) => {
|
|
1539
2275
|
module.cell.run = passthrough;
|
|
@@ -1544,12 +2280,13 @@ var registerModule = (registry, plans) => {
|
|
|
1544
2280
|
const module = { plans, cell };
|
|
1545
2281
|
registry.modules.push(module);
|
|
1546
2282
|
registry.runtimes.at(-1)?.bind(module);
|
|
1547
|
-
return (planIndex, args, callback) => cell.run(planIndex, args, callback);
|
|
2283
|
+
return (planIndex, args, callback, omitValues) => cell.run(planIndex, args, callback, omitValues);
|
|
1548
2284
|
};
|
|
1549
2285
|
var createRegistry = () => {
|
|
1550
2286
|
const registry = {
|
|
1551
2287
|
runtimes: [],
|
|
1552
2288
|
modules: [],
|
|
2289
|
+
captureRoot: passthroughCapture,
|
|
1553
2290
|
register(plans) {
|
|
1554
2291
|
return registerModule(registry, plans);
|
|
1555
2292
|
}
|
|
@@ -1558,7 +2295,12 @@ var createRegistry = () => {
|
|
|
1558
2295
|
};
|
|
1559
2296
|
var getAutomaticRuntimeRegistry = () => {
|
|
1560
2297
|
const existing = Reflect.get(globalThis, runtimeSymbol);
|
|
1561
|
-
if (existing && typeof existing === "object" && isRegistry(existing))
|
|
2298
|
+
if (existing && typeof existing === "object" && isRegistry(existing)) {
|
|
2299
|
+
if (typeof existing.captureRoot !== "function") {
|
|
2300
|
+
existing.captureRoot = passthroughCapture;
|
|
2301
|
+
}
|
|
2302
|
+
return existing;
|
|
2303
|
+
}
|
|
1562
2304
|
const registry = createRegistry();
|
|
1563
2305
|
Reflect.set(globalThis, runtimeSymbol, registry);
|
|
1564
2306
|
return registry;
|
|
@@ -1567,19 +2309,18 @@ var installAutomaticExecutionRuntime = (execution) => {
|
|
|
1567
2309
|
const registry = getAutomaticRuntimeRegistry();
|
|
1568
2310
|
const runtime = {
|
|
1569
2311
|
bind(module) {
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
return plan ? execution.runPreparedFunction(plan, args, callback) : callback();
|
|
1574
|
-
};
|
|
1575
|
-
}
|
|
2312
|
+
module.cell.run = (planIndex, args, callback, omitValues) => execution.runFunctionPlans(module.plans, planIndex, args, callback, omitValues);
|
|
2313
|
+
},
|
|
2314
|
+
captureRoot: (rootId, value) => execution.captureDerivationRoot(rootId, value)
|
|
1576
2315
|
};
|
|
1577
2316
|
registry.runtimes.push(runtime);
|
|
2317
|
+
registry.captureRoot = runtime.captureRoot;
|
|
1578
2318
|
for (const module of registry.modules) runtime.bind(module);
|
|
1579
2319
|
return () => {
|
|
1580
2320
|
const index = registry.runtimes.lastIndexOf(runtime);
|
|
1581
2321
|
if (index >= 0) registry.runtimes.splice(index, 1);
|
|
1582
2322
|
const current = registry.runtimes.at(-1);
|
|
2323
|
+
registry.captureRoot = current?.captureRoot ?? passthroughCapture;
|
|
1583
2324
|
for (const module of registry.modules) {
|
|
1584
2325
|
if (current) current.bind(module);
|
|
1585
2326
|
else bindPassthrough(module);
|
|
@@ -1644,7 +2385,7 @@ import {
|
|
|
1644
2385
|
|
|
1645
2386
|
// src/sdk-meta.ts
|
|
1646
2387
|
var SDK_NAME = "@rasputin-ai/node";
|
|
1647
|
-
var SDK_VERSION = "0.5.0-alpha.
|
|
2388
|
+
var SDK_VERSION = "0.5.0-alpha.7";
|
|
1648
2389
|
|
|
1649
2390
|
// src/rasputin-init.ts
|
|
1650
2391
|
var withExecution = (client, execution, installRuntime, manifest) => {
|