autotel-devtools 8.1.0 → 9.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 (64) hide show
  1. package/dist/cli.cjs +108 -1409
  2. package/dist/cli.cjs.map +1 -1
  3. package/dist/cli.d.cts +1 -1
  4. package/dist/cli.d.ts +1 -1
  5. package/dist/cli.js +109 -1402
  6. package/dist/cli.js.map +1 -1
  7. package/dist/error-aggregator-BvNmgn7E.d.ts +120 -0
  8. package/dist/error-aggregator-nnfbpSR7.d.cts +120 -0
  9. package/dist/exporter-1Y3GmLVS.d.cts +182 -0
  10. package/dist/exporter-CZ5HdD3o.d.ts +182 -0
  11. package/dist/genai/index.cjs +650 -537
  12. package/dist/genai/index.cjs.map +1 -1
  13. package/dist/genai/index.d.cts +164 -157
  14. package/dist/genai/index.d.ts +164 -157
  15. package/dist/genai/index.js +649 -536
  16. package/dist/genai/index.js.map +1 -1
  17. package/dist/http-BkkKa9C_.js +1128 -0
  18. package/dist/http-BkkKa9C_.js.map +1 -0
  19. package/dist/http-Yj6iSrMX.cjs +1275 -0
  20. package/dist/http-Yj6iSrMX.cjs.map +1 -0
  21. package/dist/index.cjs +50 -1708
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +21 -23
  24. package/dist/index.d.ts +21 -23
  25. package/dist/index.js +44 -1696
  26. package/dist/index.js.map +1 -1
  27. package/dist/listen-BBsxO0wm.cjs +125 -0
  28. package/dist/listen-BBsxO0wm.cjs.map +1 -0
  29. package/dist/listen-DfOCquUq.js +120 -0
  30. package/dist/listen-DfOCquUq.js.map +1 -0
  31. package/dist/resource-utils-B4UVvfnH.js +18 -0
  32. package/dist/resource-utils-B4UVvfnH.js.map +1 -0
  33. package/dist/resource-utils-DjHJB6uc.cjs +24 -0
  34. package/dist/resource-utils-DjHJB6uc.cjs.map +1 -0
  35. package/dist/server/exporter.cjs +135 -159
  36. package/dist/server/exporter.cjs.map +1 -1
  37. package/dist/server/exporter.d.cts +2 -4
  38. package/dist/server/exporter.d.ts +2 -4
  39. package/dist/server/exporter.js +134 -158
  40. package/dist/server/exporter.js.map +1 -1
  41. package/dist/server/index.cjs +29 -1640
  42. package/dist/server/index.d.cts +34 -31
  43. package/dist/server/index.d.ts +34 -31
  44. package/dist/server/index.js +5 -1610
  45. package/dist/server/log-exporter.cjs +75 -102
  46. package/dist/server/log-exporter.cjs.map +1 -1
  47. package/dist/server/log-exporter.d.cts +27 -46
  48. package/dist/server/log-exporter.d.ts +27 -46
  49. package/dist/server/log-exporter.js +74 -100
  50. package/dist/server/log-exporter.js.map +1 -1
  51. package/dist/server/remote-exporter.cjs +171 -213
  52. package/dist/server/remote-exporter.cjs.map +1 -1
  53. package/dist/server/remote-exporter.d.cts +62 -82
  54. package/dist/server/remote-exporter.d.ts +62 -82
  55. package/dist/server/remote-exporter.js +170 -212
  56. package/dist/server/remote-exporter.js.map +1 -1
  57. package/dist/widget.global.js +10 -10
  58. package/package.json +5 -5
  59. package/dist/error-aggregator-D0Uu5r38.d.ts +0 -147
  60. package/dist/error-aggregator-D1Mr221Y.d.cts +0 -147
  61. package/dist/exporter-De6p4iAD.d.cts +0 -182
  62. package/dist/exporter-De6p4iAD.d.ts +0 -182
  63. package/dist/server/index.cjs.map +0 -1
  64. package/dist/server/index.js.map +0 -1
@@ -1,114 +1,87 @@
1
- 'use strict';
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_resource_utils = require('../resource-utils-DjHJB6uc.cjs');
3
+ let _opentelemetry_core = require("@opentelemetry/core");
2
4
 
