@oas-tools/oas-telemetry 0.7.0-alpha.2 → 0.7.0-alpha.3

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 (154) hide show
  1. package/.env.example +50 -17
  2. package/README.md +242 -240
  3. package/dist/cjs/config/bootConfig.cjs +18 -0
  4. package/dist/cjs/config/config.cjs +145 -0
  5. package/dist/cjs/config/config.types.cjs +5 -0
  6. package/dist/cjs/index.cjs +19 -25
  7. package/dist/cjs/{tlmRoutes.cjs → routesManager.cjs} +28 -21
  8. package/dist/cjs/{exporters/InMemoryLogRecordExporter.cjs → telemetry/custom-implementations/exporters/InMemoryDbLogExporter.cjs} +42 -19
  9. package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.cjs +97 -0
  10. package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.cjs +118 -0
  11. package/dist/cjs/telemetry/custom-implementations/exporters/PluginLogExporter.cjs +52 -0
  12. package/dist/cjs/telemetry/custom-implementations/exporters/PluginMetricExporter.cjs +53 -0
  13. package/dist/cjs/telemetry/custom-implementations/exporters/PluginSpanExporter.cjs +69 -0
  14. package/dist/cjs/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.cjs +70 -0
  15. package/dist/cjs/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.cjs +70 -0
  16. package/dist/cjs/{utils → telemetry/custom-implementations/utils}/circular.cjs +39 -49
  17. package/dist/cjs/telemetry/custom-implementations/wrappers.cjs +175 -0
  18. package/dist/cjs/telemetry/initializeTelemetry.cjs +74 -0
  19. package/dist/cjs/telemetry/telemetryConfigurator.cjs +84 -0
  20. package/dist/cjs/telemetry/telemetryRegistry.cjs +40 -0
  21. package/dist/cjs/tlm-ai/agent.cjs +82 -63
  22. package/dist/cjs/tlm-ai/aiController.cjs +5 -4
  23. package/dist/cjs/tlm-ai/aiRoutes.cjs +9 -6
  24. package/dist/cjs/tlm-ai/tools.cjs +16 -9
  25. package/dist/cjs/tlm-auth/authController.cjs +14 -15
  26. package/dist/cjs/tlm-auth/authMiddleware.cjs +11 -10
  27. package/dist/cjs/tlm-auth/authRoutes.cjs +9 -7
  28. package/dist/cjs/tlm-log/logController.cjs +45 -18
  29. package/dist/cjs/tlm-log/logRoutes.cjs +16 -11
  30. package/dist/cjs/tlm-metric/metricsController.cjs +37 -12
  31. package/dist/cjs/tlm-metric/metricsRoutes.cjs +16 -11
  32. package/dist/cjs/tlm-plugin/pluginController.cjs +40 -19
  33. package/dist/cjs/tlm-plugin/pluginRoutes.cjs +8 -6
  34. package/dist/cjs/tlm-plugin/pluginService.cjs +25 -0
  35. package/dist/cjs/tlm-trace/traceController.cjs +54 -45
  36. package/dist/cjs/tlm-trace/traceRoutes.cjs +16 -11
  37. package/dist/cjs/tlm-ui/uiRoutes.cjs +26 -20
  38. package/dist/cjs/tlm-util/utilController.cjs +8 -9
  39. package/dist/cjs/tlm-util/utilRoutes.cjs +22 -19
  40. package/dist/cjs/types/index.cjs +0 -1
  41. package/dist/cjs/utils/logger.cjs +3 -5
  42. package/dist/cjs/utils/regexUtils.cjs +27 -0
  43. package/dist/esm/config/bootConfig.js +11 -0
  44. package/dist/esm/config/config.js +126 -0
  45. package/dist/esm/index.js +18 -29
  46. package/dist/esm/{tlmRoutes.js → routesManager.js} +27 -22
  47. package/dist/esm/{exporters/InMemoryLogRecordExporter.js → telemetry/custom-implementations/exporters/InMemoryDbLogExporter.js} +31 -17
  48. package/dist/esm/{exporters/InMemoryDBMetricsExporter.js → telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.js} +31 -17
  49. package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.js +105 -0
  50. package/dist/esm/telemetry/custom-implementations/exporters/PluginLogExporter.js +44 -0
  51. package/dist/esm/telemetry/custom-implementations/exporters/PluginMetricExporter.js +43 -0
  52. package/dist/esm/telemetry/custom-implementations/exporters/PluginSpanExporter.js +61 -0
  53. package/dist/esm/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.js +64 -0
  54. package/dist/esm/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.js +64 -0
  55. package/dist/esm/telemetry/custom-implementations/utils/circular.js +76 -0
  56. package/dist/esm/telemetry/custom-implementations/wrappers.js +163 -0
  57. package/dist/esm/telemetry/initializeTelemetry.js +71 -0
  58. package/dist/esm/telemetry/telemetryConfigurator.js +74 -0
  59. package/dist/esm/telemetry/telemetryRegistry.js +34 -0
  60. package/dist/esm/tlm-ai/agent.js +77 -59
  61. package/dist/esm/tlm-ai/aiController.js +5 -4
  62. package/dist/esm/tlm-ai/aiRoutes.js +7 -5
  63. package/dist/esm/tlm-ai/tools.js +18 -9
  64. package/dist/esm/tlm-auth/authController.js +9 -10
  65. package/dist/esm/tlm-auth/authMiddleware.js +10 -9
  66. package/dist/esm/tlm-auth/authRoutes.js +8 -6
  67. package/dist/esm/tlm-log/logController.js +36 -16
  68. package/dist/esm/tlm-log/logRoutes.js +15 -11
  69. package/dist/esm/tlm-metric/metricsController.js +29 -10
  70. package/dist/esm/tlm-metric/metricsRoutes.js +15 -11
  71. package/dist/esm/tlm-plugin/pluginController.js +40 -19
  72. package/dist/esm/tlm-plugin/pluginRoutes.js +6 -5
  73. package/dist/esm/tlm-plugin/pluginService.js +19 -0
  74. package/dist/esm/tlm-trace/traceController.js +40 -35
  75. package/dist/esm/tlm-trace/traceRoutes.js +15 -11
  76. package/dist/esm/tlm-ui/uiRoutes.js +24 -19
  77. package/dist/esm/tlm-util/utilController.js +8 -9
  78. package/dist/esm/tlm-util/utilRoutes.js +17 -15
  79. package/dist/esm/types/index.js +0 -1
  80. package/dist/esm/utils/logger.js +3 -4
  81. package/dist/esm/utils/regexUtils.js +23 -0
  82. package/dist/types/config/bootConfig.d.ts +5 -0
  83. package/dist/types/config/config.d.ts +253 -0
  84. package/dist/types/config/config.types.d.ts +34 -0
  85. package/dist/types/index.d.ts +5 -4
  86. package/dist/types/routesManager.d.ts +3 -0
  87. package/dist/types/{exporters/InMemoryLogRecordExporter.d.ts → telemetry/custom-implementations/exporters/InMemoryDbLogExporter.d.ts} +6 -6
  88. package/dist/types/{exporters/InMemoryDBMetricsExporter.d.ts → telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.d.ts} +7 -7
  89. package/dist/types/{exporters/InMemoryDbExporter.d.ts → telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.d.ts} +9 -9
  90. package/dist/types/telemetry/custom-implementations/exporters/PluginLogExporter.d.ts +8 -0
  91. package/dist/types/telemetry/custom-implementations/exporters/PluginMetricExporter.d.ts +12 -0
  92. package/dist/types/telemetry/custom-implementations/exporters/PluginSpanExporter.d.ts +14 -0
  93. package/dist/types/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.d.ts +32 -0
  94. package/dist/types/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.d.ts +34 -0
  95. package/dist/types/telemetry/custom-implementations/utils/circular.d.ts +27 -0
  96. package/dist/types/telemetry/custom-implementations/wrappers.d.ts +52 -0
  97. package/dist/types/telemetry/initializeTelemetry.d.ts +1 -0
  98. package/dist/types/telemetry/telemetryConfigurator.d.ts +2 -0
  99. package/dist/types/telemetry/telemetryRegistry.d.ts +20 -0
  100. package/dist/types/tlm-ai/agent.d.ts +2 -1
  101. package/dist/types/tlm-ai/aiController.d.ts +4 -3
  102. package/dist/types/tlm-ai/aiRoutes.d.ts +2 -2
  103. package/dist/types/tlm-ai/tools.d.ts +3 -1
  104. package/dist/types/tlm-auth/authController.d.ts +4 -3
  105. package/dist/types/tlm-auth/authMiddleware.d.ts +2 -1
  106. package/dist/types/tlm-auth/authRoutes.d.ts +2 -2
  107. package/dist/types/tlm-log/logController.d.ts +1 -0
  108. package/dist/types/tlm-log/logRoutes.d.ts +2 -2
  109. package/dist/types/tlm-metric/metricsController.d.ts +1 -0
  110. package/dist/types/tlm-metric/metricsRoutes.d.ts +2 -2
  111. package/dist/types/tlm-plugin/pluginRoutes.d.ts +1 -2
  112. package/dist/types/tlm-plugin/pluginService.d.ts +9 -0
  113. package/dist/types/tlm-trace/traceController.d.ts +7 -6
  114. package/dist/types/tlm-trace/traceRoutes.d.ts +2 -2
  115. package/dist/types/tlm-ui/uiRoutes.d.ts +1 -2
  116. package/dist/types/tlm-util/utilController.d.ts +2 -1
  117. package/dist/types/tlm-util/utilRoutes.d.ts +2 -2
  118. package/dist/types/types/index.d.ts +7 -46
  119. package/dist/types/utils/regexUtils.d.ts +1 -0
  120. package/dist/ui/assets/index-D9HsRlaQ.js +437 -0
  121. package/dist/ui/assets/index-DEyIcKBi.css +1 -0
  122. package/dist/ui/index.html +3 -3
  123. package/dist/ui/oas-tlm.svg +185 -0
  124. package/package.json +12 -7
  125. package/dist/cjs/config.cjs +0 -31
  126. package/dist/cjs/exporters/InMemoryDBMetricsExporter.cjs +0 -74
  127. package/dist/cjs/exporters/InMemoryDbExporter.cjs +0 -102
  128. package/dist/cjs/exporters/consoleExporter.cjs +0 -47
  129. package/dist/cjs/exporters/dynamicExporter.cjs +0 -57
  130. package/dist/cjs/instrumentation/index.cjs +0 -28
  131. package/dist/cjs/instrumentation/logs.cjs +0 -46
  132. package/dist/cjs/instrumentation/metrics.cjs +0 -27
  133. package/dist/cjs/instrumentation/traces.cjs +0 -19
  134. package/dist/esm/config.js +0 -20
  135. package/dist/esm/exporters/InMemoryDbExporter.js +0 -102
  136. package/dist/esm/exporters/consoleExporter.js +0 -38
  137. package/dist/esm/exporters/dynamicExporter.js +0 -50
  138. package/dist/esm/instrumentation/index.js +0 -26
  139. package/dist/esm/instrumentation/logs.js +0 -34
  140. package/dist/esm/instrumentation/metrics.js +0 -18
  141. package/dist/esm/instrumentation/traces.js +0 -12
  142. package/dist/esm/utils/circular.js +0 -84
  143. package/dist/types/config.d.ts +0 -6
  144. package/dist/types/exporters/consoleExporter.d.ts +0 -13
  145. package/dist/types/exporters/dynamicExporter.d.ts +0 -25
  146. package/dist/types/instrumentation/logs.d.ts +0 -1
  147. package/dist/types/instrumentation/metrics.d.ts +0 -1
  148. package/dist/types/instrumentation/traces.d.ts +0 -1
  149. package/dist/types/tlmRoutes.d.ts +0 -2
  150. package/dist/types/utils/circular.d.ts +0 -31
  151. package/dist/ui/assets/index-BNhZBPi2.css +0 -1
  152. package/dist/ui/assets/index-DxGAMrAl.js +0 -401
  153. package/dist/ui/vite.svg +0 -1
  154. /package/dist/{types/instrumentation/index.d.ts → esm/config/config.types.js} +0 -0
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.PluginLogExporter = void 0;
7
+ var _core = require("@opentelemetry/core");
8
+ var _logger = _interopRequireDefault(require("../../../utils/logger.cjs"));
9
+ var _wrappers = require("../wrappers.cjs");
10
+ var _pluginService = require("../../../tlm-plugin/pluginService.cjs");
11
+ var _circular = require("../utils/circular.cjs");
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ class PluginLogExporter extends _wrappers.Enabler {
14
+ constructor() {
15
+ super();
16
+ }
17
+ export(logs, resultCallback) {
18
+ _logger.default.debug('PluginLogExporter.export called with logs: ', logs.length);
19
+ try {
20
+ if (!this.isEnabled()) {
21
+ _logger.default.debug('PluginLogExporter is not enabled. Skipping export.');
22
+ return resultCallback({
23
+ code: _core.ExportResultCode.SUCCESS
24
+ });
25
+ }
26
+ const cleanLogs = logs.map(log => (0, _circular.removeCircularRefs)(log)).map(log => (0, _circular.applyNesting)(log));
27
+ _pluginService.pluginService.getPlugins().forEach((pluginResource, i) => {
28
+ if (typeof pluginResource.pluginImplementation.newLog === 'function') {
29
+ cleanLogs.forEach(log => {
30
+ _logger.default.debug(`Sending log to plugin (Plugin #${i}) <${pluginResource.name}>`);
31
+ pluginResource.pluginImplementation.newLog(log);
32
+ });
33
+ } else {
34
+ _logger.default.debug(`Plugin <${pluginResource.name}> does not implement newLog method. Skipping log export.`);
35
+ }
36
+ });
37
+ setTimeout(() => resultCallback({
38
+ code: _core.ExportResultCode.SUCCESS
39
+ }), 0);
40
+ } catch (error) {
41
+ _logger.default.error('Error exporting logs\n' + error.message + '\n' + error.stack);
42
+ return resultCallback({
43
+ code: _core.ExportResultCode.FAILED,
44
+ error: new Error('Error exporting logs\n' + error.message + '\n' + error.stack)
45
+ });
46
+ }
47
+ }
48
+ shutdown() {
49
+ return Promise.resolve();
50
+ }
51
+ }
52
+ exports.PluginLogExporter = PluginLogExporter;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.PluginMetricExporter = void 0;
7
+ var _core = require("@opentelemetry/core");
8
+ var _logger = _interopRequireDefault(require("../../../utils/logger.cjs"));
9
+ var _wrappers = require("../wrappers.cjs");
10
+ var _pluginService = require("../../../tlm-plugin/pluginService.cjs");
11
+ var _circular = require("../utils/circular.cjs");
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ class PluginMetricExporter extends _wrappers.Enabler {
14
+ constructor() {
15
+ super();
16
+ }
17
+ export(metrics, resultCallback) {
18
+ _logger.default.debug('PluginMetricExporter.export called');
19
+ try {
20
+ if (!this.isEnabled()) {
21
+ _logger.default.debug('PluginMetricExporter is not enabled. Skipping export.');
22
+ return resultCallback({
23
+ code: _core.ExportResultCode.SUCCESS
24
+ });
25
+ }
26
+ const cleanMetrics = (0, _circular.applyNesting)((0, _circular.removeCircularRefs)(metrics));
27
+ _pluginService.pluginService.getPlugins().forEach((pluginResource, i) => {
28
+ if (typeof pluginResource.pluginImplementation.newMetric === 'function') {
29
+ _logger.default.debug(`Sending metric to plugin (Plugin #${i}) <${pluginResource.name}>`);
30
+ pluginResource.pluginImplementation.newMetric(cleanMetrics);
31
+ } else {
32
+ _logger.default.debug(`Plugin <${pluginResource.name}> does not implement newMetric method. Skipping metric export.`);
33
+ }
34
+ });
35
+ setTimeout(() => resultCallback({
36
+ code: _core.ExportResultCode.SUCCESS
37
+ }), 0);
38
+ } catch (error) {
39
+ _logger.default.error('Error exporting metrics\n' + error.message + '\n' + error.stack);
40
+ return resultCallback({
41
+ code: _core.ExportResultCode.FAILED,
42
+ error: new Error('Error exporting metrics\n' + error.message + '\n' + error.stack)
43
+ });
44
+ }
45
+ }
46
+ shutdown() {
47
+ return Promise.resolve();
48
+ }
49
+ forceFlush() {
50
+ return Promise.resolve();
51
+ }
52
+ }
53
+ exports.PluginMetricExporter = PluginMetricExporter;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.PluginSpanExporter = void 0;
7
+ var _core = require("@opentelemetry/core");
8
+ var _logger = _interopRequireDefault(require("../../../utils/logger.cjs"));
9
+ var _wrappers = require("../wrappers.cjs");
10
+ var _pluginService = require("../../../tlm-plugin/pluginService.cjs");
11
+ var _circular = require("../utils/circular.cjs");
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ class PluginSpanExporter extends _wrappers.Enabler {
14
+ constructor() {
15
+ super();
16
+ this._baseUrl = '/telemetry'; // Default base URL, can be overridden by the config
17
+ }
18
+ set baseUrl(baseUrl) {
19
+ this._baseUrl = baseUrl;
20
+ }
21
+ export(readableSpans, resultCallback) {
22
+ _logger.default.debug('PluginSpanExporter.export called with spans: ', readableSpans.length);
23
+ try {
24
+ if (!this.isEnabled()) {
25
+ _logger.default.debug('PluginSpanExporter is not enabled. Skipping export.');
26
+ return resultCallback({
27
+ code: _core.ExportResultCode.SUCCESS
28
+ });
29
+ }
30
+ // Prepare spans to be inserted into the in-memory database (remove circular references and convert to nested objects)
31
+ const cleanSpans = readableSpans.map(nestedSpan => (0, _circular.removeCircularRefs)(nestedSpan)) // to avoid JSON parsing error
32
+ .map(span => (0, _circular.applyNesting)(span)) // to avoid dot notation in keys (neDB does not support dot notation in keys)
33
+ .filter(span => {
34
+ const target = span?.attributes?.http?.target; // Exclude spans where target includes 'telemetry' but NOT 'telemetry/utils'
35
+ if (target && target.includes(this._baseUrl)) {
36
+ return target.includes(this._baseUrl + '/utils');
37
+ }
38
+ return true;
39
+ });
40
+ _pluginService.pluginService.getPlugins().forEach((pluginResource, i) => {
41
+ if (typeof pluginResource.pluginImplementation.newTrace === 'function') {
42
+ cleanSpans.forEach(span => {
43
+ _logger.default.debug(`Sending span to plugin (Plugin #${i}) <${pluginResource.name}>`);
44
+ //TODO: This should be called newSpan instead of newTrace
45
+ pluginResource.pluginImplementation.newTrace(span);
46
+ });
47
+ } else {
48
+ _logger.default.debug(`Plugin <${pluginResource.name}> does not implement newTrace method. Skipping span export.`);
49
+ }
50
+ });
51
+ setTimeout(() => resultCallback({
52
+ code: _core.ExportResultCode.SUCCESS
53
+ }), 0);
54
+ } catch (error) {
55
+ _logger.default.error('Error exporting spans\n' + error.message + '\n' + error.stack);
56
+ return resultCallback({
57
+ code: _core.ExportResultCode.FAILED,
58
+ error: new Error('Error exporting spans\n' + error.message + '\n' + error.stack)
59
+ });
60
+ }
61
+ }
62
+ shutdown() {
63
+ return this.forceFlush();
64
+ }
65
+ forceFlush() {
66
+ return Promise.resolve();
67
+ }
68
+ }
69
+ exports.PluginSpanExporter = PluginSpanExporter;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DynamicMultiLogRecordProcessor = void 0;
7
+ var _core = require("@opentelemetry/core");
8
+ var _logger = _interopRequireDefault(require("../../../utils/logger.cjs"));
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
+ // optional if you want logging
11
+ class DynamicMultiLogRecordProcessor {
12
+ constructor(initialProcessors = [], forceFlushTimeoutMillis = 30000) {
13
+ this._processors = [];
14
+ this._processors = [...initialProcessors];
15
+ this._forceFlushTimeoutMillis = forceFlushTimeoutMillis;
16
+ }
17
+ /**
18
+ * Add a new LogRecordProcessor or an array of LogRecordProcessors at runtime.
19
+ */
20
+ addProcessors(processor) {
21
+ if (Array.isArray(processor)) {
22
+ this._processors.push(...processor);
23
+ } else {
24
+ this._processors.push(processor);
25
+ }
26
+ }
27
+ /**
28
+ * Remove a specific LogRecordProcessor.
29
+ */
30
+ removeProcessor(processor) {
31
+ this._processors = this._processors.filter(p => p !== processor);
32
+ }
33
+ /**
34
+ * Clear all LogRecordProcessors.
35
+ */
36
+ clearProcessors() {
37
+ this._processors = [];
38
+ }
39
+ /**
40
+ * Called when a log record is emitted.
41
+ */
42
+ onEmit(logRecord, context) {
43
+ for (const processor of this._processors) {
44
+ try {
45
+ processor.onEmit(logRecord, context);
46
+ } catch (error) {
47
+ _logger.default?.error?.('Error in onEmit of LogRecordProcessor:', error);
48
+ }
49
+ }
50
+ }
51
+ /**
52
+ * Force flush all processors with timeout.
53
+ */
54
+ async forceFlush() {
55
+ const timeout = this._forceFlushTimeoutMillis;
56
+ const promises = this._processors.map(p => (0, _core.callWithTimeout)(p.forceFlush(), timeout));
57
+ try {
58
+ await Promise.all(promises);
59
+ } catch (error) {
60
+ _logger.default?.error?.('Error during forceFlush in DynamicMultiLogRecordProcessor:', error);
61
+ }
62
+ }
63
+ /**
64
+ * Shutdown all processors.
65
+ */
66
+ async shutdown() {
67
+ await Promise.all(this._processors.map(p => p.shutdown()));
68
+ }
69
+ }
70
+ exports.DynamicMultiLogRecordProcessor = DynamicMultiLogRecordProcessor;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DynamicMultiSpanProcessor = void 0;
7
+ var _logger = _interopRequireDefault(require("../../../utils/logger.cjs"));
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
+ class DynamicMultiSpanProcessor {
10
+ constructor(initialProcessors = []) {
11
+ this._spanProcessors = [];
12
+ this._spanProcessors = [...initialProcessors];
13
+ }
14
+ /**
15
+ * Add a new SpanProcessor or an array of SpanProcessors at runtime.
16
+ */
17
+ addProcessors(processor) {
18
+ if (Array.isArray(processor)) {
19
+ this._spanProcessors.push(...processor);
20
+ } else {
21
+ this._spanProcessors.push(processor);
22
+ }
23
+ }
24
+ /**
25
+ * Remove a specific SpanProcessor if needed.
26
+ */
27
+ removeProcessor(processor) {
28
+ this._spanProcessors = this._spanProcessors.filter(p => p !== processor);
29
+ }
30
+ /**
31
+ * Clear all processors.
32
+ */
33
+ clearProcessors() {
34
+ this._spanProcessors = [];
35
+ }
36
+ /**
37
+ * Called when a span is started.
38
+ */
39
+ onStart(span, context) {
40
+ for (const processor of this._spanProcessors) {
41
+ processor.onStart(span, context);
42
+ }
43
+ }
44
+ /**
45
+ * Called when a span ends.
46
+ */
47
+ onEnd(span) {
48
+ for (const processor of this._spanProcessors) {
49
+ processor.onEnd(span);
50
+ }
51
+ }
52
+ /**
53
+ * Force flush all processors.
54
+ */
55
+ async forceFlush() {
56
+ const promises = this._spanProcessors.map(p => p.forceFlush());
57
+ try {
58
+ await Promise.all(promises);
59
+ } catch (error) {
60
+ _logger.default.error('Error during forceFlush:', error);
61
+ }
62
+ }
63
+ /**
64
+ * Shutdown all processors.
65
+ */
66
+ async shutdown() {
67
+ await Promise.all(this._spanProcessors.map(p => p.shutdown()));
68
+ }
69
+ }
70
+ exports.DynamicMultiSpanProcessor = DynamicMultiSpanProcessor;
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.applyNesting = applyNesting;
7
- exports.convertToNestedObject = convertToNestedObject;
8
7
  exports.removeCircularRefs = removeCircularRefs;
