autotel-devtools 5.0.1 → 6.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.
@@ -21,6 +21,15 @@ interface SpanData {
21
21
  timestamp: number;
22
22
  attributes?: Record<string, any>;
23
23
  }>;
24
+ links?: Array<{
25
+ traceId: string;
26
+ spanId: string;
27
+ attributes?: Record<string, any>;
28
+ }>;
29
+ scope?: {
30
+ name?: string;
31
+ version?: string;
32
+ };
24
33
  }
25
34
  interface TraceData {
26
35
  traceId: string;
@@ -95,6 +104,12 @@ interface DevtoolsServerOptions {
95
104
  maxTraceCount?: number;
96
105
  maxLogCount?: number;
97
106
  maxMetricCount?: number;
107
+ /**
108
+ * Called after each ingest, with the incremental data just broadcast to WS
109
+ * clients. Lets an embedder (e.g. the VS Code extension) react to new
110
+ * telemetry — refresh its own tree views — while the server owns the buffer.
111
+ */
112
+ onData?: (incremental: DevtoolsData) => void;
98
113
  }
99
114
  declare class DevtoolsServer {
100
115
  private wss;
@@ -107,6 +122,7 @@ declare class DevtoolsServer {
107
122
  private limits;
108
123
  private verbose;
109
124
  private _port;
125
+ private onData?;
110
126
  constructor(options?: DevtoolsServerOptions);
111
127
  get port(): number;
112
128
  get clientCount(): number;
@@ -150,6 +166,7 @@ declare class DevtoolsSpanExporter implements SpanExporter {
150
166
  * Convert OpenTelemetry span to SpanData
151
167
  */
152
168
  private convertSpan;
169
+ private convertScope;
153
170
  /**
154
171
  * Convert OpenTelemetry SpanKind to string
155
172
  */
@@ -20,6 +20,15 @@ interface SpanData {
20
20
  timestamp: number;
21
21
  attributes?: Record<string, any>;
22
22
  }>;
23
+ links?: Array<{
24
+ traceId: string;
25
+ spanId: string;
26
+ attributes?: Record<string, any>;
27
+ }>;
28
+ scope?: {
29
+ name?: string;
30
+ version?: string;
31
+ };
23
32
  }
24
33
 
25
34
  declare function isGenAiSpan(span: SpanData): boolean;
@@ -20,6 +20,15 @@ interface SpanData {
20
20
  timestamp: number;
21
21
  attributes?: Record<string, any>;
22
22
  }>;
23
+ links?: Array<{
24
+ traceId: string;
25
+ spanId: string;
26
+ attributes?: Record<string, any>;
27
+ }>;
28
+ scope?: {
29
+ name?: string;
30
+ version?: string;
31
+ };
23
32
  }
24
33
 
25
34
  declare function isGenAiSpan(span: SpanData): boolean;
package/dist/index.cjs CHANGED
@@ -9,25 +9,9 @@ var protobuf = require('protobufjs');
9
9
  var core = require('@opentelemetry/core');
10
10
 
11
11
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
12
- function _interopNamespace(e) {
13
- if (e && e.__esModule) return e;
14
- var n = Object.create(null);
15
- if (e) {
16
- Object.keys(e).forEach(function (k) {
17
- if (k !== 'default') {
18
- var d = Object.getOwnPropertyDescriptor(e, k);
19
- Object.defineProperty(n, k, d.get ? d : {
20
- enumerable: true,
21
- get: function () { return e[k]; }
22
- });
23
- }
24
- });
25
- }
26
- n.default = e;
27
- return Object.freeze(n);
28
- }
12
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
29
13
 
30
- var protobuf__namespace = /*#__PURE__*/_interopNamespace(protobuf);
14
+ var protobuf__default = /*#__PURE__*/_interopDefault(protobuf);
31
15
 
32
16
  // src/index.ts
33
17
 
@@ -383,10 +367,12 @@ var DevtoolsServer = class {
383
367
  limits;
384
368
  verbose;
385
369
  _port;
370
+ onData;
386
371
  constructor(options = {}) {
387
372
  this.limits = resolveTelemetryLimits(options);
388
373
  this.verbose = options.verbose ?? false;
389
374
  this._port = options.port ?? 4318;
375
+ this.onData = options.onData;
390
376
  this.httpServer = options.server ?? http.createServer();
391
377
  this.wss = new ws.WebSocketServer({ server: this.httpServer, path: options.path ?? "/ws" });
392
378
  this.wss.on("connection", (ws) => {
@@ -480,6 +466,12 @@ var DevtoolsServer = class {
480
466
  client.send(msg);
481
467
  }
482
468
  }
469
+ if (this.onData) {
470
+ try {
471
+ this.onData(data);
472
+ } catch {
473
+ }
474
+ }
483
475
  }
484
476
  log(message) {
485
477
  if (this.verbose) console.log(`[autotel-devtools] ${message}`);
@@ -533,7 +525,10 @@ function flattenAttributes(attrs) {
533
525
  }
534
526
  function nanoToMs(nano) {
535
527
  if (!nano) return 0;
536
- return Number(BigInt(nano) / 1000000n);
528
+ const ns = BigInt(nano);
529
+ const ms = ns / 1000000n;
530
+ const remNs = ns % 1000000n;
531
+ return Number(ms) + Number(remNs) / 1e6;
537
532
  }
538
533
  var SPAN_KIND_MAP = {
539
534
  0: "INTERNAL",
@@ -571,6 +566,7 @@ function parseOtlpTraces(payload) {
571
566
  const service = String(resourceAttrs["service.name"] || "unknown");
572
567
  const scopeSpans = rs.scopeSpans || [];
573
568
  for (const ss of scopeSpans) {
569
+ const scope = ss.scope?.name ? { name: ss.scope.name, version: ss.scope.version || void 0 } : void 0;
574
570
  for (const span of ss.spans || []) {
575
571
  const traceId = normalizeHexId(span.traceId);
576
572
  if (!traceId) continue;
@@ -595,7 +591,13 @@ function parseOtlpTraces(payload) {
595
591
  name: e.name || "",
596
592
  timestamp: nanoToMs(e.timeUnixNano),
597
593
  attributes: flattenAttributes(e.attributes)
598
- }))
594
+ })),
595
+ links: (span.links || []).map((l) => ({
596
+ traceId: normalizeHexId(l.traceId),
597
+ spanId: normalizeHexId(l.spanId),
598
+ attributes: flattenAttributes(l.attributes)
599
+ })),
600
+ scope
599
601
  };
600
602
  const existing = traceMap.get(traceId);
601
603
  if (existing) {
@@ -897,9 +899,9 @@ var TO_OBJECT_OPTIONS = {
897
899
  var cachedRoot = null;
898
900
  function getRoot() {
899
901
  if (cachedRoot) return cachedRoot;
900
- const root = new protobuf__namespace.Root();
902
+ const root = new protobuf__default.default.Root();
901
903
  for (const source of [COMMON_PROTO, RESOURCE_PROTO, TRACE_PROTO, LOGS_PROTO, METRICS_PROTO]) {
902
- protobuf__namespace.parse(source, root, { keepCase: false });
904
+ protobuf__default.default.parse(source, root, { keepCase: false });
903
905
  }
904
906
  root.resolveAll();
905
907
  cachedRoot = root;
@@ -1187,6 +1189,11 @@ var DevtoolsSpanExporter = class {
1187
1189
  timestamp: event.time[0] * 1e3 + event.time[1] / 1e6,
1188
1190
  attributes: event.attributes ? Object.fromEntries(Object.entries(event.attributes)) : void 0
1189
1191
  }));
1192
+ const links = span.links.map((link) => ({
1193
+ traceId: link.context.traceId,
1194
+ spanId: link.context.spanId,
1195
+ attributes: link.attributes ? Object.fromEntries(Object.entries(link.attributes)) : void 0
1196
+ }));
1190
1197
  return {
1191
1198
  traceId: spanContext.traceId,
1192
1199
  spanId: spanContext.spanId,
@@ -1201,9 +1208,15 @@ var DevtoolsSpanExporter = class {
1201
1208
  code: status,
1202
1209
  message: span.status.message
1203
1210
  },
1204
- events: events.length > 0 ? events : void 0
1211
+ events: events.length > 0 ? events : void 0,
1212
+ links: links.length > 0 ? links : void 0,
1213
+ scope: this.convertScope(span)
1205
1214
  };
1206
1215
  }
1216
+ convertScope(span) {
1217
+ const s = span.instrumentationScope ?? span.instrumentationLibrary;
1218
+ return s?.name ? { name: s.name, version: s.version || void 0 } : void 0;
1219
+ }
1207
1220
  /**
1208
1221
  * Convert OpenTelemetry SpanKind to string
1209
1222
  */