autotel-devtools 5.1.0 → 6.0.1
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 -3
- package/dist/cli.cjs +121 -26
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +121 -26
- package/dist/cli.js.map +1 -1
- package/dist/{error-aggregator-BkO0l8ak.d.ts → error-aggregator-CAk_pt3Z.d.ts} +1 -1
- package/dist/{error-aggregator-CtZmjm-k.d.cts → error-aggregator-CbLiuot4.d.cts} +1 -1
- package/dist/{exporter-qIQPDw29.d.cts → exporter-DjLkU621.d.cts} +17 -0
- package/dist/{exporter-qIQPDw29.d.ts → exporter-DjLkU621.d.ts} +17 -0
- package/dist/genai/index.d.cts +9 -0
- package/dist/genai/index.d.ts +9 -0
- package/dist/index.cjs +83 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +83 -15
- package/dist/index.js.map +1 -1
- package/dist/server/exporter.cjs +12 -1
- package/dist/server/exporter.cjs.map +1 -1
- package/dist/server/exporter.d.cts +1 -1
- package/dist/server/exporter.d.ts +1 -1
- package/dist/server/exporter.js +12 -1
- package/dist/server/exporter.js.map +1 -1
- package/dist/server/index.cjs +35 -3
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +3 -3
- package/dist/server/index.d.ts +3 -3
- package/dist/server/index.js +35 -3
- package/dist/server/index.js.map +1 -1
- package/dist/widget.global.js +13 -2
- package/package.json +12 -14
- package/skills/autotel-devtools/SKILL.md +5 -3
package/dist/index.cjs
CHANGED
|
@@ -367,12 +367,17 @@ var DevtoolsServer = class {
|
|
|
367
367
|
limits;
|
|
368
368
|
verbose;
|
|
369
369
|
_port;
|
|
370
|
+
onData;
|
|
370
371
|
constructor(options = {}) {
|
|
371
372
|
this.limits = resolveTelemetryLimits(options);
|
|
372
373
|
this.verbose = options.verbose ?? false;
|
|
373
374
|
this._port = options.port ?? 4318;
|
|
375
|
+
this.onData = options.onData;
|
|
374
376
|
this.httpServer = options.server ?? http.createServer();
|
|
375
377
|
this.wss = new ws.WebSocketServer({ server: this.httpServer, path: options.path ?? "/ws" });
|
|
378
|
+
this.wss.on("error", (err) => {
|
|
379
|
+
if (this.httpServer.listening) throw err;
|
|
380
|
+
});
|
|
376
381
|
this.wss.on("connection", (ws) => {
|
|
377
382
|
this.clients.add(ws);
|
|
378
383
|
this.log(`Client connected (${this.clients.size} total)`);
|
|
@@ -464,6 +469,12 @@ var DevtoolsServer = class {
|
|
|
464
469
|
client.send(msg);
|
|
465
470
|
}
|
|
466
471
|
}
|
|
472
|
+
if (this.onData) {
|
|
473
|
+
try {
|
|
474
|
+
this.onData(data);
|
|
475
|
+
} catch {
|
|
476
|
+
}
|
|
477
|
+
}
|
|
467
478
|
}
|
|
468
479
|
log(message) {
|
|
469
480
|
if (this.verbose) console.log(`[autotel-devtools] ${message}`);
|
|
@@ -517,7 +528,10 @@ function flattenAttributes(attrs) {
|
|
|
517
528
|
}
|
|
518
529
|
function nanoToMs(nano) {
|
|
519
530
|
if (!nano) return 0;
|
|
520
|
-
|
|
531
|
+
const ns = BigInt(nano);
|
|
532
|
+
const ms = ns / 1000000n;
|
|
533
|
+
const remNs = ns % 1000000n;
|
|
534
|
+
return Number(ms) + Number(remNs) / 1e6;
|
|
521
535
|
}
|
|
522
536
|
var SPAN_KIND_MAP = {
|
|
523
537
|
0: "INTERNAL",
|
|
@@ -555,6 +569,7 @@ function parseOtlpTraces(payload) {
|
|
|
555
569
|
const service = String(resourceAttrs["service.name"] || "unknown");
|
|
556
570
|
const scopeSpans = rs.scopeSpans || [];
|
|
557
571
|
for (const ss of scopeSpans) {
|
|
572
|
+
const scope = ss.scope?.name ? { name: ss.scope.name, version: ss.scope.version || void 0 } : void 0;
|
|
558
573
|
for (const span of ss.spans || []) {
|
|
559
574
|
const traceId = normalizeHexId(span.traceId);
|
|
560
575
|
if (!traceId) continue;
|
|
@@ -579,7 +594,13 @@ function parseOtlpTraces(payload) {
|
|
|
579
594
|
name: e.name || "",
|
|
580
595
|
timestamp: nanoToMs(e.timeUnixNano),
|
|
581
596
|
attributes: flattenAttributes(e.attributes)
|
|
582
|
-
}))
|
|
597
|
+
})),
|
|
598
|
+
links: (span.links || []).map((l) => ({
|
|
599
|
+
traceId: normalizeHexId(l.traceId),
|
|
600
|
+
spanId: normalizeHexId(l.spanId),
|
|
601
|
+
attributes: flattenAttributes(l.attributes)
|
|
602
|
+
})),
|
|
603
|
+
scope
|
|
583
604
|
};
|
|
584
605
|
const existing = traceMap.get(traceId);
|
|
585
606
|
if (existing) {
|
|
@@ -1018,43 +1039,79 @@ function attachDevtoolsRoutes(httpServer, devtools) {
|
|
|
1018
1039
|
});
|
|
1019
1040
|
}
|
|
1020
1041
|
var LOOPBACK = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1"]);
|
|
1042
|
+
var DEFAULT_MAX_PORT_TRIES = 20;
|
|
1021
1043
|
function formatAddress(host, port) {
|
|
1022
1044
|
return host.includes(":") ? `[${host}]:${port}` : `${host}:${port}`;
|
|
1023
1045
|
}
|
|
1024
1046
|
function listenLoopbackDualStack(args) {
|
|
1025
|
-
const { primary, port, host, attachSecondary } = args;
|
|
1047
|
+
const { primary, port, host, attachSecondary, maxTries } = args;
|
|
1048
|
+
const maxAttempts = Math.max(1, maxTries ?? DEFAULT_MAX_PORT_TRIES);
|
|
1026
1049
|
let sibling;
|
|
1027
1050
|
const ready = new Promise(
|
|
1028
|
-
(resolve2) => {
|
|
1051
|
+
(resolve2, reject) => {
|
|
1029
1052
|
const addresses = [];
|
|
1030
1053
|
const warnings = [];
|
|
1031
1054
|
const primaryHost = host === "localhost" ? "127.0.0.1" : host;
|
|
1032
|
-
|
|
1055
|
+
let candidate = port;
|
|
1056
|
+
let attempt = 0;
|
|
1057
|
+
const bindFailed = (atPort, msg) => reject(
|
|
1058
|
+
new Error(`could not bind ${formatAddress(primaryHost, atPort)}: ${msg}`)
|
|
1059
|
+
);
|
|
1060
|
+
const onError = (e) => {
|
|
1061
|
+
if (e.code !== "EADDRINUSE") return bindFailed(candidate, e.message);
|
|
1062
|
+
if (++attempt >= maxAttempts) {
|
|
1063
|
+
reject(
|
|
1064
|
+
new Error(
|
|
1065
|
+
`could not bind ${formatAddress(primaryHost, port)}: ${maxAttempts} consecutive ports in use`
|
|
1066
|
+
)
|
|
1067
|
+
);
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
candidate++;
|
|
1071
|
+
listen();
|
|
1072
|
+
};
|
|
1073
|
+
const onListening = () => {
|
|
1074
|
+
primary.removeListener("error", onError);
|
|
1075
|
+
if (candidate !== port) {
|
|
1076
|
+
warnings.push(`port ${port} was busy; using ${candidate} instead`);
|
|
1077
|
+
}
|
|
1033
1078
|
const addr = primary.address();
|
|
1034
|
-
const resolvedPort = addr && typeof addr === "object" ? addr.port :
|
|
1079
|
+
const resolvedPort = addr && typeof addr === "object" ? addr.port : candidate;
|
|
1035
1080
|
addresses.push(formatAddress(primaryHost, resolvedPort));
|
|
1036
1081
|
if (!LOOPBACK.has(host)) {
|
|
1037
|
-
resolve2({ addresses, warnings });
|
|
1082
|
+
resolve2({ addresses, port: resolvedPort, warnings });
|
|
1038
1083
|
return;
|
|
1039
1084
|
}
|
|
1040
1085
|
const siblingHost = primaryHost === "::1" ? "127.0.0.1" : "::1";
|
|
1041
1086
|
const s = http.createServer();
|
|
1042
1087
|
attachSecondary(s);
|
|
1043
|
-
const
|
|
1088
|
+
const onSiblingError = (se) => {
|
|
1044
1089
|
s.close();
|
|
1045
1090
|
warnings.push(
|
|
1046
|
-
`could not also bind ${formatAddress(siblingHost, resolvedPort)} (${
|
|
1091
|
+
`could not also bind ${formatAddress(siblingHost, resolvedPort)} (${se.message}); clients using the ${siblingHost === "::1" ? "IPv6" : "IPv4"} form of "localhost" may not connect.`
|
|
1047
1092
|
);
|
|
1048
|
-
resolve2({ addresses, warnings });
|
|
1093
|
+
resolve2({ addresses, port: resolvedPort, warnings });
|
|
1049
1094
|
};
|
|
1050
|
-
s.once("error",
|
|
1095
|
+
s.once("error", onSiblingError);
|
|
1051
1096
|
s.listen(resolvedPort, siblingHost, () => {
|
|
1052
|
-
s.off("error",
|
|
1097
|
+
s.off("error", onSiblingError);
|
|
1053
1098
|
sibling = s;
|
|
1054
1099
|
addresses.push(formatAddress(siblingHost, resolvedPort));
|
|
1055
|
-
resolve2({ addresses, warnings });
|
|
1100
|
+
resolve2({ addresses, port: resolvedPort, warnings });
|
|
1056
1101
|
});
|
|
1057
|
-
}
|
|
1102
|
+
};
|
|
1103
|
+
const listen = () => {
|
|
1104
|
+
try {
|
|
1105
|
+
primary.listen(candidate, primaryHost);
|
|
1106
|
+
} catch (e) {
|
|
1107
|
+
primary.removeListener("error", onError);
|
|
1108
|
+
primary.removeListener("listening", onListening);
|
|
1109
|
+
bindFailed(candidate, e.message);
|
|
1110
|
+
}
|
|
1111
|
+
};
|
|
1112
|
+
primary.on("error", onError);
|
|
1113
|
+
primary.once("listening", onListening);
|
|
1114
|
+
listen();
|
|
1058
1115
|
}
|
|
1059
1116
|
);
|
|
1060
1117
|
return {
|
|
@@ -1171,6 +1228,11 @@ var DevtoolsSpanExporter = class {
|
|
|
1171
1228
|
timestamp: event.time[0] * 1e3 + event.time[1] / 1e6,
|
|
1172
1229
|
attributes: event.attributes ? Object.fromEntries(Object.entries(event.attributes)) : void 0
|
|
1173
1230
|
}));
|
|
1231
|
+
const links = span.links.map((link) => ({
|
|
1232
|
+
traceId: link.context.traceId,
|
|
1233
|
+
spanId: link.context.spanId,
|
|
1234
|
+
attributes: link.attributes ? Object.fromEntries(Object.entries(link.attributes)) : void 0
|
|
1235
|
+
}));
|
|
1174
1236
|
return {
|
|
1175
1237
|
traceId: spanContext.traceId,
|
|
1176
1238
|
spanId: spanContext.spanId,
|
|
@@ -1185,9 +1247,15 @@ var DevtoolsSpanExporter = class {
|
|
|
1185
1247
|
code: status,
|
|
1186
1248
|
message: span.status.message
|
|
1187
1249
|
},
|
|
1188
|
-
events: events.length > 0 ? events : void 0
|
|
1250
|
+
events: events.length > 0 ? events : void 0,
|
|
1251
|
+
links: links.length > 0 ? links : void 0,
|
|
1252
|
+
scope: this.convertScope(span)
|
|
1189
1253
|
};
|
|
1190
1254
|
}
|
|
1255
|
+
convertScope(span) {
|
|
1256
|
+
const s = span.instrumentationScope ?? span.instrumentationLibrary;
|
|
1257
|
+
return s?.name ? { name: s.name, version: s.version || void 0 } : void 0;
|
|
1258
|
+
}
|
|
1191
1259
|
/**
|
|
1192
1260
|
* Convert OpenTelemetry SpanKind to string
|
|
1193
1261
|
*/
|