@principal-ai/otel-collector-server 0.1.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 (62) hide show
  1. package/README.md +252 -0
  2. package/dist/OTELCollectorServer.d.ts +52 -0
  3. package/dist/OTELCollectorServer.d.ts.map +1 -0
  4. package/dist/OTELCollectorServer.js +252 -0
  5. package/dist/OTELCollectorServer.js.map +1 -0
  6. package/dist/__tests__/fixtures/traces.d.ts +8 -0
  7. package/dist/__tests__/fixtures/traces.d.ts.map +1 -0
  8. package/dist/__tests__/fixtures/traces.js +186 -0
  9. package/dist/__tests__/fixtures/traces.js.map +1 -0
  10. package/dist/bin/otel-collector-server.d.ts +6 -0
  11. package/dist/bin/otel-collector-server.d.ts.map +1 -0
  12. package/dist/bin/otel-collector-server.js +132 -0
  13. package/dist/bin/otel-collector-server.js.map +1 -0
  14. package/dist/core/BinaryManager.d.ts +35 -0
  15. package/dist/core/BinaryManager.d.ts.map +1 -0
  16. package/dist/core/BinaryManager.js +143 -0
  17. package/dist/core/BinaryManager.js.map +1 -0
  18. package/dist/core/CollectorProcessManager.d.ts +60 -0
  19. package/dist/core/CollectorProcessManager.d.ts.map +1 -0
  20. package/dist/core/CollectorProcessManager.js +197 -0
  21. package/dist/core/CollectorProcessManager.js.map +1 -0
  22. package/dist/core/ConfigGenerator.d.ts +23 -0
  23. package/dist/core/ConfigGenerator.d.ts.map +1 -0
  24. package/dist/core/ConfigGenerator.js +115 -0
  25. package/dist/core/ConfigGenerator.js.map +1 -0
  26. package/dist/index.d.ts +20 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +31 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/output/ConsoleOutput.d.ts +24 -0
  31. package/dist/output/ConsoleOutput.d.ts.map +1 -0
  32. package/dist/output/ConsoleOutput.js +156 -0
  33. package/dist/output/ConsoleOutput.js.map +1 -0
  34. package/dist/output/FileOutput.d.ts +18 -0
  35. package/dist/output/FileOutput.d.ts.map +1 -0
  36. package/dist/output/FileOutput.js +88 -0
  37. package/dist/output/FileOutput.js.map +1 -0
  38. package/dist/output/MessagePortOutput.d.ts +19 -0
  39. package/dist/output/MessagePortOutput.d.ts.map +1 -0
  40. package/dist/output/MessagePortOutput.js +25 -0
  41. package/dist/output/MessagePortOutput.js.map +1 -0
  42. package/dist/output/TraceOutput.d.ts +13 -0
  43. package/dist/output/TraceOutput.d.ts.map +1 -0
  44. package/dist/output/TraceOutput.js +6 -0
  45. package/dist/output/TraceOutput.js.map +1 -0
  46. package/dist/router/PortRouter.d.ts +41 -0
  47. package/dist/router/PortRouter.d.ts.map +1 -0
  48. package/dist/router/PortRouter.js +130 -0
  49. package/dist/router/PortRouter.js.map +1 -0
  50. package/dist/server/OTLPForwardingServer.d.ts +59 -0
  51. package/dist/server/OTLPForwardingServer.d.ts.map +1 -0
  52. package/dist/server/OTLPForwardingServer.js +245 -0
  53. package/dist/server/OTLPForwardingServer.js.map +1 -0
  54. package/dist/shared/logger.d.ts +18 -0
  55. package/dist/shared/logger.d.ts.map +1 -0
  56. package/dist/shared/logger.js +59 -0
  57. package/dist/shared/logger.js.map +1 -0
  58. package/dist/shared/types.d.ts +47 -0
  59. package/dist/shared/types.d.ts.map +1 -0
  60. package/dist/shared/types.js +6 -0
  61. package/dist/shared/types.js.map +1 -0
  62. package/package.json +61 -0
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ /**
3
+ * FileOutput - Write traces to file as JSONL
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.FileOutput = void 0;
40
+ const fs = __importStar(require("fs"));
41
+ const logger_1 = require("../shared/logger");
42
+ class FileOutput {
43
+ constructor(filePath, logger) {
44
+ this.closed = false;
45
+ this.logger = logger || (0, logger_1.createLogger)('FileOutput');
46
+ // Create write stream
47
+ this.writeStream = fs.createWriteStream(filePath, {
48
+ flags: 'a', // Append mode
49
+ encoding: 'utf-8',
50
+ });
51
+ this.writeStream.on('error', (err) => {
52
+ this.logger.error('File write error:', err);
53
+ });
54
+ this.logger.info(`Writing traces to: ${filePath}`);
55
+ }
56
+ send(payload, source) {
57
+ const line = JSON.stringify({
58
+ timestamp: new Date().toISOString(),
59
+ source,
60
+ payload,
61
+ });
62
+ this.writeStream.write(line + '\n');
63
+ }
64
+ /**
65
+ * Close the file stream
66
+ */
67
+ close() {
68
+ if (this.closed) {
69
+ this.logger.debug('File stream already closed');
70
+ return Promise.resolve();
71
+ }
72
+ this.closed = true;
73
+ return new Promise((resolve, reject) => {
74
+ this.writeStream.end((err) => {
75
+ if (err) {
76
+ this.logger.error('Error closing file stream:', err);
77
+ reject(err);
78
+ }
79
+ else {
80
+ this.logger.info('File stream closed');
81
+ resolve();
82
+ }
83
+ });
84
+ });
85
+ }
86
+ }
87
+ exports.FileOutput = FileOutput;
88
+ //# sourceMappingURL=FileOutput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileOutput.js","sourceRoot":"","sources":["../../src/output/FileOutput.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,uCAAyB;AAGzB,6CAAwD;AAExD,MAAa,UAAU;IAKrB,YAAY,QAAgB,EAAE,MAAe;QAFrC,WAAM,GAAY,KAAK,CAAC;QAG9B,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,IAAA,qBAAY,EAAC,YAAY,CAAC,CAAC;QAEnD,sBAAsB;QACtB,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE;YAChD,KAAK,EAAE,GAAG,EAAE,cAAc;YAC1B,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACnC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,QAAQ,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,CAAC,OAAmC,EAAE,MAAc;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,MAAM;YACN,OAAO;SACR,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACtC,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAChD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3B,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,GAAsB,EAAE,EAAE;gBAC9C,IAAI,GAAG,EAAE,CAAC;oBACR,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;oBACrD,MAAM,CAAC,GAAG,CAAC,CAAC;gBACd,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;oBACvC,OAAO,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AArDD,gCAqDC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * MessagePortOutput - Output traces via MessagePort for Electron renderer windows
3
+ */
4
+ import { TraceOutput } from './TraceOutput';
5
+ import { PortRouter } from '../router/PortRouter';
6
+ import { IExportTraceServiceRequest } from '@opentelemetry/otlp-transformer';
7
+ export declare class MessagePortOutput implements TraceOutput {
8
+ private router;
9
+ constructor(router: PortRouter);
10
+ /**
11
+ * Send trace payload to registered windows via MessagePort
12
+ */
13
+ send(payload: IExportTraceServiceRequest, source: string): void;
14
+ /**
15
+ * Get the underlying router for registration management
16
+ */
17
+ getRouter(): PortRouter;
18
+ }
19
+ //# sourceMappingURL=MessagePortOutput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessagePortOutput.d.ts","sourceRoot":"","sources":["../../src/output/MessagePortOutput.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAE7E,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,MAAM,CAAa;gBAEf,MAAM,EAAE,UAAU;IAI9B;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,0BAA0B,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/D;;OAEG;IACH,SAAS,IAAI,UAAU;CAGxB"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ /**
3
+ * MessagePortOutput - Output traces via MessagePort for Electron renderer windows
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MessagePortOutput = void 0;
7
+ class MessagePortOutput {
8
+ constructor(router) {
9
+ this.router = router;
10
+ }
11
+ /**
12
+ * Send trace payload to registered windows via MessagePort
13
+ */
14
+ send(payload, source) {
15
+ this.router.routePayload(payload, source);
16
+ }
17
+ /**
18
+ * Get the underlying router for registration management
19
+ */
20
+ getRouter() {
21
+ return this.router;
22
+ }
23
+ }
24
+ exports.MessagePortOutput = MessagePortOutput;
25
+ //# sourceMappingURL=MessagePortOutput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessagePortOutput.js","sourceRoot":"","sources":["../../src/output/MessagePortOutput.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAMH,MAAa,iBAAiB;IAG5B,YAAY,MAAkB;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,OAAmC,EAAE,MAAc;QACtD,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF;AApBD,8CAoBC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * TraceOutput - Abstract interface for outputting traces
3
+ */
4
+ import { IExportTraceServiceRequest } from '@opentelemetry/otlp-transformer';
5
+ export interface TraceOutput {
6
+ /**
7
+ * Send traces to output destination
8
+ * @param payload - Raw OTLP trace payload
9
+ * @param source - Source URL the traces came from
10
+ */
11
+ send(payload: IExportTraceServiceRequest, source: string): void;
12
+ }
13
+ //# sourceMappingURL=TraceOutput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TraceOutput.d.ts","sourceRoot":"","sources":["../../src/output/TraceOutput.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAE7E,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,IAAI,CAAC,OAAO,EAAE,0BAA0B,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACjE"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * TraceOutput - Abstract interface for outputting traces
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=TraceOutput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TraceOutput.js","sourceRoot":"","sources":["../../src/output/TraceOutput.ts"],"names":[],"mappings":";AAAA;;GAEG"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * PortRouter - Routes OTLP traces to registered renderer windows via MessagePort
3
+ */
4
+ import { MessagePort } from 'worker_threads';
5
+ import { Logger } from '../shared/logger';
6
+ import { PortRegistration } from '../shared/types';
7
+ import { IExportTraceServiceRequest } from '@opentelemetry/otlp-transformer';
8
+ export declare class PortRouter {
9
+ private logger;
10
+ private portRegistry;
11
+ constructor(logger?: Logger);
12
+ /**
13
+ * Register a MessagePort for a specific window and source URL
14
+ */
15
+ registerPort(windowId: string, sourceUrl: string, port: MessagePort): void;
16
+ /**
17
+ * Unregister a MessagePort for a specific window and source URL
18
+ */
19
+ unregisterPort(windowId: string, sourceUrl: string): void;
20
+ /**
21
+ * Unregister all MessagePorts for a specific window
22
+ */
23
+ unregisterWindow(windowId: string): void;
24
+ /**
25
+ * Route OTLP payload to registered windows based on source URL
26
+ */
27
+ routePayload(payload: IExportTraceServiceRequest, sourceUrl: string): void;
28
+ /**
29
+ * Get all active registrations
30
+ */
31
+ getRegistrations(): Map<string, PortRegistration[]>;
32
+ /**
33
+ * Get count of active registrations
34
+ */
35
+ getRegistrationCount(): number;
36
+ /**
37
+ * Get all registered source URLs
38
+ */
39
+ getRegisteredSources(): string[];
40
+ }
41
+ //# sourceMappingURL=PortRouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PortRouter.d.ts","sourceRoot":"","sources":["../../src/router/PortRouter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAgB,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAE7E,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAkC;gBAE1C,MAAM,CAAC,EAAE,MAAM;IAK3B;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI;IA0B1E;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAoBzD;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAuBxC;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,0BAA0B,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IA4B1E;;OAEG;IACH,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAInD;;OAEG;IACH,oBAAoB,IAAI,MAAM;IAQ9B;;OAEG;IACH,oBAAoB,IAAI,MAAM,EAAE;CAGjC"}
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ /**
3
+ * PortRouter - Routes OTLP traces to registered renderer windows via MessagePort
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PortRouter = void 0;
7
+ const logger_1 = require("../shared/logger");
8
+ class PortRouter {
9
+ constructor(logger) {
10
+ this.logger = logger || (0, logger_1.createLogger)('PortRouter');
11
+ this.portRegistry = new Map();
12
+ }
13
+ /**
14
+ * Register a MessagePort for a specific window and source URL
15
+ */
16
+ registerPort(windowId, sourceUrl, port) {
17
+ this.logger.info(`Registering port for window ${windowId}, source: ${sourceUrl}`);
18
+ const registration = {
19
+ windowId,
20
+ sourceUrl,
21
+ port,
22
+ registeredAt: Date.now(),
23
+ };
24
+ // Get or create registry for this source URL
25
+ const existing = this.portRegistry.get(sourceUrl) || [];
26
+ // Check if this window is already registered for this source
27
+ const existingIndex = existing.findIndex(r => r.windowId === windowId);
28
+ if (existingIndex >= 0) {
29
+ this.logger.warn(`Window ${windowId} already registered for ${sourceUrl}, replacing`);
30
+ existing[existingIndex] = registration;
31
+ }
32
+ else {
33
+ existing.push(registration);
34
+ }
35
+ this.portRegistry.set(sourceUrl, existing);
36
+ this.logger.debug(`Port registry now has ${existing.length} registrations for ${sourceUrl}`);
37
+ }
38
+ /**
39
+ * Unregister a MessagePort for a specific window and source URL
40
+ */
41
+ unregisterPort(windowId, sourceUrl) {
42
+ this.logger.info(`Unregistering port for window ${windowId}, source: ${sourceUrl}`);
43
+ const registrations = this.portRegistry.get(sourceUrl);
44
+ if (!registrations) {
45
+ this.logger.warn(`No registrations found for source: ${sourceUrl}`);
46
+ return;
47
+ }
48
+ const filtered = registrations.filter(r => r.windowId !== windowId);
49
+ if (filtered.length === 0) {
50
+ this.portRegistry.delete(sourceUrl);
51
+ this.logger.debug(`Removed source ${sourceUrl} from registry (no more registrations)`);
52
+ }
53
+ else {
54
+ this.portRegistry.set(sourceUrl, filtered);
55
+ this.logger.debug(`${filtered.length} registrations remaining for ${sourceUrl}`);
56
+ }
57
+ }
58
+ /**
59
+ * Unregister all MessagePorts for a specific window
60
+ */
61
+ unregisterWindow(windowId) {
62
+ this.logger.info(`Unregistering all ports for window ${windowId}`);
63
+ let removedCount = 0;
64
+ const sourcesToRemove = [];
65
+ for (const [sourceUrl, registrations] of this.portRegistry.entries()) {
66
+ const filtered = registrations.filter(r => r.windowId !== windowId);
67
+ removedCount += registrations.length - filtered.length;
68
+ if (filtered.length === 0) {
69
+ sourcesToRemove.push(sourceUrl);
70
+ }
71
+ else {
72
+ this.portRegistry.set(sourceUrl, filtered);
73
+ }
74
+ }
75
+ // Remove sources with no registrations
76
+ sourcesToRemove.forEach(source => this.portRegistry.delete(source));
77
+ this.logger.info(`Unregistered ${removedCount} ports for window ${windowId}`);
78
+ }
79
+ /**
80
+ * Route OTLP payload to registered windows based on source URL
81
+ */
82
+ routePayload(payload, sourceUrl) {
83
+ const registrations = this.portRegistry.get(sourceUrl);
84
+ if (!registrations || registrations.length === 0) {
85
+ this.logger.debug(`No registrations for source: ${sourceUrl}, dropping traces`);
86
+ return;
87
+ }
88
+ this.logger.debug(`Routing traces from ${sourceUrl} to ${registrations.length} window(s)`);
89
+ const message = {
90
+ type: 'TRACE_BATCH',
91
+ payload,
92
+ source: sourceUrl,
93
+ timestamp: Date.now(),
94
+ };
95
+ for (const registration of registrations) {
96
+ try {
97
+ registration.port.postMessage(message);
98
+ this.logger.debug(`Sent traces to window ${registration.windowId}`);
99
+ }
100
+ catch (err) {
101
+ this.logger.error(`Failed to send to window ${registration.windowId}:`, err);
102
+ // Consider auto-unregistering failed ports?
103
+ }
104
+ }
105
+ }
106
+ /**
107
+ * Get all active registrations
108
+ */
109
+ getRegistrations() {
110
+ return new Map(this.portRegistry);
111
+ }
112
+ /**
113
+ * Get count of active registrations
114
+ */
115
+ getRegistrationCount() {
116
+ let count = 0;
117
+ for (const registrations of this.portRegistry.values()) {
118
+ count += registrations.length;
119
+ }
120
+ return count;
121
+ }
122
+ /**
123
+ * Get all registered source URLs
124
+ */
125
+ getRegisteredSources() {
126
+ return Array.from(this.portRegistry.keys());
127
+ }
128
+ }
129
+ exports.PortRouter = PortRouter;
130
+ //# sourceMappingURL=PortRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PortRouter.js","sourceRoot":"","sources":["../../src/router/PortRouter.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAGH,6CAAwD;AAIxD,MAAa,UAAU;IAIrB,YAAY,MAAe;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,IAAA,qBAAY,EAAC,YAAY,CAAC,CAAC;QACnD,IAAI,CAAC,YAAY,GAAG,IAAI,GAAG,EAAE,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,QAAgB,EAAE,SAAiB,EAAE,IAAiB;QACjE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,+BAA+B,QAAQ,aAAa,SAAS,EAAE,CAAC,CAAC;QAElF,MAAM,YAAY,GAAqB;YACrC,QAAQ;YACR,SAAS;YACT,IAAI;YACJ,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE;SACzB,CAAC;QAEF,6CAA6C;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAExD,6DAA6D;QAC7D,MAAM,aAAa,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QACvE,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,QAAQ,2BAA2B,SAAS,aAAa,CAAC,CAAC;YACtF,QAAQ,CAAC,aAAa,CAAC,GAAG,YAAY,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC9B,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,QAAQ,CAAC,MAAM,sBAAsB,SAAS,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,QAAgB,EAAE,SAAiB;QAChD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iCAAiC,QAAQ,aAAa,SAAS,EAAE,CAAC,CAAC;QAEpF,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sCAAsC,SAAS,EAAE,CAAC,CAAC;YACpE,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QAEpE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACpC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,SAAS,wCAAwC,CAAC,CAAC;QACzF,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAC3C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,MAAM,gCAAgC,SAAS,EAAE,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,QAAgB;QAC/B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sCAAsC,QAAQ,EAAE,CAAC,CAAC;QAEnE,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,MAAM,eAAe,GAAa,EAAE,CAAC;QAErC,KAAK,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC;YACrE,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;YACpE,YAAY,IAAI,aAAa,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAEvD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1B,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAClC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;QAED,uCAAuC;QACvC,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAEpE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,YAAY,qBAAqB,QAAQ,EAAE,CAAC,CAAC;IAChF,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,OAAmC,EAAE,SAAiB;QACjE,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAEvD,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,SAAS,mBAAmB,CAAC,CAAC;YAChF,OAAO;QACT,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,SAAS,OAAO,aAAa,CAAC,MAAM,YAAY,CAAC,CAAC;QAE3F,MAAM,OAAO,GAAG;YACd,IAAI,EAAE,aAAa;YACnB,OAAO;YACP,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;QAEF,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;YACzC,IAAI,CAAC;gBACH,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;gBACvC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC;YACtE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,YAAY,CAAC,QAAQ,GAAG,EAAE,GAAG,CAAC,CAAC;gBAC7E,4CAA4C;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,oBAAoB;QAClB,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,aAAa,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;YACvD,KAAK,IAAI,aAAa,CAAC,MAAM,CAAC;QAChC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,oBAAoB;QAClB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9C,CAAC;CACF;AA9ID,gCA8IC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * OTLPForwardingServer - HTTP server that receives OTLP traces from Go collector
3
+ */
4
+ import { TraceOutput } from '../output/TraceOutput';
5
+ import { Logger } from '../shared/logger';
6
+ export interface HTTPServerConfig {
7
+ port: number;
8
+ enableCORS?: boolean;
9
+ }
10
+ export declare class OTLPForwardingServer {
11
+ private config;
12
+ private traceOutput;
13
+ private logger;
14
+ private server;
15
+ private port;
16
+ private tracesReceived;
17
+ constructor(config: HTTPServerConfig, traceOutput: TraceOutput, logger?: Logger);
18
+ /**
19
+ * Start the HTTP server
20
+ */
21
+ start(): Promise<void>;
22
+ /**
23
+ * Stop the HTTP server
24
+ */
25
+ stop(): Promise<void>;
26
+ /**
27
+ * Get the server port
28
+ */
29
+ getPort(): number;
30
+ /**
31
+ * Get traces received count
32
+ */
33
+ getTracesReceived(): number;
34
+ /**
35
+ * Handle incoming HTTP request
36
+ */
37
+ private handleRequest;
38
+ /**
39
+ * Handle OTLP trace request - supports both JSON and protobuf formats
40
+ */
41
+ private handleTraceRequest;
42
+ /**
43
+ * Handle health check request
44
+ */
45
+ private handleHealthCheck;
46
+ /**
47
+ * Handle CORS headers
48
+ */
49
+ private handleCORS;
50
+ /**
51
+ * Read request body as Buffer
52
+ */
53
+ private readBody;
54
+ /**
55
+ * Extract source URL from OTLP payload
56
+ */
57
+ private extractSourceUrl;
58
+ }
59
+ //# sourceMappingURL=OTLPForwardingServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OTLPForwardingServer.d.ts","sourceRoot":"","sources":["../../src/server/OTLPForwardingServer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAgB,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,oBAAoB;IAO7B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,WAAW;IAPrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,cAAc,CAAa;gBAGzB,MAAM,EAAE,gBAAgB,EACxB,WAAW,EAAE,WAAW,EAChC,MAAM,CAAC,EAAE,MAAM;IAMjB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB3B;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;OAEG;IACH,OAAO,CAAC,aAAa;IA2BrB;;OAEG;YACW,kBAAkB;IA0DhC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;OAEG;IACH,OAAO,CAAC,UAAU;IAUlB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAkBhB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAuBzB"}
@@ -0,0 +1,245 @@
1
+ "use strict";
2
+ /**
3
+ * OTLPForwardingServer - HTTP server that receives OTLP traces from Go collector
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.OTLPForwardingServer = void 0;
40
+ const http = __importStar(require("http"));
41
+ const root = __importStar(require("@opentelemetry/otlp-transformer/build/esm/generated/root"));
42
+ const logger_1 = require("../shared/logger");
43
+ class OTLPForwardingServer {
44
+ constructor(config, traceOutput, logger) {
45
+ this.config = config;
46
+ this.traceOutput = traceOutput;
47
+ this.server = null;
48
+ this.tracesReceived = 0;
49
+ this.logger = logger || (0, logger_1.createLogger)('OTLPForwardingServer');
50
+ this.port = config.port;
51
+ }
52
+ /**
53
+ * Start the HTTP server
54
+ */
55
+ async start() {
56
+ return new Promise((resolve, reject) => {
57
+ this.server = http.createServer((req, res) => {
58
+ this.handleRequest(req, res);
59
+ });
60
+ this.server.on('error', (err) => {
61
+ this.logger.error('Server error:', err);
62
+ reject(err);
63
+ });
64
+ this.server.listen(this.port, () => {
65
+ this.logger.info(`OTLP forwarding server listening on http://localhost:${this.port}`);
66
+ resolve();
67
+ });
68
+ });
69
+ }
70
+ /**
71
+ * Stop the HTTP server
72
+ */
73
+ async stop() {
74
+ if (!this.server) {
75
+ return;
76
+ }
77
+ return new Promise((resolve, reject) => {
78
+ this.server.close((err) => {
79
+ if (err) {
80
+ this.logger.error('Error stopping server:', err);
81
+ reject(err);
82
+ }
83
+ else {
84
+ this.logger.info('Server stopped');
85
+ this.server = null;
86
+ resolve();
87
+ }
88
+ });
89
+ });
90
+ }
91
+ /**
92
+ * Get the server port
93
+ */
94
+ getPort() {
95
+ return this.port;
96
+ }
97
+ /**
98
+ * Get traces received count
99
+ */
100
+ getTracesReceived() {
101
+ return this.tracesReceived;
102
+ }
103
+ /**
104
+ * Handle incoming HTTP request
105
+ */
106
+ handleRequest(req, res) {
107
+ // Handle CORS preflight
108
+ if (this.config.enableCORS && req.method === 'OPTIONS') {
109
+ this.handleCORS(req, res);
110
+ res.writeHead(204);
111
+ res.end();
112
+ return;
113
+ }
114
+ // Health check endpoint
115
+ if (req.url === '/health' && req.method === 'GET') {
116
+ this.handleHealthCheck(req, res);
117
+ return;
118
+ }
119
+ // OTLP traces endpoint
120
+ if (req.url === '/v1/traces' && req.method === 'POST') {
121
+ // Handle async trace request - must use void to explicitly ignore promise
122
+ void this.handleTraceRequest(req, res);
123
+ return;
124
+ }
125
+ // Not found
126
+ res.writeHead(404, { 'Content-Type': 'application/json' });
127
+ res.end(JSON.stringify({ error: 'Not found' }));
128
+ }
129
+ /**
130
+ * Handle OTLP trace request - supports both JSON and protobuf formats
131
+ */
132
+ async handleTraceRequest(req, res) {
133
+ try {
134
+ // Read body as buffer
135
+ const bodyBuffer = await this.readBody(req);
136
+ // Determine format from Content-Type header
137
+ const contentType = req.headers['content-type'] || 'application/json';
138
+ let payload;
139
+ if (contentType.includes('application/x-protobuf') || contentType.includes('application/octet-stream')) {
140
+ // Decode protobuf format
141
+ this.logger.debug('Decoding protobuf trace request');
142
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
143
+ const rootAny = root;
144
+ const traceRequestType = rootAny.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;
145
+ const decoded = traceRequestType.decode(bodyBuffer);
146
+ payload = traceRequestType.toObject(decoded, {
147
+ longs: String,
148
+ enums: String,
149
+ bytes: String,
150
+ });
151
+ }
152
+ else {
153
+ // Parse JSON format (default)
154
+ this.logger.debug('Parsing JSON trace request');
155
+ const bodyString = bodyBuffer.toString('utf-8');
156
+ payload = JSON.parse(bodyString);
157
+ }
158
+ // Extract source URL
159
+ const sourceUrl = this.extractSourceUrl(payload);
160
+ // Forward to output
161
+ this.traceOutput.send(payload, sourceUrl);
162
+ this.tracesReceived++;
163
+ // Send success response
164
+ this.handleCORS(req, res);
165
+ res.writeHead(200, { 'Content-Type': 'application/json' });
166
+ res.end(JSON.stringify({ status: 'ok' }));
167
+ this.logger.debug(`Received traces from ${sourceUrl}`);
168
+ }
169
+ catch (err) {
170
+ const errorMessage = err instanceof Error ? err.message : String(err);
171
+ const errorStack = err instanceof Error ? err.stack : undefined;
172
+ this.logger.error('Error handling trace request:', errorMessage);
173
+ if (errorStack) {
174
+ this.logger.error('Stack trace:', errorStack);
175
+ }
176
+ if (!res.headersSent) {
177
+ res.writeHead(500, { 'Content-Type': 'application/json' });
178
+ res.end(JSON.stringify({ error: 'Internal server error' }));
179
+ }
180
+ }
181
+ }
182
+ /**
183
+ * Handle health check request
184
+ */
185
+ handleHealthCheck(req, res) {
186
+ this.handleCORS(req, res);
187
+ res.writeHead(200, { 'Content-Type': 'application/json' });
188
+ res.end(JSON.stringify({
189
+ status: 'healthy',
190
+ tracesReceived: this.tracesReceived,
191
+ }));
192
+ }
193
+ /**
194
+ * Handle CORS headers
195
+ */
196
+ handleCORS(_req, res) {
197
+ if (!this.config.enableCORS) {
198
+ return;
199
+ }
200
+ res.setHeader('Access-Control-Allow-Origin', '*');
201
+ res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
202
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
203
+ }
204
+ /**
205
+ * Read request body as Buffer
206
+ */
207
+ readBody(req) {
208
+ return new Promise((resolve, reject) => {
209
+ const chunks = [];
210
+ req.on('data', (chunk) => {
211
+ chunks.push(chunk);
212
+ });
213
+ req.on('end', () => {
214
+ resolve(Buffer.concat(chunks));
215
+ });
216
+ req.on('error', (err) => {
217
+ reject(err);
218
+ });
219
+ });
220
+ }
221
+ /**
222
+ * Extract source URL from OTLP payload
223
+ */
224
+ extractSourceUrl(payload) {
225
+ // Try to extract from resource attributes
226
+ const resourceSpans = payload.resourceSpans?.[0];
227
+ if (!resourceSpans) {
228
+ return 'unknown';
229
+ }
230
+ const attributes = resourceSpans.resource?.attributes || [];
231
+ // Look for dev.server.url attribute
232
+ const devServerUrl = attributes.find((attr) => attr.key === 'dev.server.url');
233
+ if (devServerUrl?.value?.stringValue) {
234
+ return devServerUrl.value.stringValue;
235
+ }
236
+ // Fallback to service.name
237
+ const serviceName = attributes.find((attr) => attr.key === 'service.name');
238
+ if (serviceName?.value?.stringValue) {
239
+ return serviceName.value.stringValue;
240
+ }
241
+ return 'unknown';
242
+ }
243
+ }
244
+ exports.OTLPForwardingServer = OTLPForwardingServer;
245
+ //# sourceMappingURL=OTLPForwardingServer.js.map