3
- var core = require('@opentelemetry/core');
4
-
5
- // src/server/log-exporter.ts
6
-
7
- // src/server/resource-utils.ts
8
- function getResourceName(resource, fallback = "unknown") {
9
- if (!resource) return fallback;
10
- const candidates = [
11
- resource["service.name"],
12
- resource["service.namespace"],
13
- resource["deployment.environment.name"],
14
- resource["host.name"],
15
- resource["container.name"],
16
- resource["process.executable.name"]
17
- ];
18
- for (const candidate of candidates) {
19
- if (typeof candidate === "string" && candidate.trim().length > 0) {
20
- return candidate;
21
- }
22
- }
23
- return fallback;
24
- }
25
-
26
- // src/server/log-exporter.ts
27
- var defaultTimeout = 5e3;
5
+ //#region src/server/log-exporter.ts
6
+ const defaultTimeout = 5e3;
28
7
  function hrTimeToMs(hrTime) {
29
- return hrTime[0] * 1e3 + hrTime[1] / 1e6;
8
+ return hrTime[0] * 1e3 + hrTime[1] / 1e6;
30
9
  }
31
10
  function bodyToPayload(body) {
32
- if (body === void 0) return "";
33
- if (typeof body === "string") return body;
34
- if (typeof body === "object" && body !== null) return body;
35
- return String(body);
11
+ if (body === void 0) return "";
12
+ if (typeof body === "string") return body;
13
+ if (typeof body === "object" && body !== null) return body;
14
+ return String(body);
36
15
  }
37
16
  function recordToLogData(record, index) {
38
- const id = `log-${Date.now()}-${index}-${Math.random().toString(36).slice(2, 9)}`;
39
- const timestamp = hrTimeToMs(record.hrTime);
40
- const body = bodyToPayload(record.body);
41
- const attributes = record.attributes && Object.keys(record.attributes).length > 0 ? record.attributes : void 0;
42
- const resource = record.resource?.attributes && Object.keys(record.resource.attributes).length > 0 ? record.resource.attributes : void 0;
43
- const log = {
44
- id,
45
- resourceName: getResourceName(resource),
46
- severityText: record.severityText,
47
- severityNumber: record.severityNumber,
48
- body,
49
- timestamp,
50
- attributes,
51
- resource
52
- };
53
- if (record.spanContext) {
54
- log.traceId = record.spanContext.traceId;
55
- log.spanId = record.spanContext.spanId;
56
- }
57
- return log;
17
+ const id = `log-${Date.now()}-${index}-${Math.random().toString(36).slice(2, 9)}`;
18
+ const timestamp = hrTimeToMs(record.hrTime);
19
+ const body = bodyToPayload(record.body);
20
+ const attributes = record.attributes && Object.keys(record.attributes).length > 0 ? record.attributes : void 0;
21
+ const resource = record.resource?.attributes && Object.keys(record.resource.attributes).length > 0 ? record.resource.attributes : void 0;
22
+ const log = {
23
+ id,
24
+ resourceName: require_resource_utils.getResourceName(resource),
25
+ severityText: record.severityText,
26
+ severityNumber: record.severityNumber,
27
+ body,
28
+ timestamp,
29
+ attributes,
30
+ resource
31
+ };
32
+ if (record.spanContext) {
33
+ log.traceId = record.spanContext.traceId;
34
+ log.spanId = record.spanContext.spanId;
35
+ }
36
+ return log;
58
37
  }
