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