@autter/runtime-node 1.3.3 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/dist/index.cjs +516 -107
- package/dist/index.d.cts +39 -1
- package/dist/index.d.ts +39 -1
- package/dist/index.js +482 -78
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -17,8 +17,8 @@ var IpWindow = class {
|
|
|
17
17
|
return entry.count <= this.limitPerMinute;
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
|
-
function firstForwardedFor(
|
|
21
|
-
const raw = Array.isArray(
|
|
20
|
+
function firstForwardedFor(value2) {
|
|
21
|
+
const raw = Array.isArray(value2) ? value2[0] : value2;
|
|
22
22
|
return raw ? (raw.split(",")[0] ?? "").trim() : "";
|
|
23
23
|
}
|
|
24
24
|
var DEFAULT_ENDPOINT = "https://otlp.autter.dev";
|
|
@@ -32,6 +32,7 @@ var EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
|
32
32
|
"track_event",
|
|
33
33
|
"outcome",
|
|
34
34
|
"request_failure",
|
|
35
|
+
"csp_violation",
|
|
35
36
|
"timing"
|
|
36
37
|
]);
|
|
37
38
|
var SEVERITIES = /* @__PURE__ */ new Set(["fatal", "error", "warning", "info"]);
|
|
@@ -203,10 +204,10 @@ function createBrowserRelayHandler(opts) {
|
|
|
203
204
|
|
|
204
205
|
// src/server.ts
|
|
205
206
|
import { ServerResponse } from "http";
|
|
206
|
-
import { randomUUID } from "crypto";
|
|
207
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
207
208
|
import {
|
|
208
209
|
context,
|
|
209
|
-
trace,
|
|
210
|
+
trace as trace2,
|
|
210
211
|
SpanKind,
|
|
211
212
|
SpanStatusCode,
|
|
212
213
|
TraceFlags
|
|
@@ -309,13 +310,13 @@ function installAutterAutoFlush(options = {}) {
|
|
|
309
310
|
const signals = options.signals ?? DEFAULT_SIGNALS;
|
|
310
311
|
const flushOnUncaughtException = options.flushOnUncaughtException !== false;
|
|
311
312
|
let disposed = false;
|
|
312
|
-
let
|
|
313
|
+
let inFlight2 = null;
|
|
313
314
|
const doFlush = async () => {
|
|
314
315
|
const targets = options.targets ?? activeFlushTargets();
|
|
315
316
|
if (targets.length === 0) return true;
|
|
316
|
-
let
|
|
317
|
+
let timer2;
|
|
317
318
|
const timedOut = new Promise((resolve) => {
|
|
318
|
-
|
|
319
|
+
timer2 = setTimeout(() => resolve(false), timeoutMs);
|
|
319
320
|
});
|
|
320
321
|
const drained = Promise.allSettled(
|
|
321
322
|
targets.map(
|
|
@@ -328,7 +329,7 @@ function installAutterAutoFlush(options = {}) {
|
|
|
328
329
|
try {
|
|
329
330
|
ok = await Promise.race([drained, timedOut]);
|
|
330
331
|
} finally {
|
|
331
|
-
clearTimeout(
|
|
332
|
+
clearTimeout(timer2);
|
|
332
333
|
}
|
|
333
334
|
if (ok) {
|
|
334
335
|
telemetryStats.markAllFlushed();
|
|
@@ -344,13 +345,13 @@ function installAutterAutoFlush(options = {}) {
|
|
|
344
345
|
};
|
|
345
346
|
const flush = (reason = "exit") => {
|
|
346
347
|
if (disposed) return Promise.resolve(false);
|
|
347
|
-
if (!
|
|
348
|
-
|
|
349
|
-
|
|
348
|
+
if (!inFlight2) {
|
|
349
|
+
inFlight2 = doFlush().finally(() => {
|
|
350
|
+
inFlight2 = null;
|
|
350
351
|
});
|
|
351
352
|
}
|
|
352
353
|
if (isDebugEnabled()) debugLog(`auto-flush requested on ${reason}`);
|
|
353
|
-
return
|
|
354
|
+
return inFlight2;
|
|
354
355
|
};
|
|
355
356
|
const signalCounts = /* @__PURE__ */ new Map();
|
|
356
357
|
let handlingUncaughtException = false;
|
|
@@ -489,8 +490,8 @@ function compile(options) {
|
|
|
489
490
|
scrubEmailValues: options?.scrubEmailValues !== false
|
|
490
491
|
};
|
|
491
492
|
}
|
|
492
|
-
function redactString(
|
|
493
|
-
let out =
|
|
493
|
+
function redactString(value2, r) {
|
|
494
|
+
let out = value2.replace(r.privateKeyBlock, r.mask);
|
|
494
495
|
for (const re of r.valuePatterns) {
|
|
495
496
|
out = out.replace(re, r.mask);
|
|
496
497
|
}
|
|
@@ -508,40 +509,40 @@ function canTraverse(depth, state) {
|
|
|
508
509
|
state.remainingWork -= 1;
|
|
509
510
|
return true;
|
|
510
511
|
}
|
|
511
|
-
function redactValue(
|
|
512
|
-
if (typeof
|
|
512
|
+
function redactValue(value2, r, state, depth) {
|
|
513
|
+
if (typeof value2 === "string") return redactString(value2, r);
|
|
513
514
|
let isArray = false;
|
|
514
515
|
try {
|
|
515
|
-
isArray = Array.isArray(
|
|
516
|
+
isArray = Array.isArray(value2);
|
|
516
517
|
} catch {
|
|
517
518
|
return r.mask;
|
|
518
519
|
}
|
|
519
520
|
if (isArray) {
|
|
520
|
-
return redactArray(
|
|
521
|
+
return redactArray(value2, r, state, depth);
|
|
521
522
|
}
|
|
522
|
-
if (typeof
|
|
523
|
-
return redactObject(
|
|
523
|
+
if (typeof value2 === "object" && value2 !== null) {
|
|
524
|
+
return redactObject(value2, r, state, depth);
|
|
524
525
|
}
|
|
525
|
-
return
|
|
526
|
+
return value2;
|
|
526
527
|
}
|
|
527
|
-
function redactArray(
|
|
528
|
-
const existing = state.ancestors.get(
|
|
528
|
+
function redactArray(value2, r, state, depth) {
|
|
529
|
+
const existing = state.ancestors.get(value2);
|
|
529
530
|
if (existing) return r.mask;
|
|
530
531
|
if (!canTraverse(depth, state)) return r.mask;
|
|
531
532
|
const out = [];
|
|
532
|
-
state.ancestors.set(
|
|
533
|
+
state.ancestors.set(value2, out);
|
|
533
534
|
let length;
|
|
534
535
|
try {
|
|
535
|
-
length =
|
|
536
|
+
length = value2.length;
|
|
536
537
|
} catch {
|
|
537
|
-
state.ancestors.delete(
|
|
538
|
+
state.ancestors.delete(value2);
|
|
538
539
|
return r.mask;
|
|
539
540
|
}
|
|
540
541
|
const limit = Math.min(length, MAX_COLLECTION_ENTRIES);
|
|
541
542
|
for (let i = 0; i < limit; i += 1) {
|
|
542
543
|
let item;
|
|
543
544
|
try {
|
|
544
|
-
item =
|
|
545
|
+
item = value2[i];
|
|
545
546
|
} catch {
|
|
546
547
|
out.push(r.mask);
|
|
547
548
|
continue;
|
|
@@ -551,21 +552,21 @@ function redactArray(value, r, state, depth) {
|
|
|
551
552
|
if (length > limit) {
|
|
552
553
|
out.push(r.mask);
|
|
553
554
|
}
|
|
554
|
-
state.ancestors.delete(
|
|
555
|
+
state.ancestors.delete(value2);
|
|
555
556
|
return out;
|
|
556
557
|
}
|
|
557
|
-
function redactObject(
|
|
558
|
-
const existing = state.ancestors.get(
|
|
558
|
+
function redactObject(value2, r, state, depth) {
|
|
559
|
+
const existing = state.ancestors.get(value2);
|
|
559
560
|
if (existing) return r.mask;
|
|
560
561
|
if (!canTraverse(depth, state)) return r.mask;
|
|
561
562
|
const out = {};
|
|
562
|
-
state.ancestors.set(
|
|
563
|
+
state.ancestors.set(value2, out);
|
|
563
564
|
let count = 0;
|
|
564
565
|
let truncated = false;
|
|
565
566
|
try {
|
|
566
|
-
for (const key in
|
|
567
|
+
for (const key in value2) {
|
|
567
568
|
if (!Object.prototype.propertyIsEnumerable.call(
|
|
568
|
-
|
|
569
|
+
value2,
|
|
569
570
|
key
|
|
570
571
|
)) {
|
|
571
572
|
continue;
|
|
@@ -576,7 +577,7 @@ function redactObject(value, r, state, depth) {
|
|
|
576
577
|
}
|
|
577
578
|
let nestedValue;
|
|
578
579
|
try {
|
|
579
|
-
nestedValue =
|
|
580
|
+
nestedValue = value2[key];
|
|
580
581
|
} catch {
|
|
581
582
|
out[key] = r.mask;
|
|
582
583
|
count += 1;
|
|
@@ -596,7 +597,7 @@ function redactObject(value, r, state, depth) {
|
|
|
596
597
|
if (truncated) {
|
|
597
598
|
out.__redaction_truncated__ = r.mask;
|
|
598
599
|
}
|
|
599
|
-
state.ancestors.delete(
|
|
600
|
+
state.ancestors.delete(value2);
|
|
600
601
|
return out;
|
|
601
602
|
}
|
|
602
603
|
var USAGE_TOKEN_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -613,10 +614,10 @@ var USAGE_TOKEN_KEYS = /* @__PURE__ */ new Set([
|
|
|
613
614
|
"gen_ai.usage.total_tokens",
|
|
614
615
|
"gen_ai.usage.token_count"
|
|
615
616
|
]);
|
|
616
|
-
function isSensitiveKey(key,
|
|
617
|
+
function isSensitiveKey(key, value2, r) {
|
|
617
618
|
const lowered = key.toLowerCase();
|
|
618
619
|
if (USAGE_TOKEN_KEYS.has(lowered)) {
|
|
619
|
-
return !(typeof
|
|
620
|
+
return !(typeof value2 === "number" && Number.isFinite(value2) && value2 >= 0);
|
|
620
621
|
}
|
|
621
622
|
return r.keyPatterns.some((re) => re.test(lowered));
|
|
622
623
|
}
|
|
@@ -645,9 +646,9 @@ function redactWith(attributes, r) {
|
|
|
645
646
|
truncated = true;
|
|
646
647
|
break;
|
|
647
648
|
}
|
|
648
|
-
let
|
|
649
|
+
let value2;
|
|
649
650
|
try {
|
|
650
|
-
|
|
651
|
+
value2 = attributes[key];
|
|
651
652
|
} catch {
|
|
652
653
|
out[key] = r.mask;
|
|
653
654
|
count += 1;
|
|
@@ -656,8 +657,8 @@ function redactWith(attributes, r) {
|
|
|
656
657
|
}
|
|
657
658
|
count += 1;
|
|
658
659
|
state.remainingWork -= 1;
|
|
659
|
-
if (
|
|
660
|
-
out[key] = isSensitiveKey(key,
|
|
660
|
+
if (value2 === void 0) continue;
|
|
661
|
+
out[key] = isSensitiveKey(key, value2, r) ? r.mask : redactValue(value2, r, state, 0);
|
|
661
662
|
}
|
|
662
663
|
} catch {
|
|
663
664
|
truncated = true;
|
|
@@ -720,6 +721,390 @@ function startMemoryMetrics() {
|
|
|
720
721
|
};
|
|
721
722
|
}
|
|
722
723
|
|
|
724
|
+
// src/logger.ts
|
|
725
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
726
|
+
import { randomUUID } from "crypto";
|
|
727
|
+
import { trace } from "@opentelemetry/api";
|
|
728
|
+
var local = new AsyncLocalStorage();
|
|
729
|
+
var config = null;
|
|
730
|
+
var queue = [];
|
|
731
|
+
var queueBytes = 0;
|
|
732
|
+
var inFlightBytes = 0;
|
|
733
|
+
var timer;
|
|
734
|
+
var flushing = null;
|
|
735
|
+
var dropped = 0;
|
|
736
|
+
var inFlight = 0;
|
|
737
|
+
var stopping = false;
|
|
738
|
+
var failureStreak = 0;
|
|
739
|
+
var severity = { debug: 5, info: 9, warning: 13, error: 17 };
|
|
740
|
+
function safe(attributes = {}) {
|
|
741
|
+
const redacted = config?.redact(attributes) ?? redactAttributes(attributes);
|
|
742
|
+
let budget = 512;
|
|
743
|
+
let characters = 16384;
|
|
744
|
+
let truncated = false;
|
|
745
|
+
const visit = (input, depth) => {
|
|
746
|
+
if (--budget < 0 || depth > 6) {
|
|
747
|
+
truncated = true;
|
|
748
|
+
return "[truncated]";
|
|
749
|
+
}
|
|
750
|
+
if (typeof input === "string") {
|
|
751
|
+
const text = input.replace(/(https?:\/\/[^\s?#]+)[?#][^\s]*/gi, "$1");
|
|
752
|
+
const kept = text.slice(0, Math.max(0, characters));
|
|
753
|
+
truncated ||= kept.length < text.length;
|
|
754
|
+
characters -= kept.length;
|
|
755
|
+
return kept;
|
|
756
|
+
}
|
|
757
|
+
if (typeof input === "number")
|
|
758
|
+
return Number.isFinite(input) ? input : void 0;
|
|
759
|
+
if (typeof input === "boolean" || input === null) return input;
|
|
760
|
+
if (Array.isArray(input)) {
|
|
761
|
+
truncated ||= input.length > 64;
|
|
762
|
+
return input.slice(0, 64).map((item) => visit(item, depth + 1));
|
|
763
|
+
}
|
|
764
|
+
if (input && typeof input === "object") {
|
|
765
|
+
const entries = Object.entries(input);
|
|
766
|
+
if (depth === 0) {
|
|
767
|
+
const priority = (key) => /^autter\.(?:operation|event)\./.test(key) ? 2 : /^exception\./.test(key) ? 1 : 0;
|
|
768
|
+
entries.sort(([a], [b]) => priority(b) - priority(a));
|
|
769
|
+
}
|
|
770
|
+
truncated ||= entries.length > 100;
|
|
771
|
+
return Object.fromEntries(
|
|
772
|
+
entries.slice(0, 100).filter(([key]) => !/^(?:__proto__|constructor|prototype)$/.test(key)).map(([key, item]) => [key.slice(0, 200), visit(item, depth + 1)])
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
return void 0;
|
|
776
|
+
};
|
|
777
|
+
const result = visit(redacted, 0);
|
|
778
|
+
if (truncated) result["autter.context.truncated"] = true;
|
|
779
|
+
return result;
|
|
780
|
+
}
|
|
781
|
+
function operationAttributes(state) {
|
|
782
|
+
return state ? {
|
|
783
|
+
"autter.operation.id": state.id,
|
|
784
|
+
"autter.operation.name": state.name,
|
|
785
|
+
...state.parentId ? { "autter.operation.parent_id": state.parentId } : {},
|
|
786
|
+
...state.attributes
|
|
787
|
+
} : {};
|
|
788
|
+
}
|
|
789
|
+
function userAttributes(attributes = {}) {
|
|
790
|
+
return Object.fromEntries(
|
|
791
|
+
Object.entries(safe(attributes)).filter(
|
|
792
|
+
([key]) => !/^autter\.(?:operation|event)\./.test(key)
|
|
793
|
+
)
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
function mergeContext(current, next = {}) {
|
|
797
|
+
const merge = (left, right, depth) => {
|
|
798
|
+
const result = { ...left };
|
|
799
|
+
for (const [key, value2] of Object.entries(right)) {
|
|
800
|
+
const prior = result[key];
|
|
801
|
+
result[key] = depth < 6 && value2 && typeof value2 === "object" && !Array.isArray(value2) && prior && typeof prior === "object" && !Array.isArray(prior) ? merge(prior, value2, depth + 1) : value2;
|
|
802
|
+
}
|
|
803
|
+
return result;
|
|
804
|
+
};
|
|
805
|
+
return userAttributes(merge(current, userAttributes(next), 0));
|
|
806
|
+
}
|
|
807
|
+
function traceAttributes(state) {
|
|
808
|
+
return Object.fromEntries(
|
|
809
|
+
Object.entries(operationAttributes(state)).filter(([, item]) => item !== null && item !== void 0).map(([key, item]) => [
|
|
810
|
+
key,
|
|
811
|
+
typeof item === "object" ? JSON.stringify(item) : item
|
|
812
|
+
])
|
|
813
|
+
);
|
|
814
|
+
}
|
|
815
|
+
function scheduleFlush() {
|
|
816
|
+
if (!timer && config && !stopping && queue.length) {
|
|
817
|
+
timer = setTimeout(
|
|
818
|
+
() => {
|
|
819
|
+
timer = void 0;
|
|
820
|
+
void flushRuntimeLogs().catch(() => {
|
|
821
|
+
});
|
|
822
|
+
},
|
|
823
|
+
Math.min(3e4, 2e3 * 2 ** Math.min(failureStreak, 4))
|
|
824
|
+
);
|
|
825
|
+
timer.unref();
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
function value(input) {
|
|
829
|
+
if (typeof input === "number") return { doubleValue: input };
|
|
830
|
+
if (typeof input === "boolean") return { boolValue: input };
|
|
831
|
+
if (Array.isArray(input))
|
|
832
|
+
return { arrayValue: { values: input.slice(0, 64).map(value) } };
|
|
833
|
+
if (input && typeof input === "object")
|
|
834
|
+
return {
|
|
835
|
+
kvlistValue: {
|
|
836
|
+
values: Object.entries(input).slice(0, 128).map(([key, item]) => ({ key, value: value(item) }))
|
|
837
|
+
}
|
|
838
|
+
};
|
|
839
|
+
return { stringValue: String(input ?? "").slice(0, 32e3) };
|
|
840
|
+
}
|
|
841
|
+
function emit(level, message, attributes, extra = {}) {
|
|
842
|
+
const state = local.getStore();
|
|
843
|
+
if (state?.sealed) return;
|
|
844
|
+
if (extra["autter.event.type"] !== "operation" && severity[level] < severity[config?.options?.minLevel ?? "debug"])
|
|
845
|
+
return;
|
|
846
|
+
const span = trace.getActiveSpan()?.spanContext();
|
|
847
|
+
const user = mergeContext(state?.attributes ?? {}, attributes);
|
|
848
|
+
const exceptions = Object.fromEntries(
|
|
849
|
+
Object.entries(user).filter(([key]) => key.startsWith("exception."))
|
|
850
|
+
);
|
|
851
|
+
const attrs = safe({
|
|
852
|
+
"autter.event.id": randomUUID(),
|
|
853
|
+
...extra,
|
|
854
|
+
...exceptions,
|
|
855
|
+
...operationAttributes(state),
|
|
856
|
+
...user
|
|
857
|
+
});
|
|
858
|
+
const record = {
|
|
859
|
+
timeUnixNano: String(BigInt(Date.now()) * 1000000n),
|
|
860
|
+
severityNumber: severity[level],
|
|
861
|
+
severityText: level.toUpperCase(),
|
|
862
|
+
body: value(String(safe({ message }).message ?? "").slice(0, 4e3)),
|
|
863
|
+
attributes: Object.entries(attrs).map(([key, item]) => ({
|
|
864
|
+
key,
|
|
865
|
+
value: value(item)
|
|
866
|
+
})),
|
|
867
|
+
...span && /^[a-f0-9]{32}$/.test(span.traceId) && !/^0+$/.test(span.traceId) ? { traceId: span.traceId, spanId: span.spanId } : {}
|
|
868
|
+
};
|
|
869
|
+
if (config?.options?.console !== false)
|
|
870
|
+
console.log(
|
|
871
|
+
JSON.stringify({ ...attrs, level, message: record.body.stringValue })
|
|
872
|
+
);
|
|
873
|
+
if (!config) return;
|
|
874
|
+
if (stopping) {
|
|
875
|
+
dropped++;
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
const bytes = Buffer.byteLength(JSON.stringify(record));
|
|
879
|
+
if (bytes > 256 * 1024 || queue.length + inFlight >= 1e3 || queueBytes + inFlightBytes + bytes > 4 * 1024 * 1024) {
|
|
880
|
+
dropped++;
|
|
881
|
+
console.warn(
|
|
882
|
+
"[autter-runtime] log buffer or record limit reached; record dropped"
|
|
883
|
+
);
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
queue.push({ record, bytes });
|
|
887
|
+
queueBytes += bytes;
|
|
888
|
+
scheduleFlush();
|
|
889
|
+
}
|
|
890
|
+
function configureRuntimeLogger(next) {
|
|
891
|
+
config = next;
|
|
892
|
+
stopping = false;
|
|
893
|
+
failureStreak = 0;
|
|
894
|
+
}
|
|
895
|
+
function runtimeLogStats() {
|
|
896
|
+
return { buffered: queue.length + inFlight, dropped };
|
|
897
|
+
}
|
|
898
|
+
async function flushRuntimeLogs() {
|
|
899
|
+
if (flushing) return flushing;
|
|
900
|
+
if (!config || !queue.length) return;
|
|
901
|
+
if (timer) {
|
|
902
|
+
clearTimeout(timer);
|
|
903
|
+
timer = void 0;
|
|
904
|
+
}
|
|
905
|
+
const activeConfig = config;
|
|
906
|
+
const deadline = Date.now() + 1e4;
|
|
907
|
+
flushing = (async () => {
|
|
908
|
+
const count = queue.length;
|
|
909
|
+
for (let remaining = count; remaining > 0; ) {
|
|
910
|
+
const batch = [];
|
|
911
|
+
inFlightBytes = 0;
|
|
912
|
+
while (batch.length < Math.min(50, remaining) && queue.length) {
|
|
913
|
+
const next = queue[0];
|
|
914
|
+
if (batch.length && inFlightBytes + next.bytes > 512 * 1024) break;
|
|
915
|
+
batch.push(queue.shift());
|
|
916
|
+
inFlightBytes += next.bytes;
|
|
917
|
+
queueBytes -= next.bytes;
|
|
918
|
+
}
|
|
919
|
+
remaining -= batch.length;
|
|
920
|
+
inFlight = batch.length;
|
|
921
|
+
const body = JSON.stringify({
|
|
922
|
+
resourceLogs: [
|
|
923
|
+
{
|
|
924
|
+
resource: {
|
|
925
|
+
attributes: Object.entries({
|
|
926
|
+
"service.name": activeConfig.service,
|
|
927
|
+
"deployment.environment.name": activeConfig.environment,
|
|
928
|
+
...activeConfig.release ? { "service.version": activeConfig.release } : {}
|
|
929
|
+
}).map(([key, item]) => ({ key, value: value(item) }))
|
|
930
|
+
},
|
|
931
|
+
scopeLogs: [
|
|
932
|
+
{
|
|
933
|
+
scope: { name: "autter-runtime" },
|
|
934
|
+
logRecords: batch.map((entry) => entry.record)
|
|
935
|
+
}
|
|
936
|
+
]
|
|
937
|
+
}
|
|
938
|
+
]
|
|
939
|
+
});
|
|
940
|
+
let failure;
|
|
941
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
942
|
+
try {
|
|
943
|
+
if (Date.now() >= deadline)
|
|
944
|
+
throw new Error("Runtime log flush exceeded 10 seconds");
|
|
945
|
+
const response = await fetch(`${activeConfig.endpoint}/v1/logs`, {
|
|
946
|
+
method: "POST",
|
|
947
|
+
headers: {
|
|
948
|
+
"content-type": "application/json",
|
|
949
|
+
authorization: `Bearer ${activeConfig.apiKey}`
|
|
950
|
+
},
|
|
951
|
+
body,
|
|
952
|
+
signal: AbortSignal.timeout(
|
|
953
|
+
Math.max(1, Math.min(3e3, deadline - Date.now()))
|
|
954
|
+
)
|
|
955
|
+
});
|
|
956
|
+
if (!response.ok)
|
|
957
|
+
throw new Error(`Runtime log export failed (${response.status})`);
|
|
958
|
+
failure = void 0;
|
|
959
|
+
break;
|
|
960
|
+
} catch (error) {
|
|
961
|
+
failure = error;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
inFlight = 0;
|
|
965
|
+
if (failure) {
|
|
966
|
+
failureStreak++;
|
|
967
|
+
queue = [...batch, ...queue];
|
|
968
|
+
queueBytes += inFlightBytes;
|
|
969
|
+
inFlightBytes = 0;
|
|
970
|
+
throw failure;
|
|
971
|
+
}
|
|
972
|
+
inFlightBytes = 0;
|
|
973
|
+
failureStreak = 0;
|
|
974
|
+
}
|
|
975
|
+
})().finally(() => {
|
|
976
|
+
flushing = null;
|
|
977
|
+
scheduleFlush();
|
|
978
|
+
});
|
|
979
|
+
return flushing;
|
|
980
|
+
}
|
|
981
|
+
async function shutdownRuntimeLogger() {
|
|
982
|
+
stopping = true;
|
|
983
|
+
try {
|
|
984
|
+
await flushRuntimeLogs();
|
|
985
|
+
} finally {
|
|
986
|
+
if (queue.length) {
|
|
987
|
+
dropped += queue.length;
|
|
988
|
+
console.warn(
|
|
989
|
+
`[autter-runtime] ${queue.length} log records could not be delivered before shutdown`
|
|
990
|
+
);
|
|
991
|
+
}
|
|
992
|
+
queue = [];
|
|
993
|
+
queueBytes = 0;
|
|
994
|
+
config = null;
|
|
995
|
+
if (timer) clearTimeout(timer);
|
|
996
|
+
timer = void 0;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
function createRuntimeLogger(attributes = {}) {
|
|
1000
|
+
const attrs = userAttributes(attributes);
|
|
1001
|
+
return {
|
|
1002
|
+
debug: (message, extra) => emit("debug", message, mergeContext(attrs, extra)),
|
|
1003
|
+
info: (message, extra) => emit("info", message, mergeContext(attrs, extra)),
|
|
1004
|
+
warn: (message, extra) => emit("warning", message, mergeContext(attrs, extra)),
|
|
1005
|
+
error: (error, extra) => emit("error", error instanceof Error ? error.message : String(error), {
|
|
1006
|
+
...attrs,
|
|
1007
|
+
...extra,
|
|
1008
|
+
...error instanceof Error ? {
|
|
1009
|
+
"exception.type": error.name,
|
|
1010
|
+
"exception.stacktrace": error.stack ?? ""
|
|
1011
|
+
} : {}
|
|
1012
|
+
})
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
var runtimeLogger = createRuntimeLogger();
|
|
1016
|
+
function withRuntimeOperation(name, fn, attributes = {}) {
|
|
1017
|
+
const parent = local.getStore();
|
|
1018
|
+
const state = {
|
|
1019
|
+
id: randomUUID(),
|
|
1020
|
+
name: String(safe({ name }).name).slice(0, 200),
|
|
1021
|
+
parentId: parent?.sealed ? void 0 : parent?.id,
|
|
1022
|
+
attributes: mergeContext(
|
|
1023
|
+
parent?.sealed ? {} : parent?.attributes ?? {},
|
|
1024
|
+
attributes
|
|
1025
|
+
),
|
|
1026
|
+
startedAt: Date.now(),
|
|
1027
|
+
outcome: "succeeded",
|
|
1028
|
+
steps: []
|
|
1029
|
+
};
|
|
1030
|
+
const operation = {
|
|
1031
|
+
id: state.id,
|
|
1032
|
+
setContext: (attrs) => {
|
|
1033
|
+
if (!state.sealed) {
|
|
1034
|
+
state.attributes = mergeContext(state.attributes, attrs);
|
|
1035
|
+
trace.getActiveSpan()?.setAttributes(traceAttributes(state));
|
|
1036
|
+
}
|
|
1037
|
+
},
|
|
1038
|
+
outcome: (status, message) => {
|
|
1039
|
+
if (state.sealed) return;
|
|
1040
|
+
state.outcome = status;
|
|
1041
|
+
state.message = message;
|
|
1042
|
+
if (status === "failed")
|
|
1043
|
+
state.reportingStack = new Error("Operation outcome reported here").stack ?? "";
|
|
1044
|
+
},
|
|
1045
|
+
step: async (stepName, stepFn) => {
|
|
1046
|
+
const started = Date.now();
|
|
1047
|
+
let status = "succeeded";
|
|
1048
|
+
try {
|
|
1049
|
+
return await stepFn();
|
|
1050
|
+
} catch (error) {
|
|
1051
|
+
status = "failed";
|
|
1052
|
+
throw error;
|
|
1053
|
+
} finally {
|
|
1054
|
+
if (!state.sealed && state.steps.length < 64)
|
|
1055
|
+
state.steps.push({
|
|
1056
|
+
name: String(safe({ name: stepName }).name).slice(0, 200),
|
|
1057
|
+
status,
|
|
1058
|
+
durationMs: Date.now() - started
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1063
|
+
const run = () => local.run(state, async () => {
|
|
1064
|
+
let thrown;
|
|
1065
|
+
try {
|
|
1066
|
+
return await fn(operation);
|
|
1067
|
+
} catch (error) {
|
|
1068
|
+
state.outcome = "failed";
|
|
1069
|
+
thrown = error;
|
|
1070
|
+
throw error;
|
|
1071
|
+
} finally {
|
|
1072
|
+
trace.getActiveSpan()?.setAttributes({
|
|
1073
|
+
...traceAttributes(state),
|
|
1074
|
+
"autter.operation.outcome": state.outcome
|
|
1075
|
+
});
|
|
1076
|
+
if (state.outcome === "failed" && !thrown)
|
|
1077
|
+
config?.reportOutcome(
|
|
1078
|
+
state.name,
|
|
1079
|
+
state.message ?? "Operation failed",
|
|
1080
|
+
{
|
|
1081
|
+
...traceAttributes(state),
|
|
1082
|
+
"autter.outcome.stack": state.reportingStack ?? ""
|
|
1083
|
+
}
|
|
1084
|
+
);
|
|
1085
|
+
emit(
|
|
1086
|
+
state.outcome === "failed" ? "error" : "info",
|
|
1087
|
+
state.message ?? `${state.name}: ${state.outcome}`,
|
|
1088
|
+
{
|
|
1089
|
+
...operationAttributes(state),
|
|
1090
|
+
...thrown instanceof Error ? {
|
|
1091
|
+
"exception.type": thrown.name,
|
|
1092
|
+
"exception.stacktrace": thrown.stack ?? ""
|
|
1093
|
+
} : {}
|
|
1094
|
+
},
|
|
1095
|
+
{
|
|
1096
|
+
"autter.event.type": "operation",
|
|
1097
|
+
"autter.operation.outcome": state.outcome,
|
|
1098
|
+
"autter.operation.duration_ms": Date.now() - state.startedAt,
|
|
1099
|
+
"autter.operation.steps": state.steps
|
|
1100
|
+
}
|
|
1101
|
+
);
|
|
1102
|
+
state.sealed = true;
|
|
1103
|
+
}
|
|
1104
|
+
});
|
|
1105
|
+
return config ? config.run(state.name, run, traceAttributes(state)) : run();
|
|
1106
|
+
}
|
|
1107
|
+
|
|
723
1108
|
// src/server.ts
|
|
724
1109
|
var LLM_MARKER_ATTRIBUTES = [
|
|
725
1110
|
"gen_ai.operation.name",
|
|
@@ -848,7 +1233,7 @@ var ErrorTraceRetentionProcessor = class {
|
|
|
848
1233
|
}
|
|
849
1234
|
/** Promote the active trace, if any — called on captured errors. */
|
|
850
1235
|
retainActiveTrace() {
|
|
851
|
-
const active2 =
|
|
1236
|
+
const active2 = trace2.getActiveSpan()?.spanContext();
|
|
852
1237
|
if (!active2 || (active2.traceFlags & TraceFlags.SAMPLED) !== 0) return;
|
|
853
1238
|
const entry = this.entryFor(active2.traceId);
|
|
854
1239
|
if (entry.retained) return;
|
|
@@ -951,7 +1336,7 @@ async function runLlmSpan(tracer, info, fn) {
|
|
|
951
1336
|
};
|
|
952
1337
|
try {
|
|
953
1338
|
const result = await context.with(
|
|
954
|
-
|
|
1339
|
+
trace2.setSpan(context.active(), span),
|
|
955
1340
|
() => fn(handle)
|
|
956
1341
|
);
|
|
957
1342
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
@@ -1000,7 +1385,7 @@ async function runWithSpan(tracer, name, fn, attributes) {
|
|
|
1000
1385
|
const span = tracer.startSpan(name, { attributes });
|
|
1001
1386
|
try {
|
|
1002
1387
|
const result = await context.with(
|
|
1003
|
-
|
|
1388
|
+
trace2.setSpan(context.active(), span),
|
|
1004
1389
|
fn
|
|
1005
1390
|
);
|
|
1006
1391
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
@@ -1052,7 +1437,7 @@ function initAutterServer(options) {
|
|
|
1052
1437
|
activeRedactor = makeRedactor(options.redactAttributes ?? true);
|
|
1053
1438
|
const resource = new Resource({
|
|
1054
1439
|
[ATTR_SERVICE_NAME]: options.service,
|
|
1055
|
-
"service.instance.id": (options.instanceId || process.env.AUTTER_RUNTIME_INSTANCE_ID ||
|
|
1440
|
+
"service.instance.id": (options.instanceId || process.env.AUTTER_RUNTIME_INSTANCE_ID || randomUUID2()).slice(0, 128),
|
|
1056
1441
|
...options.release ? { [ATTR_SERVICE_VERSION]: options.release } : {},
|
|
1057
1442
|
"deployment.environment": environment,
|
|
1058
1443
|
// Tells the ingester request metrics arrive on the metrics pipe, so
|
|
@@ -1139,7 +1524,7 @@ function initAutterServer(options) {
|
|
|
1139
1524
|
const isError = error instanceof Error;
|
|
1140
1525
|
const message = isError ? error.message : String(error);
|
|
1141
1526
|
const redacted = activeRedactor(attributes);
|
|
1142
|
-
const activeSpan =
|
|
1527
|
+
const activeSpan = trace2.getActiveSpan();
|
|
1143
1528
|
const reuseActive = activeSpan?.isRecording() === true;
|
|
1144
1529
|
const span = reuseActive ? activeSpan : errorTracer.startSpan(isError ? error.name : "Error");
|
|
1145
1530
|
span.setAttributes({ "autter.severity": "error", ...redacted });
|
|
@@ -1167,20 +1552,20 @@ function initAutterServer(options) {
|
|
|
1167
1552
|
span.setStatus({ code: SpanStatusCode.ERROR, message });
|
|
1168
1553
|
if (!reuseActive) span.end();
|
|
1169
1554
|
}
|
|
1170
|
-
function captureMessage2(message,
|
|
1171
|
-
if (
|
|
1555
|
+
function captureMessage2(message, severity2 = "warning", attributes) {
|
|
1556
|
+
if (severity2 === "error" || severity2 === "fatal") {
|
|
1172
1557
|
errorTraceBuffer?.retainActiveTrace();
|
|
1173
1558
|
}
|
|
1174
1559
|
telemetryStats.markCaptured();
|
|
1175
1560
|
const stack = new Error().stack?.split("\n").filter((line, i) => i === 0 || !line.includes("captureMessage")).join("\n");
|
|
1176
1561
|
const span = errorTracer.startSpan("Message", {
|
|
1177
|
-
attributes: { "autter.severity":
|
|
1562
|
+
attributes: { "autter.severity": severity2, ...activeRedactor(attributes) }
|
|
1178
1563
|
});
|
|
1179
1564
|
span.addEvent("exception", {
|
|
1180
1565
|
"exception.type": "Message",
|
|
1181
1566
|
"exception.message": message,
|
|
1182
1567
|
...stack ? { "exception.stacktrace": stack } : {},
|
|
1183
|
-
"autter.severity":
|
|
1568
|
+
"autter.severity": severity2
|
|
1184
1569
|
});
|
|
1185
1570
|
span.setStatus({ code: SpanStatusCode.ERROR, message });
|
|
1186
1571
|
span.end();
|
|
@@ -1188,7 +1573,7 @@ function initAutterServer(options) {
|
|
|
1188
1573
|
function reportOutcome2(name, message, attributes) {
|
|
1189
1574
|
errorTraceBuffer?.retainActiveTrace();
|
|
1190
1575
|
telemetryStats.markCaptured();
|
|
1191
|
-
const activeSpan =
|
|
1576
|
+
const activeSpan = trace2.getActiveSpan();
|
|
1192
1577
|
const reuseActive = activeSpan?.isRecording() === true;
|
|
1193
1578
|
const span = reuseActive ? activeSpan : errorTracer.startSpan("OutcomeFailure");
|
|
1194
1579
|
const safeOutcome = activeRedactor({ "autter.outcome.name": name.slice(0, 200), "autter.outcome.message": message.slice(0, 1e3) });
|
|
@@ -1203,6 +1588,17 @@ function initAutterServer(options) {
|
|
|
1203
1588
|
span.setStatus({ code: SpanStatusCode.ERROR, message: safeMessage });
|
|
1204
1589
|
if (!reuseActive) span.end();
|
|
1205
1590
|
}
|
|
1591
|
+
configureRuntimeLogger({
|
|
1592
|
+
endpoint,
|
|
1593
|
+
apiKey: options.apiKey,
|
|
1594
|
+
service: options.service,
|
|
1595
|
+
environment,
|
|
1596
|
+
release: options.release,
|
|
1597
|
+
options: options.logging,
|
|
1598
|
+
redact: activeRedactor,
|
|
1599
|
+
run: (name, fn, attributes) => runWithSpan(processTracer, name, fn, activeRedactor(attributes)),
|
|
1600
|
+
reportOutcome: reportOutcome2
|
|
1601
|
+
});
|
|
1206
1602
|
if (options.captureGlobalErrors !== false) {
|
|
1207
1603
|
process.on("uncaughtExceptionMonitor", (err) => {
|
|
1208
1604
|
captureException2(err, { "autter.unhandled": true });
|
|
@@ -1213,6 +1609,7 @@ function initAutterServer(options) {
|
|
|
1213
1609
|
const flushTarget = {
|
|
1214
1610
|
forceFlush: async () => {
|
|
1215
1611
|
const results = await Promise.allSettled([
|
|
1612
|
+
flushRuntimeLogs(),
|
|
1216
1613
|
Promise.resolve().then(() => alwaysOnProvider.forceFlush()),
|
|
1217
1614
|
Promise.resolve().then(() => mainSpanProcessor.forceFlush()),
|
|
1218
1615
|
...errorTraceBuffer ? [Promise.resolve().then(() => errorTraceBuffer.forceFlush())] : [],
|
|
@@ -1239,6 +1636,7 @@ function initAutterServer(options) {
|
|
|
1239
1636
|
withLlmCall: (info, fn) => runLlmSpan(llmTracer, info, fn),
|
|
1240
1637
|
trackLlmCall: (call) => recordLlmCall(llmTracer, call),
|
|
1241
1638
|
shutdown: async () => {
|
|
1639
|
+
const logShutdown = await Promise.allSettled([shutdownRuntimeLogger()]);
|
|
1242
1640
|
stopMemoryMetrics?.();
|
|
1243
1641
|
active = null;
|
|
1244
1642
|
activeAlwaysOnProvider = null;
|
|
@@ -1247,6 +1645,7 @@ function initAutterServer(options) {
|
|
|
1247
1645
|
unregisterFlushTargets();
|
|
1248
1646
|
telemetryStats.markAllFlushed();
|
|
1249
1647
|
await Promise.allSettled([alwaysOnProvider.shutdown(), sdk.shutdown()]);
|
|
1648
|
+
if (logShutdown[0]?.status === "rejected") throw logShutdown[0].reason;
|
|
1250
1649
|
}
|
|
1251
1650
|
};
|
|
1252
1651
|
active = server;
|
|
@@ -1258,7 +1657,7 @@ function captureException(error, attributes) {
|
|
|
1258
1657
|
active.captureException(error, attributes);
|
|
1259
1658
|
return;
|
|
1260
1659
|
}
|
|
1261
|
-
const span =
|
|
1660
|
+
const span = trace2.getTracer("autter-errors").startSpan(error instanceof Error ? error.name : "Error", { attributes });
|
|
1262
1661
|
if (error instanceof Error) span.recordException(error);
|
|
1263
1662
|
span.setStatus({
|
|
1264
1663
|
code: SpanStatusCode.ERROR,
|
|
@@ -1268,38 +1667,38 @@ function captureException(error, attributes) {
|
|
|
1268
1667
|
}
|
|
1269
1668
|
function withProcessSpan(name, fn, attributes) {
|
|
1270
1669
|
if (active) return active.withProcessSpan(name, fn, attributes);
|
|
1271
|
-
return runWithSpan(
|
|
1670
|
+
return runWithSpan(trace2.getTracer("autter-processes"), name, fn, attributes);
|
|
1272
1671
|
}
|
|
1273
1672
|
function withLlmCall(info, fn) {
|
|
1274
1673
|
if (active) return active.withLlmCall(info, fn);
|
|
1275
|
-
return runLlmSpan(
|
|
1674
|
+
return runLlmSpan(trace2.getTracer("autter-llm"), info, fn);
|
|
1276
1675
|
}
|
|
1277
1676
|
function trackLlmCall(call) {
|
|
1278
1677
|
if (active) {
|
|
1279
1678
|
active.trackLlmCall(call);
|
|
1280
1679
|
return;
|
|
1281
1680
|
}
|
|
1282
|
-
recordLlmCall(
|
|
1681
|
+
recordLlmCall(trace2.getTracer("autter-llm"), call);
|
|
1283
1682
|
}
|
|
1284
|
-
function captureMessage(message,
|
|
1683
|
+
function captureMessage(message, severity2 = "warning", attributes) {
|
|
1285
1684
|
if (active) {
|
|
1286
|
-
active.captureMessage(message,
|
|
1685
|
+
active.captureMessage(message, severity2, attributes);
|
|
1287
1686
|
return;
|
|
1288
1687
|
}
|
|
1289
|
-
const span =
|
|
1290
|
-
attributes: { "autter.severity":
|
|
1688
|
+
const span = trace2.getTracer("autter-errors").startSpan("Message", {
|
|
1689
|
+
attributes: { "autter.severity": severity2, ...attributes }
|
|
1291
1690
|
});
|
|
1292
1691
|
span.addEvent("exception", {
|
|
1293
1692
|
"exception.type": "Message",
|
|
1294
1693
|
"exception.message": message,
|
|
1295
|
-
"autter.severity":
|
|
1694
|
+
"autter.severity": severity2
|
|
1296
1695
|
});
|
|
1297
1696
|
span.setStatus({ code: SpanStatusCode.ERROR, message });
|
|
1298
1697
|
span.end();
|
|
1299
1698
|
}
|
|
1300
1699
|
function reportOutcome(name, message, attributes) {
|
|
1301
1700
|
if (active) return active.reportOutcome(name, message, attributes);
|
|
1302
|
-
const span =
|
|
1701
|
+
const span = trace2.getTracer("autter-outcomes").startSpan("OutcomeFailure");
|
|
1303
1702
|
const safeOutcome = redactAttributes({ "autter.outcome.name": name.slice(0, 200), "autter.outcome.message": message.slice(0, 1e3) });
|
|
1304
1703
|
const safeName = String(safeOutcome["autter.outcome.name"] ?? "operation");
|
|
1305
1704
|
const safeMessage = String(safeOutcome["autter.outcome.message"] ?? "failed");
|
|
@@ -1316,11 +1715,11 @@ function makeSafeCapture(options) {
|
|
|
1316
1715
|
const clean = (attributes) => attributes ? { ...redactAttributes(attributes, options) } : void 0;
|
|
1317
1716
|
return {
|
|
1318
1717
|
captureException: (error, attributes) => captureException(error, clean(attributes)),
|
|
1319
|
-
captureMessage: (message,
|
|
1718
|
+
captureMessage: (message, severity2, attributes) => captureMessage(message, severity2 ?? "warning", clean(attributes))
|
|
1320
1719
|
};
|
|
1321
1720
|
}
|
|
1322
1721
|
function alwaysOnTracer(name) {
|
|
1323
|
-
return activeAlwaysOnProvider ? activeAlwaysOnProvider.getTracer(name) :
|
|
1722
|
+
return activeAlwaysOnProvider ? activeAlwaysOnProvider.getTracer(name) : trace2.getTracer(name);
|
|
1324
1723
|
}
|
|
1325
1724
|
function autterLlmTracer() {
|
|
1326
1725
|
return alwaysOnTracer("autter-llm");
|
|
@@ -1340,7 +1739,7 @@ async function emitLlmSelftestTrace() {
|
|
|
1340
1739
|
attributes: { "autter.selftest": true }
|
|
1341
1740
|
},
|
|
1342
1741
|
(llm) => {
|
|
1343
|
-
traceId =
|
|
1742
|
+
traceId = trace2.getActiveSpan()?.spanContext().traceId ?? "";
|
|
1344
1743
|
llm.setUsage({ inputTokens: 1, outputTokens: 1 });
|
|
1345
1744
|
llm.setCost(0);
|
|
1346
1745
|
}
|
|
@@ -1458,9 +1857,9 @@ function wrapStream(stream, span) {
|
|
|
1458
1857
|
throw err;
|
|
1459
1858
|
}
|
|
1460
1859
|
},
|
|
1461
|
-
async return(
|
|
1860
|
+
async return(value3) {
|
|
1462
1861
|
finish();
|
|
1463
|
-
return inner.return ? inner.return(
|
|
1862
|
+
return inner.return ? inner.return(value3) : { done: true, value: void 0 };
|
|
1464
1863
|
},
|
|
1465
1864
|
async throw(err) {
|
|
1466
1865
|
finish(err);
|
|
@@ -1470,8 +1869,8 @@ function wrapStream(stream, span) {
|
|
|
1470
1869
|
};
|
|
1471
1870
|
};
|
|
1472
1871
|
}
|
|
1473
|
-
const
|
|
1474
|
-
return typeof
|
|
1872
|
+
const value2 = Reflect.get(target, prop, receiver);
|
|
1873
|
+
return typeof value2 === "function" ? value2.bind(target) : value2;
|
|
1475
1874
|
}
|
|
1476
1875
|
});
|
|
1477
1876
|
}
|
|
@@ -1533,30 +1932,30 @@ function instrumentLlmClient(client, options) {
|
|
|
1533
1932
|
if (cached) return cached;
|
|
1534
1933
|
const proxy = new Proxy(target, {
|
|
1535
1934
|
get(t, prop, receiver) {
|
|
1536
|
-
const
|
|
1537
|
-
if (typeof prop === "symbol") return
|
|
1935
|
+
const value2 = Reflect.get(t, prop, receiver);
|
|
1936
|
+
if (typeof prop === "symbol") return value2;
|
|
1538
1937
|
const propPath = path ? `${path}.${prop}` : prop;
|
|
1539
|
-
if (typeof
|
|
1938
|
+
if (typeof value2 === "function") {
|
|
1540
1939
|
if (CALL_METHODS.has(prop)) {
|
|
1541
1940
|
return (...args) => {
|
|
1542
1941
|
const first = args[0];
|
|
1543
1942
|
if (first && typeof first === "object" && typeof first.model === "string") {
|
|
1544
1943
|
return traceCall(
|
|
1545
|
-
|
|
1944
|
+
value2,
|
|
1546
1945
|
t,
|
|
1547
1946
|
propPath,
|
|
1548
1947
|
args
|
|
1549
1948
|
);
|
|
1550
1949
|
}
|
|
1551
|
-
return
|
|
1950
|
+
return value2.apply(t, args);
|
|
1552
1951
|
};
|
|
1553
1952
|
}
|
|
1554
|
-
return
|
|
1953
|
+
return value2.bind(t);
|
|
1555
1954
|
}
|
|
1556
|
-
if (
|
|
1557
|
-
return deepProxy(
|
|
1955
|
+
if (value2 !== null && typeof value2 === "object" && !(value2 instanceof Promise)) {
|
|
1956
|
+
return deepProxy(value2, propPath);
|
|
1558
1957
|
}
|
|
1559
|
-
return
|
|
1958
|
+
return value2;
|
|
1560
1959
|
}
|
|
1561
1960
|
});
|
|
1562
1961
|
proxied.set(target, proxy);
|
|
@@ -1613,16 +2012,21 @@ export {
|
|
|
1613
2012
|
captureMessage,
|
|
1614
2013
|
createBrowserRelayFetchHandler,
|
|
1615
2014
|
createBrowserRelayHandler,
|
|
2015
|
+
createRuntimeLogger,
|
|
1616
2016
|
emitLlmSelftestTrace,
|
|
2017
|
+
flushRuntimeLogs,
|
|
1617
2018
|
initAutterServer,
|
|
1618
2019
|
installAutterAutoFlush,
|
|
1619
2020
|
instrumentLlmClient,
|
|
1620
2021
|
makeSafeCapture,
|
|
1621
2022
|
redactAttributes,
|
|
1622
2023
|
reportOutcome,
|
|
2024
|
+
runtimeLogStats,
|
|
2025
|
+
runtimeLogger,
|
|
1623
2026
|
sanitizeBrowserPayload,
|
|
1624
2027
|
startCaughtExceptionSampler,
|
|
1625
2028
|
trackLlmCall,
|
|
1626
2029
|
withLlmCall,
|
|
1627
|
-
withProcessSpan
|
|
2030
|
+
withProcessSpan,
|
|
2031
|
+
withRuntimeOperation
|
|
1628
2032
|
};
|