59
38
  var DevtoolsLogExporter = class {
60
- endpoint;
61
- apiKey;
62
- timeout;
63
- isShutdown = false;
64
- constructor(options) {
65
- this.endpoint = options.endpoint.replace(/\/$/, "");
66
- this.apiKey = options.apiKey ?? "";
67
- this.timeout = options.timeout ?? defaultTimeout;
68
- }
69
- export(logs, resultCallback) {
70
- if (this.isShutdown || logs.length === 0) {
71
- resultCallback({ code: core.ExportResultCode.SUCCESS });
72
- return;
73
- }
74
- const payload = { logs: logs.map((r, i) => recordToLogData(r, i)) };
75
- const url = `${this.endpoint}/ingest/logs`;
76
- const headers = {
77
- "Content-Type": "application/json"
78
- };
79
- if (this.apiKey) {
80
- headers["Authorization"] = `Bearer ${this.apiKey}`;
81
- }
82
- const controller = new AbortController();
83
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
84
- fetch(url, {
85
- method: "POST",
86
- headers,
87
- body: JSON.stringify(payload),
88
- signal: controller.signal
89
- }).then((res) => {
90
- clearTimeout(timeoutId);
91
- if (!res.ok) {
92
- throw new Error(`Devtools log ingest failed: ${res.status} ${res.statusText}`);
93
- }
94
- resultCallback({ code: core.ExportResultCode.SUCCESS });
95
- }).catch((err) => {
96
- clearTimeout(timeoutId);
97
- resultCallback({
98
- code: core.ExportResultCode.FAILED,
99
- error: err instanceof Error ? err : new Error(String(err))
100
- });
101
- });
102
- }
103
- shutdown() {
104
- this.isShutdown = true;
105
- return Promise.resolve();
106
- }
107
- forceFlush() {
108
- return Promise.resolve();
109
- }
39
+ endpoint;
40
+ apiKey;
41
+ timeout;
42
+ isShutdown = false;
43
+ constructor(options) {
44
+ this.endpoint = options.endpoint.replace(/\/$/, "");
45
+ this.apiKey = options.apiKey ?? "";
46
+ this.timeout = options.timeout ?? defaultTimeout;
47
+ }
48
+ export(logs, resultCallback) {
49
+ if (this.isShutdown || logs.length === 0) {
50
+ resultCallback({ code: _opentelemetry_core.ExportResultCode.SUCCESS });
51
+ return;
52
+ }
53
+ const payload = { logs: logs.map((r, i) => recordToLogData(r, i)) };
54
+ const url = `${this.endpoint}/ingest/logs`;
55
+ const headers = { "Content-Type": "application/json" };
56
+ if (this.apiKey) headers["Authorization"] = `Bearer ${this.apiKey}`;
57
+ const controller = new AbortController();
58
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
59
+ fetch(url, {
60
+ method: "POST",
61
+ headers,
62
+ body: JSON.stringify(payload),
63
+ signal: controller.signal
64
+ }).then((res) => {
65
+ clearTimeout(timeoutId);
66
+ if (!res.ok) throw new Error(`Devtools log ingest failed: ${res.status} ${res.statusText}`);
67
+ resultCallback({ code: _opentelemetry_core.ExportResultCode.SUCCESS });
68
+ }).catch((err) => {
69
+ clearTimeout(timeoutId);
70
+ resultCallback({
71
+ code: _opentelemetry_core.ExportResultCode.FAILED,
72
+ error: err instanceof Error ? err : new Error(String(err))
73
+ });
74
+ });
75
+ }
76
+ shutdown() {
77
+ this.isShutdown = true;
78
+ return Promise.resolve();
79
+ }
80
+ forceFlush() {
81
+ return Promise.resolve();
82
+ }
110
83
  };
111
84
 
85
+ //#endregion
112
86
  exports.DevtoolsLogExporter = DevtoolsLogExporter;