9
8
  function removeCircularRefs(obj) {
10
9
  // const seen = new WeakMap(); // Used to keep track of visited objects
@@ -34,57 +33,48 @@ function removeCircularRefs(obj) {
34
33
  * @param {any} obj - The object to process.
35
34
  * @returns {any} - The object with all dot-separated keys converted to nested objects.
36
35
  * @example
37
- * // Input:
38
- * // {
39
- * // "http.method": "GET",
40
- * // "http.url": "http://example.com",
41
- * // "nested.obj.key": "value"
42
- * // }
43
- * // Output:
44
- * // {
45
- * // "http": {
46
- * // "method": "GET",
47
- * // "url": "http://example.com"
48
- * // },
49
- * // "nested": {
50
- * // "obj": {
51
- * // "key": "value"
52
- * // }
53
- * // }
54
- * // }
36
+ * Input:
37
+ * {
38
+ * "http.method": "GET",
39
+ * "http.url": "http://example.com",
40
+ * "nested.obj.key": "value"
41
+ * }
42
+ * Output:
43
+ * {
44
+ * "http": {
45
+ * "method": "GET",
46
+ * "url": "http://example.com"
47
+ * },
48
+ * "nested": {
49
+ * "obj": {
50
+ * "key": "value"
51
+ * }
52
+ * }
53
+ * }
55
54
  */
56
- function convertToNestedObject(obj) {
57
- const result = {};
58
- for (const key in obj) {
59
- const keys = key.split('.');
60
- let temp = result;
61
- for (let i = 0; i < keys.length; i++) {
62
- const currentKey = keys[i];
63
- if (i === keys.length - 1) {
64
- // Last key, set the value
65
- temp[currentKey] = obj[key];
66
- } else {
67
- // Intermediate key, ensure the object exists
68
- if (!temp[currentKey]) {
69
- temp[currentKey] = {};
55
+ function applyNesting(obj) {
56
+ if (Array.isArray(obj)) {
57
+ return obj.map(item => applyNesting(item));
58
+ } else if (typeof obj === 'object' && obj !== null) {
59
+ const result = {};
60
+ for (const key in obj) {
61
+ const value = applyNesting(obj[key]);
62
+ const keys = key.split('.');
63
+ let temp = result;
64
+ for (let i = 0; i < keys.length; i++) {
65
+ const currentKey = keys[i];
66
+ if (i === keys.length - 1) {
67
+ temp[currentKey] = value;
68
+ } else {
69
+ if (!temp[currentKey]) {
70
+ temp[currentKey] = {};
71
+ }
72
+ temp = temp[currentKey];
70
73
  }
71
- temp = temp[currentKey];
72
74
  }
73
75
  }
76
+ return result;
77
+ } else {
78
+ return obj;
74
79
  }
75
- return result;
76
- }
77
- /**
78
- * Applies nesting to all dot-separated keys within an object.
79
- */
80
- function applyNesting(obj) {
81
- for (const key in obj) {
82
- const value = obj[key];
83
- if (Array.isArray(value)) {
84
- obj[key] = value.map(item => typeof item === 'object' && item !== null ? applyNesting(item) : item);
85
- } else if (typeof value === 'object' && value !== null) {
86
- obj[key] = applyNesting(value);
87
- }
88
- }
89
- return convertToNestedObject(obj);
90
80
  }
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.EnablerSpanExporter = exports.EnablerMultiSpanExporter = exports.EnablerMultiLogExporter = exports.EnablerMetricReader = exports.EnablerLogExporter = exports.Enabler = void 0;
7
+ var _resources = require("@opentelemetry/resources");
8
+ var _logger = _interopRequireDefault(require("../../utils/logger.cjs"));
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
+ class Enabler {
11
+ constructor(enabled) {
12
+ this._enabled = true;
13
+ if (typeof enabled === 'boolean') {
14
+ this._enabled = enabled;
15
+ }
16
+ }
17
+ setEnabledValue(value) {
18
+ this._enabled = value;
19
+ }
20
+ enable() {
21
+ this._enabled = true;
22
+ }
23
+ disable() {
24
+ this._enabled = false;
25
+ }
26
+ isEnabled() {
27
+ return this._enabled;
28
+ }
29
+ toggle() {
30
+ this._enabled = !this._enabled;
31
+ }
32
+ }
33
+ /*
34
+ * Classes for enabler exporters, allowing enable/disable toggling of exporters at runtime.
35
+ *
36
+ * This class is designed to work for trace and log exporters, where multiple exporters can be active simultaneously
37
+ * (e.g., via a MultiExporter and one processor). By toggling the exporter, you can dynamically enable or
38
+ * disable the export operation without removing the exporter from the pipeline.
39
+ *
40
+ * For metrics, the OpenTelemetry model is different: there are two types of readers. PullMetricExporters do not have
41
+ * an exporter instance, and PushMetricExporters do, but only allow a single exporter per reader (with optional
42
+ * `selectAggregationTemporality` and `selectAggregation` attributes). Therefore, multiple exporters per reader are not
43
+ * supported for metrics.
44
+ *
45
+ * For metrics readers, a separate `DeactivableReader` class is recommended, which is even more efficient: when
46
+ * disabled, the reader's `collect` method is not called at all, saving additional resources compared to disabling the exporter.
47
+ *
48
+ */
49
+ exports.Enabler = Enabler;
50
+ class EnablerSpanExporter extends Enabler {
51
+ constructor(exporter) {
52
+ super();
53
+ this.exporter = exporter;
54
+ }
55
+ export(spans, resultCallback) {
56
+ if (this.isEnabled()) {
57
+ this.exporter.export(spans, resultCallback);
58
+ }
59
+ }
60
+ shutdown() {
61
+ return this.exporter.shutdown();
62
+ }
63
+ forceFlush() {
64
+ if (typeof this.exporter.forceFlush === 'function') {
65
+ return this.exporter.forceFlush();
66
+ }
67
+ return Promise.resolve();
68
+ }
69
+ }
70
+ exports.EnablerSpanExporter = EnablerSpanExporter;
71
+ class EnablerLogExporter extends Enabler {
72
+ constructor(exporter) {
73
+ super();
74
+ this.exporter = exporter;
75
+ }
76
+ export(logs, resultCallback) {
77
+ if (this.isEnabled()) {
78
+ this.exporter.export(logs, resultCallback);
79
+ }
80
+ }
81
+ shutdown() {
82
+ return this.exporter.shutdown();
83
+ }
84
+ }
85
+ exports.EnablerLogExporter = EnablerLogExporter;
86
+ class EnablerMultiExporter extends Enabler {
87
+ constructor(exporters) {
88
+ super();
89
+ this._exporters = [];
90
+ if (exporters && Array.isArray(exporters)) {
91
+ this._exporters = exporters;
92
+ }
93
+ }
94
+ addExporters(exporter) {
95
+ if (!this._exporters) {
96
+ this._exporters = [];
97
+ }
98
+ if (Array.isArray(exporter)) {
99
+ this._exporters.push(...exporter);
100
+ } else {
101
+ this._exporters.push(exporter);
102
+ }
103
+ }
104
+ }
105
+ class EnablerMultiSpanExporter extends EnablerMultiExporter {
106
+ export(spans, resultCallback) {
107
+ _logger.default.debug(`EnablerMultiSpanExporter.export called with ${spans.length} spans, exporters: ${this._exporters?.length ?? 0}, enabled: ${this.isEnabled()}`);
108
+ if (this.isEnabled() && this._exporters) {
109
+ this._exporters.forEach(exporter => exporter.export(spans, resultCallback));
110
+ }
111
+ }
112
+ async shutdown() {
113
+ if (this._exporters) {
114
+ await Promise.all(this._exporters.map(exporter => exporter.shutdown()));
115
+ }
116
+ return;
117
+ }
118
+ }
119
+ exports.EnablerMultiSpanExporter = EnablerMultiSpanExporter;
120
+ class EnablerMultiLogExporter extends EnablerMultiExporter {
121
+ export(logs, resultCallback) {
122
+ if (this.isEnabled() && this._exporters) {
123
+ this._exporters.forEach(exporter => exporter.export(logs, resultCallback));
124
+ }
125
+ }
126
+ async shutdown() {
127
+ if (this._exporters) {
128
+ await Promise.all(this._exporters.map(exporter => exporter.shutdown()));
129
+ }
130
+ return;
131
+ }
132
+ }
133
+ exports.EnablerMultiLogExporter = EnablerMultiLogExporter;
134
+ class EnablerMetricReader extends Enabler {
135
+ constructor(reader) {
136
+ super();
137
+ this.reader = reader;
138
+ }
139
+ forceFlush(options) {
140
+ if (this.isEnabled()) {
141
+ return this.reader.forceFlush(options);
142
+ }
143
+ return Promise.resolve();
144
+ }
145
+ setMetricProducer(metricProducer) {
146
+ if (this.isEnabled()) {
147
+ this.reader.setMetricProducer(metricProducer);
148
+ }
149
+ }
150
+ selectAggregation(instrumentType) {
151
+ return this.reader.selectAggregation(instrumentType);
152
+ }
153
+ selectAggregationTemporality(instrumentType) {
154
+ return this.reader.selectAggregationTemporality(instrumentType);
155
+ }
156
+ selectCardinalityLimit(instrumentType) {
157
+ return this.reader.selectCardinalityLimit(instrumentType);
158
+ }
159
+ async collect(options) {
160
+ if (this.isEnabled()) {
161
+ return await this.reader.collect(options);
162
+ }
163
+ return {
164
+ resourceMetrics: {
165
+ resource: (0, _resources.resourceFromAttributes)({}),
166
+ scopeMetrics: []
167
+ },
168
+ errors: []
169
+ };
170
+ }
171
+ shutdown(options) {
172
+ return this.reader.shutdown(options);
173
+ }
174
+ }
175
+ exports.EnablerMetricReader = EnablerMetricReader;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+
3
+ var _instrumentationHttp = require("@opentelemetry/instrumentation-http");
4
+ var _logger = _interopRequireDefault(require("../utils/logger.cjs"));
5
+ var _instrumentation = require("@opentelemetry/instrumentation");
6
+ var _telemetryRegistry = require("./telemetryRegistry.cjs");
7
+ var _sdkTraceNode = require("@opentelemetry/sdk-trace-node");
8
+ var _apiLogs = require("@opentelemetry/api-logs");
9
+ var _sdkLogs = require("@opentelemetry/sdk-logs");
10
+ var _bootConfig = require("../config/bootConfig.cjs");
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ // THIS INSTRUMENTATIONS NEED TO BE LOADED BEFORE ANYTHING ELSE
13
+ // They use monkey-patching to instrument the HTTP server and client.
14
+ // THIS FILE MUST BE CALLED BEFORE ANYTHING ELSE
15
+ if (_bootConfig.bootEnvVariables.OASTLM_BOOT_MODULE_DISABLED) {
16
+ _logger.default.info('🚫 OASTLM module is disabled, Providers not initialized.');
17
+ } else {
18
+ _logger.default.info('🚀 Initializing Open Telemetry');
19
+ initializeTraces();
20
+ initializeMetrics();
21
+ initializeLogs();
22
+ (0, _instrumentation.registerInstrumentations)({
23
+ instrumentations: [new _instrumentationHttp.HttpInstrumentation()
24
+ // new ExpressInstrumentation(),
25
+ ]
26
+ });
27
+ }
28
+ function initializeTraces() {
29
+ _logger.default.info('📊 Initializing TracerProvider');
30
+ const tracerProvider = new _sdkTraceNode.NodeTracerProvider({
31
+ resource: _telemetryRegistry.oasTelemetryResource,
32
+ spanProcessors: [_telemetryRegistry.dynamicMultiSpanProcessor]
33
+ });
34
+ tracerProvider.register();
35
+ }
36
+ function initializeLogs() {
37
+ _logger.default.info('📜 Initializing LoggerProvider');
38
+ // Create and configure LoggerProvider
39
+ const loggerProvider = new _sdkLogs.LoggerProvider({
40
+ resource: _telemetryRegistry.oasTelemetryResource,
41
+ processors: [_telemetryRegistry.dynamicMultiLogProcessor]
42
+ });
43
+ // Get a logger instance
44
+ const loggerInstance = loggerProvider.getLogger('oas-telemetry'); // Use loggerProvider to get the logger
45
+ // Override console methods to emit logs via OpenTelemetry, like an instrumentation
46
+ const originalConsoleMethods = {
47
+ log: console.log,
48
+ warn: console.warn,
49
+ error: console.error,
50
+ info: console.info,
51
+ debug: console.debug
52
+ };
53
+ Object.keys(originalConsoleMethods).forEach(method => {
54
+ // @ts-expect-error yes
55
+ console[method] = (...args) => {
56
+ loggerInstance.emit({
57
+ severityNumber: _apiLogs.SeverityNumber[method.toUpperCase()] || _apiLogs.SeverityNumber.INFO,
58
+ severityText: method.toUpperCase(),
59
+ body: args.join(' '),
60
+ attributes: {
61
+ 'source.source': `console.${method}`
62
+ }
63
+ });
64
+ // @ts-expect-error yes
65
+ originalConsoleMethods[method](...args);
66
+ };
67
+ });
68
+ }
69
+ function initializeMetrics() {
70
+ _logger.default.info('📈 Initializing MeterProvider');
71
+ // WARN: This is a custom provider that allows adding readers dynamically at runtime.
72
+ // WARN: Default PeriodicExportingMetricReader is added post initialization (see telemetryConfigurator.ts)
73
+ // The in memory exporter is added by default to that reader. More readers are allowed to be added dynamically
74
+ }