@autter/runtime-node 1.9.1 → 1.10.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 +30 -6
- package/dist/chunk-3UODRQBD.js +878 -0
- package/dist/chunk-HBH64LWQ.cjs +878 -0
- package/dist/{chunk-VIP2EL47.js → chunk-KWAJIELR.js} +304 -201
- package/dist/{chunk-3P573RHA.cjs → chunk-S6WJ5YLP.cjs} +304 -201
- package/dist/{chunk-FV64SIRQ.cjs → chunk-STOXJZ7Z.cjs} +21 -10
- package/dist/{chunk-D3PJ7TQ4.js → chunk-V65UY6LU.js} +13 -2
- package/dist/cli.cjs +36 -9
- package/dist/cli.js +32 -5
- package/dist/index.cjs +622 -281
- package/dist/index.d.cts +152 -11
- package/dist/index.d.ts +152 -11
- package/dist/index.js +403 -62
- package/dist/testing.cjs +8 -8
- package/dist/testing.js +2 -2
- package/package.json +2 -1
- package/dist/chunk-FYMEBULO.js +0 -203
- package/dist/chunk-LYXQC4FI.cjs +0 -203
package/dist/index.js
CHANGED
|
@@ -51,15 +51,17 @@ import {
|
|
|
51
51
|
stopLoggedErrorCapture,
|
|
52
52
|
toClientError,
|
|
53
53
|
withRuntimeOperation
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-V65UY6LU.js";
|
|
55
55
|
import {
|
|
56
|
-
runDoctor
|
|
57
|
-
|
|
56
|
+
runDoctor,
|
|
57
|
+
runVerify
|
|
58
|
+
} from "./chunk-3UODRQBD.js";
|
|
58
59
|
import {
|
|
59
60
|
COMPAT_MANIFEST,
|
|
60
61
|
CountingExporter,
|
|
61
62
|
INGESTER_VERSION_HEADER,
|
|
62
63
|
SDK_IDENTITY,
|
|
64
|
+
authHeaders,
|
|
63
65
|
configureCompatCheck,
|
|
64
66
|
debugLog,
|
|
65
67
|
ensureCompatConfigured,
|
|
@@ -69,14 +71,18 @@ import {
|
|
|
69
71
|
installAutterAutoFlush,
|
|
70
72
|
isDebugEnabled,
|
|
71
73
|
noteCompatFeature,
|
|
74
|
+
noteIngestRefusal,
|
|
72
75
|
noteRelayRejection,
|
|
73
76
|
observeIngesterResponse,
|
|
74
77
|
registerFlushTarget,
|
|
78
|
+
resolveIngestKey,
|
|
75
79
|
setDebugMode,
|
|
76
80
|
sharedSlot,
|
|
77
81
|
telemetryStats,
|
|
78
|
-
unregisterFlushTargets
|
|
79
|
-
|
|
82
|
+
unregisterFlushTargets,
|
|
83
|
+
warnKeyKind,
|
|
84
|
+
warnMissingKey
|
|
85
|
+
} from "./chunk-KWAJIELR.js";
|
|
80
86
|
|
|
81
87
|
// src/relay.ts
|
|
82
88
|
var IpWindow = class {
|
|
@@ -358,18 +364,53 @@ function relayFingerprint(raw, redactor) {
|
|
|
358
364
|
}
|
|
359
365
|
var defaultRelayRedactor = makeRedactor(true);
|
|
360
366
|
function sanitizeBrowserPayload(raw, redactor = defaultRelayRedactor) {
|
|
361
|
-
|
|
367
|
+
const checked = checkBrowserPayload(raw, redactor);
|
|
368
|
+
return "payload" in checked ? checked.payload : null;
|
|
369
|
+
}
|
|
370
|
+
var MAX_RELAY_ISSUES = 5;
|
|
371
|
+
function describe(value) {
|
|
372
|
+
if (value === null) return "null";
|
|
373
|
+
if (Array.isArray(value)) return "an array";
|
|
374
|
+
if (typeof value === "string") return value ? `"${value.slice(0, 40)}"` : "an empty string";
|
|
375
|
+
return typeof value === "undefined" ? "missing" : `a ${typeof value}`;
|
|
376
|
+
}
|
|
377
|
+
function checkBrowserPayload(raw, redactor = defaultRelayRedactor) {
|
|
378
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
379
|
+
return { issues: [{ path: [], message: `expected a JSON object, got ${describe(raw)}` }] };
|
|
380
|
+
}
|
|
362
381
|
const p = raw;
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
382
|
+
const issues = [];
|
|
383
|
+
const issue = (path, message) => {
|
|
384
|
+
if (issues.length < MAX_RELAY_ISSUES) issues.push({ path, message });
|
|
385
|
+
};
|
|
386
|
+
if (p.version !== 1) issue(["version"], `expected 1, got ${describe(p.version)}`);
|
|
387
|
+
if (typeof p.service !== "string" || !p.service) issue(["service"], `expected a non-empty string, got ${describe(p.service)}`);
|
|
388
|
+
if (typeof p.environment !== "string" || !p.environment) {
|
|
389
|
+
issue(["environment"], `expected a non-empty string, got ${describe(p.environment)}`);
|
|
390
|
+
}
|
|
391
|
+
if (!Array.isArray(p.events)) issue(["events"], `expected an array, got ${describe(p.events)}`);
|
|
392
|
+
else if (p.events.length > MAX_EVENTS) issue(["events"], `at most ${MAX_EVENTS} events per batch, got ${p.events.length}`);
|
|
393
|
+
if (Array.isArray(p.events) && p.events.length <= MAX_EVENTS) {
|
|
394
|
+
p.events.forEach((rawEvent, index) => {
|
|
395
|
+
if (typeof rawEvent !== "object" || rawEvent === null) {
|
|
396
|
+
issue(["events", index], `expected an object, got ${describe(rawEvent)}`);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
const e = rawEvent;
|
|
400
|
+
if (typeof e.type !== "string" || !EVENT_TYPES.has(e.type)) {
|
|
401
|
+
issue(["events", index, "type"], `expected one of ${[...EVENT_TYPES].join(", ")}, got ${describe(e.type)}`);
|
|
402
|
+
}
|
|
403
|
+
if (typeof e.timestamp !== "string") {
|
|
404
|
+
issue(["events", index, "timestamp"], `expected an ISO 8601 string, got ${describe(e.timestamp)}`);
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
if (issues.length) return { issues };
|
|
409
|
+
const service = p.service;
|
|
410
|
+
const environment = p.environment;
|
|
367
411
|
const events = [];
|
|
368
412
|
for (const rawEvent of p.events) {
|
|
369
|
-
if (typeof rawEvent !== "object" || rawEvent === null) return null;
|
|
370
413
|
const e = rawEvent;
|
|
371
|
-
if (typeof e.type !== "string" || !EVENT_TYPES.has(e.type)) return null;
|
|
372
|
-
if (typeof e.timestamp !== "string") return null;
|
|
373
414
|
events.push({
|
|
374
415
|
type: e.type,
|
|
375
416
|
timestamp: e.timestamp,
|
|
@@ -390,20 +431,24 @@ function sanitizeBrowserPayload(raw, redactor = defaultRelayRedactor) {
|
|
|
390
431
|
...typeof e.traceId === "string" && TRACE_ID.test(e.traceId) ? { traceId: e.traceId } : {}
|
|
391
432
|
});
|
|
392
433
|
}
|
|
393
|
-
return {
|
|
434
|
+
return { payload: {
|
|
394
435
|
version: 1,
|
|
395
436
|
...typeof p.sessionId === "string" ? { sessionId: p.sessionId.slice(0, 100) } : {},
|
|
396
|
-
service:
|
|
397
|
-
environment:
|
|
437
|
+
service: service.slice(0, 200),
|
|
438
|
+
environment: environment.slice(0, 100),
|
|
398
439
|
...typeof p.release === "string" ? { release: p.release.slice(0, 200) } : {},
|
|
399
440
|
// @autter/runtime-browser version, for the ingester's compat records.
|
|
400
441
|
...typeof p.sdk === "string" && /^\d{1,6}\.\d{1,6}\.\d{1,6}[0-9A-Za-z.+-]{0,20}$/.test(p.sdk) ? { sdk: p.sdk } : {},
|
|
401
442
|
events
|
|
402
|
-
};
|
|
443
|
+
} };
|
|
403
444
|
}
|
|
445
|
+
var NO_KEY_BODY = {
|
|
446
|
+
error: "relay has no ingest key",
|
|
447
|
+
fix: "set AUTTER_RUNTIME_KEY (a server key, autter_rt_\u2026) where the relay runs"
|
|
448
|
+
};
|
|
404
449
|
var FORWARD_ATTEMPTS = 3;
|
|
405
450
|
var FORWARD_MAX_WAIT_MS = 1e4;
|
|
406
|
-
function forward(payload, opts) {
|
|
451
|
+
function forward(payload, opts, apiKey) {
|
|
407
452
|
const endpoint = (opts.endpoint ?? DEFAULT_ENDPOINT).replace(/\/$/, "");
|
|
408
453
|
const url = `${endpoint}/v1/browser`;
|
|
409
454
|
const compat = opts.compatCheck !== false;
|
|
@@ -416,7 +461,7 @@ function forward(payload, opts) {
|
|
|
416
461
|
method: "POST",
|
|
417
462
|
headers: {
|
|
418
463
|
"content-type": "application/json",
|
|
419
|
-
|
|
464
|
+
...authHeaders(apiKey)
|
|
420
465
|
},
|
|
421
466
|
body,
|
|
422
467
|
signal: AbortSignal.timeout(1e4)
|
|
@@ -433,6 +478,15 @@ function forward(payload, opts) {
|
|
|
433
478
|
await sleep(seconds > 0 ? Math.min(seconds * 1e3, FORWARD_MAX_WAIT_MS) : 1e3 * 2 ** (n - 1));
|
|
434
479
|
return attempt(n + 1);
|
|
435
480
|
}
|
|
481
|
+
if (!response.ok) {
|
|
482
|
+
noteIngestRefusal({
|
|
483
|
+
status: response.status,
|
|
484
|
+
route: "/v1/browser",
|
|
485
|
+
endpoint,
|
|
486
|
+
body: await response.clone().text().catch(() => ""),
|
|
487
|
+
via: "relay"
|
|
488
|
+
});
|
|
489
|
+
}
|
|
436
490
|
if (!compat) return;
|
|
437
491
|
const types = new Set(
|
|
438
492
|
(payload.events ?? []).map((e) => String(e.type))
|
|
@@ -457,10 +511,19 @@ function createBrowserRelayFetchHandler(opts) {
|
|
|
457
511
|
const maxBody = opts.maxBodyBytes ?? DEFAULT_MAX_BODY;
|
|
458
512
|
const redactor = opts.redact === void 0 || opts.redact === true ? defaultRelayRedactor : makeRedactor(opts.redact);
|
|
459
513
|
const limiter = opts.perIpRateLimit === false ? null : new IpWindow(opts.perIpRateLimit ?? 120);
|
|
514
|
+
const apiKey = resolveIngestKey(opts.apiKey);
|
|
515
|
+
if (!apiKey) warnMissingKey("relay");
|
|
516
|
+
else warnKeyKind(apiKey);
|
|
460
517
|
return async (request) => {
|
|
461
518
|
if (request.method !== "POST") {
|
|
462
519
|
return new Response(null, { status: 405 });
|
|
463
520
|
}
|
|
521
|
+
if (!apiKey) {
|
|
522
|
+
return new Response(JSON.stringify(NO_KEY_BODY), {
|
|
523
|
+
status: 500,
|
|
524
|
+
headers: { "content-type": "application/json" }
|
|
525
|
+
});
|
|
526
|
+
}
|
|
464
527
|
if (limiter) {
|
|
465
528
|
const ip = fetchClientKey(request, opts);
|
|
466
529
|
if (!limiter.allow(ip)) {
|
|
@@ -490,13 +553,14 @@ function createBrowserRelayFetchHandler(opts) {
|
|
|
490
553
|
status: 400
|
|
491
554
|
});
|
|
492
555
|
}
|
|
493
|
-
const
|
|
494
|
-
if (!payload) {
|
|
495
|
-
return new Response(JSON.stringify({ error: "invalid payload" }), {
|
|
496
|
-
status: 400
|
|
556
|
+
const checked = checkBrowserPayload(raw, redactor);
|
|
557
|
+
if (!("payload" in checked)) {
|
|
558
|
+
return new Response(JSON.stringify({ error: "invalid payload", issues: checked.issues }), {
|
|
559
|
+
status: 400,
|
|
560
|
+
headers: { "content-type": "application/json" }
|
|
497
561
|
});
|
|
498
562
|
}
|
|
499
|
-
forward(payload, opts);
|
|
563
|
+
forward(checked.payload, opts, apiKey);
|
|
500
564
|
return new Response(null, { status: 202 });
|
|
501
565
|
};
|
|
502
566
|
}
|
|
@@ -513,13 +577,16 @@ function createBrowserRelayHandler(opts) {
|
|
|
513
577
|
res.end();
|
|
514
578
|
}
|
|
515
579
|
}
|
|
580
|
+
const apiKey = resolveIngestKey(opts.apiKey);
|
|
581
|
+
if (!apiKey) warnMissingKey("relay");
|
|
582
|
+
else warnKeyKind(apiKey);
|
|
516
583
|
function handleParsed(raw, res) {
|
|
517
|
-
const
|
|
518
|
-
if (!payload) {
|
|
519
|
-
respond(res, 400, { error: "invalid payload" });
|
|
584
|
+
const checked = checkBrowserPayload(raw, redactor);
|
|
585
|
+
if (!("payload" in checked)) {
|
|
586
|
+
respond(res, 400, { error: "invalid payload", issues: checked.issues });
|
|
520
587
|
return;
|
|
521
588
|
}
|
|
522
|
-
forward(payload, opts);
|
|
589
|
+
forward(checked.payload, opts, apiKey);
|
|
523
590
|
respond(res, 202);
|
|
524
591
|
}
|
|
525
592
|
return (req, res) => {
|
|
@@ -527,6 +594,10 @@ function createBrowserRelayHandler(opts) {
|
|
|
527
594
|
respond(res, 405);
|
|
528
595
|
return;
|
|
529
596
|
}
|
|
597
|
+
if (!apiKey) {
|
|
598
|
+
respond(res, 500, NO_KEY_BODY);
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
530
601
|
if (limiter) {
|
|
531
602
|
const ip = nodeClientKey(req, opts);
|
|
532
603
|
if (!limiter.allow(ip)) {
|
|
@@ -576,13 +647,13 @@ function createBrowserRelayHandler(opts) {
|
|
|
576
647
|
|
|
577
648
|
// src/server.ts
|
|
578
649
|
import { errorMonitor } from "events";
|
|
579
|
-
import { createRequire } from "module";
|
|
580
|
-
import { join } from "path";
|
|
650
|
+
import { createRequire as createRequire2 } from "module";
|
|
651
|
+
import { join as join2 } from "path";
|
|
581
652
|
import { ServerResponse } from "http";
|
|
582
653
|
import { randomUUID } from "crypto";
|
|
583
654
|
import {
|
|
584
|
-
context as
|
|
585
|
-
trace as
|
|
655
|
+
context as context3,
|
|
656
|
+
trace as trace3,
|
|
586
657
|
SpanKind,
|
|
587
658
|
SpanStatusCode,
|
|
588
659
|
TraceFlags
|
|
@@ -828,6 +899,73 @@ var RedactingMetricExporter = class {
|
|
|
828
899
|
}
|
|
829
900
|
};
|
|
830
901
|
|
|
902
|
+
// src/ingest-exporters.ts
|
|
903
|
+
import { ExportResultCode as ExportResultCode2 } from "@opentelemetry/core";
|
|
904
|
+
import {
|
|
905
|
+
AggregationTemporality as AggregationTemporality2
|
|
906
|
+
} from "@opentelemetry/sdk-metrics";
|
|
907
|
+
function refusalOf(result) {
|
|
908
|
+
if (result.code === ExportResultCode2.SUCCESS) return null;
|
|
909
|
+
const error = result.error;
|
|
910
|
+
return typeof error?.code === "number" ? { status: error.code, body: error.data } : null;
|
|
911
|
+
}
|
|
912
|
+
var NO_KEY = {
|
|
913
|
+
code: ExportResultCode2.FAILED,
|
|
914
|
+
error: new Error("no Autter ingest key: not sent (set AUTTER_RUNTIME_KEY)")
|
|
915
|
+
};
|
|
916
|
+
function observe(endpoint, route, callback) {
|
|
917
|
+
return (result) => {
|
|
918
|
+
const refusal = refusalOf(result);
|
|
919
|
+
if (refusal) noteIngestRefusal({ ...refusal, endpoint, route });
|
|
920
|
+
callback(result);
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
var IngestSpanExporter = class {
|
|
924
|
+
constructor(inner, target) {
|
|
925
|
+
this.inner = inner;
|
|
926
|
+
this.target = target;
|
|
927
|
+
}
|
|
928
|
+
inner;
|
|
929
|
+
target;
|
|
930
|
+
export(spans, resultCallback) {
|
|
931
|
+
if (!this.target.hasKey) {
|
|
932
|
+
resultCallback(NO_KEY);
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
this.inner.export(spans, observe(this.target.endpoint, "/v1/traces", resultCallback));
|
|
936
|
+
}
|
|
937
|
+
shutdown() {
|
|
938
|
+
return this.inner.shutdown();
|
|
939
|
+
}
|
|
940
|
+
forceFlush() {
|
|
941
|
+
return this.inner.forceFlush?.() ?? Promise.resolve();
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
var IngestMetricExporter = class {
|
|
945
|
+
constructor(inner, target) {
|
|
946
|
+
this.inner = inner;
|
|
947
|
+
this.target = target;
|
|
948
|
+
}
|
|
949
|
+
inner;
|
|
950
|
+
target;
|
|
951
|
+
export(metrics2, resultCallback) {
|
|
952
|
+
if (!this.target.hasKey) {
|
|
953
|
+
resultCallback(NO_KEY);
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
this.inner.export(metrics2, observe(this.target.endpoint, "/v1/metrics", resultCallback));
|
|
957
|
+
}
|
|
958
|
+
forceFlush() {
|
|
959
|
+
return this.inner.forceFlush();
|
|
960
|
+
}
|
|
961
|
+
shutdown() {
|
|
962
|
+
return this.inner.shutdown();
|
|
963
|
+
}
|
|
964
|
+
selectAggregationTemporality(instrumentType) {
|
|
965
|
+
return this.inner.selectAggregationTemporality ? this.inner.selectAggregationTemporality(instrumentType) : AggregationTemporality2.CUMULATIVE;
|
|
966
|
+
}
|
|
967
|
+
};
|
|
968
|
+
|
|
831
969
|
// src/memory.ts
|
|
832
970
|
import { PerformanceObserver } from "perf_hooks";
|
|
833
971
|
import { getHeapStatistics } from "v8";
|
|
@@ -936,6 +1074,27 @@ function captureAtBoundary(error, state, rule = void 0, attributes) {
|
|
|
936
1074
|
} catch {
|
|
937
1075
|
}
|
|
938
1076
|
}
|
|
1077
|
+
function requestScopeAttributes() {
|
|
1078
|
+
try {
|
|
1079
|
+
const out = {};
|
|
1080
|
+
const state = local.getStore();
|
|
1081
|
+
const active = context.active();
|
|
1082
|
+
const metadata = getRPCMetadata(active);
|
|
1083
|
+
const http = metadata?.type === RPCType.HTTP ? metadata : void 0;
|
|
1084
|
+
const spanAttributes = http?.span?.attributes;
|
|
1085
|
+
const req = state?.req;
|
|
1086
|
+
const nodeRequest = !!req && typeof req === "object" && typeof req.url === "string" && req.url.startsWith("/");
|
|
1087
|
+
const requestId = state?.requestId ?? spanAttributes?.["autter.request.id"];
|
|
1088
|
+
if (typeof requestId === "string" && requestId) out["autter.request.id"] = requestId;
|
|
1089
|
+
const route = http?.route ?? spanAttributes?.["http.route"] ?? (nodeRequest ? expressRouteOf(req) ?? normalizeRoutePath(pathOf(req)) : void 0);
|
|
1090
|
+
if (typeof route === "string" && route) out["http.route"] = route;
|
|
1091
|
+
const method = (nodeRequest ? req.method : void 0) ?? spanAttributes?.["http.request.method"] ?? spanAttributes?.["http.method"];
|
|
1092
|
+
if (typeof method === "string" && method) out["http.request.method"] = method.toUpperCase();
|
|
1093
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
1094
|
+
} catch {
|
|
1095
|
+
return void 0;
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
939
1098
|
function requestStateOf(req) {
|
|
940
1099
|
if (!req || typeof req !== "object") return void 0;
|
|
941
1100
|
return req[REQUEST_STATE];
|
|
@@ -1425,6 +1584,173 @@ function installUnhandledRejectionCapture(capture, mode = unhandledRejectionsMod
|
|
|
1425
1584
|
};
|
|
1426
1585
|
}
|
|
1427
1586
|
|
|
1587
|
+
// src/express-errors.ts
|
|
1588
|
+
import { createRequire } from "module";
|
|
1589
|
+
import { join } from "path";
|
|
1590
|
+
import { context as context2, trace as trace2 } from "@opentelemetry/api";
|
|
1591
|
+
import { Hook } from "require-in-the-middle";
|
|
1592
|
+
var PATCHED = /* @__PURE__ */ Symbol.for("autter.runtime.express.layer");
|
|
1593
|
+
var WRAPPED = /* @__PURE__ */ Symbol.for("autter.runtime.express.next");
|
|
1594
|
+
var ERRORS = /* @__PURE__ */ Symbol.for("autter.runtime.express.errors");
|
|
1595
|
+
var MAX_ERRORS = 8;
|
|
1596
|
+
function noteExpressError(req, error) {
|
|
1597
|
+
if (error === void 0 || error === null || error === false) return;
|
|
1598
|
+
if (error === "route" || error === "router") return;
|
|
1599
|
+
if (!req || typeof req !== "object") return;
|
|
1600
|
+
try {
|
|
1601
|
+
const target = req;
|
|
1602
|
+
let list = target[ERRORS];
|
|
1603
|
+
if (!list) {
|
|
1604
|
+
list = [];
|
|
1605
|
+
target[ERRORS] = list;
|
|
1606
|
+
}
|
|
1607
|
+
if (list.length < MAX_ERRORS && !list.includes(error)) list.push(error);
|
|
1608
|
+
} catch {
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
function wrapNext(req, next) {
|
|
1612
|
+
if (typeof next !== "function") return next;
|
|
1613
|
+
const fn = next;
|
|
1614
|
+
const existing = fn[WRAPPED];
|
|
1615
|
+
if (existing) return existing;
|
|
1616
|
+
const wrapped = function autterExpressNext(...args) {
|
|
1617
|
+
if (args.length > 0) noteExpressError(req, args[0]);
|
|
1618
|
+
return fn.apply(this, args);
|
|
1619
|
+
};
|
|
1620
|
+
try {
|
|
1621
|
+
fn[WRAPPED] = wrapped;
|
|
1622
|
+
} catch {
|
|
1623
|
+
}
|
|
1624
|
+
return wrapped;
|
|
1625
|
+
}
|
|
1626
|
+
function patchLayerPrototype(proto) {
|
|
1627
|
+
if (!proto || typeof proto !== "object") return false;
|
|
1628
|
+
const target = proto;
|
|
1629
|
+
if (target[PATCHED]) return true;
|
|
1630
|
+
const requestName = typeof target.handleRequest === "function" ? "handleRequest" : typeof target.handle_request === "function" ? "handle_request" : null;
|
|
1631
|
+
const errorName = typeof target.handleError === "function" ? "handleError" : typeof target.handle_error === "function" ? "handle_error" : null;
|
|
1632
|
+
if (!requestName || !errorName) return false;
|
|
1633
|
+
const handleRequest = target[requestName];
|
|
1634
|
+
const handleError = target[errorName];
|
|
1635
|
+
target[requestName] = function autterHandleRequest(req, res, next) {
|
|
1636
|
+
let wrapped = next;
|
|
1637
|
+
try {
|
|
1638
|
+
wrapped = wrapNext(req, next);
|
|
1639
|
+
} catch {
|
|
1640
|
+
wrapped = next;
|
|
1641
|
+
}
|
|
1642
|
+
return handleRequest.call(this, req, res, wrapped);
|
|
1643
|
+
};
|
|
1644
|
+
target[errorName] = function autterHandleError(error, req, res, next) {
|
|
1645
|
+
let wrapped = next;
|
|
1646
|
+
try {
|
|
1647
|
+
noteExpressError(req, error);
|
|
1648
|
+
wrapped = wrapNext(req, next);
|
|
1649
|
+
} catch {
|
|
1650
|
+
wrapped = next;
|
|
1651
|
+
}
|
|
1652
|
+
return handleError.call(this, error, req, res, wrapped);
|
|
1653
|
+
};
|
|
1654
|
+
try {
|
|
1655
|
+
Object.defineProperty(target, PATCHED, { value: true });
|
|
1656
|
+
} catch {
|
|
1657
|
+
target[PATCHED] = true;
|
|
1658
|
+
}
|
|
1659
|
+
return true;
|
|
1660
|
+
}
|
|
1661
|
+
var LAYER_FILES = ["express/lib/router/layer.js", "router/lib/layer.js"];
|
|
1662
|
+
function patchLayerModule(exports) {
|
|
1663
|
+
try {
|
|
1664
|
+
const Layer = exports;
|
|
1665
|
+
if (typeof Layer === "function" && patchLayerPrototype(Layer.prototype))
|
|
1666
|
+
debugLog("express: error capture installed");
|
|
1667
|
+
} catch {
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
function scanModuleCache() {
|
|
1671
|
+
try {
|
|
1672
|
+
const cache = createRequire(join(process.cwd(), "autter-runtime-express.cjs")).cache;
|
|
1673
|
+
for (const [key, entry] of Object.entries(cache)) {
|
|
1674
|
+
const path = key.replace(/\\/g, "/");
|
|
1675
|
+
if (LAYER_FILES.some((file) => path.endsWith(`/node_modules/${file}`)))
|
|
1676
|
+
patchLayerModule(entry?.exports);
|
|
1677
|
+
}
|
|
1678
|
+
} catch {
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
var installed = false;
|
|
1682
|
+
function installExpressErrorCapture() {
|
|
1683
|
+
if (installed) return;
|
|
1684
|
+
installed = true;
|
|
1685
|
+
scanModuleCache();
|
|
1686
|
+
try {
|
|
1687
|
+
new Hook(["express", "router"], { internals: true }, (exports, name) => {
|
|
1688
|
+
const file = name.replace(/\\/g, "/");
|
|
1689
|
+
if (LAYER_FILES.includes(file)) patchLayerModule(exports);
|
|
1690
|
+
return exports;
|
|
1691
|
+
});
|
|
1692
|
+
} catch {
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
function patchFromRequest(req) {
|
|
1696
|
+
try {
|
|
1697
|
+
const app = req?.app;
|
|
1698
|
+
if (!app || typeof app !== "function" && typeof app !== "object") return;
|
|
1699
|
+
const router = app._router ?? app.router;
|
|
1700
|
+
const layer = router?.stack?.[0];
|
|
1701
|
+
if (layer && typeof layer === "object" && patchLayerPrototype(Object.getPrototypeOf(layer)))
|
|
1702
|
+
debugLog("express: error capture installed (from a request)");
|
|
1703
|
+
} catch {
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
function declaredStatus(error) {
|
|
1707
|
+
if (!error || typeof error !== "object") return void 0;
|
|
1708
|
+
try {
|
|
1709
|
+
const value = error.status ?? error.statusCode;
|
|
1710
|
+
const status = typeof value === "string" ? Number(value) : value;
|
|
1711
|
+
return typeof status === "number" && Number.isInteger(status) && status >= 400 && status < 600 ? status : void 0;
|
|
1712
|
+
} catch {
|
|
1713
|
+
return void 0;
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
function watchExpressResponse(span, res, enabled) {
|
|
1717
|
+
const req = res.req;
|
|
1718
|
+
if (!req) return;
|
|
1719
|
+
const ctx = context2.active();
|
|
1720
|
+
let done = false;
|
|
1721
|
+
const settle = (finished) => {
|
|
1722
|
+
if (done) return;
|
|
1723
|
+
done = true;
|
|
1724
|
+
try {
|
|
1725
|
+
const errors = req[ERRORS];
|
|
1726
|
+
if (!errors?.length) {
|
|
1727
|
+
patchFromRequest(req);
|
|
1728
|
+
return;
|
|
1729
|
+
}
|
|
1730
|
+
req[ERRORS] = void 0;
|
|
1731
|
+
if (!enabled()) return;
|
|
1732
|
+
if (finished && !(res.statusCode >= 500)) return;
|
|
1733
|
+
if (errors.some((error2) => isCaptured(error2))) return;
|
|
1734
|
+
const error = errors.find((candidate) => {
|
|
1735
|
+
const status = declaredStatus(candidate);
|
|
1736
|
+
return status === void 0 || status >= 500;
|
|
1737
|
+
});
|
|
1738
|
+
if (error === void 0) return;
|
|
1739
|
+
const state = requestStateOf(req);
|
|
1740
|
+
if (state && !state.sealed) noteOperationError(error, false, state);
|
|
1741
|
+
const run = () => captureAtBoundary(error, state, true);
|
|
1742
|
+
if (span.isRecording()) context2.with(trace2.setSpan(ctx, span), run);
|
|
1743
|
+
else context2.with(ctx, run);
|
|
1744
|
+
} catch {
|
|
1745
|
+
}
|
|
1746
|
+
};
|
|
1747
|
+
try {
|
|
1748
|
+
res.prependListener("finish", () => settle(true));
|
|
1749
|
+
res.prependListener("close", () => settle(false));
|
|
1750
|
+
} catch {
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1428
1754
|
// src/route-label.ts
|
|
1429
1755
|
import { getRPCMetadata as getRPCMetadata2, RPCType as RPCType2 } from "@opentelemetry/core";
|
|
1430
1756
|
var ours = /* @__PURE__ */ new WeakMap();
|
|
@@ -1596,7 +1922,7 @@ var ErrorTraceRetentionProcessor = class {
|
|
|
1596
1922
|
}
|
|
1597
1923
|
/** Promote the active trace, if any — called on captured errors. */
|
|
1598
1924
|
retainActiveTrace() {
|
|
1599
|
-
const active =
|
|
1925
|
+
const active = trace3.getActiveSpan()?.spanContext();
|
|
1600
1926
|
if (!active || (active.traceFlags & TraceFlags.SAMPLED) !== 0) return;
|
|
1601
1927
|
const entry = this.entryFor(active.traceId);
|
|
1602
1928
|
if (entry.retained) return;
|
|
@@ -1709,8 +2035,8 @@ async function runLlmSpan(tracer, info, fn) {
|
|
|
1709
2035
|
setAttributes: (attributes) => span.setAttributes(S.redactor(attributes))
|
|
1710
2036
|
};
|
|
1711
2037
|
try {
|
|
1712
|
-
const result = await
|
|
1713
|
-
|
|
2038
|
+
const result = await context3.with(
|
|
2039
|
+
trace3.setSpan(context3.active(), span),
|
|
1714
2040
|
() => fn(handle)
|
|
1715
2041
|
);
|
|
1716
2042
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
@@ -1753,8 +2079,8 @@ async function runWithSpan(tracer, name, fn, attributes, links) {
|
|
|
1753
2079
|
...links?.length ? { links } : {}
|
|
1754
2080
|
});
|
|
1755
2081
|
try {
|
|
1756
|
-
const result = await
|
|
1757
|
-
|
|
2082
|
+
const result = await context3.with(
|
|
2083
|
+
trace3.setSpan(context3.active(), span),
|
|
1758
2084
|
fn
|
|
1759
2085
|
);
|
|
1760
2086
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
@@ -1784,7 +2110,7 @@ function redactWithActive(attributes) {
|
|
|
1784
2110
|
}
|
|
1785
2111
|
function patchLoadedHttpModules() {
|
|
1786
2112
|
try {
|
|
1787
|
-
const load =
|
|
2113
|
+
const load = createRequire2(join2(process.cwd(), "autter-runtime-http.cjs"));
|
|
1788
2114
|
load("http");
|
|
1789
2115
|
load("https");
|
|
1790
2116
|
} catch {
|
|
@@ -1793,7 +2119,7 @@ function patchLoadedHttpModules() {
|
|
|
1793
2119
|
var METRIC_ROUTE_ATTR = "autter.metric_has_route";
|
|
1794
2120
|
function captureRequestRoute(span, response) {
|
|
1795
2121
|
if (!(response instanceof ServerResponse)) return;
|
|
1796
|
-
const rpcMetadata = getRPCMetadata3(
|
|
2122
|
+
const rpcMetadata = getRPCMetadata3(context3.active());
|
|
1797
2123
|
if (rpcMetadata?.type !== RPCType3.HTTP) return;
|
|
1798
2124
|
let failed = false;
|
|
1799
2125
|
response.on(errorMonitor, () => {
|
|
@@ -1809,6 +2135,7 @@ function captureRequestRoute(span, response) {
|
|
|
1809
2135
|
setRoute();
|
|
1810
2136
|
if (rpcMetadata.route && !failed) span.setAttribute(METRIC_ROUTE_ATTR, true);
|
|
1811
2137
|
});
|
|
2138
|
+
if (S.expressErrors) watchExpressResponse(span, response, () => S.expressErrors === true);
|
|
1812
2139
|
if (S.hookRequests) startHookRequest(response);
|
|
1813
2140
|
}
|
|
1814
2141
|
function structuredErrorAttributes(error) {
|
|
@@ -1830,12 +2157,14 @@ function initAutterServer(options) {
|
|
|
1830
2157
|
/\/$/,
|
|
1831
2158
|
""
|
|
1832
2159
|
);
|
|
1833
|
-
const
|
|
2160
|
+
const apiKey = resolveIngestKey(options.apiKey);
|
|
2161
|
+
const headers = authHeaders(apiKey);
|
|
2162
|
+
const ingestTarget = { endpoint, hasKey: apiKey !== null };
|
|
1834
2163
|
const redactor = makeRedactor(options.redactAttributes ?? true);
|
|
1835
2164
|
const queryPolicy = makeUrlQueryPolicy(options.keepQueryParams);
|
|
1836
2165
|
const traceExporter = () => new CountingExporter(
|
|
1837
2166
|
new RedactingSpanExporter(
|
|
1838
|
-
new OTLPTraceExporter({ url: `${endpoint}/v1/traces`, headers }),
|
|
2167
|
+
new IngestSpanExporter(new OTLPTraceExporter({ url: `${endpoint}/v1/traces`, headers }), ingestTarget),
|
|
1839
2168
|
() => redactor,
|
|
1840
2169
|
queryPolicy
|
|
1841
2170
|
)
|
|
@@ -1843,6 +2172,8 @@ function initAutterServer(options) {
|
|
|
1843
2172
|
const environment = options.environment ?? process.env.NODE_ENV ?? "production";
|
|
1844
2173
|
if (isDebugEnabled() || options.debug === true) setDebugMode(true);
|
|
1845
2174
|
debugLog(`initialising service=${options.service} endpoint=${endpoint}`);
|
|
2175
|
+
if (apiKey === null) warnMissingKey("server", options.service);
|
|
2176
|
+
else warnKeyKind(apiKey);
|
|
1846
2177
|
S.redactor = redactor;
|
|
1847
2178
|
const distro = options.distro ?? SDK_IDENTITY;
|
|
1848
2179
|
configureCompatCheck({ endpoint, enabled: options.compatCheck !== false, sdk: distro });
|
|
@@ -1891,7 +2222,7 @@ function initAutterServer(options) {
|
|
|
1891
2222
|
const mainSpanProcessor = new BatchSpanProcessor(traceExporter());
|
|
1892
2223
|
const metricReader = new PeriodicExportingMetricReader({
|
|
1893
2224
|
exporter: new RedactingMetricExporter(
|
|
1894
|
-
new OTLPMetricExporter({
|
|
2225
|
+
new IngestMetricExporter(new OTLPMetricExporter({
|
|
1895
2226
|
url: `${endpoint}/v1/metrics`,
|
|
1896
2227
|
headers,
|
|
1897
2228
|
// Deltas, not lifetime totals: the ingester SUMs data points
|
|
@@ -1899,7 +2230,7 @@ function initAutterServer(options) {
|
|
|
1899
2230
|
// temporality would re-count every past request on each
|
|
1900
2231
|
// 60 s export.
|
|
1901
2232
|
temporalityPreference: AggregationTemporalityPreference.DELTA
|
|
1902
|
-
}),
|
|
2233
|
+
}), ingestTarget),
|
|
1903
2234
|
() => redactor
|
|
1904
2235
|
),
|
|
1905
2236
|
exportIntervalMillis: options.metricIntervalMs ?? 6e4
|
|
@@ -1961,9 +2292,11 @@ function initAutterServer(options) {
|
|
|
1961
2292
|
const fingerprint = fingerprintEventAttributes(split.fingerprint, redactor.text);
|
|
1962
2293
|
if (fingerprint["autter.fingerprint"]) noteCompatFeature("fingerprint_override");
|
|
1963
2294
|
const redacted = redactor(split.attributes);
|
|
1964
|
-
const
|
|
1965
|
-
const
|
|
2295
|
+
const crash = attributes?.["autter.unhandled"] === true;
|
|
2296
|
+
const activeSpan = trace3.getActiveSpan();
|
|
2297
|
+
const reuseActive = !crash && activeSpan?.isRecording() === true;
|
|
1966
2298
|
const span = reuseActive ? activeSpan : errorTracer.startSpan(isErr ? error.name : "Error");
|
|
2299
|
+
const scope = reuseActive ? void 0 : requestScopeAttributes();
|
|
1967
2300
|
const structured = structuredErrorAttributes(error);
|
|
1968
2301
|
const causes = errorAttributes(error);
|
|
1969
2302
|
const declared = {
|
|
@@ -1972,6 +2305,7 @@ function initAutterServer(options) {
|
|
|
1972
2305
|
};
|
|
1973
2306
|
const requestId = currentOperation()?.requestId;
|
|
1974
2307
|
span.setAttributes({
|
|
2308
|
+
...scope,
|
|
1975
2309
|
"autter.severity": "error",
|
|
1976
2310
|
...redacted,
|
|
1977
2311
|
...structured,
|
|
@@ -2028,7 +2362,7 @@ function initAutterServer(options) {
|
|
|
2028
2362
|
if (!errorFilter({ type: "OutcomeFailure", message: `${name}: ${message}` })) return;
|
|
2029
2363
|
errorTraceBuffer?.retainActiveTrace();
|
|
2030
2364
|
telemetryStats.markCaptured();
|
|
2031
|
-
const activeSpan =
|
|
2365
|
+
const activeSpan = trace3.getActiveSpan();
|
|
2032
2366
|
const reuseActive = activeSpan?.isRecording() === true;
|
|
2033
2367
|
const span = reuseActive ? activeSpan : errorTracer.startSpan("OutcomeFailure");
|
|
2034
2368
|
const safeOutcome = redactor({ "autter.outcome.name": name.slice(0, 200), "autter.outcome.message": message.slice(0, 1e3) });
|
|
@@ -2057,7 +2391,7 @@ function initAutterServer(options) {
|
|
|
2057
2391
|
const split = splitFingerprint(attributes);
|
|
2058
2392
|
const fingerprint = fingerprintEventAttributes(split.fingerprint, redactor.text);
|
|
2059
2393
|
const redacted = redactor(split.attributes);
|
|
2060
|
-
const activeSpan =
|
|
2394
|
+
const activeSpan = trace3.getActiveSpan();
|
|
2061
2395
|
const reuseActive = activeSpan?.isRecording() === true;
|
|
2062
2396
|
const span = reuseActive ? activeSpan : errorTracer.startSpan(isErr ? error.name : "Error");
|
|
2063
2397
|
markCaptured(error);
|
|
@@ -2076,7 +2410,7 @@ function initAutterServer(options) {
|
|
|
2076
2410
|
}
|
|
2077
2411
|
configureRuntimeLogger({
|
|
2078
2412
|
endpoint,
|
|
2079
|
-
apiKey:
|
|
2413
|
+
apiKey: apiKey ?? "",
|
|
2080
2414
|
service: options.service,
|
|
2081
2415
|
environment,
|
|
2082
2416
|
distro,
|
|
@@ -2087,6 +2421,8 @@ function initAutterServer(options) {
|
|
|
2087
2421
|
reportOutcome: reportOutcome2
|
|
2088
2422
|
});
|
|
2089
2423
|
S.hookRequests = options.logging?.requests === true;
|
|
2424
|
+
S.expressErrors = options.captureExpressErrors !== false;
|
|
2425
|
+
if (S.expressErrors) installExpressErrorCapture();
|
|
2090
2426
|
S.handled = captureHandled;
|
|
2091
2427
|
startLoggedErrorCapture(options.captureLoggedErrors);
|
|
2092
2428
|
let onCrash = null;
|
|
@@ -2145,6 +2481,7 @@ function initAutterServer(options) {
|
|
|
2145
2481
|
S.alwaysOnProvider = null;
|
|
2146
2482
|
S.handled = null;
|
|
2147
2483
|
S.hookRequests = false;
|
|
2484
|
+
S.expressErrors = false;
|
|
2148
2485
|
S.redactor = makeRedactor(true);
|
|
2149
2486
|
}
|
|
2150
2487
|
autoFlushHandle?.dispose();
|
|
@@ -2173,7 +2510,7 @@ function captureException(error, attributes) {
|
|
|
2173
2510
|
const split = splitFingerprint(attributes);
|
|
2174
2511
|
const fingerprint = fingerprintEventAttributes(split.fingerprint, S.redactor.text);
|
|
2175
2512
|
notifyException(error, { ...split.attributes, ...fingerprint });
|
|
2176
|
-
const span =
|
|
2513
|
+
const span = trace3.getTracer("autter-errors").startSpan(isError(error) ? error.name : "Error", {
|
|
2177
2514
|
attributes: { ...S.redactor(split.attributes), ...fingerprint }
|
|
2178
2515
|
});
|
|
2179
2516
|
recordError(span, error);
|
|
@@ -2195,7 +2532,7 @@ function captureHandledError(error, attributes, severity) {
|
|
|
2195
2532
|
markCaptured(error);
|
|
2196
2533
|
const split = splitFingerprint(attributes);
|
|
2197
2534
|
notifyException(error, { ...split.attributes, "autter.severity": severity });
|
|
2198
|
-
const span =
|
|
2535
|
+
const span = trace3.getTracer("autter-errors").startSpan(isError(error) ? error.name : "Error");
|
|
2199
2536
|
span.addEvent("exception", {
|
|
2200
2537
|
...S.redactor(split.attributes),
|
|
2201
2538
|
"exception.type": isError(error) ? error.name : "Error",
|
|
@@ -2213,13 +2550,13 @@ function serverActive() {
|
|
|
2213
2550
|
setRequestExceptionCapturer((error, attributes) => captureException(error, attributes));
|
|
2214
2551
|
setHandledCapture(captureHandledError);
|
|
2215
2552
|
setRequestSpanAnnotator((attributes) => {
|
|
2216
|
-
const span =
|
|
2553
|
+
const span = trace3.getActiveSpan();
|
|
2217
2554
|
if (span?.isRecording()) span.setAttributes(S.redactor(splitFingerprint(attributes).attributes));
|
|
2218
2555
|
});
|
|
2219
2556
|
function withProcessSpan(name, fn, attributes) {
|
|
2220
2557
|
if (S.active) return S.active.withProcessSpan(name, fn, attributes);
|
|
2221
2558
|
return runWithSpan(
|
|
2222
|
-
|
|
2559
|
+
trace3.getTracer("autter-processes"),
|
|
2223
2560
|
name,
|
|
2224
2561
|
fn,
|
|
2225
2562
|
S.redactor(attributes)
|
|
@@ -2227,14 +2564,14 @@ function withProcessSpan(name, fn, attributes) {
|
|
|
2227
2564
|
}
|
|
2228
2565
|
function withLlmCall(info, fn) {
|
|
2229
2566
|
if (S.active) return S.active.withLlmCall(info, fn);
|
|
2230
|
-
return runLlmSpan(
|
|
2567
|
+
return runLlmSpan(trace3.getTracer("autter-llm"), info, fn);
|
|
2231
2568
|
}
|
|
2232
2569
|
function trackLlmCall(call) {
|
|
2233
2570
|
if (S.active) {
|
|
2234
2571
|
S.active.trackLlmCall(call);
|
|
2235
2572
|
return;
|
|
2236
2573
|
}
|
|
2237
|
-
recordLlmCall(
|
|
2574
|
+
recordLlmCall(trace3.getTracer("autter-llm"), call);
|
|
2238
2575
|
}
|
|
2239
2576
|
function captureMessage(message, severity = "warning", attributes) {
|
|
2240
2577
|
if (S.active) {
|
|
@@ -2242,7 +2579,7 @@ function captureMessage(message, severity = "warning", attributes) {
|
|
|
2242
2579
|
return;
|
|
2243
2580
|
}
|
|
2244
2581
|
const safeMessage = S.redactor.text(message);
|
|
2245
|
-
const span =
|
|
2582
|
+
const span = trace3.getTracer("autter-errors").startSpan("Message", {
|
|
2246
2583
|
attributes: { "autter.severity": severity, ...S.redactor(attributes) }
|
|
2247
2584
|
});
|
|
2248
2585
|
span.addEvent("exception", {
|
|
@@ -2256,7 +2593,7 @@ function captureMessage(message, severity = "warning", attributes) {
|
|
|
2256
2593
|
}
|
|
2257
2594
|
function reportOutcome(name, message, attributes) {
|
|
2258
2595
|
if (S.active) return S.active.reportOutcome(name, message, attributes);
|
|
2259
|
-
const span =
|
|
2596
|
+
const span = trace3.getTracer("autter-outcomes").startSpan("OutcomeFailure");
|
|
2260
2597
|
const safeOutcome = redactAttributes({ "autter.outcome.name": name.slice(0, 200), "autter.outcome.message": message.slice(0, 1e3) });
|
|
2261
2598
|
const safeName = String(safeOutcome["autter.outcome.name"] ?? "operation");
|
|
2262
2599
|
const safeMessage = String(safeOutcome["autter.outcome.message"] ?? "failed");
|
|
@@ -2277,7 +2614,7 @@ function makeSafeCapture(options) {
|
|
|
2277
2614
|
};
|
|
2278
2615
|
}
|
|
2279
2616
|
function alwaysOnTracer(name) {
|
|
2280
|
-
return S.alwaysOnProvider ? S.alwaysOnProvider.getTracer(name) :
|
|
2617
|
+
return S.alwaysOnProvider ? S.alwaysOnProvider.getTracer(name) : trace3.getTracer(name);
|
|
2281
2618
|
}
|
|
2282
2619
|
function autterLlmTracer() {
|
|
2283
2620
|
return alwaysOnTracer("autter-llm");
|
|
@@ -2297,7 +2634,7 @@ async function emitLlmSelftestTrace() {
|
|
|
2297
2634
|
attributes: { "autter.selftest": true }
|
|
2298
2635
|
},
|
|
2299
2636
|
(llm) => {
|
|
2300
|
-
traceId =
|
|
2637
|
+
traceId = trace3.getActiveSpan()?.spanContext().traceId ?? "";
|
|
2301
2638
|
llm.setUsage({ inputTokens: 1, outputTokens: 1 });
|
|
2302
2639
|
llm.setCost(0);
|
|
2303
2640
|
}
|
|
@@ -2618,7 +2955,7 @@ function autterKoa(options = {}) {
|
|
|
2618
2955
|
// src/logging-only.ts
|
|
2619
2956
|
import {
|
|
2620
2957
|
SpanStatusCode as SpanStatusCode3,
|
|
2621
|
-
trace as
|
|
2958
|
+
trace as trace4
|
|
2622
2959
|
} from "@opentelemetry/api";
|
|
2623
2960
|
var L = sharedSlot("logging", () => ({ active: null }));
|
|
2624
2961
|
function initAutterLogging(options) {
|
|
@@ -2653,7 +2990,7 @@ function initAutterLogging(options) {
|
|
|
2653
2990
|
const split = splitFingerprint(attributes);
|
|
2654
2991
|
const fingerprint = fingerprintEventAttributes(split.fingerprint, redact.text);
|
|
2655
2992
|
const redacted = redact(split.attributes);
|
|
2656
|
-
const span =
|
|
2993
|
+
const span = trace4.getActiveSpan();
|
|
2657
2994
|
if (mode === "auto" && span?.isRecording()) {
|
|
2658
2995
|
noteOperationError(error);
|
|
2659
2996
|
notifyException(error, { ...redacted, ...fingerprint });
|
|
@@ -2694,7 +3031,7 @@ function initAutterLogging(options) {
|
|
|
2694
3031
|
const fingerprint = fingerprintEventAttributes(split.fingerprint, redact.text);
|
|
2695
3032
|
const redacted = redact(split.attributes);
|
|
2696
3033
|
notifyException(error, { ...redacted, ...fingerprint, "autter.severity": severity });
|
|
2697
|
-
const span =
|
|
3034
|
+
const span = trace4.getActiveSpan();
|
|
2698
3035
|
if (mode === "auto" && span?.isRecording()) {
|
|
2699
3036
|
span.addEvent("exception", {
|
|
2700
3037
|
...redacted,
|
|
@@ -2712,7 +3049,9 @@ function initAutterLogging(options) {
|
|
|
2712
3049
|
const captured = /* @__PURE__ */ new WeakSet();
|
|
2713
3050
|
configureRuntimeLogger({
|
|
2714
3051
|
endpoint,
|
|
2715
|
-
|
|
3052
|
+
// Normalised ("undefined"/empty is no key), no env fallback: without
|
|
3053
|
+
// an apiKey this mode logs locally only, by design.
|
|
3054
|
+
apiKey: resolveIngestKey(options.apiKey, {}) ?? "",
|
|
2716
3055
|
service: options.service,
|
|
2717
3056
|
environment,
|
|
2718
3057
|
...options.release ? { release: options.release } : {},
|
|
@@ -2872,6 +3211,7 @@ export {
|
|
|
2872
3211
|
captureException,
|
|
2873
3212
|
captureMessage,
|
|
2874
3213
|
captureRequestError,
|
|
3214
|
+
checkBrowserPayload,
|
|
2875
3215
|
consoleSink,
|
|
2876
3216
|
createBrowserRelayFetchHandler,
|
|
2877
3217
|
createBrowserRelayHandler,
|
|
@@ -2899,6 +3239,7 @@ export {
|
|
|
2899
3239
|
reportOutcome,
|
|
2900
3240
|
runDoctor,
|
|
2901
3241
|
runInBackground,
|
|
3242
|
+
runVerify,
|
|
2902
3243
|
runtimeContext,
|
|
2903
3244
|
runtimeLogStats,
|
|
2904
3245
|
runtimeLogger,
|