autotel-devtools 6.0.1 → 6.1.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 +19 -0
- package/dist/cli.cjs +66 -4
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +66 -4
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +33 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +33 -4
- package/dist/index.js.map +1 -1
- package/dist/server/index.cjs +56 -4
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +17 -1
- package/dist/server/index.d.ts +17 -1
- package/dist/server/index.js +55 -5
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -916,7 +916,38 @@ function decodeOtlpMetricsRequest(body) {
|
|
|
916
916
|
return decodeRequest("opentelemetry.proto.metrics.v1.ExportMetricsServiceRequest", body);
|
|
917
917
|
}
|
|
918
918
|
|
|
919
|
+
// src/server/identity.ts
|
|
920
|
+
var DEVTOOLS_IDENTITY = "autotel-devtools";
|
|
921
|
+
async function probePortHolder(host, port, timeoutMs = 500) {
|
|
922
|
+
const authority = host.includes(":") ? `[${host}]` : host;
|
|
923
|
+
const controller = new AbortController();
|
|
924
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
925
|
+
try {
|
|
926
|
+
const res = await fetch(`http://${authority}:${port}/healthz`, {
|
|
927
|
+
signal: controller.signal
|
|
928
|
+
});
|
|
929
|
+
if (res.headers.get("x-autotel-devtools")) return "autotel-devtools";
|
|
930
|
+
try {
|
|
931
|
+
const body = await res.json();
|
|
932
|
+
if (body && body.service === DEVTOOLS_IDENTITY) return "autotel-devtools";
|
|
933
|
+
} catch {
|
|
934
|
+
}
|
|
935
|
+
return "foreign";
|
|
936
|
+
} catch {
|
|
937
|
+
return "none";
|
|
938
|
+
} finally {
|
|
939
|
+
clearTimeout(timer);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
|
|
919
943
|
// src/server/http.ts
|
|
944
|
+
function sendOtlpError(res, req, e) {
|
|
945
|
+
sendJson(res, 400, {
|
|
946
|
+
error: "Invalid OTLP payload",
|
|
947
|
+
message: e instanceof Error ? e.message : String(e),
|
|
948
|
+
contentType: req.headers["content-type"] ?? null
|
|
949
|
+
});
|
|
950
|
+
}
|
|
920
951
|
var PROTOBUF_DECODERS = {
|
|
921
952
|
traces: decodeOtlpTraceRequest,
|
|
922
953
|
logs: decodeOtlpLogsRequest,
|
|
@@ -937,6 +968,18 @@ function findPackageRoot() {
|
|
|
937
968
|
return dir;
|
|
938
969
|
}
|
|
939
970
|
var FULLPAGE_HTML = `<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>autotel-devtools</title><style>*{margin:0;padding:0;box-sizing:border-box}html,body{height:100%;width:100%;overflow:hidden}</style></head><body><script src="/widget.js?mode=fullpage"></script></body></html>`;
|
|
971
|
+
var cachedVersion = null;
|
|
972
|
+
function getVersion() {
|
|
973
|
+
if (cachedVersion !== null) return cachedVersion;
|
|
974
|
+
let version = "unknown";
|
|
975
|
+
try {
|
|
976
|
+
const pkg = JSON.parse(readFileSync(resolve(findPackageRoot(), "package.json"), "utf8"));
|
|
977
|
+
if (typeof pkg.version === "string") version = pkg.version;
|
|
978
|
+
} catch {
|
|
979
|
+
}
|
|
980
|
+
cachedVersion = version;
|
|
981
|
+
return version;
|
|
982
|
+
}
|
|
940
983
|
var cachedWidgetJs = null;
|
|
941
984
|
function getWidgetJs() {
|
|
942
985
|
if (!cachedWidgetJs) {
|
|
@@ -963,6 +1006,8 @@ function attachDevtoolsRoutes(httpServer, devtools) {
|
|
|
963
1006
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
964
1007
|
res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
|
|
965
1008
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
1009
|
+
res.setHeader("x-autotel-devtools", getVersion());
|
|
1010
|
+
res.setHeader("Access-Control-Expose-Headers", "x-autotel-devtools");
|
|
966
1011
|
if (req.method === "OPTIONS") {
|
|
967
1012
|
res.writeHead(204);
|
|
968
1013
|
res.end();
|
|
@@ -981,7 +1026,12 @@ function attachDevtoolsRoutes(httpServer, devtools) {
|
|
|
981
1026
|
return;
|
|
982
1027
|
}
|
|
983
1028
|
if (req.method === "GET" && url === "/healthz") {
|
|
984
|
-
sendJson(res, 200, {
|
|
1029
|
+
sendJson(res, 200, {
|
|
1030
|
+
ok: true,
|
|
1031
|
+
service: DEVTOOLS_IDENTITY,
|
|
1032
|
+
version: getVersion(),
|
|
1033
|
+
clients: devtools.clientCount
|
|
1034
|
+
});
|
|
985
1035
|
return;
|
|
986
1036
|
}
|
|
987
1037
|
if (req.method === "GET" && url === "/v1/traces") {
|
|
@@ -1001,7 +1051,7 @@ function attachDevtoolsRoutes(httpServer, devtools) {
|
|
|
1001
1051
|
devtools.addTraces(traces);
|
|
1002
1052
|
sendJson(res, 200, { acceptedTraces: traces.length });
|
|
1003
1053
|
} catch (e) {
|
|
1004
|
-
|
|
1054
|
+
sendOtlpError(res, req, e);
|
|
1005
1055
|
}
|
|
1006
1056
|
return;
|
|
1007
1057
|
}
|
|
@@ -1012,7 +1062,7 @@ function attachDevtoolsRoutes(httpServer, devtools) {
|
|
|
1012
1062
|
devtools.addLogs(logs);
|
|
1013
1063
|
sendJson(res, 200, { acceptedLogs: logs.length });
|
|
1014
1064
|
} catch (e) {
|
|
1015
|
-
|
|
1065
|
+
sendOtlpError(res, req, e);
|
|
1016
1066
|
}
|
|
1017
1067
|
return;
|
|
1018
1068
|
}
|
|
@@ -1022,7 +1072,7 @@ function attachDevtoolsRoutes(httpServer, devtools) {
|
|
|
1022
1072
|
const count = countOtlpMetrics(payload);
|
|
1023
1073
|
sendJson(res, 200, { acceptedMetrics: count });
|
|
1024
1074
|
} catch (e) {
|
|
1025
|
-
|
|
1075
|
+
sendOtlpError(res, req, e);
|
|
1026
1076
|
}
|
|
1027
1077
|
return;
|
|
1028
1078
|
}
|
|
@@ -1239,6 +1289,18 @@ async function main() {
|
|
|
1239
1289
|
attachSecondary: (s) => attachDevtoolsRoutes(s, wsServer)
|
|
1240
1290
|
});
|
|
1241
1291
|
const { addresses, warnings, port: boundPort } = await listeners.ready;
|
|
1292
|
+
if (boundPort !== options.port) {
|
|
1293
|
+
const holder = await probePortHolder(options.host, options.port);
|
|
1294
|
+
if (holder === "autotel-devtools") {
|
|
1295
|
+
warnings.push(
|
|
1296
|
+
`another autotel-devtools is already running on port ${options.port}; this instance is on ${boundPort}. Use the existing one, or stop it and restart here.`
|
|
1297
|
+
);
|
|
1298
|
+
} else {
|
|
1299
|
+
warnings.push(
|
|
1300
|
+
`port ${options.port} is held by another process that is NOT autotel-devtools. Anything exporting OTLP to :${options.port} is reaching that process, not this devtools. Point your exporter at :${boundPort}, or free :${options.port} and restart.`
|
|
1301
|
+
);
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1242
1304
|
const uiBase = `http://${options.host === "localhost" ? "127.0.0.1" : options.host}:${boundPort}`;
|
|
1243
1305
|
const title = options.title || "autotel-devtools";
|
|
1244
1306
|
process.stdout.write(`
|