@rasputin-ai/node 0.5.0-alpha.1 → 0.5.0-alpha.11
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 +23 -4
- 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 +1181 -330
- 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);
|
|
404
461
|
}
|
|
405
|
-
|
|
406
|
-
if (
|
|
407
|
-
|
|
408
|
-
this.
|
|
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);
|
|
482
|
+
}
|
|
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;
|
|
1841
|
+
}
|
|
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;
|
|
1115
1848
|
}
|
|
1116
|
-
|
|
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
|
-
|
|
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,
|
|
1151
1894
|
callId,
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
timestampMs: elapsedMs(recording.startedAtNs),
|
|
1161
|
-
durationMs: elapsedMs(startedAtNs),
|
|
1162
|
-
error: capturedError.value
|
|
1163
|
-
};
|
|
1164
|
-
const droppedBefore = recording.events.dropped;
|
|
1165
|
-
const retained = recording.events.forceCompletedCall(enter, terminal);
|
|
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,282 @@ var createExecutionRecorder = (options) => {
|
|
|
1288
2057
|
return void 0;
|
|
1289
2058
|
}
|
|
1290
2059
|
};
|
|
1291
|
-
const
|
|
1292
|
-
const store = storage.getStore();
|
|
2060
|
+
const runPreparedFunctionFromStore = (store, plan, args, callback, omitValues) => {
|
|
1293
2061
|
if (!store || store.recording.finished) return callback();
|
|
1294
2062
|
stats.functionCallsObserved++;
|
|
1295
2063
|
const recorderStartedAtNs = process.hrtime.bigint();
|
|
1296
2064
|
if (store.suppressCapture || plan.excluded) {
|
|
1297
2065
|
stats.functionCallsExcluded++;
|
|
1298
|
-
return
|
|
2066
|
+
return runStore({ ...store, suppressCapture: true }, () => {
|
|
1299
2067
|
addRecorderTime(store.recording, process.hrtime.bigint() - recorderStartedAtNs);
|
|
1300
2068
|
return callback();
|
|
1301
2069
|
});
|
|
1302
2070
|
}
|
|
2071
|
+
const recording = store.recording;
|
|
2072
|
+
recording.inFlightCalls++;
|
|
1303
2073
|
const parentCallId = store.currentCallId;
|
|
1304
|
-
const group = repeatedCallGroup(
|
|
2074
|
+
const group = repeatedCallGroup(recording, plan, parentCallId);
|
|
1305
2075
|
group.observedCalls++;
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
}
|
|
2076
|
+
const journal = acquireJournal(recording);
|
|
2077
|
+
if (group.observedCalls === 1) journal?.notePlan(plan.runtimePlanId);
|
|
1309
2078
|
if (group.observedCalls > maxCapturedCallsPerFunction) {
|
|
1310
2079
|
const startedAtNs2 = process.hrtime.bigint();
|
|
1311
|
-
const startedAtMs = elapsedMs(store.recording.startedAtNs, startedAtNs2);
|
|
1312
2080
|
try {
|
|
1313
2081
|
const result = callback();
|
|
1314
2082
|
if (isPromiseLike(result)) {
|
|
1315
|
-
addRecorderTime(
|
|
2083
|
+
addRecorderTime(recording, startedAtNs2 - recorderStartedAtNs);
|
|
1316
2084
|
return result.then(
|
|
1317
2085
|
(value) => {
|
|
1318
2086
|
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);
|
|
2087
|
+
recordSuppressedCall(recording, group, parentCallId, startedAtNs2, callbackEndedAtNs2);
|
|
2088
|
+
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs2);
|
|
2089
|
+
settleInFlight(recording);
|
|
1329
2090
|
return value;
|
|
1330
2091
|
},
|
|
1331
2092
|
(error) => {
|
|
1332
2093
|
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);
|
|
2094
|
+
captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs2, error);
|
|
2095
|
+
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs2);
|
|
2096
|
+
settleInFlight(recording);
|
|
1343
2097
|
throw error;
|
|
1344
2098
|
}
|
|
1345
2099
|
);
|
|
1346
2100
|
}
|
|
1347
2101
|
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);
|
|
2102
|
+
recordSuppressedCall(recording, group, parentCallId, startedAtNs2, callbackEndedAtNs);
|
|
2103
|
+
addRecorderTime(recording, startedAtNs2 - recorderStartedAtNs);
|
|
2104
|
+
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs);
|
|
2105
|
+
settleInFlight(recording);
|
|
1359
2106
|
return result;
|
|
1360
2107
|
} catch (error) {
|
|
1361
2108
|
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);
|
|
2109
|
+
captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs2, error);
|
|
2110
|
+
addRecorderTime(recording, startedAtNs2 - recorderStartedAtNs);
|
|
2111
|
+
addRecorderTime(recording, process.hrtime.bigint() - callbackEndedAtNs);
|
|
2112
|
+
settleInFlight(recording);
|
|
1373
2113
|
throw error;
|
|
1374
2114
|
}
|
|
1375
2115
|
}
|
|
1376
2116
|
const startedAtNs = process.hrtime.bigint();
|
|
1377
|
-
if (!
|
|
1378
|
-
|
|
2117
|
+
if (!journal) {
|
|
2118
|
+
memoryBudget.reserveCall(recording.memory, plan.estimatedCallBytes);
|
|
2119
|
+
return runStore(
|
|
2120
|
+
store,
|
|
2121
|
+
() => observeRecordedCallback(
|
|
2122
|
+
recording,
|
|
2123
|
+
recorderStartedAtNs,
|
|
2124
|
+
callback,
|
|
2125
|
+
() => settleInFlight(recording),
|
|
2126
|
+
(error) => {
|
|
2127
|
+
rememberError(error, recording);
|
|
2128
|
+
settleInFlight(recording);
|
|
2129
|
+
}
|
|
2130
|
+
)
|
|
2131
|
+
);
|
|
2132
|
+
}
|
|
2133
|
+
if (!journal.canStartCall()) {
|
|
1379
2134
|
const captureSuccess = () => {
|
|
1380
|
-
const droppedBefore =
|
|
1381
|
-
|
|
1382
|
-
countDroppedEvents(
|
|
2135
|
+
const droppedBefore = recording.journal?.dropped ?? 0;
|
|
2136
|
+
recording.journal?.dropCall();
|
|
2137
|
+
countDroppedEvents(recording, droppedBefore);
|
|
2138
|
+
settleInFlight(recording);
|
|
1383
2139
|
};
|
|
1384
|
-
return
|
|
2140
|
+
return runStore(
|
|
1385
2141
|
store,
|
|
1386
2142
|
() => observeRecordedCallback(
|
|
1387
|
-
|
|
2143
|
+
recording,
|
|
1388
2144
|
recorderStartedAtNs,
|
|
1389
2145
|
callback,
|
|
1390
2146
|
captureSuccess,
|
|
1391
|
-
(error) =>
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
parentCallId,
|
|
1396
|
-
startedAtNs,
|
|
1397
|
-
startedAtMs,
|
|
1398
|
-
error
|
|
1399
|
-
)
|
|
2147
|
+
(error) => {
|
|
2148
|
+
captureCompletedThrow(recording, plan, args, parentCallId, startedAtNs, error);
|
|
2149
|
+
settleInFlight(recording);
|
|
2150
|
+
}
|
|
1400
2151
|
)
|
|
1401
2152
|
);
|
|
1402
2153
|
}
|
|
1403
|
-
if (!memoryBudget.reserveCall(
|
|
2154
|
+
if (!memoryBudget.reserveCall(recording.memory, plan.estimatedCallBytes)) {
|
|
1404
2155
|
return observeRecordedCallback(
|
|
1405
|
-
|
|
2156
|
+
recording,
|
|
1406
2157
|
recorderStartedAtNs,
|
|
1407
2158
|
callback,
|
|
1408
|
-
() =>
|
|
1409
|
-
|
|
1410
|
-
|
|
2159
|
+
() => settleInFlight(recording),
|
|
2160
|
+
(error) => {
|
|
2161
|
+
rememberError(error, recording);
|
|
2162
|
+
settleInFlight(recording);
|
|
2163
|
+
}
|
|
1411
2164
|
);
|
|
1412
2165
|
}
|
|
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(
|
|
2166
|
+
const callId = ++recording.nextCallId;
|
|
2167
|
+
const enterTimestampNs = process.hrtime.bigint() - recording.startedAtNs;
|
|
2168
|
+
const capturedArgs = omitValues ? Array.from(args, () => rasputinOmitted()) : Array.from(args, (argument) => captureValue(recording, argument));
|
|
2169
|
+
journal.startCall(plan.runtimePlanId, callId, parentCallId, enterTimestampNs, capturedArgs);
|
|
2170
|
+
const callStore = { recording, currentCallId: callId };
|
|
2171
|
+
return runStore(
|
|
1425
2172
|
callStore,
|
|
1426
2173
|
() => observeRecordedCallback(
|
|
1427
|
-
|
|
2174
|
+
recording,
|
|
1428
2175
|
recorderStartedAtNs,
|
|
1429
2176
|
callback,
|
|
1430
2177
|
(value) => {
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
}
|
|
1438
|
-
|
|
2178
|
+
if (recording.journal) {
|
|
2179
|
+
const timestampNs = process.hrtime.bigint() - recording.startedAtNs;
|
|
2180
|
+
const durationNs = process.hrtime.bigint() - startedAtNs;
|
|
2181
|
+
const returnValue = omitValues ? rasputinOmitted() : captureValue(recording, value);
|
|
2182
|
+
recording.journal.finishCall(KIND_EXIT, callId, timestampNs, durationNs, returnValue);
|
|
2183
|
+
stats.functionCallsCaptured++;
|
|
2184
|
+
}
|
|
2185
|
+
settleInFlight(recording);
|
|
1439
2186
|
},
|
|
1440
2187
|
(error) => {
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
2188
|
+
if (!recording.journal) {
|
|
2189
|
+
rememberError(error, recording);
|
|
2190
|
+
settleInFlight(recording);
|
|
2191
|
+
return;
|
|
2192
|
+
}
|
|
2193
|
+
const capturedError = serializedError(recording, error, callId);
|
|
2194
|
+
recording.journal.finishCall(
|
|
2195
|
+
KIND_THROW,
|
|
1444
2196
|
callId,
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
2197
|
+
process.hrtime.bigint() - recording.startedAtNs,
|
|
2198
|
+
process.hrtime.bigint() - startedAtNs,
|
|
2199
|
+
capturedError.value
|
|
2200
|
+
);
|
|
1449
2201
|
stats.functionCallsCaptured++;
|
|
1450
2202
|
capturedError.commit();
|
|
1451
|
-
rememberError(error,
|
|
2203
|
+
rememberError(error, recording);
|
|
2204
|
+
settleInFlight(recording);
|
|
1452
2205
|
}
|
|
1453
2206
|
)
|
|
1454
2207
|
);
|
|
1455
2208
|
};
|
|
1456
|
-
const
|
|
1457
|
-
|
|
2209
|
+
const runPreparedFunction = (plan, args, callback, omitValues) => {
|
|
2210
|
+
const store = storage.getStore();
|
|
2211
|
+
if (store && !store.recording.finished && !store.recording.sawAutomatic) {
|
|
2212
|
+
store.recording.sawAutomatic = true;
|
|
2213
|
+
}
|
|
2214
|
+
return runPreparedFunctionFromStore(store, plan, args, callback, omitValues);
|
|
2215
|
+
};
|
|
2216
|
+
const runFunction = (input, args, callback) => {
|
|
2217
|
+
const store = storage.getStore();
|
|
2218
|
+
if (store && !store.recording.finished) store.recording.sawManual = true;
|
|
2219
|
+
return runPreparedFunctionFromStore(
|
|
2220
|
+
store,
|
|
2221
|
+
preparePlan(normalizeFunctionDefinition(input)),
|
|
2222
|
+
args,
|
|
2223
|
+
callback
|
|
2224
|
+
);
|
|
2225
|
+
};
|
|
2226
|
+
const runFunctionPlans = (plans, planIndex, args, callback, omitValues) => {
|
|
2227
|
+
const store = storage.getStore();
|
|
1458
2228
|
const plan = preparedPlansFor(plans)[planIndex];
|
|
1459
|
-
|
|
2229
|
+
if (store && !store.recording.finished && !store.recording.sawAutomatic) {
|
|
2230
|
+
store.recording.sawAutomatic = true;
|
|
2231
|
+
}
|
|
2232
|
+
return plan ? runPreparedFunctionFromStore(store, plan, args, callback, omitValues) : callback();
|
|
1460
2233
|
};
|
|
2234
|
+
const prepareFunctionPlans = (plans) => preparedPlansFor(plans);
|
|
1461
2235
|
function trace(input, fn) {
|
|
1462
2236
|
const definition = typeof input === "string" ? manualFunctionDefinition(input) : { ...input, functionId: runtimeFunctionId2(input) };
|
|
1463
2237
|
const plan = preparePlan(definition);
|
|
1464
2238
|
return function traced(...args) {
|
|
1465
|
-
|
|
2239
|
+
const store = storage.getStore();
|
|
2240
|
+
if (store && !store.recording.finished) store.recording.sawManual = true;
|
|
2241
|
+
return runPreparedFunctionFromStore(store, plan, args, () => fn.apply(this, args));
|
|
1466
2242
|
};
|
|
1467
2243
|
}
|
|
2244
|
+
const captureDerivationRoot = (rootId, value) => {
|
|
2245
|
+
const store = storage.getStore();
|
|
2246
|
+
if (!store || store.recording.finished || store.suppressCapture) return value;
|
|
2247
|
+
const recording = store.recording;
|
|
2248
|
+
if (recording.memory.mode !== "full") return value;
|
|
2249
|
+
if (recording.derivationRoots.length >= maxEventsPerExecution) return value;
|
|
2250
|
+
const recorderStartedAtNs = process.hrtime.bigint();
|
|
2251
|
+
try {
|
|
2252
|
+
const serialized = captureValue(recording, value);
|
|
2253
|
+
if (recording.memory.mode !== "full") return value;
|
|
2254
|
+
if (!memoryBudget.reserveStorage(recording.memory, DERIVATION_ROOT_RECORD_BYTES)) {
|
|
2255
|
+
return value;
|
|
2256
|
+
}
|
|
2257
|
+
const completeness = capturedValueCompleteness(serialized);
|
|
2258
|
+
const bytes = jsonLiteralUtf8Bytes(serialized);
|
|
2259
|
+
recording.derivationRoots.push({
|
|
2260
|
+
rootId,
|
|
2261
|
+
callId: store.currentCallId ?? 0,
|
|
2262
|
+
value: serialized,
|
|
2263
|
+
completeness
|
|
2264
|
+
});
|
|
2265
|
+
recording.derivationRootBytes += bytes;
|
|
2266
|
+
stats.derivationRootsCaptured++;
|
|
2267
|
+
stats.derivationRootBytes += bytes;
|
|
2268
|
+
stats.derivationFallbackExpressions++;
|
|
2269
|
+
return value;
|
|
2270
|
+
} finally {
|
|
2271
|
+
addRecorderTime(recording, process.hrtime.bigint() - recorderStartedAtNs);
|
|
2272
|
+
}
|
|
2273
|
+
};
|
|
1468
2274
|
return {
|
|
1469
2275
|
createScope,
|
|
1470
2276
|
run,
|
|
1471
2277
|
getErrorState,
|
|
1472
2278
|
runFunction,
|
|
1473
2279
|
runFunctionPlans,
|
|
2280
|
+
prepareFunctionPlans,
|
|
1474
2281
|
runPreparedFunction,
|
|
1475
2282
|
trace,
|
|
1476
|
-
|
|
2283
|
+
captureDerivationRoot,
|
|
2284
|
+
getStats: () => {
|
|
2285
|
+
const manifest = snapshotInstrumentationManifest();
|
|
2286
|
+
const plans = manifest?.derivationPlans ?? [];
|
|
2287
|
+
return {
|
|
2288
|
+
...stats,
|
|
2289
|
+
...memoryBudget.getStats(),
|
|
2290
|
+
...journalPool.stats(),
|
|
2291
|
+
derivationCandidateFunctions: plans.filter((plan) => !plan.fallbackReason).length,
|
|
2292
|
+
derivationFallbackFunctions: plans.filter((plan) => plan.fallbackReason).length,
|
|
2293
|
+
derivationFallbackReasons: { ...stats.derivationFallbackReasons },
|
|
2294
|
+
...phases ? {
|
|
2295
|
+
phaseAlsNs: Number(phases.alsNs),
|
|
2296
|
+
phaseMaterializeNs: Number(phases.materializeNs)
|
|
2297
|
+
} : {}
|
|
2298
|
+
};
|
|
2299
|
+
}
|
|
1477
2300
|
};
|
|
1478
2301
|
};
|
|
1479
2302
|
|
|
1480
2303
|
// src/execution-recorder/automatic-runtime.ts
|
|
1481
2304
|
var AUTOMATIC_RUNTIME_SYMBOL = "rasputin.execution.runtime.v2";
|
|
1482
2305
|
var runtimeSymbol = Symbol.for(AUTOMATIC_RUNTIME_SYMBOL);
|
|
2306
|
+
var passthroughCapture = (_rootId, value) => value;
|
|
2307
|
+
var passthrough = (_planIndex, _args, callback) => callback();
|
|
2308
|
+
var bindPassthrough = (module) => {
|
|
2309
|
+
module.cell.run = passthrough;
|
|
2310
|
+
};
|
|
2311
|
+
var isRegistry = (value) => Array.isArray(Reflect.get(value, "runtimes")) && Array.isArray(Reflect.get(value, "modules")) && typeof Reflect.get(value, "register") === "function";
|
|
2312
|
+
var registerModule = (registry, plans) => {
|
|
2313
|
+
const cell = { run: passthrough };
|
|
2314
|
+
const module = { plans, cell };
|
|
2315
|
+
registry.modules.push(module);
|
|
2316
|
+
registry.runtimes.at(-1)?.bind(module);
|
|
2317
|
+
return (planIndex, args, callback, omitValues) => cell.run(planIndex, args, callback, omitValues);
|
|
2318
|
+
};
|
|
1483
2319
|
var createRegistry = () => {
|
|
1484
|
-
const
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
2320
|
+
const registry = {
|
|
2321
|
+
runtimes: [],
|
|
2322
|
+
modules: [],
|
|
2323
|
+
captureRoot: passthroughCapture,
|
|
1488
2324
|
register(plans) {
|
|
1489
|
-
return (
|
|
1490
|
-
const runtime = runtimes.at(-1);
|
|
1491
|
-
return runtime ? runtime.run(plans, planIndex, args, callback) : callback();
|
|
1492
|
-
};
|
|
2325
|
+
return registerModule(registry, plans);
|
|
1493
2326
|
}
|
|
1494
2327
|
};
|
|
2328
|
+
return registry;
|
|
1495
2329
|
};
|
|
1496
2330
|
var getAutomaticRuntimeRegistry = () => {
|
|
1497
2331
|
const existing = Reflect.get(globalThis, runtimeSymbol);
|
|
1498
|
-
if (existing &&
|
|
1499
|
-
existing.
|
|
2332
|
+
if (existing && typeof existing === "object" && isRegistry(existing)) {
|
|
2333
|
+
if (typeof existing.captureRoot !== "function") {
|
|
2334
|
+
existing.captureRoot = passthroughCapture;
|
|
2335
|
+
}
|
|
1500
2336
|
return existing;
|
|
1501
2337
|
}
|
|
1502
2338
|
const registry = createRegistry();
|
|
@@ -1506,12 +2342,27 @@ var getAutomaticRuntimeRegistry = () => {
|
|
|
1506
2342
|
var installAutomaticExecutionRuntime = (execution) => {
|
|
1507
2343
|
const registry = getAutomaticRuntimeRegistry();
|
|
1508
2344
|
const runtime = {
|
|
1509
|
-
|
|
2345
|
+
bind(module) {
|
|
2346
|
+
const prepared = execution.prepareFunctionPlans(module.plans);
|
|
2347
|
+
module.cell.run = (planIndex, args, callback, omitValues) => {
|
|
2348
|
+
const plan = prepared[planIndex];
|
|
2349
|
+
return plan ? execution.runPreparedFunction(plan, args, callback, omitValues) : callback();
|
|
2350
|
+
};
|
|
2351
|
+
},
|
|
2352
|
+
captureRoot: (rootId, value) => execution.captureDerivationRoot(rootId, value)
|
|
1510
2353
|
};
|
|
1511
2354
|
registry.runtimes.push(runtime);
|
|
2355
|
+
registry.captureRoot = runtime.captureRoot;
|
|
2356
|
+
for (const module of registry.modules) runtime.bind(module);
|
|
1512
2357
|
return () => {
|
|
1513
2358
|
const index = registry.runtimes.lastIndexOf(runtime);
|
|
1514
2359
|
if (index >= 0) registry.runtimes.splice(index, 1);
|
|
2360
|
+
const current = registry.runtimes.at(-1);
|
|
2361
|
+
registry.captureRoot = current?.captureRoot ?? passthroughCapture;
|
|
2362
|
+
for (const module of registry.modules) {
|
|
2363
|
+
if (current) current.bind(module);
|
|
2364
|
+
else bindPassthrough(module);
|
|
2365
|
+
}
|
|
1515
2366
|
};
|
|
1516
2367
|
};
|
|
1517
2368
|
|
|
@@ -1572,7 +2423,7 @@ import {
|
|
|
1572
2423
|
|
|
1573
2424
|
// src/sdk-meta.ts
|
|
1574
2425
|
var SDK_NAME = "@rasputin-ai/node";
|
|
1575
|
-
var SDK_VERSION = "0.5.0-alpha.
|
|
2426
|
+
var SDK_VERSION = "0.5.0-alpha.11";
|
|
1576
2427
|
|
|
1577
2428
|
// src/rasputin-init.ts
|
|
1578
2429
|
var withExecution = (client, execution, installRuntime, manifest) => {
|