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/server/exporter.cjs
CHANGED
|
@@ -105,6 +105,11 @@ var DevtoolsSpanExporter = class {
|
|
|
105
105
|
timestamp: event.time[0] * 1e3 + event.time[1] / 1e6,
|
|
106
106
|
attributes: event.attributes ? Object.fromEntries(Object.entries(event.attributes)) : void 0
|
|
107
107
|
}));
|
|
108
|
+
const links = span.links.map((link) => ({
|
|
109
|
+
traceId: link.context.traceId,
|
|
110
|
+
spanId: link.context.spanId,
|
|
111
|
+
attributes: link.attributes ? Object.fromEntries(Object.entries(link.attributes)) : void 0
|
|
112
|
+
}));
|
|
108
113
|
return {
|
|
109
114
|
traceId: spanContext.traceId,
|
|
110
115
|
spanId: spanContext.spanId,
|
|
@@ -119,9 +124,15 @@ var DevtoolsSpanExporter = class {
|
|
|
119
124
|
code: status,
|
|
120
125
|
message: span.status.message
|
|
121
126
|
},
|
|
122
|
-
events: events.length > 0 ? events : void 0
|
|
127
|
+
events: events.length > 0 ? events : void 0,
|
|
128
|
+
links: links.length > 0 ? links : void 0,
|
|
129
|
+
scope: this.convertScope(span)
|
|
123
130
|
};
|
|
124
131
|
}
|
|
132
|
+
convertScope(span) {
|
|
133
|
+
const s = span.instrumentationScope ?? span.instrumentationLibrary;
|
|
134
|
+
return s?.name ? { name: s.name, version: s.version || void 0 } : void 0;
|
|
135
|
+
}
|
|
125
136
|
/**
|
|
126
137
|
* Convert OpenTelemetry SpanKind to string
|
|
127
138
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/exporter.ts"],"names":[],"mappings":";;;AASO,IAAM,uBAAN,MAAmD;AAAA,EAChD,MAAA;AAAA,EACA,WAAA;AAAA,EAER,WAAA,CAAY,MAAA,EAAwB,WAAA,GAAsB,iBAAA,EAAmB;AAC3E,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,WAAA,GAAc,WAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,CACJ,KAAA,EACA,cAAA,EACe;AAGf,IAAA,cAAA,CAAe,EAAE,IAAA,EAAM,CAAA,EAAuB,CAAA;AAG9C,IAAA,OAAA,CAAQ,OAAA,EAAQ,CAAE,IAAA,CAAK,MAAM;AAC3B,MAAA,IAAI;AACF,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,6BAAA,EAAgC,KAAA,CAAM,MAAM,CAAA,QAAA,CAAU,CAAA;AAGlE,QAAA,MAAM,QAAA,uBAAe,GAAA,EAA4B;AAEjD,QAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,UAAA,MAAM,OAAA,GAAU,IAAA,CAAK,WAAA,EAAY,CAAE,OAAA;AACnC,UAAA,IAAI,CAAC,QAAA,CAAS,GAAA,CAAI,OAAO,CAAA,EAAG;AAC1B,YAAA,QAAA,CAAS,GAAA,CAAI,OAAA,EAAS,EAAE,CAAA;AAAA,UAC1B;AACA,UAAA,QAAA,CAAS,GAAA,CAAI,OAAO,CAAA,CAAG,IAAA,CAAK,IAAI,CAAA;AAAA,QAClC;AAGA,QAAA,KAAA,MAAW,CAAC,OAAA,EAAS,UAAU,CAAA,IAAK,QAAA,EAAU;AAC5C,UAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,kBAAA,CAAmB,OAAA,EAAS,UAAU,CAAA;AACzD,UAAA,OAAA,CAAQ,GAAA;AAAA,YACN,CAAA,gCAAA,EAAmC,QAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA,MAAA,EAAS,WAAW,MAAM,CAAA,MAAA;AAAA,WACnF;AACA,UAAA,IAAA,CAAK,MAAA,CAAO,SAAS,KAAK,CAAA;AAAA,QAC5B;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAA,CAAM,oCAAoC,KAAK,CAAA;AAAA,MACzD;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAA,GAA0B;AAAA,EAEhC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAA,GAA4B;AAAA,EAElC;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAA,CACN,SACA,KAAA,EACW;AAEX,IAAA,MAAM,QAAA,GAAuB,MAAM,GAAA,CAAI,CAAC,SAAS,IAAA,CAAK,WAAA,CAAY,IAAI,CAAC,CAAA;AAGvE,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,YAAY,CAAA,IAAK,QAAA,CAAS,CAAC,CAAA;AAGpE,IAAA,QAAA,CAAS,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,SAAA,GAAY,EAAE,SAAS,CAAA;AAEjD,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,GAAG,QAAA,CAAS,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAC,CAAA;AAC9D,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,GAAG,QAAA,CAAS,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,CAAC,CAAA;AAG1D,IAAA,MAAM,QAAA,GAAW,SAAS,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,MAAA,CAAO,SAAS,OAAO,CAAA;AAC/D,IAAA,MAAM,MAAA,GAAS,WAAW,OAAA,GAAU,IAAA;AAEpC,IAAA,OAAO;AAAA,MACL,OAAA;AAAA,MACA,aAAA,EAAe,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA;AAAA,MAClC,QAAA;AAAA,MACA,KAAA,EAAO,QAAA;AAAA,MACP,SAAA;AAAA,MACA,OAAA;AAAA,MACA,UAAU,OAAA,GAAU,SAAA;AAAA,MACpB,MAAA;AAAA,MACA,SAAS,IAAA,CAAK;AAAA,KAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,IAAA,EAA8B;AAChD,IAAA,MAAM,WAAA,GAAc,KAAK,WAAA,EAAY;AACrC,IAAA,MAAM,SAAA,GAAY,KAAK,SAAA,CAAU,CAAC,IAAI,GAAA,GAAO,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,GAAI,GAAA;AACjE,IAAA,MAAM,OAAA,GAAU,KAAK,OAAA,CAAQ,CAAC,IAAI,GAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA,GAAI,GAAA;AAG3D,IAAA,MAAM,aAAkC,EAAC;AACzC,IAAA,KAAA,MAAW,CAAC,KAAK,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,IAAA,CAAK,UAAU,CAAA,EAAG;AAC1D,MAAA,UAAA,CAAW,GAAG,CAAA,GAAI,KAAA;AAAA,IACpB;AAGA,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,IAAA;AAC/B,IAAA,IAAI,MAAA;AACJ,IAAA,QAAQ,UAAA;AAAY,MAClB,KAAK,CAAA,EAAG;AACN,QAAA,MAAA,GAAS,OAAA;AACT,QAAA;AAAA,MACF;AAAA,MACA,KAAK,CAAA,EAAG;AACN,QAAA,MAAA,GAAS,IAAA;AACT,QAAA;AAAA,MACF;AAAA,MACA,KAAK,CAAA,EAAG;AACN,QAAA,MAAA,GAAS,OAAA;AACT,QAAA;AAAA,MACF;AAAA,MACA,SAAS;AACP,QAAA,MAAA,GAAS,OAAA;AAAA,MACX;AAAA;AAIF,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,MACzC,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,SAAA,EAAW,MAAM,IAAA,CAAK,CAAC,IAAI,GAAA,GAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,GAAI,GAAA;AAAA,MAClD,UAAA,EAAY,KAAA,CAAM,UAAA,GACd,MAAA,CAAO,WAAA,CAAY,OAAO,OAAA,CAAQ,KAAA,CAAM,UAAU,CAAC,CAAA,GACnD;AAAA,KACN,CAAE,CAAA;AAEF,IAAA,OAAO;AAAA,MACL,SAAS,WAAA,CAAY,OAAA;AAAA,MACrB,QAAQ,WAAA,CAAY,MAAA;AAAA,MACpB,cAAe,IAAA,CAAa,YAAA;AAAA,MAC5B,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,IAAA,EAAM,IAAA,CAAK,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA;AAAA,MACpC,SAAA;AAAA,MACA,OAAA;AAAA,MACA,UAAU,OAAA,GAAU,SAAA;AAAA,MACpB,UAAA;AAAA,MACA,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,EAAS,KAAK,MAAA,CAAO;AAAA,OACvB;AAAA,MACA,MAAA,EAAQ,MAAA,CAAO,MAAA,GAAS,CAAA,GAAI,MAAA,GAAS;AAAA,KACvC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,gBACN,IAAA,EAC4D;AAC5D,IAAA,QAAQ,IAAA;AAAM,MACZ,KAAK,CAAA,EAAG;AACN,QAAA,OAAO,UAAA;AAAA,MACT;AAAA,MACA,KAAK,CAAA,EAAG;AACN,QAAA,OAAO,QAAA;AAAA,MACT;AAAA,MACA,KAAK,CAAA,EAAG;AACN,QAAA,OAAO,QAAA;AAAA,MACT;AAAA,MACA,KAAK,CAAA,EAAG;AACN,QAAA,OAAO,UAAA;AAAA,MACT;AAAA,MACA,KAAK,CAAA,EAAG;AACN,QAAA,OAAO,UAAA;AAAA,MACT;AAAA,MACA,SAAS;AACP,QAAA,OAAO,UAAA;AAAA,MACT;AAAA;AACF,EACF;AACF","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 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 };\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,"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"]}
|
package/dist/server/exporter.js
CHANGED
|
@@ -103,6 +103,11 @@ var DevtoolsSpanExporter = class {
|
|
|
103
103
|
timestamp: event.time[0] * 1e3 + event.time[1] / 1e6,
|
|
104
104
|
attributes: event.attributes ? Object.fromEntries(Object.entries(event.attributes)) : void 0
|
|
105
105
|
}));
|
|
106
|
+
const links = span.links.map((link) => ({
|
|
107
|
+
traceId: link.context.traceId,
|
|
108
|
+
spanId: link.context.spanId,
|
|
109
|
+
attributes: link.attributes ? Object.fromEntries(Object.entries(link.attributes)) : void 0
|
|
110
|
+
}));
|
|
106
111
|
return {
|
|
107
112
|
traceId: spanContext.traceId,
|
|
108
113
|
spanId: spanContext.spanId,
|
|
@@ -117,9 +122,15 @@ var DevtoolsSpanExporter = class {
|
|
|
117
122
|
code: status,
|
|
118
123
|
message: span.status.message
|
|
119
124
|
},
|
|
120
|
-
events: events.length > 0 ? events : void 0
|
|
125
|
+
events: events.length > 0 ? events : void 0,
|
|
126
|
+
links: links.length > 0 ? links : void 0,
|
|
127
|
+
scope: this.convertScope(span)
|
|
121
128
|
};
|
|
122
129
|
}
|
|
130
|
+
convertScope(span) {
|
|
131
|
+
const s = span.instrumentationScope ?? span.instrumentationLibrary;
|
|
132
|
+
return s?.name ? { name: s.name, version: s.version || void 0 } : void 0;
|
|
133
|
+
}
|
|
123
134
|
/**
|
|
124
135
|
* Convert OpenTelemetry SpanKind to string
|
|
125
136
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/exporter.ts"],"names":[],"mappings":"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","file":"exporter.js","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 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 };\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,"sources":["../../src/server/exporter.ts"],"names":[],"mappings":";AASO,IAAM,uBAAN,MAAmD;AAAA,EAChD,MAAA;AAAA,EACA,WAAA;AAAA,EAER,WAAA,CAAY,MAAA,EAAwB,WAAA,GAAsB,iBAAA,EAAmB;AAC3E,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,WAAA,GAAc,WAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,CACJ,KAAA,EACA,cAAA,EACe;AAGf,IAAA,cAAA,CAAe,EAAE,IAAA,EAAM,CAAA,EAAuB,CAAA;AAG9C,IAAA,OAAA,CAAQ,OAAA,EAAQ,CAAE,IAAA,CAAK,MAAM;AAC3B,MAAA,IAAI;AACF,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,6BAAA,EAAgC,KAAA,CAAM,MAAM,CAAA,QAAA,CAAU,CAAA;AAGlE,QAAA,MAAM,QAAA,uBAAe,GAAA,EAA4B;AAEjD,QAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,UAAA,MAAM,OAAA,GAAU,IAAA,CAAK,WAAA,EAAY,CAAE,OAAA;AACnC,UAAA,IAAI,CAAC,QAAA,CAAS,GAAA,CAAI,OAAO,CAAA,EAAG;AAC1B,YAAA,QAAA,CAAS,GAAA,CAAI,OAAA,EAAS,EAAE,CAAA;AAAA,UAC1B;AACA,UAAA,QAAA,CAAS,GAAA,CAAI,OAAO,CAAA,CAAG,IAAA,CAAK,IAAI,CAAA;AAAA,QAClC;AAGA,QAAA,KAAA,MAAW,CAAC,OAAA,EAAS,UAAU,CAAA,IAAK,QAAA,EAAU;AAC5C,UAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,kBAAA,CAAmB,OAAA,EAAS,UAAU,CAAA;AACzD,UAAA,OAAA,CAAQ,GAAA;AAAA,YACN,CAAA,gCAAA,EAAmC,QAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA,MAAA,EAAS,WAAW,MAAM,CAAA,MAAA;AAAA,WACnF;AACA,UAAA,IAAA,CAAK,MAAA,CAAO,SAAS,KAAK,CAAA;AAAA,QAC5B;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAA,CAAM,oCAAoC,KAAK,CAAA;AAAA,MACzD;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAA,GAA0B;AAAA,EAEhC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAA,GAA4B;AAAA,EAElC;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAA,CACN,SACA,KAAA,EACW;AAEX,IAAA,MAAM,QAAA,GAAuB,MAAM,GAAA,CAAI,CAAC,SAAS,IAAA,CAAK,WAAA,CAAY,IAAI,CAAC,CAAA;AAGvE,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,YAAY,CAAA,IAAK,QAAA,CAAS,CAAC,CAAA;AAGpE,IAAA,QAAA,CAAS,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,SAAA,GAAY,EAAE,SAAS,CAAA;AAEjD,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,GAAG,QAAA,CAAS,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAC,CAAA;AAC9D,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,GAAG,QAAA,CAAS,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,CAAC,CAAA;AAG1D,IAAA,MAAM,QAAA,GAAW,SAAS,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,MAAA,CAAO,SAAS,OAAO,CAAA;AAC/D,IAAA,MAAM,MAAA,GAAS,WAAW,OAAA,GAAU,IAAA;AAEpC,IAAA,OAAO;AAAA,MACL,OAAA;AAAA,MACA,aAAA,EAAe,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA;AAAA,MAClC,QAAA;AAAA,MACA,KAAA,EAAO,QAAA;AAAA,MACP,SAAA;AAAA,MACA,OAAA;AAAA,MACA,UAAU,OAAA,GAAU,SAAA;AAAA,MACpB,MAAA;AAAA,MACA,SAAS,IAAA,CAAK;AAAA,KAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,IAAA,EAA8B;AAChD,IAAA,MAAM,WAAA,GAAc,KAAK,WAAA,EAAY;AACrC,IAAA,MAAM,SAAA,GAAY,KAAK,SAAA,CAAU,CAAC,IAAI,GAAA,GAAO,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,GAAI,GAAA;AACjE,IAAA,MAAM,OAAA,GAAU,KAAK,OAAA,CAAQ,CAAC,IAAI,GAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA,GAAI,GAAA;AAG3D,IAAA,MAAM,aAAkC,EAAC;AACzC,IAAA,KAAA,MAAW,CAAC,KAAK,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,IAAA,CAAK,UAAU,CAAA,EAAG;AAC1D,MAAA,UAAA,CAAW,GAAG,CAAA,GAAI,KAAA;AAAA,IACpB;AAGA,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,IAAA;AAC/B,IAAA,IAAI,MAAA;AACJ,IAAA,QAAQ,UAAA;AAAY,MAClB,KAAK,CAAA,EAAG;AACN,QAAA,MAAA,GAAS,OAAA;AACT,QAAA;AAAA,MACF;AAAA,MACA,KAAK,CAAA,EAAG;AACN,QAAA,MAAA,GAAS,IAAA;AACT,QAAA;AAAA,MACF;AAAA,MACA,KAAK,CAAA,EAAG;AACN,QAAA,MAAA,GAAS,OAAA;AACT,QAAA;AAAA,MACF;AAAA,MACA,SAAS;AACP,QAAA,MAAA,GAAS,OAAA;AAAA,MACX;AAAA;AAIF,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,MACzC,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,SAAA,EAAW,MAAM,IAAA,CAAK,CAAC,IAAI,GAAA,GAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,GAAI,GAAA;AAAA,MAClD,UAAA,EAAY,KAAA,CAAM,UAAA,GACd,MAAA,CAAO,WAAA,CAAY,OAAO,OAAA,CAAQ,KAAA,CAAM,UAAU,CAAC,CAAA,GACnD;AAAA,KACN,CAAE,CAAA;AAGF,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,MACtC,OAAA,EAAS,KAAK,OAAA,CAAQ,OAAA;AAAA,MACtB,MAAA,EAAQ,KAAK,OAAA,CAAQ,MAAA;AAAA,MACrB,UAAA,EAAY,IAAA,CAAK,UAAA,GACb,MAAA,CAAO,WAAA,CAAY,OAAO,OAAA,CAAQ,IAAA,CAAK,UAAU,CAAC,CAAA,GAClD;AAAA,KACN,CAAE,CAAA;AAEF,IAAA,OAAO;AAAA,MACL,SAAS,WAAA,CAAY,OAAA;AAAA,MACrB,QAAQ,WAAA,CAAY,MAAA;AAAA,MACpB,cAAe,IAAA,CAAa,YAAA;AAAA,MAC5B,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,IAAA,EAAM,IAAA,CAAK,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA;AAAA,MACpC,SAAA;AAAA,MACA,OAAA;AAAA,MACA,UAAU,OAAA,GAAU,SAAA;AAAA,MACpB,UAAA;AAAA,MACA,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,EAAS,KAAK,MAAA,CAAO;AAAA,OACvB;AAAA,MACA,MAAA,EAAQ,MAAA,CAAO,MAAA,GAAS,CAAA,GAAI,MAAA,GAAS,MAAA;AAAA,MACrC,KAAA,EAAO,KAAA,CAAM,MAAA,GAAS,CAAA,GAAI,KAAA,GAAQ,MAAA;AAAA,MAClC,KAAA,EAAO,IAAA,CAAK,YAAA,CAAa,IAAI;AAAA,KAC/B;AAAA,EACF;AAAA,EAEQ,aAAa,IAAA,EAAuC;AAC1D,IAAA,MAAM,CAAA,GACH,IAAA,CAAa,oBAAA,IACb,IAAA,CAAa,sBAAA;AAChB,IAAA,OAAO,CAAA,EAAG,IAAA,GAAO,EAAE,IAAA,EAAM,CAAA,CAAE,MAAM,OAAA,EAAS,CAAA,CAAE,OAAA,IAAW,MAAA,EAAU,GAAI,MAAA;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA,EAKQ,gBACN,IAAA,EAC4D;AAC5D,IAAA,QAAQ,IAAA;AAAM,MACZ,KAAK,CAAA,EAAG;AACN,QAAA,OAAO,UAAA;AAAA,MACT;AAAA,MACA,KAAK,CAAA,EAAG;AACN,QAAA,OAAO,QAAA;AAAA,MACT;AAAA,MACA,KAAK,CAAA,EAAG;AACN,QAAA,OAAO,QAAA;AAAA,MACT;AAAA,MACA,KAAK,CAAA,EAAG;AACN,QAAA,OAAO,UAAA;AAAA,MACT;AAAA,MACA,KAAK,CAAA,EAAG;AACN,QAAA,OAAO,UAAA;AAAA,MACT;AAAA,MACA,SAAS;AACP,QAAA,OAAO,UAAA;AAAA,MACT;AAAA;AACF,EACF;AACF","file":"exporter.js","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"]}
|
package/dist/server/index.cjs
CHANGED
|
@@ -375,12 +375,17 @@ var DevtoolsServer = class {
|
|
|
375
375
|
limits;
|
|
376
376
|
verbose;
|
|
377
377
|
_port;
|
|
378
|
+
onData;
|
|
378
379
|
constructor(options = {}) {
|
|
379
380
|
this.limits = resolveTelemetryLimits(options);
|
|
380
381
|
this.verbose = options.verbose ?? false;
|
|
381
382
|
this._port = options.port ?? 4318;
|
|
383
|
+
this.onData = options.onData;
|
|
382
384
|
this.httpServer = options.server ?? http.createServer();
|
|
383
385
|
this.wss = new ws.WebSocketServer({ server: this.httpServer, path: options.path ?? "/ws" });
|
|
386
|
+
this.wss.on("error", (err) => {
|
|
387
|
+
if (this.httpServer.listening) throw err;
|
|
388
|
+
});
|
|
384
389
|
this.wss.on("connection", (ws) => {
|
|
385
390
|
this.clients.add(ws);
|
|
386
391
|
this.log(`Client connected (${this.clients.size} total)`);
|
|
@@ -472,6 +477,12 @@ var DevtoolsServer = class {
|
|
|
472
477
|
client.send(msg);
|
|
473
478
|
}
|
|
474
479
|
}
|
|
480
|
+
if (this.onData) {
|
|
481
|
+
try {
|
|
482
|
+
this.onData(data);
|
|
483
|
+
} catch {
|
|
484
|
+
}
|
|
485
|
+
}
|
|
475
486
|
}
|
|
476
487
|
log(message) {
|
|
477
488
|
if (this.verbose) console.log(`[autotel-devtools] ${message}`);
|
|
@@ -589,6 +600,11 @@ var DevtoolsSpanExporter = class {
|
|
|
589
600
|
timestamp: event.time[0] * 1e3 + event.time[1] / 1e6,
|
|
590
601
|
attributes: event.attributes ? Object.fromEntries(Object.entries(event.attributes)) : void 0
|
|
591
602
|
}));
|
|
603
|
+
const links = span.links.map((link) => ({
|
|
604
|
+
traceId: link.context.traceId,
|
|
605
|
+
spanId: link.context.spanId,
|
|
606
|
+
attributes: link.attributes ? Object.fromEntries(Object.entries(link.attributes)) : void 0
|
|
607
|
+
}));
|
|
592
608
|
return {
|
|
593
609
|
traceId: spanContext.traceId,
|
|
594
610
|
spanId: spanContext.spanId,
|
|
@@ -603,9 +619,15 @@ var DevtoolsSpanExporter = class {
|
|
|
603
619
|
code: status,
|
|
604
620
|
message: span.status.message
|
|
605
621
|
},
|
|
606
|
-
events: events.length > 0 ? events : void 0
|
|
622
|
+
events: events.length > 0 ? events : void 0,
|
|
623
|
+
links: links.length > 0 ? links : void 0,
|
|
624
|
+
scope: this.convertScope(span)
|
|
607
625
|
};
|
|
608
626
|
}
|
|
627
|
+
convertScope(span) {
|
|
628
|
+
const s = span.instrumentationScope ?? span.instrumentationLibrary;
|
|
629
|
+
return s?.name ? { name: s.name, version: s.version || void 0 } : void 0;
|
|
630
|
+
}
|
|
609
631
|
/**
|
|
610
632
|
* Convert OpenTelemetry SpanKind to string
|
|
611
633
|
*/
|
|
@@ -974,7 +996,10 @@ function flattenAttributes(attrs) {
|
|
|
974
996
|
}
|
|
975
997
|
function nanoToMs(nano) {
|
|
976
998
|
if (!nano) return 0;
|
|
977
|
-
|
|
999
|
+
const ns = BigInt(nano);
|
|
1000
|
+
const ms = ns / 1000000n;
|
|
1001
|
+
const remNs = ns % 1000000n;
|
|
1002
|
+
return Number(ms) + Number(remNs) / 1e6;
|
|
978
1003
|
}
|
|
979
1004
|
var SPAN_KIND_MAP = {
|
|
980
1005
|
0: "INTERNAL",
|
|
@@ -1012,6 +1037,7 @@ function parseOtlpTraces(payload) {
|
|
|
1012
1037
|
const service = String(resourceAttrs["service.name"] || "unknown");
|
|
1013
1038
|
const scopeSpans = rs.scopeSpans || [];
|
|
1014
1039
|
for (const ss of scopeSpans) {
|
|
1040
|
+
const scope = ss.scope?.name ? { name: ss.scope.name, version: ss.scope.version || void 0 } : void 0;
|
|
1015
1041
|
for (const span of ss.spans || []) {
|
|
1016
1042
|
const traceId = normalizeHexId(span.traceId);
|
|
1017
1043
|
if (!traceId) continue;
|
|
@@ -1036,7 +1062,13 @@ function parseOtlpTraces(payload) {
|
|
|
1036
1062
|
name: e.name || "",
|
|
1037
1063
|
timestamp: nanoToMs(e.timeUnixNano),
|
|
1038
1064
|
attributes: flattenAttributes(e.attributes)
|
|
1039
|
-
}))
|
|
1065
|
+
})),
|
|
1066
|
+
links: (span.links || []).map((l) => ({
|
|
1067
|
+
traceId: normalizeHexId(l.traceId),
|
|
1068
|
+
spanId: normalizeHexId(l.spanId),
|
|
1069
|
+
attributes: flattenAttributes(l.attributes)
|
|
1070
|
+
})),
|
|
1071
|
+
scope
|
|
1040
1072
|
};
|
|
1041
1073
|
const existing = traceMap.get(traceId);
|
|
1042
1074
|
if (existing) {
|