113
- //# sourceMappingURL=log-exporter.cjs.map
114
87
  //# sourceMappingURL=log-exporter.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/resource-utils.ts","../../src/server/log-exporter.ts"],"names":["ExportResultCode"],"mappings":";;;;;;;AAAO,SAAS,eAAA,CACd,QAAA,EACA,QAAA,GAAW,SAAA,EACH;AACR,EAAA,IAAI,CAAC,UAAU,OAAO,QAAA;AAEtB,EAAA,MAAM,UAAA,GAAa;AAAA,IACjB,SAAS,cAAc,CAAA;AAAA,IACvB,SAAS,mBAAmB,CAAA;AAAA,IAC5B,SAAS,6BAA6B,CAAA;AAAA,IACtC,SAAS,WAAW,CAAA;AAAA,IACpB,SAAS,gBAAgB,CAAA;AAAA,IACzB,SAAS,yBAAyB;AAAA,GACpC;AAEA,EAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,IAAA,IAAI,OAAO,SAAA,KAAc,QAAA,IAAY,UAAU,IAAA,EAAK,CAAE,SAAS,CAAA,EAAG;AAChE,MAAA,OAAO,SAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,OAAO,QAAA;AACT;;;ACwBA,IAAM,cAAA,GAAiB,GAAA;AAEvB,SAAS,WAAW,MAAA,EAAkC;AACpD,EAAA,OAAO,OAAO,CAAC,CAAA,GAAI,GAAA,GAAO,MAAA,CAAO,CAAC,CAAA,GAAI,GAAA;AACxC;AAEA,SAAS,cAAc,IAAA,EAAmE;AACxF,EAAA,IAAI,IAAA,KAAS,QAAW,OAAO,EAAA;AAC/B,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,OAAO,IAAA;AACrC,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,MAAM,OAAO,IAAA;AACtD,EAAA,OAAO,OAAO,IAAI,CAAA;AACpB;AAEA,SAAS,eAAA,CAAgB,QAA2B,KAAA,EAAwB;AAC1E,EAAA,MAAM,KAAK,CAAA,IAAA,EAAO,IAAA,CAAK,GAAA,EAAK,IAAI,KAAK,CAAA,CAAA,EAAI,IAAA,CAAK,MAAA,GAAS,QAAA,CAAS,EAAE,EAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AAC/E,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,MAAA,CAAO,MAAM,CAAA;AAC1C,EAAA,MAAM,IAAA,GAAO,aAAA,CAAc,MAAA,CAAO,IAAI,CAAA;AACtC,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,UAAA,IAAc,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA,CAAE,MAAA,GAAS,CAAA,GAC3E,MAAA,CAAO,UAAA,GACR,MAAA;AACJ,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,EAAU,UAAA,IAAc,OAAO,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,UAAU,CAAA,CAAE,MAAA,GAAS,CAAA,GAC5F,MAAA,CAAO,SAAS,UAAA,GACjB,MAAA;AAEJ,EAAA,MAAM,GAAA,GAAe;AAAA,IACnB,EAAA;AAAA,IACA,YAAA,EAAc,gBAAgB,QAAQ,CAAA;AAAA,IACtC,cAAc,MAAA,CAAO,YAAA;AAAA,IACrB,gBAAgB,MAAA,CAAO,cAAA;AAAA,IACvB,IAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,IAAI,OAAO,WAAA,EAAa;AACtB,IAAA,GAAA,CAAI,OAAA,GAAU,OAAO,WAAA,CAAY,OAAA;AACjC,IAAA,GAAA,CAAI,MAAA,GAAS,OAAO,WAAA,CAAY,MAAA;AAAA,EAClC;AAEA,EAAA,OAAO,GAAA;AACT;AAEO,IAAM,sBAAN,MAAuD;AAAA,EACpD,QAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA,GAAa,KAAA;AAAA,EAErB,YAAY,OAAA,EAAqC;AAC/C,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA,CAAQ,QAAA,CAAS,OAAA,CAAQ,OAAO,EAAE,CAAA;AAClD,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,MAAA,IAAU,EAAA;AAChC,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,OAAA,IAAW,cAAA;AAAA,EACpC;AAAA,EAEA,MAAA,CAAO,MAA2B,cAAA,EAAsD;AACtF,IAAA,IAAI,IAAA,CAAK,UAAA,IAAc,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AACxC,MAAA,cAAA,CAAe,EAAE,IAAA,EAAMA,qBAAA,CAAiB,OAAA,EAAS,CAAA;AACjD,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,EAAE,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,KAAM,eAAA,CAAgB,CAAA,EAAG,CAAC,CAAC,CAAA,EAAE;AAClE,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,QAAQ,CAAA,YAAA,CAAA;AAC5B,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,cAAA,EAAgB;AAAA,KAClB;AACA,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,IAClD;AAEA,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,YAAY,UAAA,CAAW,MAAM,WAAW,KAAA,EAAM,EAAG,KAAK,OAAO,CAAA;AAEnE,IAAA,KAAA,CAAM,GAAA,EAAK;AAAA,MACT,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA;AAAA,MACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAAA,MAC5B,QAAQ,UAAA,CAAW;AAAA,KACpB,CAAA,CACE,IAAA,CAAK,CAAC,GAAA,KAAQ;AACb,MAAA,YAAA,CAAa,SAAS,CAAA;AACtB,MAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,QAAA,MAAM,IAAI,MAAM,CAAA,4BAAA,EAA+B,GAAA,CAAI,MAAM,CAAA,CAAA,EAAI,GAAA,CAAI,UAAU,CAAA,CAAE,CAAA;AAAA,MAC/E;AACA,MAAA,cAAA,CAAe,EAAE,IAAA,EAAMA,qBAAA,CAAiB,OAAA,EAAS,CAAA;AAAA,IACnD,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,GAAA,KAAQ;AACd,MAAA,YAAA,CAAa,SAAS,CAAA;AACtB,MAAA,cAAA,CAAe;AAAA,QACb,MAAMA,qBAAA,CAAiB,MAAA;AAAA,QACvB,KAAA,EAAO,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC;AAAA,OAC1D,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACL;AAAA,EAEA,QAAA,GAA0B;AACxB,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAClB,IAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,EACzB;AAAA,EAEA,UAAA,GAA4B;AAC1B,IAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,EACzB;AACF","file":"log-exporter.cjs","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","/**\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(body: ReadableLogRecord['body']): string | Record<string, unknown> {\n if (body === undefined) return '';\n if (typeof body === 'string') return body;\n if (typeof body === 'object' && body !== null) 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 = record.attributes && Object.keys(record.attributes).length > 0\n ? (record.attributes as Record<string, unknown>)\n : undefined;\n const resource = record.resource?.attributes && 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(logs: ReadableLogRecord[], resultCallback: (result: ExportResult) => void): 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(`Devtools log ingest failed: ${res.status} ${res.statusText}`);\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"]}
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(body: ReadableLogRecord['body']): string | Record<string, unknown> {\n if (body === undefined) return '';\n if (typeof body === 'string') return body;\n if (typeof body === 'object' && body !== null) 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 = record.attributes && Object.keys(record.attributes).length > 0\n ? (record.attributes as Record<string, unknown>)\n : undefined;\n const resource = record.resource?.attributes && 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(logs: ReadableLogRecord[], resultCallback: (result: ExportResult) => void): 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(`Devtools log ingest failed: ${res.status} ${res.statusText}`);\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,cAAc,MAAmE;CACxF,IAAI,SAAS,QAAW,OAAO;CAC/B,IAAI,OAAO,SAAS,UAAU,OAAO;CACrC,IAAI,OAAO,SAAS,YAAY,SAAS,MAAM,OAAO;CACtD,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,aAAa,OAAO,cAAc,OAAO,KAAK,OAAO,UAAU,CAAC,CAAC,SAAS,IAC3E,OAAO,aACR;CACJ,MAAM,WAAW,OAAO,UAAU,cAAc,OAAO,KAAK,OAAO,SAAS,UAAU,CAAC,CAAC,SAAS,IAC5F,OAAO,SAAS,aACjB;CAEJ,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,OAAO,MAA2B,gBAAsD;EACtF,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,MAAM,+BAA+B,IAAI,OAAO,GAAG,IAAI,YAAY;GAE/E,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,51 +1,32 @@
1
- import { ExportResult } from '@opentelemetry/core';
2
- import { LogRecordExporter, ReadableLogRecord } from '@opentelemetry/sdk-logs';
3
-
4
- /**
5
- * Log record exporter that sends OTel logs to a Devtools server HTTP ingest.
6
- * Use with BatchLogRecordProcessor when you want to view logs in the Autotel widget/extension.
7
- *
8
- * @example
9
- * ```typescript
10
- * import { BatchLogRecordProcessor } from '@opentelemetry/sdk-logs';
11
- * import { DevtoolsLogExporter } from '@autotel/devtools/server';
12
- * import { init } from 'autotel';
13
- *
14
- * init({
15
- * service: 'my-app',
16
- * logRecordProcessors: [
17
- * new BatchLogRecordProcessor(
18
- * new DevtoolsLogExporter({ endpoint: 'http://localhost:8082' })
19
- * ),
20
- * ],
21
- * });
22
- * ```
23
- */
1
+ import { ExportResult } from "@opentelemetry/core";
2
+ import { LogRecordExporter, ReadableLogRecord } from "@opentelemetry/sdk-logs";
24
3
 
4
+ //#region src/server/log-exporter.d.ts
25
5
  interface DevtoolsLogExporterOptions {
26
- /**
27
- * Base URL of the Devtools HTTP ingest server
28
- * e.g. 'http://localhost:8082'
29
- */
30
- endpoint: string;
31
- /**
32
- * API key for authentication (if server requires it)
33
- */
34
- apiKey?: string;
35
- /**
36
- * Request timeout in milliseconds (default: 5000)
37
- */
38
- timeout?: number;
6
+ /**
7
+ * Base URL of the Devtools HTTP ingest server
8
+ * e.g. 'http://localhost:8082'
9
+ */
10
+ endpoint: string;
11
+ /**
12
+ * API key for authentication (if server requires it)
13
+ */
14
+ apiKey?: string;
15
+ /**
16
+ * Request timeout in milliseconds (default: 5000)
17
+ */
18
+ timeout?: number;
39
19
  }
40
20
  declare class DevtoolsLogExporter implements LogRecordExporter {
41
- private endpoint;
42
- private apiKey;
43
- private timeout;
44
- private isShutdown;
45
- constructor(options: DevtoolsLogExporterOptions);
46
- export(logs: ReadableLogRecord[], resultCallback: (result: ExportResult) => void): void;
47
- shutdown(): Promise<void>;
48
- forceFlush(): Promise<void>;
21
+ private endpoint;
22
+ private apiKey;
23
+ private timeout;
24
+ private isShutdown;
25
+ constructor(options: DevtoolsLogExporterOptions);
26
+ export(logs: ReadableLogRecord[], resultCallback: (result: ExportResult) => void): void;
27
+ shutdown(): Promise<void>;
28
+ forceFlush(): Promise<void>;
49
29
  }
50
-
51
- export { DevtoolsLogExporter, type DevtoolsLogExporterOptions };
30
+ //#endregion
31
+ export { DevtoolsLogExporter, DevtoolsLogExporterOptions };
32
+ //# sourceMappingURL=log-exporter.d.cts.map
@@ -1,51 +1,32 @@
1
- import { ExportResult } from '@opentelemetry/core';
2
- import { LogRecordExporter, ReadableLogRecord } from '@opentelemetry/sdk-logs';
3
-
4
- /**
5
- * Log record exporter that sends OTel logs to a Devtools server HTTP ingest.
6
- * Use with BatchLogRecordProcessor when you want to view logs in the Autotel widget/extension.
7
- *
8
- * @example
9
- * ```typescript
10
- * import { BatchLogRecordProcessor } from '@opentelemetry/sdk-logs';
11
- * import { DevtoolsLogExporter } from '@autotel/devtools/server';
12
- * import { init } from 'autotel';
13
- *
14
- * init({
15
- * service: 'my-app',
16
- * logRecordProcessors: [
17
- * new BatchLogRecordProcessor(
18
- * new DevtoolsLogExporter({ endpoint: 'http://localhost:8082' })
19
- * ),
20
- * ],
21
- * });
22
- * ```
23
- */
1
+ import { ExportResult } from "@opentelemetry/core";
2
+ import { LogRecordExporter, ReadableLogRecord } from "@opentelemetry/sdk-logs";
24
3
 
4
+ //#region src/server/log-exporter.d.ts
25
5
  interface DevtoolsLogExporterOptions {
26
- /**
27
- * Base URL of the Devtools HTTP ingest server
28
- * e.g. 'http://localhost:8082'
29
- */
30
- endpoint: string;
31
- /**
32
- * API key for authentication (if server requires it)
33
- */
34
- apiKey?: string;
35
- /**
36
- * Request timeout in milliseconds (default: 5000)
37
- */
38
- timeout?: number;
6
+ /**
7
+ * Base URL of the Devtools HTTP ingest server
8
+ * e.g. 'http://localhost:8082'
9
+ */
10
+ endpoint: string;
11
+ /**
12
+ * API key for authentication (if server requires it)
13
+ */
14
+ apiKey?: string;
15
+ /**
16
+ * Request timeout in milliseconds (default: 5000)
17
+ */
18
+ timeout?: number;
39
19
  }
40
20
  declare class DevtoolsLogExporter implements LogRecordExporter {
41
- private endpoint;
42
- private apiKey;
43
- private timeout;
44
- private isShutdown;
45
- constructor(options: DevtoolsLogExporterOptions);
46
- export(logs: ReadableLogRecord[], resultCallback: (result: ExportResult) => void): void;
47
- shutdown(): Promise<void>;
48
- forceFlush(): Promise<void>;
21
+ private endpoint;
22
+ private apiKey;
23
+ private timeout;
24
+ private isShutdown;
25
+ constructor(options: DevtoolsLogExporterOptions);
26
+ export(logs: ReadableLogRecord[], resultCallback: (result: ExportResult) => void): void;
27
+ shutdown(): Promise<void>;
28
+ forceFlush(): Promise<void>;
49
29
  }
50
-
51
- export { DevtoolsLogExporter, type DevtoolsLogExporterOptions };
30
+ //#endregion
31
+ export { DevtoolsLogExporter, DevtoolsLogExporterOptions };
32
+ //# sourceMappingURL=log-exporter.d.ts.map
@@ -1,112 +1,86 @@
1
- import { ExportResultCode } from '@opentelemetry/core';
1
+ import { t as getResourceName } from "../resource-utils-B4UVvfnH.js";
2
+ import { ExportResultCode } from "@opentelemetry/core";
2
3
 
3
- // src/server/log-exporter.ts
4
-
5
- // src/server/resource-utils.ts
6
- function getResourceName(resource, fallback = "unknown") {
7
- if (!resource) return fallback;
8
- const candidates = [
9
- resource["service.name"],
10
- resource["service.namespace"],
11
- resource["deployment.environment.name"],
12
- resource["host.name"],
13
- resource["container.name"],
14
- resource["process.executable.name"]
15
- ];
16
- for (const candidate of candidates) {
17
- if (typeof candidate === "string" && candidate.trim().length > 0) {
18
- return candidate;
19
- }
20
- }
21
- return fallback;
22
- }
23
-
24
- // src/server/log-exporter.ts
25
- var defaultTimeout = 5e3;
4
+ //#region src/server/log-exporter.ts
5
+ const defaultTimeout = 5e3;
26
6
  function hrTimeToMs(hrTime) {
27
- return hrTime[0] * 1e3 + hrTime[1] / 1e6;
7
+ return hrTime[0] * 1e3 + hrTime[1] / 1e6;
28
8
  }
29
9
  function bodyToPayload(body) {
30
- if (body === void 0) return "";
31
- if (typeof body === "string") return body;
32
- if (typeof body === "object" && body !== null) return body;
33
- return String(body);
10
+ if (body === void 0) return "";
11
+ if (typeof body === "string") return body;
12
+ if (typeof body === "object" && body !== null) return body;
13
+ return String(body);
34
14
  }
35
15
  function recordToLogData(record, index) {
36
- const id = `log-${Date.now()}-${index}-${Math.random().toString(36).slice(2, 9)}`;
37
- const timestamp = hrTimeToMs(record.hrTime);
38
- const body = bodyToPayload(record.body);
39
- const attributes = record.attributes && Object.keys(record.attributes).length > 0 ? record.attributes : void 0;
40
- const resource = record.resource?.attributes && Object.keys(record.resource.attributes).length > 0 ? record.resource.attributes : void 0;
41
- const log = {
42
- id,
43
- resourceName: getResourceName(resource),
44
- severityText: record.severityText,
45
- severityNumber: record.severityNumber,
46
- body,
47
- timestamp,
48
- attributes,
49
- resource
50
- };
51
- if (record.spanContext) {
52
- log.traceId = record.spanContext.traceId;
53
- log.spanId = record.spanContext.spanId;
54
- }
55
- return log;
16
+ const id = `log-${Date.now()}-${index}-${Math.random().toString(36).slice(2, 9)}`;
17
+ const timestamp = hrTimeToMs(record.hrTime);
18
+ const body = bodyToPayload(record.body);
19
+ const attributes = record.attributes && Object.keys(record.attributes).length > 0 ? record.attributes : void 0;
20
+ const resource = record.resource?.attributes && Object.keys(record.resource.attributes).length > 0 ? record.resource.attributes : void 0;
21
+ const log = {
22
+ id,
23
+ resourceName: getResourceName(resource),
24
+ severityText: record.severityText,
25
+ severityNumber: record.severityNumber,
26
+ body,
27
+ timestamp,
28
+ attributes,
29
+ resource
30
+ };
31
+ if (record.spanContext) {
32
+ log.traceId = record.spanContext.traceId;
33
+ log.spanId = record.spanContext.spanId;
34
+ }
35
+ return log;
56
36
  }
57
37
  var DevtoolsLogExporter = class {
58
- endpoint;
59
- apiKey;
60
- timeout;
61
- isShutdown = false;
62
- constructor(options) {
63
- this.endpoint = options.endpoint.replace(/\/$/, "");
64
- this.apiKey = options.apiKey ?? "";
65
- this.timeout = options.timeout ?? defaultTimeout;
66
- }
67
- export(logs, resultCallback) {
68
- if (this.isShutdown || logs.length === 0) {
69
- resultCallback({ code: ExportResultCode.SUCCESS });
70
- return;
71
- }
72
- const payload = { logs: logs.map((r, i) => recordToLogData(r, i)) };
73
- const url = `${this.endpoint}/ingest/logs`;
74
- const headers = {
75
- "Content-Type": "application/json"
76
- };
77
- if (this.apiKey) {
78
- headers["Authorization"] = `Bearer ${this.apiKey}`;
79
- }
80
- const controller = new AbortController();
81
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
82
- fetch(url, {
83
- method: "POST",
84
- headers,
85
- body: JSON.stringify(payload),
86
- signal: controller.signal
87
- }).then((res) => {
88
- clearTimeout(timeoutId);
89
- if (!res.ok) {
90
- throw new Error(`Devtools log ingest failed: ${res.status} ${res.statusText}`);
91
- }
92
- resultCallback({ code: ExportResultCode.SUCCESS });
93
- }).catch((err) => {
94
- clearTimeout(timeoutId);
95
- resultCallback({
96
- code: ExportResultCode.FAILED,
97
- error: err instanceof Error ? err : new Error(String(err))
98
- });
99
- });
100
- }
101
- shutdown() {
102
- this.isShutdown = true;
103
- return Promise.resolve();
104
- }
105
- forceFlush() {
106
- return Promise.resolve();
107
- }
38
+ endpoint;
39
+ apiKey;
40
+ timeout;
41
+ isShutdown = false;
42
+ constructor(options) {
43
+ this.endpoint = options.endpoint.replace(/\/$/, "");
44
+ this.apiKey = options.apiKey ?? "";
45
+ this.timeout = options.timeout ?? defaultTimeout;
46
+ }
47
+ export(logs, resultCallback) {
48
+ if (this.isShutdown || logs.length === 0) {
49
+ resultCallback({ code: ExportResultCode.SUCCESS });
50
+ return;
51
+ }
52
+ const payload = { logs: logs.map((r, i) => recordToLogData(r, i)) };
53
+ const url = `${this.endpoint}/ingest/logs`;
54
+ const headers = { "Content-Type": "application/json" };
55
+ if (this.apiKey) headers["Authorization"] = `Bearer ${this.apiKey}`;
56
+ const controller = new AbortController();
57
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
58
+ fetch(url, {
59
+ method: "POST",
60
+ headers,
61
+ body: JSON.stringify(payload),
62
+ signal: controller.signal
63
+ }).then((res) => {
64
+ clearTimeout(timeoutId);
65
+ if (!res.ok) throw new Error(`Devtools log ingest failed: ${res.status} ${res.statusText}`);
66
+ resultCallback({ code: ExportResultCode.SUCCESS });
67
+ }).catch((err) => {
68
+ clearTimeout(timeoutId);
69
+ resultCallback({
70
+ code: ExportResultCode.FAILED,
71
+ error: err instanceof Error ? err : new Error(String(err))
72
+ });
73
+ });
74
+ }
75
+ shutdown() {
76
+ this.isShutdown = true;
77
+ return Promise.resolve();
78
+ }
79
+ forceFlush() {
80
+ return Promise.resolve();
81
+ }
108
82
  };
109
83
 
84
+ //#endregion
110
85
  export { DevtoolsLogExporter };
111
- //# sourceMappingURL=log-exporter.js.map
112
86
  //# sourceMappingURL=log-exporter.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/resource-utils.ts","../../src/server/log-exporter.ts"],"names":[],"mappings":"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","file":"log-exporter.js","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","/**\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(body: ReadableLogRecord['body']): string | Record<string, unknown> {\n if (body === undefined) return '';\n if (typeof body === 'string') return body;\n if (typeof body === 'object' && body !== null) 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 = record.attributes && Object.keys(record.attributes).length > 0\n ? (record.attributes as Record<string, unknown>)\n : undefined;\n const resource = record.resource?.attributes && 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(logs: ReadableLogRecord[], resultCallback: (result: ExportResult) => void): 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(`Devtools log ingest failed: ${res.status} ${res.statusText}`);\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"]}
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(body: ReadableLogRecord['body']): string | Record<string, unknown> {\n if (body === undefined) return '';\n if (typeof body === 'string') return body;\n if (typeof body === 'object' && body !== null) 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 = record.attributes && Object.keys(record.attributes).length > 0\n ? (record.attributes as Record<string, unknown>)\n : undefined;\n const resource = record.resource?.attributes && 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(logs: ReadableLogRecord[], resultCallback: (result: ExportResult) => void): 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(`Devtools log ingest failed: ${res.status} ${res.statusText}`);\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,cAAc,MAAmE;CACxF,IAAI,SAAS,QAAW,OAAO;CAC/B,IAAI,OAAO,SAAS,UAAU,OAAO;CACrC,IAAI,OAAO,SAAS,YAAY,SAAS,MAAM,OAAO;CACtD,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,aAAa,OAAO,cAAc,OAAO,KAAK,OAAO,UAAU,CAAC,CAAC,SAAS,IAC3E,OAAO,aACR;CACJ,MAAM,WAAW,OAAO,UAAU,cAAc,OAAO,KAAK,OAAO,SAAS,UAAU,CAAC,CAAC,SAAS,IAC5F,OAAO,SAAS,aACjB;CAEJ,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,OAAO,MAA2B,gBAAsD;EACtF,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,MAAM,+BAA+B,IAAI,OAAO,GAAG,IAAI,YAAY;GAE/E,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"}