autotel-devtools 15.0.0 → 17.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.
Files changed (52) hide show
  1. package/dist/cli.cjs +1 -2
  2. package/dist/cli.js +1 -2
  3. package/dist/error-aggregator-BrgYNNoC.d.ts +1 -2
  4. package/dist/error-aggregator-bZ-prq97.d.cts +1 -2
  5. package/dist/exporter-BLqTs00O.d.ts +1 -2
  6. package/dist/exporter-BSIS3Qgy.d.cts +1 -2
  7. package/dist/genai/index.cjs +1 -2
  8. package/dist/genai/index.d.cts +1 -2
  9. package/dist/genai/index.d.ts +1 -2
  10. package/dist/genai/index.js +1 -2
  11. package/dist/http-BUHnkhrC.cjs +1 -2
  12. package/dist/http-yIS667nX.js +1 -2
  13. package/dist/index.cjs +1 -2
  14. package/dist/index.d.cts +1 -2
  15. package/dist/index.d.ts +1 -2
  16. package/dist/index.js +1 -2
  17. package/dist/listen-DGzVi7DE.cjs +1 -2
  18. package/dist/listen-NVMbBWHw.js +1 -2
  19. package/dist/resource-utils-B4UVvfnH.js +1 -2
  20. package/dist/resource-utils-DjHJB6uc.cjs +1 -2
  21. package/dist/server/exporter.cjs +1 -2
  22. package/dist/server/exporter.js +1 -2
  23. package/dist/server/index.d.cts +1 -2
  24. package/dist/server/index.d.ts +1 -2
  25. package/dist/server/log-exporter.cjs +1 -2
  26. package/dist/server/log-exporter.d.cts +1 -2
  27. package/dist/server/log-exporter.d.ts +1 -2
  28. package/dist/server/log-exporter.js +1 -2
  29. package/dist/server/remote-exporter.cjs +1 -2
  30. package/dist/server/remote-exporter.d.cts +1 -2
  31. package/dist/server/remote-exporter.d.ts +1 -2
  32. package/dist/server/remote-exporter.js +1 -2
  33. package/dist/widget.global.js +13 -13
  34. package/package.json +18 -18
  35. package/dist/cli.cjs.map +0 -1
  36. package/dist/cli.js.map +0 -1
  37. package/dist/genai/index.cjs.map +0 -1
  38. package/dist/genai/index.js.map +0 -1
  39. package/dist/http-BUHnkhrC.cjs.map +0 -1
  40. package/dist/http-yIS667nX.js.map +0 -1
  41. package/dist/index.cjs.map +0 -1
  42. package/dist/index.js.map +0 -1
  43. package/dist/listen-DGzVi7DE.cjs.map +0 -1
  44. package/dist/listen-NVMbBWHw.js.map +0 -1
  45. package/dist/resource-utils-B4UVvfnH.js.map +0 -1
  46. package/dist/resource-utils-DjHJB6uc.cjs.map +0 -1
  47. package/dist/server/exporter.cjs.map +0 -1
  48. package/dist/server/exporter.js.map +0 -1
  49. package/dist/server/log-exporter.cjs.map +0 -1
  50. package/dist/server/log-exporter.js.map +0 -1
  51. package/dist/server/remote-exporter.cjs.map +0 -1
  52. package/dist/server/remote-exporter.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"log-exporter.cjs","names":["getResourceName","ExportResultCode"],"sources":["../../src/server/log-exporter.ts"],"sourcesContent":["/**\n * Log record exporter that sends OTel logs to a Devtools server HTTP ingest.\n * Use with BatchLogRecordProcessor when you want to view logs in the Autotel widget/extension.\n *\n * @example\n * ```typescript\n * import { BatchLogRecordProcessor } from '@opentelemetry/sdk-logs';\n * import { DevtoolsLogExporter } from '@autotel/devtools/server';\n * import { init } from 'autotel';\n *\n * init({\n * service: 'my-app',\n * logRecordProcessors: [\n * new BatchLogRecordProcessor(\n * new DevtoolsLogExporter({ endpoint: 'http://localhost:8082' })\n * ),\n * ],\n * });\n * ```\n */\n\nimport type { ExportResult } from '@opentelemetry/core';\nimport { ExportResultCode } from '@opentelemetry/core';\nimport type { LogRecordExporter } from '@opentelemetry/sdk-logs';\nimport type { ReadableLogRecord } from '@opentelemetry/sdk-logs';\nimport type { LogData } from './types';\nimport { getResourceName } from './resource-utils';\n\nexport interface DevtoolsLogExporterOptions {\n /**\n * Base URL of the Devtools HTTP ingest server\n * e.g. 'http://localhost:8082'\n */\n endpoint: string;\n\n /**\n * API key for authentication (if server requires it)\n */\n apiKey?: string;\n\n /**\n * Request timeout in milliseconds (default: 5000)\n */\n timeout?: number;\n}\n\nconst defaultTimeout = 5000;\n\nfunction hrTimeToMs(hrTime: [number, number]): number {\n return hrTime[0] * 1000 + hrTime[1] / 1e6;\n}\n\nfunction bodyToPayload(\n body: ReadableLogRecord['body'],\n): string | Record<string, unknown> {\n if (body === undefined) return '';\n if (typeof body === 'string') return body;\n if (typeof body === 'object' && body !== null)\n return body as Record<string, unknown>;\n return String(body);\n}\n\nfunction recordToLogData(record: ReadableLogRecord, index: number): LogData {\n const id = `log-${Date.now()}-${index}-${Math.random().toString(36).slice(2, 9)}`;\n const timestamp = hrTimeToMs(record.hrTime);\n const body = bodyToPayload(record.body);\n const attributes =\n record.attributes && Object.keys(record.attributes).length > 0\n ? (record.attributes as Record<string, unknown>)\n : undefined;\n const resource =\n record.resource?.attributes &&\n Object.keys(record.resource.attributes).length > 0\n ? (record.resource.attributes as Record<string, unknown>)\n : undefined;\n\n const log: LogData = {\n id,\n resourceName: getResourceName(resource),\n severityText: record.severityText,\n severityNumber: record.severityNumber,\n body,\n timestamp,\n attributes,\n resource,\n };\n\n if (record.spanContext) {\n log.traceId = record.spanContext.traceId;\n log.spanId = record.spanContext.spanId;\n }\n\n return log;\n}\n\nexport class DevtoolsLogExporter implements LogRecordExporter {\n private endpoint: string;\n private apiKey: string;\n private timeout: number;\n private isShutdown = false;\n\n constructor(options: DevtoolsLogExporterOptions) {\n this.endpoint = options.endpoint.replace(/\\/$/, '');\n this.apiKey = options.apiKey ?? '';\n this.timeout = options.timeout ?? defaultTimeout;\n }\n\n export(\n logs: ReadableLogRecord[],\n resultCallback: (result: ExportResult) => void,\n ): void {\n if (this.isShutdown || logs.length === 0) {\n resultCallback({ code: ExportResultCode.SUCCESS });\n return;\n }\n\n const payload = { logs: logs.map((r, i) => recordToLogData(r, i)) };\n const url = `${this.endpoint}/ingest/logs`;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (this.apiKey) {\n headers['Authorization'] = `Bearer ${this.apiKey}`;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n signal: controller.signal,\n })\n .then((res) => {\n clearTimeout(timeoutId);\n if (!res.ok) {\n throw new Error(\n `Devtools log ingest failed: ${res.status} ${res.statusText}`,\n );\n }\n resultCallback({ code: ExportResultCode.SUCCESS });\n })\n .catch((err) => {\n clearTimeout(timeoutId);\n resultCallback({\n code: ExportResultCode.FAILED,\n error: err instanceof Error ? err : new Error(String(err)),\n });\n });\n }\n\n shutdown(): Promise<void> {\n this.isShutdown = true;\n return Promise.resolve();\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve();\n }\n}\n"],"mappings":";;;;;AA8CA,MAAM,iBAAiB;AAEvB,SAAS,WAAW,QAAkC;CACpD,OAAO,OAAO,KAAK,MAAO,OAAO,KAAK;AACxC;AAEA,SAAS,cACP,MACkC;CAClC,IAAI,SAAS,QAAW,OAAO;CAC/B,IAAI,OAAO,SAAS,UAAU,OAAO;CACrC,IAAI,OAAO,SAAS,YAAY,SAAS,MACvC,OAAO;CACT,OAAO,OAAO,IAAI;AACpB;AAEA,SAAS,gBAAgB,QAA2B,OAAwB;CAC1E,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE,GAAG,MAAM,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;CAC9E,MAAM,YAAY,WAAW,OAAO,MAAM;CAC1C,MAAM,OAAO,cAAc,OAAO,IAAI;CACtC,MAAM,aACJ,OAAO,cAAc,OAAO,KAAK,OAAO,UAAU,CAAC,CAAC,SAAS,IACxD,OAAO,aACR;CACN,MAAM,WACJ,OAAO,UAAU,cACjB,OAAO,KAAK,OAAO,SAAS,UAAU,CAAC,CAAC,SAAS,IAC5C,OAAO,SAAS,aACjB;CAEN,MAAM,MAAe;EACnB;EACA,cAAcA,uCAAgB,QAAQ;EACtC,cAAc,OAAO;EACrB,gBAAgB,OAAO;EACvB;EACA;EACA;EACA;CACF;CAEA,IAAI,OAAO,aAAa;EACtB,IAAI,UAAU,OAAO,YAAY;EACjC,IAAI,SAAS,OAAO,YAAY;CAClC;CAEA,OAAO;AACT;AAEA,IAAa,sBAAb,MAA8D;CAC5D,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ,aAAa;CAErB,YAAY,SAAqC;EAC/C,KAAK,WAAW,QAAQ,SAAS,QAAQ,OAAO,EAAE;EAClD,KAAK,SAAS,QAAQ,UAAU;EAChC,KAAK,UAAU,QAAQ,WAAW;CACpC;CAEA,OACE,MACA,gBACM;EACN,IAAI,KAAK,cAAc,KAAK,WAAW,GAAG;GACxC,eAAe,EAAE,MAAMC,qCAAiB,QAAQ,CAAC;GACjD;EACF;EAEA,MAAM,UAAU,EAAE,MAAM,KAAK,KAAK,GAAG,MAAM,gBAAgB,GAAG,CAAC,CAAC,EAAE;EAClE,MAAM,MAAM,GAAG,KAAK,SAAS;EAC7B,MAAM,UAAkC,EACtC,gBAAgB,mBAClB;EACA,IAAI,KAAK,QACP,QAAQ,mBAAmB,UAAU,KAAK;EAG5C,MAAM,aAAa,IAAI,gBAAgB;EACvC,MAAM,YAAY,iBAAiB,WAAW,MAAM,GAAG,KAAK,OAAO;EAEnE,MAAM,KAAK;GACT,QAAQ;GACR;GACA,MAAM,KAAK,UAAU,OAAO;GAC5B,QAAQ,WAAW;EACrB,CAAC,CAAC,CACC,MAAM,QAAQ;GACb,aAAa,SAAS;GACtB,IAAI,CAAC,IAAI,IACP,MAAM,IAAI,MACR,+BAA+B,IAAI,OAAO,GAAG,IAAI,YACnD;GAEF,eAAe,EAAE,MAAMA,qCAAiB,QAAQ,CAAC;EACnD,CAAC,CAAC,CACD,OAAO,QAAQ;GACd,aAAa,SAAS;GACtB,eAAe;IACb,MAAMA,qCAAiB;IACvB,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;GAC3D,CAAC;EACH,CAAC;CACL;CAEA,WAA0B;EACxB,KAAK,aAAa;EAClB,OAAO,QAAQ,QAAQ;CACzB;CAEA,aAA4B;EAC1B,OAAO,QAAQ,QAAQ;CACzB;AACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"log-exporter.js","names":[],"sources":["../../src/server/log-exporter.ts"],"sourcesContent":["/**\n * Log record exporter that sends OTel logs to a Devtools server HTTP ingest.\n * Use with BatchLogRecordProcessor when you want to view logs in the Autotel widget/extension.\n *\n * @example\n * ```typescript\n * import { BatchLogRecordProcessor } from '@opentelemetry/sdk-logs';\n * import { DevtoolsLogExporter } from '@autotel/devtools/server';\n * import { init } from 'autotel';\n *\n * init({\n * service: 'my-app',\n * logRecordProcessors: [\n * new BatchLogRecordProcessor(\n * new DevtoolsLogExporter({ endpoint: 'http://localhost:8082' })\n * ),\n * ],\n * });\n * ```\n */\n\nimport type { ExportResult } from '@opentelemetry/core';\nimport { ExportResultCode } from '@opentelemetry/core';\nimport type { LogRecordExporter } from '@opentelemetry/sdk-logs';\nimport type { ReadableLogRecord } from '@opentelemetry/sdk-logs';\nimport type { LogData } from './types';\nimport { getResourceName } from './resource-utils';\n\nexport interface DevtoolsLogExporterOptions {\n /**\n * Base URL of the Devtools HTTP ingest server\n * e.g. 'http://localhost:8082'\n */\n endpoint: string;\n\n /**\n * API key for authentication (if server requires it)\n */\n apiKey?: string;\n\n /**\n * Request timeout in milliseconds (default: 5000)\n */\n timeout?: number;\n}\n\nconst defaultTimeout = 5000;\n\nfunction hrTimeToMs(hrTime: [number, number]): number {\n return hrTime[0] * 1000 + hrTime[1] / 1e6;\n}\n\nfunction bodyToPayload(\n body: ReadableLogRecord['body'],\n): string | Record<string, unknown> {\n if (body === undefined) return '';\n if (typeof body === 'string') return body;\n if (typeof body === 'object' && body !== null)\n return body as Record<string, unknown>;\n return String(body);\n}\n\nfunction recordToLogData(record: ReadableLogRecord, index: number): LogData {\n const id = `log-${Date.now()}-${index}-${Math.random().toString(36).slice(2, 9)}`;\n const timestamp = hrTimeToMs(record.hrTime);\n const body = bodyToPayload(record.body);\n const attributes =\n record.attributes && Object.keys(record.attributes).length > 0\n ? (record.attributes as Record<string, unknown>)\n : undefined;\n const resource =\n record.resource?.attributes &&\n Object.keys(record.resource.attributes).length > 0\n ? (record.resource.attributes as Record<string, unknown>)\n : undefined;\n\n const log: LogData = {\n id,\n resourceName: getResourceName(resource),\n severityText: record.severityText,\n severityNumber: record.severityNumber,\n body,\n timestamp,\n attributes,\n resource,\n };\n\n if (record.spanContext) {\n log.traceId = record.spanContext.traceId;\n log.spanId = record.spanContext.spanId;\n }\n\n return log;\n}\n\nexport class DevtoolsLogExporter implements LogRecordExporter {\n private endpoint: string;\n private apiKey: string;\n private timeout: number;\n private isShutdown = false;\n\n constructor(options: DevtoolsLogExporterOptions) {\n this.endpoint = options.endpoint.replace(/\\/$/, '');\n this.apiKey = options.apiKey ?? '';\n this.timeout = options.timeout ?? defaultTimeout;\n }\n\n export(\n logs: ReadableLogRecord[],\n resultCallback: (result: ExportResult) => void,\n ): void {\n if (this.isShutdown || logs.length === 0) {\n resultCallback({ code: ExportResultCode.SUCCESS });\n return;\n }\n\n const payload = { logs: logs.map((r, i) => recordToLogData(r, i)) };\n const url = `${this.endpoint}/ingest/logs`;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (this.apiKey) {\n headers['Authorization'] = `Bearer ${this.apiKey}`;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n signal: controller.signal,\n })\n .then((res) => {\n clearTimeout(timeoutId);\n if (!res.ok) {\n throw new Error(\n `Devtools log ingest failed: ${res.status} ${res.statusText}`,\n );\n }\n resultCallback({ code: ExportResultCode.SUCCESS });\n })\n .catch((err) => {\n clearTimeout(timeoutId);\n resultCallback({\n code: ExportResultCode.FAILED,\n error: err instanceof Error ? err : new Error(String(err)),\n });\n });\n }\n\n shutdown(): Promise<void> {\n this.isShutdown = true;\n return Promise.resolve();\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve();\n }\n}\n"],"mappings":";;;;AA8CA,MAAM,iBAAiB;AAEvB,SAAS,WAAW,QAAkC;CACpD,OAAO,OAAO,KAAK,MAAO,OAAO,KAAK;AACxC;AAEA,SAAS,cACP,MACkC;CAClC,IAAI,SAAS,QAAW,OAAO;CAC/B,IAAI,OAAO,SAAS,UAAU,OAAO;CACrC,IAAI,OAAO,SAAS,YAAY,SAAS,MACvC,OAAO;CACT,OAAO,OAAO,IAAI;AACpB;AAEA,SAAS,gBAAgB,QAA2B,OAAwB;CAC1E,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE,GAAG,MAAM,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;CAC9E,MAAM,YAAY,WAAW,OAAO,MAAM;CAC1C,MAAM,OAAO,cAAc,OAAO,IAAI;CACtC,MAAM,aACJ,OAAO,cAAc,OAAO,KAAK,OAAO,UAAU,CAAC,CAAC,SAAS,IACxD,OAAO,aACR;CACN,MAAM,WACJ,OAAO,UAAU,cACjB,OAAO,KAAK,OAAO,SAAS,UAAU,CAAC,CAAC,SAAS,IAC5C,OAAO,SAAS,aACjB;CAEN,MAAM,MAAe;EACnB;EACA,cAAc,gBAAgB,QAAQ;EACtC,cAAc,OAAO;EACrB,gBAAgB,OAAO;EACvB;EACA;EACA;EACA;CACF;CAEA,IAAI,OAAO,aAAa;EACtB,IAAI,UAAU,OAAO,YAAY;EACjC,IAAI,SAAS,OAAO,YAAY;CAClC;CAEA,OAAO;AACT;AAEA,IAAa,sBAAb,MAA8D;CAC5D,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ,aAAa;CAErB,YAAY,SAAqC;EAC/C,KAAK,WAAW,QAAQ,SAAS,QAAQ,OAAO,EAAE;EAClD,KAAK,SAAS,QAAQ,UAAU;EAChC,KAAK,UAAU,QAAQ,WAAW;CACpC;CAEA,OACE,MACA,gBACM;EACN,IAAI,KAAK,cAAc,KAAK,WAAW,GAAG;GACxC,eAAe,EAAE,MAAM,iBAAiB,QAAQ,CAAC;GACjD;EACF;EAEA,MAAM,UAAU,EAAE,MAAM,KAAK,KAAK,GAAG,MAAM,gBAAgB,GAAG,CAAC,CAAC,EAAE;EAClE,MAAM,MAAM,GAAG,KAAK,SAAS;EAC7B,MAAM,UAAkC,EACtC,gBAAgB,mBAClB;EACA,IAAI,KAAK,QACP,QAAQ,mBAAmB,UAAU,KAAK;EAG5C,MAAM,aAAa,IAAI,gBAAgB;EACvC,MAAM,YAAY,iBAAiB,WAAW,MAAM,GAAG,KAAK,OAAO;EAEnE,MAAM,KAAK;GACT,QAAQ;GACR;GACA,MAAM,KAAK,UAAU,OAAO;GAC5B,QAAQ,WAAW;EACrB,CAAC,CAAC,CACC,MAAM,QAAQ;GACb,aAAa,SAAS;GACtB,IAAI,CAAC,IAAI,IACP,MAAM,IAAI,MACR,+BAA+B,IAAI,OAAO,GAAG,IAAI,YACnD;GAEF,eAAe,EAAE,MAAM,iBAAiB,QAAQ,CAAC;EACnD,CAAC,CAAC,CACD,OAAO,QAAQ;GACd,aAAa,SAAS;GACtB,eAAe;IACb,MAAM,iBAAiB;IACvB,OAAO,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;GAC3D,CAAC;EACH,CAAC;CACL;CAEA,WAA0B;EACxB,KAAK,aAAa;EAClB,OAAO,QAAQ,QAAQ;CACzB;CAEA,aAA4B;EAC1B,OAAO,QAAQ,QAAQ;CACzB;AACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"remote-exporter.cjs","names":[],"sources":["../../src/server/remote-exporter.ts"],"sourcesContent":["/**\n * Remote Span Exporter for sending traces to a hosted DevtoolsServer\n *\n * Use this when the DevtoolsServer is running on a different machine/process.\n *\n * @example\n * ```typescript\n * import { DevtoolsRemoteExporter } from '@autotel/devtools/server';\n * import { init } from 'autotel';\n *\n * init({\n * service: 'my-app',\n * spanExporters: [\n * new DevtoolsRemoteExporter({\n * endpoint: 'https://autotel.mycompany.com',\n * apiKey: process.env.AUTOTEL_API_KEY,\n * })\n * ]\n * });\n * ```\n */\n\nimport type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';\nimport type { ExportResult, ExportResultCode } from '@opentelemetry/core';\nimport type { TraceData, SpanData } from './types';\n\nexport interface DevtoolsRemoteExporterOptions {\n /**\n * Base URL of the Devtools server\n * e.g., 'https://autotel.mycompany.com' or 'http://localhost:8082'\n */\n endpoint: string;\n\n /**\n * API key for authentication (if server requires it)\n */\n apiKey?: string;\n\n /**\n * Service name for traces (default: 'unknown-service')\n */\n serviceName?: string;\n\n /**\n * Request timeout in milliseconds (default: 5000)\n */\n timeout?: number;\n\n /**\n * Retry failed requests (default: true)\n */\n retry?: boolean;\n\n /**\n * Number of retries (default: 3)\n */\n retryCount?: number;\n\n /**\n * Retry delay in milliseconds (default: 1000)\n */\n retryDelay?: number;\n\n /**\n * Enable verbose logging (default: false)\n */\n verbose?: boolean;\n}\n\nexport class DevtoolsRemoteExporter implements SpanExporter {\n private options: Required<DevtoolsRemoteExporterOptions>;\n private pendingExports: Promise<void>[] = [];\n\n constructor(options: DevtoolsRemoteExporterOptions) {\n this.options = {\n endpoint: options.endpoint.replace(/\\/$/, ''), // Remove trailing slash\n apiKey: options.apiKey ?? '',\n serviceName: options.serviceName ?? 'unknown-service',\n timeout: options.timeout ?? 5000,\n retry: options.retry ?? true,\n retryCount: options.retryCount ?? 3,\n retryDelay: options.retryDelay ?? 1000,\n verbose: options.verbose ?? false,\n };\n }\n\n /**\n * Export spans to the remote server\n */\n async export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void,\n ): Promise<void> {\n // Start export asynchronously\n const exportPromise = this.doExport(spans)\n .then(() => {\n resultCallback({ code: 0 as ExportResultCode }); // SUCCESS\n })\n .catch((error) => {\n this.log(`Export failed: ${error.message}`);\n resultCallback({ code: 1 as ExportResultCode }); // FAILED\n });\n\n this.pendingExports.push(exportPromise);\n\n // Clean up completed exports\n exportPromise.finally(() => {\n const index = this.pendingExports.indexOf(exportPromise);\n if (index !== -1) {\n this.pendingExports.splice(index, 1);\n }\n });\n }\n\n private async doExport(spans: ReadableSpan[]): Promise<void> {\n if (spans.length === 0) return;\n\n this.log(`Exporting ${spans.length} span(s) to ${this.options.endpoint}`);\n\n // Group spans by trace ID and convert\n const traceMap = new Map<string, ReadableSpan[]>();\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 const traces: TraceData[] = [];\n for (const [traceId, traceSpans] of traceMap) {\n traces.push(this.convertToTraceData(traceId, traceSpans));\n }\n\n // Send with retry\n await this.sendWithRetry({ traces });\n }\n\n private async sendWithRetry(payload: { traces: TraceData[] }): Promise<void> {\n let lastError: Error | null = null;\n const maxAttempts = this.options.retry ? this.options.retryCount : 1;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n await this.send(payload);\n return;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n this.log(\n `Attempt ${attempt}/${maxAttempts} failed: ${lastError.message}`,\n );\n\n if (attempt < maxAttempts) {\n await this.sleep(this.options.retryDelay * attempt); // Exponential backoff\n }\n }\n }\n\n throw lastError || new Error('Export failed');\n }\n\n private async send(payload: { traces: TraceData[] }): Promise<void> {\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n this.options.timeout,\n );\n\n try {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (this.options.apiKey) {\n headers['Authorization'] = `Bearer ${this.options.apiKey}`;\n }\n\n const response = await fetch(`${this.options.endpoint}/ingest/traces`, {\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`HTTP ${response.status}: ${text}`);\n }\n\n const result = (await response.json()) as { processed: number };\n this.log(`Successfully sent ${result.processed} trace(s)`);\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Shutdown the exporter, waiting for pending exports\n */\n async shutdown(): Promise<void> {\n this.log('Shutting down, waiting for pending exports...');\n await Promise.allSettled(this.pendingExports);\n this.log('Shutdown complete');\n }\n\n /**\n * Force flush pending exports\n */\n async forceFlush(): Promise<void> {\n await Promise.allSettled(this.pendingExports);\n }\n\n private convertToTraceData(\n traceId: string,\n spans: ReadableSpan[],\n ): TraceData {\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 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),\n rootSpan,\n spans: spanData,\n startTime,\n endTime,\n duration: endTime - startTime,\n status: status as 'OK' | 'ERROR' | 'UNSET',\n service: this.options.serviceName,\n };\n }\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 const attributes: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(span.attributes)) {\n attributes[key] = value;\n }\n\n let status: 'OK' | 'ERROR' | 'UNSET';\n switch (span.status.code) {\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 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 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 private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n private log(message: string): void {\n if (this.options.verbose) {\n console.log(`[Devtools Remote Exporter] ${message}`);\n }\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"remote-exporter.js","names":[],"sources":["../../src/server/remote-exporter.ts"],"sourcesContent":["/**\n * Remote Span Exporter for sending traces to a hosted DevtoolsServer\n *\n * Use this when the DevtoolsServer is running on a different machine/process.\n *\n * @example\n * ```typescript\n * import { DevtoolsRemoteExporter } from '@autotel/devtools/server';\n * import { init } from 'autotel';\n *\n * init({\n * service: 'my-app',\n * spanExporters: [\n * new DevtoolsRemoteExporter({\n * endpoint: 'https://autotel.mycompany.com',\n * apiKey: process.env.AUTOTEL_API_KEY,\n * })\n * ]\n * });\n * ```\n */\n\nimport type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';\nimport type { ExportResult, ExportResultCode } from '@opentelemetry/core';\nimport type { TraceData, SpanData } from './types';\n\nexport interface DevtoolsRemoteExporterOptions {\n /**\n * Base URL of the Devtools server\n * e.g., 'https://autotel.mycompany.com' or 'http://localhost:8082'\n */\n endpoint: string;\n\n /**\n * API key for authentication (if server requires it)\n */\n apiKey?: string;\n\n /**\n * Service name for traces (default: 'unknown-service')\n */\n serviceName?: string;\n\n /**\n * Request timeout in milliseconds (default: 5000)\n */\n timeout?: number;\n\n /**\n * Retry failed requests (default: true)\n */\n retry?: boolean;\n\n /**\n * Number of retries (default: 3)\n */\n retryCount?: number;\n\n /**\n * Retry delay in milliseconds (default: 1000)\n */\n retryDelay?: number;\n\n /**\n * Enable verbose logging (default: false)\n */\n verbose?: boolean;\n}\n\nexport class DevtoolsRemoteExporter implements SpanExporter {\n private options: Required<DevtoolsRemoteExporterOptions>;\n private pendingExports: Promise<void>[] = [];\n\n constructor(options: DevtoolsRemoteExporterOptions) {\n this.options = {\n endpoint: options.endpoint.replace(/\\/$/, ''), // Remove trailing slash\n apiKey: options.apiKey ?? '',\n serviceName: options.serviceName ?? 'unknown-service',\n timeout: options.timeout ?? 5000,\n retry: options.retry ?? true,\n retryCount: options.retryCount ?? 3,\n retryDelay: options.retryDelay ?? 1000,\n verbose: options.verbose ?? false,\n };\n }\n\n /**\n * Export spans to the remote server\n */\n async export(\n spans: ReadableSpan[],\n resultCallback: (result: ExportResult) => void,\n ): Promise<void> {\n // Start export asynchronously\n const exportPromise = this.doExport(spans)\n .then(() => {\n resultCallback({ code: 0 as ExportResultCode }); // SUCCESS\n })\n .catch((error) => {\n this.log(`Export failed: ${error.message}`);\n resultCallback({ code: 1 as ExportResultCode }); // FAILED\n });\n\n this.pendingExports.push(exportPromise);\n\n // Clean up completed exports\n exportPromise.finally(() => {\n const index = this.pendingExports.indexOf(exportPromise);\n if (index !== -1) {\n this.pendingExports.splice(index, 1);\n }\n });\n }\n\n private async doExport(spans: ReadableSpan[]): Promise<void> {\n if (spans.length === 0) return;\n\n this.log(`Exporting ${spans.length} span(s) to ${this.options.endpoint}`);\n\n // Group spans by trace ID and convert\n const traceMap = new Map<string, ReadableSpan[]>();\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 const traces: TraceData[] = [];\n for (const [traceId, traceSpans] of traceMap) {\n traces.push(this.convertToTraceData(traceId, traceSpans));\n }\n\n // Send with retry\n await this.sendWithRetry({ traces });\n }\n\n private async sendWithRetry(payload: { traces: TraceData[] }): Promise<void> {\n let lastError: Error | null = null;\n const maxAttempts = this.options.retry ? this.options.retryCount : 1;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n await this.send(payload);\n return;\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n this.log(\n `Attempt ${attempt}/${maxAttempts} failed: ${lastError.message}`,\n );\n\n if (attempt < maxAttempts) {\n await this.sleep(this.options.retryDelay * attempt); // Exponential backoff\n }\n }\n }\n\n throw lastError || new Error('Export failed');\n }\n\n private async send(payload: { traces: TraceData[] }): Promise<void> {\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n this.options.timeout,\n );\n\n try {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (this.options.apiKey) {\n headers['Authorization'] = `Bearer ${this.options.apiKey}`;\n }\n\n const response = await fetch(`${this.options.endpoint}/ingest/traces`, {\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`HTTP ${response.status}: ${text}`);\n }\n\n const result = (await response.json()) as { processed: number };\n this.log(`Successfully sent ${result.processed} trace(s)`);\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Shutdown the exporter, waiting for pending exports\n */\n async shutdown(): Promise<void> {\n this.log('Shutting down, waiting for pending exports...');\n await Promise.allSettled(this.pendingExports);\n this.log('Shutdown complete');\n }\n\n /**\n * Force flush pending exports\n */\n async forceFlush(): Promise<void> {\n await Promise.allSettled(this.pendingExports);\n }\n\n private convertToTraceData(\n traceId: string,\n spans: ReadableSpan[],\n ): TraceData {\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 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),\n rootSpan,\n spans: spanData,\n startTime,\n endTime,\n duration: endTime - startTime,\n status: status as 'OK' | 'ERROR' | 'UNSET',\n service: this.options.serviceName,\n };\n }\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 const attributes: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(span.attributes)) {\n attributes[key] = value;\n }\n\n let status: 'OK' | 'ERROR' | 'UNSET';\n switch (span.status.code) {\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 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 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 private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n private log(message: string): void {\n if (this.options.verbose) {\n console.log(`[Devtools Remote Exporter] ${message}`);\n }\n }\n}\n"],"mappings":"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"}