autotel-devtools 8.1.1 → 10.0.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/dist/cli.cjs +108 -1429
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +109 -1422
- package/dist/cli.js.map +1 -1
- package/dist/error-aggregator-BvNmgn7E.d.ts +120 -0
- package/dist/error-aggregator-nnfbpSR7.d.cts +120 -0
- package/dist/exporter-1Y3GmLVS.d.cts +182 -0
- package/dist/exporter-CZ5HdD3o.d.ts +182 -0
- package/dist/genai/index.cjs +650 -537
- package/dist/genai/index.cjs.map +1 -1
- package/dist/genai/index.d.cts +164 -157
- package/dist/genai/index.d.ts +164 -157
- package/dist/genai/index.js +649 -536
- package/dist/genai/index.js.map +1 -1
- package/dist/http-BkkKa9C_.js +1128 -0
- package/dist/http-BkkKa9C_.js.map +1 -0
- package/dist/http-Yj6iSrMX.cjs +1275 -0
- package/dist/http-Yj6iSrMX.cjs.map +1 -0
- package/dist/index.cjs +50 -1728
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -23
- package/dist/index.d.ts +21 -23
- package/dist/index.js +44 -1716
- package/dist/index.js.map +1 -1
- package/dist/listen-BBsxO0wm.cjs +125 -0
- package/dist/listen-BBsxO0wm.cjs.map +1 -0
- package/dist/listen-DfOCquUq.js +120 -0
- package/dist/listen-DfOCquUq.js.map +1 -0
- package/dist/resource-utils-B4UVvfnH.js +18 -0
- package/dist/resource-utils-B4UVvfnH.js.map +1 -0
- package/dist/resource-utils-DjHJB6uc.cjs +24 -0
- package/dist/resource-utils-DjHJB6uc.cjs.map +1 -0
- package/dist/server/exporter.cjs +135 -159
- package/dist/server/exporter.cjs.map +1 -1
- package/dist/server/exporter.d.cts +2 -4
- package/dist/server/exporter.d.ts +2 -4
- package/dist/server/exporter.js +134 -158
- package/dist/server/exporter.js.map +1 -1
- package/dist/server/index.cjs +29 -1660
- package/dist/server/index.d.cts +34 -31
- package/dist/server/index.d.ts +34 -31
- package/dist/server/index.js +5 -1630
- package/dist/server/log-exporter.cjs +75 -102
- package/dist/server/log-exporter.cjs.map +1 -1
- package/dist/server/log-exporter.d.cts +27 -46
- package/dist/server/log-exporter.d.ts +27 -46
- package/dist/server/log-exporter.js +74 -100
- package/dist/server/log-exporter.js.map +1 -1
- package/dist/server/remote-exporter.cjs +171 -213
- package/dist/server/remote-exporter.cjs.map +1 -1
- package/dist/server/remote-exporter.d.cts +62 -82
- package/dist/server/remote-exporter.d.ts +62 -82
- package/dist/server/remote-exporter.js +170 -212
- package/dist/server/remote-exporter.js.map +1 -1
- package/package.json +5 -5
- package/dist/error-aggregator-D0Uu5r38.d.ts +0 -147
- package/dist/error-aggregator-D1Mr221Y.d.cts +0 -147
- package/dist/exporter-De6p4iAD.d.cts +0 -182
- package/dist/exporter-De6p4iAD.d.ts +0 -182
- package/dist/server/index.cjs.map +0 -1
- package/dist/server/index.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listen-DfOCquUq.js","names":[],"sources":["../src/server/listen.ts"],"sourcesContent":["// src/server/listen.ts\nimport { createServer, type Server } from 'node:http'\n\nconst LOOPBACK = new Set(['localhost', '127.0.0.1', '::1'])\n\n/** How many consecutive ports to try before giving up. The default sweeps\n * 4318..4337 — a tight enough window that we don't accidentally squat on\n * something a sibling tool is using, but wide enough that the common case\n * (\"a previous devtools is still running\") succeeds. */\nconst DEFAULT_MAX_PORT_TRIES = 20\n\nexport interface LoopbackListeners {\n /** Resolves once the primary and (attempted) sibling listeners are up.\n * `port` is the port the primary actually bound to — it may differ from\n * the requested port when fallback was needed. */\n ready: Promise<{ addresses: string[]; port: number; warnings: string[] }>\n /** Close the sibling listener (the primary server is owned by the caller). */\n closeSibling: () => Promise<void>\n}\n\n/** Format host:port, bracketing IPv6 literals (e.g. `[::1]:4318`). */\nexport function formatAddress(host: string, port: number): string {\n return host.includes(':') ? `[${host}]:${port}` : `${host}:${port}`\n}\n\n/**\n * Listen on `host:port`, and when `host` is a loopback literal, ALSO listen on\n * the sibling loopback family (IPv4 ⟷ IPv6) so a client reaches the collector\n * whether the OS resolves `localhost` to `127.0.0.1` or `::1`.\n *\n * This kills a notoriously silent footgun: a dev-server proxy targeting\n * `http://localhost:PORT` on macOS resolves `localhost` to `::1`, but a\n * collector bound only to `127.0.0.1` never receives the request — spans\n * vanish with no error. Binding both loopback families makes `localhost` work\n * regardless of resolution order.\n *\n * If `port` is busy (EADDRINUSE), the listener walks forward up to `maxTries`\n * consecutive ports and binds the first one that's free. The resolved port\n * is returned in `ready` so callers can print correct URLs and OTLP\n * endpoints. Each fallback produces a warning.\n *\n * The sibling listener serves the same HTTP routes (via `attachSecondary`);\n * the WebSocket/UI stays on the primary address. If the sibling cannot bind\n * (e.g. no IPv6, or the port is taken on that family), it is reported as a\n * warning rather than a fatal error.\n */\nexport function listenLoopbackDualStack(args: {\n primary: Server\n port: number\n host: string\n attachSecondary: (server: Server) => void\n maxTries?: number\n}): LoopbackListeners {\n const { primary, port, host, attachSecondary, maxTries } = args\n const maxAttempts = Math.max(1, maxTries ?? DEFAULT_MAX_PORT_TRIES)\n let sibling: Server | undefined\n\n const ready = new Promise<{ addresses: string[]; port: number; warnings: string[] }>(\n (resolve, reject) => {\n const addresses: string[] = []\n const warnings: string[] = []\n // Normalise `localhost` to an explicit family so the primary bind is\n // deterministic and we know which sibling family to add.\n const primaryHost = host === 'localhost' ? '127.0.0.1' : host\n\n // The port currently being attempted, and how many we've burned so far.\n // One persistent handler pair owns the whole forward-walk; we just bump\n // `candidate` and re-`listen()` on the same server (the caller owns it\n // and has the WSS/routes attached, so we can't swap in a fresh one).\n let candidate = port\n let attempt = 0\n\n const bindFailed = (atPort: number, msg: string) =>\n reject(\n new Error(`could not bind ${formatAddress(primaryHost, atPort)}: ${msg}`),\n )\n\n // Walk forward from `port` until we find a free port. Anything that\n // isn't EADDRINUSE (EACCES, EAFNOSUPPORT, …) is fatal — it won't fix\n // itself on the next port.\n const onError = (e: NodeJS.ErrnoException) => {\n if (e.code !== 'EADDRINUSE') return bindFailed(candidate, e.message)\n if (++attempt >= maxAttempts) {\n reject(\n new Error(\n `could not bind ${formatAddress(primaryHost, port)}: ${maxAttempts} consecutive ports in use`,\n ),\n )\n return\n }\n candidate++\n listen()\n }\n\n const onListening = () => {\n // Bind succeeded — stop owning the primary's `error` event so a later\n // runtime error doesn't get mistaken for a bind failure.\n primary.removeListener('error', onError)\n if (candidate !== port) {\n warnings.push(`port ${port} was busy; using ${candidate} instead`)\n }\n const addr = primary.address()\n const resolvedPort =\n addr && typeof addr === 'object' ? addr.port : candidate\n addresses.push(formatAddress(primaryHost, resolvedPort))\n\n if (!LOOPBACK.has(host)) {\n resolve({ addresses, port: resolvedPort, warnings })\n return\n }\n\n const siblingHost = primaryHost === '::1' ? '127.0.0.1' : '::1'\n const s = createServer()\n attachSecondary(s)\n\n const onSiblingError = (se: Error) => {\n s.close()\n warnings.push(\n `could not also bind ${formatAddress(siblingHost, resolvedPort)} (${se.message}); ` +\n `clients using the ${siblingHost === '::1' ? 'IPv6' : 'IPv4'} form of \"localhost\" may not connect.`,\n )\n resolve({ addresses, port: resolvedPort, warnings })\n }\n s.once('error', onSiblingError)\n s.listen(resolvedPort, siblingHost, () => {\n s.off('error', onSiblingError)\n sibling = s\n addresses.push(formatAddress(siblingHost, resolvedPort))\n resolve({ addresses, port: resolvedPort, warnings })\n })\n }\n\n const listen = () => {\n try {\n primary.listen(candidate, primaryHost)\n } catch (e) {\n // `candidate` can overflow 65535 when the top port is busy; Node\n // throws a RangeError synchronously instead of emitting 'error'.\n primary.removeListener('error', onError)\n primary.removeListener('listening', onListening)\n bindFailed(candidate, (e as Error).message)\n }\n }\n\n primary.on('error', onError)\n primary.once('listening', onListening)\n listen()\n },\n )\n\n return {\n ready,\n closeSibling: () =>\n new Promise<void>((res) => {\n if (!sibling) return res()\n sibling.close(() => res())\n }),\n }\n}\n"],"mappings":";;;AAGA,MAAM,WAAW,IAAI,IAAI;CAAC;CAAa;CAAa;AAAK,CAAC;;;;;AAM1D,MAAM,yBAAyB;;AAY/B,SAAgB,cAAc,MAAc,MAAsB;CAChE,OAAO,KAAK,SAAS,GAAG,IAAI,IAAI,KAAK,IAAI,SAAS,GAAG,KAAK,GAAG;AAC/D;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,wBAAwB,MAMlB;CACpB,MAAM,EAAE,SAAS,MAAM,MAAM,iBAAiB,aAAa;CAC3D,MAAM,cAAc,KAAK,IAAI,GAAG,YAAY,sBAAsB;CAClE,IAAI;CA+FJ,OAAO;EACL,WA9FgB,SACf,SAAS,WAAW;GACnB,MAAM,YAAsB,CAAC;GAC7B,MAAM,WAAqB,CAAC;GAG5B,MAAM,cAAc,SAAS,cAAc,cAAc;GAMzD,IAAI,YAAY;GAChB,IAAI,UAAU;GAEd,MAAM,cAAc,QAAgB,QAClC,uBACE,IAAI,MAAM,kBAAkB,cAAc,aAAa,MAAM,EAAE,IAAI,KAAK,CAC1E;GAKF,MAAM,WAAW,MAA6B;IAC5C,IAAI,EAAE,SAAS,cAAc,OAAO,WAAW,WAAW,EAAE,OAAO;IACnE,IAAI,EAAE,WAAW,aAAa;KAC5B,uBACE,IAAI,MACF,kBAAkB,cAAc,aAAa,IAAI,EAAE,IAAI,YAAY,0BACrE,CACF;KACA;IACF;IACA;IACA,OAAO;GACT;GAEA,MAAM,oBAAoB;IAGxB,QAAQ,eAAe,SAAS,OAAO;IACvC,IAAI,cAAc,MAChB,SAAS,KAAK,QAAQ,KAAK,mBAAmB,UAAU,SAAS;IAEnE,MAAM,OAAO,QAAQ,QAAQ;IAC7B,MAAM,eACJ,QAAQ,OAAO,SAAS,WAAW,KAAK,OAAO;IACjD,UAAU,KAAK,cAAc,aAAa,YAAY,CAAC;IAEvD,IAAI,CAAC,SAAS,IAAI,IAAI,GAAG;KACvB,QAAQ;MAAE;MAAW,MAAM;MAAc;KAAS,CAAC;KACnD;IACF;IAEA,MAAM,cAAc,gBAAgB,QAAQ,cAAc;IAC1D,MAAM,IAAI,aAAa;IACvB,gBAAgB,CAAC;IAEjB,MAAM,kBAAkB,OAAc;KACpC,EAAE,MAAM;KACR,SAAS,KACP,uBAAuB,cAAc,aAAa,YAAY,EAAE,IAAI,GAAG,QAAQ,uBACxD,gBAAgB,QAAQ,SAAS,OAAO,sCACjE;KACA,QAAQ;MAAE;MAAW,MAAM;MAAc;KAAS,CAAC;IACrD;IACA,EAAE,KAAK,SAAS,cAAc;IAC9B,EAAE,OAAO,cAAc,mBAAmB;KACxC,EAAE,IAAI,SAAS,cAAc;KAC7B,UAAU;KACV,UAAU,KAAK,cAAc,aAAa,YAAY,CAAC;KACvD,QAAQ;MAAE;MAAW,MAAM;MAAc;KAAS,CAAC;IACrD,CAAC;GACH;GAEA,MAAM,eAAe;IACnB,IAAI;KACF,QAAQ,OAAO,WAAW,WAAW;IACvC,SAAS,GAAG;KAGV,QAAQ,eAAe,SAAS,OAAO;KACvC,QAAQ,eAAe,aAAa,WAAW;KAC/C,WAAW,WAAY,EAAY,OAAO;IAC5C;GACF;GAEA,QAAQ,GAAG,SAAS,OAAO;GAC3B,QAAQ,KAAK,aAAa,WAAW;GACrC,OAAO;EACT,CAII;EACJ,oBACE,IAAI,SAAe,QAAQ;GACzB,IAAI,CAAC,SAAS,OAAO,IAAI;GACzB,QAAQ,YAAY,IAAI,CAAC;EAC3B,CAAC;CACL;AACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/server/resource-utils.ts
|
|
2
|
+
function getResourceName(resource, fallback = "unknown") {
|
|
3
|
+
if (!resource) return fallback;
|
|
4
|
+
const candidates = [
|
|
5
|
+
resource["service.name"],
|
|
6
|
+
resource["service.namespace"],
|
|
7
|
+
resource["deployment.environment.name"],
|
|
8
|
+
resource["host.name"],
|
|
9
|
+
resource["container.name"],
|
|
10
|
+
resource["process.executable.name"]
|
|
11
|
+
];
|
|
12
|
+
for (const candidate of candidates) if (typeof candidate === "string" && candidate.trim().length > 0) return candidate;
|
|
13
|
+
return fallback;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { getResourceName as t };
|
|
18
|
+
//# sourceMappingURL=resource-utils-B4UVvfnH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-utils-B4UVvfnH.js","names":[],"sources":["../src/server/resource-utils.ts"],"sourcesContent":["export function getResourceName(\n resource: Record<string, unknown> | undefined,\n fallback = 'unknown',\n): string {\n if (!resource) return fallback\n\n const candidates = [\n resource['service.name'],\n resource['service.namespace'],\n resource['deployment.environment.name'],\n resource['host.name'],\n resource['container.name'],\n resource['process.executable.name'],\n ]\n\n for (const candidate of candidates) {\n if (typeof candidate === 'string' && candidate.trim().length > 0) {\n return candidate\n }\n }\n\n return fallback\n}\n"],"mappings":";AAAA,SAAgB,gBACd,UACA,WAAW,WACH;CACR,IAAI,CAAC,UAAU,OAAO;CAEtB,MAAM,aAAa;EACjB,SAAS;EACT,SAAS;EACT,SAAS;EACT,SAAS;EACT,SAAS;EACT,SAAS;CACX;CAEA,KAAK,MAAM,aAAa,YACtB,IAAI,OAAO,cAAc,YAAY,UAAU,KAAK,CAAC,CAAC,SAAS,GAC7D,OAAO;CAIX,OAAO;AACT"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/server/resource-utils.ts
|
|
3
|
+
function getResourceName(resource, fallback = "unknown") {
|
|
4
|
+
if (!resource) return fallback;
|
|
5
|
+
const candidates = [
|
|
6
|
+
resource["service.name"],
|
|
7
|
+
resource["service.namespace"],
|
|
8
|
+
resource["deployment.environment.name"],
|
|
9
|
+
resource["host.name"],
|
|
10
|
+
resource["container.name"],
|
|
11
|
+
resource["process.executable.name"]
|
|
12
|
+
];
|
|
13
|
+
for (const candidate of candidates) if (typeof candidate === "string" && candidate.trim().length > 0) return candidate;
|
|
14
|
+
return fallback;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
Object.defineProperty(exports, 'getResourceName', {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return getResourceName;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
//# sourceMappingURL=resource-utils-DjHJB6uc.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-utils-DjHJB6uc.cjs","names":[],"sources":["../src/server/resource-utils.ts"],"sourcesContent":["export function getResourceName(\n resource: Record<string, unknown> | undefined,\n fallback = 'unknown',\n): string {\n if (!resource) return fallback\n\n const candidates = [\n resource['service.name'],\n resource['service.namespace'],\n resource['deployment.environment.name'],\n resource['host.name'],\n resource['container.name'],\n resource['process.executable.name'],\n ]\n\n for (const candidate of candidates) {\n if (typeof candidate === 'string' && candidate.trim().length > 0) {\n return candidate\n }\n }\n\n return fallback\n}\n"],"mappings":";;AAAA,SAAgB,gBACd,UACA,WAAW,WACH;CACR,IAAI,CAAC,UAAU,OAAO;CAEtB,MAAM,aAAa;EACjB,SAAS;EACT,SAAS;EACT,SAAS;EACT,SAAS;EACT,SAAS;EACT,SAAS;CACX;CAEA,KAAK,MAAM,aAAa,YACtB,IAAI,OAAO,cAAc,YAAY,UAAU,KAAK,CAAC,CAAC,SAAS,GAC7D,OAAO;CAIX,OAAO;AACT"}
|
package/dist/server/exporter.cjs
CHANGED
|
@@ -1,165 +1,141 @@
|
|
|
1
|
-
'
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
//#region src/server/exporter.ts
|
|
4
4
|
var DevtoolsSpanExporter = class {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
* Convert OpenTelemetry SpanKind to string
|
|
138
|
-
*/
|
|
139
|
-
convertSpanKind(kind) {
|
|
140
|
-
switch (kind) {
|
|
141
|
-
case 0: {
|
|
142
|
-
return "INTERNAL";
|
|
143
|
-
}
|
|
144
|
-
case 1: {
|
|
145
|
-
return "SERVER";
|
|
146
|
-
}
|
|
147
|
-
case 2: {
|
|
148
|
-
return "CLIENT";
|
|
149
|
-
}
|
|
150
|
-
case 3: {
|
|
151
|
-
return "PRODUCER";
|
|
152
|
-
}
|
|
153
|
-
case 4: {
|
|
154
|
-
return "CONSUMER";
|
|
155
|
-
}
|
|
156
|
-
default: {
|
|
157
|
-
return "INTERNAL";
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
5
|
+
server;
|
|
6
|
+
serviceName;
|
|
7
|
+
constructor(server, serviceName = "unknown-service") {
|
|
8
|
+
this.server = server;
|
|
9
|
+
this.serviceName = serviceName;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Export spans to the WebSocket server
|
|
13
|
+
*/
|
|
14
|
+
async export(spans, resultCallback) {
|
|
15
|
+
resultCallback({ code: 0 });
|
|
16
|
+
Promise.resolve().then(() => {
|
|
17
|
+
try {
|
|
18
|
+
console.log(`[Autotel Exporter] Exporting ${spans.length} span(s)`);
|
|
19
|
+
const traceMap = /* @__PURE__ */ new Map();
|
|
20
|
+
for (const span of spans) {
|
|
21
|
+
const traceId = span.spanContext().traceId;
|
|
22
|
+
if (!traceMap.has(traceId)) traceMap.set(traceId, []);
|
|
23
|
+
traceMap.get(traceId).push(span);
|
|
24
|
+
}
|
|
25
|
+
for (const [traceId, traceSpans] of traceMap) {
|
|
26
|
+
const trace = this.convertToTraceData(traceId, traceSpans);
|
|
27
|
+
console.log(`[Autotel Exporter] Adding trace ${traceId.slice(0, 16)} with ${traceSpans.length} spans`);
|
|
28
|
+
this.server.addTrace(trace);
|
|
29
|
+
}
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error("[Autotel Exporter] Export error:", error);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Shutdown the exporter
|
|
37
|
+
*/
|
|
38
|
+
async shutdown() {}
|
|
39
|
+
/**
|
|
40
|
+
* Force flush any buffered spans
|
|
41
|
+
*/
|
|
42
|
+
async forceFlush() {}
|
|
43
|
+
/**
|
|
44
|
+
* Convert OpenTelemetry spans to TraceData
|
|
45
|
+
*/
|
|
46
|
+
convertToTraceData(traceId, spans) {
|
|
47
|
+
const spanData = spans.map((span) => this.convertSpan(span));
|
|
48
|
+
const rootSpan = spanData.find((s) => !s.parentSpanId) || spanData[0];
|
|
49
|
+
spanData.sort((a, b) => a.startTime - b.startTime);
|
|
50
|
+
const startTime = Math.min(...spanData.map((s) => s.startTime));
|
|
51
|
+
const endTime = Math.max(...spanData.map((s) => s.endTime));
|
|
52
|
+
const status = spanData.some((s) => s.status.code === "ERROR") ? "ERROR" : "OK";
|
|
53
|
+
return {
|
|
54
|
+
traceId,
|
|
55
|
+
correlationId: traceId.slice(0, 16),
|
|
56
|
+
rootSpan,
|
|
57
|
+
spans: spanData,
|
|
58
|
+
startTime,
|
|
59
|
+
endTime,
|
|
60
|
+
duration: endTime - startTime,
|
|
61
|
+
status,
|
|
62
|
+
service: this.serviceName
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Convert OpenTelemetry span to SpanData
|
|
67
|
+
*/
|
|
68
|
+
convertSpan(span) {
|
|
69
|
+
const spanContext = span.spanContext();
|
|
70
|
+
const startTime = span.startTime[0] * 1e3 + span.startTime[1] / 1e6;
|
|
71
|
+
const endTime = span.endTime[0] * 1e3 + span.endTime[1] / 1e6;
|
|
72
|
+
const attributes = {};
|
|
73
|
+
for (const [key, value] of Object.entries(span.attributes)) attributes[key] = value;
|
|
74
|
+
const statusCode = span.status.code;
|
|
75
|
+
let status;
|
|
76
|
+
switch (statusCode) {
|
|
77
|
+
case 0:
|
|
78
|
+
status = "UNSET";
|
|
79
|
+
break;
|
|
80
|
+
case 1:
|
|
81
|
+
status = "OK";
|
|
82
|
+
break;
|
|
83
|
+
case 2:
|
|
84
|
+
status = "ERROR";
|
|
85
|
+
break;
|
|
86
|
+
default: status = "UNSET";
|
|
87
|
+
}
|
|
88
|
+
const events = span.events.map((event) => ({
|
|
89
|
+
name: event.name,
|
|
90
|
+
timestamp: event.time[0] * 1e3 + event.time[1] / 1e6,
|
|
91
|
+
attributes: event.attributes ? Object.fromEntries(Object.entries(event.attributes)) : void 0
|
|
92
|
+
}));
|
|
93
|
+
const links = span.links.map((link) => ({
|
|
94
|
+
traceId: link.context.traceId,
|
|
95
|
+
spanId: link.context.spanId,
|
|
96
|
+
attributes: link.attributes ? Object.fromEntries(Object.entries(link.attributes)) : void 0
|
|
97
|
+
}));
|
|
98
|
+
return {
|
|
99
|
+
traceId: spanContext.traceId,
|
|
100
|
+
spanId: spanContext.spanId,
|
|
101
|
+
parentSpanId: span.parentSpanId,
|
|
102
|
+
name: span.name,
|
|
103
|
+
kind: this.convertSpanKind(span.kind),
|
|
104
|
+
startTime,
|
|
105
|
+
endTime,
|
|
106
|
+
duration: endTime - startTime,
|
|
107
|
+
attributes,
|
|
108
|
+
status: {
|
|
109
|
+
code: status,
|
|
110
|
+
message: span.status.message
|
|
111
|
+
},
|
|
112
|
+
events: events.length > 0 ? events : void 0,
|
|
113
|
+
links: links.length > 0 ? links : void 0,
|
|
114
|
+
scope: this.convertScope(span)
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
convertScope(span) {
|
|
118
|
+
const s = span.instrumentationScope ?? span.instrumentationLibrary;
|
|
119
|
+
return s?.name ? {
|
|
120
|
+
name: s.name,
|
|
121
|
+
version: s.version || void 0
|
|
122
|
+
} : void 0;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Convert OpenTelemetry SpanKind to string
|
|
126
|
+
*/
|
|
127
|
+
convertSpanKind(kind) {
|
|
128
|
+
switch (kind) {
|
|
129
|
+
case 0: return "INTERNAL";
|
|
130
|
+
case 1: return "SERVER";
|
|
131
|
+
case 2: return "CLIENT";
|
|
132
|
+
case 3: return "PRODUCER";
|
|
133
|
+
case 4: return "CONSUMER";
|
|
134
|
+
default: return "INTERNAL";
|
|
135
|
+
}
|
|
136
|
+
}
|
|
161
137
|
};
|
|
162
138
|
|
|
139
|
+
//#endregion
|
|
163
140
|
exports.DevtoolsSpanExporter = DevtoolsSpanExporter;
|
|
164
|
-
//# sourceMappingURL=exporter.cjs.map
|
|
165
141
|
//# sourceMappingURL=exporter.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/exporter.ts"],"names":[],"mappings":"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","file":"exporter.cjs","sourcesContent":["/**\n * OpenTelemetry SpanExporter that streams spans to DevtoolsServer\n */\n\nimport type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';\nimport type { ExportResult, ExportResultCode } from '@opentelemetry/core';\nimport type { DevtoolsServer } from './server';\nimport type { TraceData, SpanData } from './types';\n\nexport class DevtoolsSpanExporter implements SpanExporter {\n private server: DevtoolsServer;\n private serviceName: string;\n\n constructor(server: DevtoolsServer, serviceName: string = 'unknown-service') {\n this.server = server;\n this.serviceName = serviceName;\n }\n\n /**\n * Export spans to the WebSocket server\n */\n async export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void,\n ): Promise<void> {\n // Immediately call the callback to unblock the span processor\n // Then process the spans asynchronously\n resultCallback({ code: 0 as ExportResultCode });\n\n // Process spans asynchronously without blocking\n Promise.resolve().then(() => {\n try {\n console.log(`[Autotel Exporter] Exporting ${spans.length} span(s)`);\n\n // Group spans by trace ID\n const traceMap = new Map<string, ReadableSpan[]>();\n\n for (const span of spans) {\n const traceId = span.spanContext().traceId;\n if (!traceMap.has(traceId)) {\n traceMap.set(traceId, []);\n }\n traceMap.get(traceId)!.push(span);\n }\n\n // Convert each trace and send to server\n for (const [traceId, traceSpans] of traceMap) {\n const trace = this.convertToTraceData(traceId, traceSpans);\n console.log(\n `[Autotel Exporter] Adding trace ${traceId.slice(0, 16)} with ${traceSpans.length} spans`,\n );\n this.server.addTrace(trace);\n }\n } catch (error) {\n console.error('[Autotel Exporter] Export error:', error);\n }\n });\n }\n\n /**\n * Shutdown the exporter\n */\n async shutdown(): Promise<void> {\n // Nothing to clean up\n }\n\n /**\n * Force flush any buffered spans\n */\n async forceFlush(): Promise<void> {\n // Nothing to flush\n }\n\n /**\n * Convert OpenTelemetry spans to TraceData\n */\n private convertToTraceData(\n traceId: string,\n spans: ReadableSpan[],\n ): TraceData {\n // Convert spans\n const spanData: SpanData[] = spans.map((span) => this.convertSpan(span));\n\n // Find root span (no parent)\n const rootSpan = spanData.find((s) => !s.parentSpanId) || spanData[0];\n\n // Sort spans by start time\n spanData.sort((a, b) => a.startTime - b.startTime);\n\n const startTime = Math.min(...spanData.map((s) => s.startTime));\n const endTime = Math.max(...spanData.map((s) => s.endTime));\n\n // Determine overall status (ERROR if any span errored)\n const hasError = spanData.some((s) => s.status.code === 'ERROR');\n const status = hasError ? 'ERROR' : 'OK';\n\n return {\n traceId,\n correlationId: traceId.slice(0, 16), // First 16 chars\n rootSpan,\n spans: spanData,\n startTime,\n endTime,\n duration: endTime - startTime,\n status: status as 'OK' | 'ERROR' | 'UNSET',\n service: this.serviceName,\n };\n }\n\n /**\n * Convert OpenTelemetry span to SpanData\n */\n private convertSpan(span: ReadableSpan): SpanData {\n const spanContext = span.spanContext();\n const startTime = span.startTime[0] * 1000 + span.startTime[1] / 1_000_000;\n const endTime = span.endTime[0] * 1000 + span.endTime[1] / 1_000_000;\n\n // Convert attributes\n const attributes: Record<string, any> = {};\n for (const [key, value] of Object.entries(span.attributes)) {\n attributes[key] = value;\n }\n\n // Convert status\n const statusCode = span.status.code;\n let status: 'OK' | 'ERROR' | 'UNSET';\n switch (statusCode) {\n case 0: {\n status = 'UNSET';\n break;\n }\n case 1: {\n status = 'OK';\n break;\n }\n case 2: {\n status = 'ERROR';\n break;\n }\n default: {\n status = 'UNSET';\n }\n }\n\n // Convert events\n const events = span.events.map((event) => ({\n name: event.name,\n timestamp: event.time[0] * 1000 + event.time[1] / 1_000_000,\n attributes: event.attributes\n ? Object.fromEntries(Object.entries(event.attributes))\n : undefined,\n }));\n\n // Convert links\n const links = span.links.map((link) => ({\n traceId: link.context.traceId,\n spanId: link.context.spanId,\n attributes: link.attributes\n ? Object.fromEntries(Object.entries(link.attributes))\n : undefined,\n }));\n\n return {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n parentSpanId: (span as any).parentSpanId,\n name: span.name,\n kind: this.convertSpanKind(span.kind),\n startTime,\n endTime,\n duration: endTime - startTime,\n attributes,\n status: {\n code: status,\n message: span.status.message,\n },\n events: events.length > 0 ? events : undefined,\n links: links.length > 0 ? links : undefined,\n scope: this.convertScope(span),\n };\n }\n\n private convertScope(span: ReadableSpan): SpanData['scope'] {\n const s =\n (span as any).instrumentationScope ??\n (span as any).instrumentationLibrary;\n return s?.name ? { name: s.name, version: s.version || undefined } : undefined;\n }\n\n /**\n * Convert OpenTelemetry SpanKind to string\n */\n private convertSpanKind(\n kind: number,\n ): 'INTERNAL' | 'SERVER' | 'CLIENT' | 'PRODUCER' | 'CONSUMER' {\n switch (kind) {\n case 0: {\n return 'INTERNAL';\n }\n case 1: {\n return 'SERVER';\n }\n case 2: {\n return 'CLIENT';\n }\n case 3: {\n return 'PRODUCER';\n }\n case 4: {\n return 'CONSUMER';\n }\n default: {\n return 'INTERNAL';\n }\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"exporter.cjs","names":[],"sources":["../../src/server/exporter.ts"],"sourcesContent":["/**\n * OpenTelemetry SpanExporter that streams spans to DevtoolsServer\n */\n\nimport type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';\nimport type { ExportResult, ExportResultCode } from '@opentelemetry/core';\nimport type { DevtoolsServer } from './server';\nimport type { TraceData, SpanData } from './types';\n\nexport class DevtoolsSpanExporter implements SpanExporter {\n private server: DevtoolsServer;\n private serviceName: string;\n\n constructor(server: DevtoolsServer, serviceName: string = 'unknown-service') {\n this.server = server;\n this.serviceName = serviceName;\n }\n\n /**\n * Export spans to the WebSocket server\n */\n async export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void,\n ): Promise<void> {\n // Immediately call the callback to unblock the span processor\n // Then process the spans asynchronously\n resultCallback({ code: 0 as ExportResultCode });\n\n // Process spans asynchronously without blocking\n Promise.resolve().then(() => {\n try {\n console.log(`[Autotel Exporter] Exporting ${spans.length} span(s)`);\n\n // Group spans by trace ID\n const traceMap = new Map<string, ReadableSpan[]>();\n\n for (const span of spans) {\n const traceId = span.spanContext().traceId;\n if (!traceMap.has(traceId)) {\n traceMap.set(traceId, []);\n }\n traceMap.get(traceId)!.push(span);\n }\n\n // Convert each trace and send to server\n for (const [traceId, traceSpans] of traceMap) {\n const trace = this.convertToTraceData(traceId, traceSpans);\n console.log(\n `[Autotel Exporter] Adding trace ${traceId.slice(0, 16)} with ${traceSpans.length} spans`,\n );\n this.server.addTrace(trace);\n }\n } catch (error) {\n console.error('[Autotel Exporter] Export error:', error);\n }\n });\n }\n\n /**\n * Shutdown the exporter\n */\n async shutdown(): Promise<void> {\n // Nothing to clean up\n }\n\n /**\n * Force flush any buffered spans\n */\n async forceFlush(): Promise<void> {\n // Nothing to flush\n }\n\n /**\n * Convert OpenTelemetry spans to TraceData\n */\n private convertToTraceData(\n traceId: string,\n spans: ReadableSpan[],\n ): TraceData {\n // Convert spans\n const spanData: SpanData[] = spans.map((span) => this.convertSpan(span));\n\n // Find root span (no parent)\n const rootSpan = spanData.find((s) => !s.parentSpanId) || spanData[0];\n\n // Sort spans by start time\n spanData.sort((a, b) => a.startTime - b.startTime);\n\n const startTime = Math.min(...spanData.map((s) => s.startTime));\n const endTime = Math.max(...spanData.map((s) => s.endTime));\n\n // Determine overall status (ERROR if any span errored)\n const hasError = spanData.some((s) => s.status.code === 'ERROR');\n const status = hasError ? 'ERROR' : 'OK';\n\n return {\n traceId,\n correlationId: traceId.slice(0, 16), // First 16 chars\n rootSpan,\n spans: spanData,\n startTime,\n endTime,\n duration: endTime - startTime,\n status: status as 'OK' | 'ERROR' | 'UNSET',\n service: this.serviceName,\n };\n }\n\n /**\n * Convert OpenTelemetry span to SpanData\n */\n private convertSpan(span: ReadableSpan): SpanData {\n const spanContext = span.spanContext();\n const startTime = span.startTime[0] * 1000 + span.startTime[1] / 1_000_000;\n const endTime = span.endTime[0] * 1000 + span.endTime[1] / 1_000_000;\n\n // Convert attributes\n const attributes: Record<string, any> = {};\n for (const [key, value] of Object.entries(span.attributes)) {\n attributes[key] = value;\n }\n\n // Convert status\n const statusCode = span.status.code;\n let status: 'OK' | 'ERROR' | 'UNSET';\n switch (statusCode) {\n case 0: {\n status = 'UNSET';\n break;\n }\n case 1: {\n status = 'OK';\n break;\n }\n case 2: {\n status = 'ERROR';\n break;\n }\n default: {\n status = 'UNSET';\n }\n }\n\n // Convert events\n const events = span.events.map((event) => ({\n name: event.name,\n timestamp: event.time[0] * 1000 + event.time[1] / 1_000_000,\n attributes: event.attributes\n ? Object.fromEntries(Object.entries(event.attributes))\n : undefined,\n }));\n\n // Convert links\n const links = span.links.map((link) => ({\n traceId: link.context.traceId,\n spanId: link.context.spanId,\n attributes: link.attributes\n ? Object.fromEntries(Object.entries(link.attributes))\n : undefined,\n }));\n\n return {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n parentSpanId: (span as any).parentSpanId,\n name: span.name,\n kind: this.convertSpanKind(span.kind),\n startTime,\n endTime,\n duration: endTime - startTime,\n attributes,\n status: {\n code: status,\n message: span.status.message,\n },\n events: events.length > 0 ? events : undefined,\n links: links.length > 0 ? links : undefined,\n scope: this.convertScope(span),\n };\n }\n\n private convertScope(span: ReadableSpan): SpanData['scope'] {\n const s =\n (span as any).instrumentationScope ??\n (span as any).instrumentationLibrary;\n return s?.name ? { name: s.name, version: s.version || undefined } : undefined;\n }\n\n /**\n * Convert OpenTelemetry SpanKind to string\n */\n private convertSpanKind(\n kind: number,\n ): 'INTERNAL' | 'SERVER' | 'CLIENT' | 'PRODUCER' | 'CONSUMER' {\n switch (kind) {\n case 0: {\n return 'INTERNAL';\n }\n case 1: {\n return 'SERVER';\n }\n case 2: {\n return 'CLIENT';\n }\n case 3: {\n return 'PRODUCER';\n }\n case 4: {\n return 'CONSUMER';\n }\n default: {\n return 'INTERNAL';\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
export { a as DevtoolsSpanExporter } from '../exporter-De6p4iAD.cjs';
|
|
4
|
-
import 'node:http';
|
|
1
|
+
import { t as DevtoolsSpanExporter } from "../exporter-1Y3GmLVS.cjs";
|
|
2
|
+
export { DevtoolsSpanExporter };
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
export { a as DevtoolsSpanExporter } from '../exporter-De6p4iAD.js';
|
|
4
|
-
import 'node:http';
|
|
1
|
+
import { t as DevtoolsSpanExporter } from "../exporter-CZ5HdD3o.js";
|
|
2
|
+
export { DevtoolsSpanExporter };
|