@oas-tools/oas-telemetry 0.6.1 → 0.7.0-alpha.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 (131) hide show
  1. package/README.md +442 -442
  2. package/dist/{config.cjs → cjs/config.cjs} +6 -7
  3. package/dist/{exporters → cjs/exporters}/InMemoryDBMetricsExporter.cjs +5 -40
  4. package/dist/cjs/exporters/InMemoryDbExporter.cjs +87 -0
  5. package/dist/cjs/exporters/InMemoryLogRecordExporter.cjs +110 -0
  6. package/dist/{exporters → cjs/exporters}/consoleExporter.cjs +2 -7
  7. package/dist/{exporters → cjs/exporters}/dynamicExporter.cjs +12 -19
  8. package/dist/cjs/index.cjs +43 -0
  9. package/dist/cjs/instrumentation/index.cjs +28 -0
  10. package/dist/cjs/instrumentation/logs.cjs +46 -0
  11. package/dist/cjs/instrumentation/metrics.cjs +27 -0
  12. package/dist/cjs/instrumentation/traces.cjs +19 -0
  13. package/dist/{openTelemetry.cjs → cjs/openTelemetry.cjs} +6 -8
  14. package/dist/{systemMetrics.cjs → cjs/systemMetrics.cjs} +7 -7
  15. package/dist/cjs/tlm-ai/agent.cjs +79 -0
  16. package/dist/cjs/tlm-ai/aiController.cjs +69 -0
  17. package/dist/cjs/tlm-ai/aiRoutes.cjs +13 -0
  18. package/dist/cjs/tlm-ai/knownMicroservices.cjs +13 -0
  19. package/dist/cjs/tlm-ai/tools.cjs +504 -0
  20. package/dist/{routes/authRoutes.cjs → cjs/tlm-auth/authController.cjs} +21 -28
  21. package/dist/{middleware → cjs/tlm-auth}/authMiddleware.cjs +1 -1
  22. package/dist/cjs/tlm-auth/authRoutes.cjs +14 -0
  23. package/dist/cjs/tlm-log/logController.cjs +55 -0
  24. package/dist/cjs/tlm-log/logRoutes.cjs +13 -0
  25. package/dist/{routes → cjs/tlm-metric}/metricsRoutes.cjs +1 -2
  26. package/dist/{controllers → cjs/tlm-plugin}/pluginController.cjs +31 -41
  27. package/dist/cjs/tlm-plugin/pluginRoutes.cjs +13 -0
  28. package/dist/{controllers/telemetryController.cjs → cjs/tlm-trace/traceController.cjs} +8 -19
  29. package/dist/cjs/tlm-trace/traceRoutes.cjs +17 -0
  30. package/dist/cjs/tlm-ui/uiController.cjs +27 -0
  31. package/dist/cjs/tlm-ui/uiRoutes.cjs +31 -0
  32. package/dist/cjs/tlm-util/utilController.cjs +63 -0
  33. package/dist/cjs/tlm-util/utilRoutes.cjs +12 -0
  34. package/dist/cjs/tlmRoutes.cjs +79 -0
  35. package/dist/cjs/types/index.cjs +8 -0
  36. package/dist/cjs/utils/circular.cjs +90 -0
  37. package/dist/cjs/utils/logger.cjs +28 -0
  38. package/{src → dist/esm}/config.js +20 -23
  39. package/{src → dist/esm}/exporters/InMemoryDBMetricsExporter.js +57 -111
  40. package/dist/esm/exporters/InMemoryDbExporter.js +87 -0
  41. package/dist/esm/exporters/InMemoryLogRecordExporter.js +95 -0
  42. package/{src → dist/esm}/exporters/consoleExporter.js +38 -47
  43. package/{src → dist/esm}/exporters/dynamicExporter.js +50 -62
  44. package/dist/esm/index.js +39 -0
  45. package/dist/esm/instrumentation/index.js +26 -0
  46. package/dist/esm/instrumentation/logs.js +34 -0
  47. package/dist/esm/instrumentation/metrics.js +18 -0
  48. package/dist/esm/instrumentation/traces.js +12 -0
  49. package/{src → dist/esm}/openTelemetry.js +50 -58
  50. package/dist/esm/systemMetrics.js +82 -0
  51. package/dist/esm/tlm-ai/agent.js +68 -0
  52. package/dist/esm/tlm-ai/aiController.js +45 -0
  53. package/dist/esm/tlm-ai/aiRoutes.js +7 -0
  54. package/dist/esm/tlm-ai/knownMicroservices.js +5 -0
  55. package/dist/esm/tlm-ai/tools.js +490 -0
  56. package/dist/esm/tlm-auth/authController.js +41 -0
  57. package/{src/middleware → dist/esm/tlm-auth}/authMiddleware.js +12 -14
  58. package/dist/esm/tlm-auth/authRoutes.js +7 -0
  59. package/dist/esm/tlm-log/logController.js +36 -0
  60. package/dist/esm/tlm-log/logRoutes.js +7 -0
  61. package/{src/controllers → dist/esm/tlm-metric}/metricsController.js +28 -30
  62. package/{src/routes → dist/esm/tlm-metric}/metricsRoutes.js +8 -15
  63. package/{src/controllers → dist/esm/tlm-plugin}/pluginController.js +103 -115
  64. package/dist/esm/tlm-plugin/pluginRoutes.js +7 -0
  65. package/dist/esm/tlm-trace/traceController.js +54 -0
  66. package/dist/esm/tlm-trace/traceRoutes.js +11 -0
  67. package/dist/esm/tlm-ui/uiController.js +20 -0
  68. package/dist/esm/tlm-ui/uiRoutes.js +23 -0
  69. package/dist/esm/tlm-util/utilController.js +57 -0
  70. package/dist/esm/tlm-util/utilRoutes.js +6 -0
  71. package/dist/esm/tlmRoutes.js +72 -0
  72. package/dist/esm/types/index.js +4 -0
  73. package/dist/esm/utils/circular.js +84 -0
  74. package/dist/esm/utils/logger.js +19 -0
  75. package/dist/types/config.d.ts +6 -0
  76. package/dist/types/exporters/InMemoryDBMetricsExporter.d.ts +15 -0
  77. package/dist/types/exporters/InMemoryDbExporter.d.ts +24 -0
  78. package/dist/types/exporters/InMemoryLogRecordExporter.d.ts +27 -0
  79. package/dist/types/exporters/consoleExporter.d.ts +13 -0
  80. package/dist/types/exporters/dynamicExporter.d.ts +25 -0
  81. package/dist/types/index.d.ts +8 -0
  82. package/dist/types/instrumentation/index.d.ts +1 -0
  83. package/dist/types/instrumentation/logs.d.ts +1 -0
  84. package/dist/types/instrumentation/metrics.d.ts +1 -0
  85. package/dist/types/instrumentation/traces.d.ts +1 -0
  86. package/dist/types/openTelemetry.d.ts +1 -0
  87. package/dist/types/systemMetrics.d.ts +26 -0
  88. package/dist/types/tlm-ai/agent.d.ts +1 -0
  89. package/dist/types/tlm-ai/aiController.d.ts +4 -0
  90. package/dist/types/tlm-ai/aiRoutes.d.ts +2 -0
  91. package/dist/types/tlm-ai/knownMicroservices.d.ts +6 -0
  92. package/dist/types/tlm-ai/tools.d.ts +45 -0
  93. package/dist/types/tlm-auth/authController.d.ts +4 -0
  94. package/dist/types/tlm-auth/authMiddleware.d.ts +2 -0
  95. package/dist/types/tlm-auth/authRoutes.d.ts +2 -0
  96. package/dist/types/tlm-log/logController.d.ts +4 -0
  97. package/dist/types/tlm-log/logRoutes.d.ts +2 -0
  98. package/dist/types/tlm-metric/metricsController.d.ts +4 -0
  99. package/dist/types/tlm-metric/metricsRoutes.d.ts +2 -0
  100. package/dist/types/tlm-plugin/pluginController.d.ts +3 -0
  101. package/dist/types/tlm-plugin/pluginRoutes.d.ts +2 -0
  102. package/dist/types/tlm-trace/traceController.d.ts +7 -0
  103. package/dist/types/tlm-trace/traceRoutes.d.ts +2 -0
  104. package/dist/types/tlm-ui/uiController.d.ts +8 -0
  105. package/dist/types/tlm-ui/uiRoutes.d.ts +2 -0
  106. package/dist/types/tlm-util/utilController.d.ts +3 -0
  107. package/dist/types/tlm-util/utilRoutes.d.ts +2 -0
  108. package/dist/types/tlmRoutes.d.ts +2 -0
  109. package/dist/types/types/index.d.ts +56 -0
  110. package/dist/types/utils/circular.d.ts +31 -0
  111. package/dist/types/utils/logger.d.ts +9 -0
  112. package/dist/ui/assets/index-BNhZBPi2.css +1 -0
  113. package/dist/ui/assets/index-DxGAMrAl.js +401 -0
  114. package/dist/ui/index.html +14 -0
  115. package/dist/ui/vite.svg +1 -0
  116. package/package.json +80 -77
  117. package/dist/controllers/uiController.cjs +0 -78
  118. package/dist/exporters/InMemoryDbExporter.cjs +0 -178
  119. package/dist/index.cjs +0 -110
  120. package/dist/routes/telemetryRoutes.cjs +0 -31
  121. package/dist/services/uiService.cjs +0 -1520
  122. package/src/controllers/telemetryController.js +0 -69
  123. package/src/controllers/uiController.js +0 -69
  124. package/src/dev/ui/login.html +0 -32
  125. package/src/exporters/InMemoryDbExporter.js +0 -181
  126. package/src/index.js +0 -114
  127. package/src/routes/authRoutes.js +0 -53
  128. package/src/routes/telemetryRoutes.js +0 -38
  129. package/src/services/uiService.js +0 -1520
  130. package/src/systemMetrics.js +0 -102
  131. /package/dist/{controllers → cjs/tlm-metric}/metricsController.cjs +0 -0
@@ -1,47 +1,38 @@
1
- export class ConsoleExporter {
2
-
3
- // PLUGIN SYSTEM -----------------------------------------------------------
4
- plugins = [];
5
-
6
- // OPEN TELEMETRY EXPORTER INTERFACE ---------------------------------------
7
- export(readableSpans, resultCallback) {
8
- console.log('ConsoleExporter | Received spans: ', readableSpans.length);
9
- setTimeout(() => resultCallback({ code: 0 }), 0);
10
- }
11
-
12
- shutdown() {
13
- return this.forceFlush();
14
- }
15
-
16
- forceFlush() {
17
- return Promise.resolve();
18
- }
19
-
20
- // OAS-TOOLS OAS-TELEMETRY EXPORTER INTERFACE ---------------------------------------
21
-
22
- start() {
23
- console.log("Exporter started");
24
- }
25
-
26
- stop() {
27
- console.log("Exporter stopped");
28
- }
29
-
30
- reset() {
31
- console.log("Exporter reset");
32
- }
33
-
34
- isRunning() {
35
- return true;
36
- }
37
-
38
- find(search, callback) {
39
- console.log("Getting finished spans");
40
- callback(null, []);
41
- return [];
42
- }
43
-
44
- async getFinishedSpans() {
45
- return [];
46
- }
47
- }
1
+ export class ConsoleExporter {
2
+ constructor() {
3
+ // PLUGIN SYSTEM -----------------------------------------------------------
4
+ this.plugins = [];
5
+ }
6
+ // OPEN TELEMETRY EXPORTER INTERFACE ---------------------------------------
7
+ export(readableSpans, resultCallback) {
8
+ console.log('ConsoleExporter | Received spans: ', readableSpans.length);
9
+ setTimeout(() => resultCallback({ code: 0 }), 0);
10
+ }
11
+ shutdown() {
12
+ return this.forceFlush();
13
+ }
14
+ forceFlush() {
15
+ return Promise.resolve();
16
+ }
17
+ // OAS-TOOLS OAS-TELEMETRY EXPORTER INTERFACE ---------------------------------------
18
+ start() {
19
+ console.log("Exporter started");
20
+ }
21
+ stop() {
22
+ console.log("Exporter stopped");
23
+ }
24
+ reset() {
25
+ console.log("Exporter reset");
26
+ }
27
+ isRunning() {
28
+ return true;
29
+ }
30
+ find(search, callback) {
31
+ console.log("Getting finished spans");
32
+ callback(null, []);
33
+ return [];
34
+ }
35
+ getFinishedSpans() {
36
+ return [];
37
+ }
38
+ }
@@ -1,62 +1,50 @@
1
- import { ConsoleExporter } from "./consoleExporter.js";
2
-
3
-
4
- /**
5
- * DynamicExporter is a class that can be used to dynamically change the exporter used by OpenTelemetry.
6
- * This is useful when you want to change the exporter at runtime.
7
- * Links start, stop and export methods to the Real exporter.
8
- */
9
- export class DynamicExporter {
10
-
11
- exporter;
12
- /**
13
- * @returns {Array<PluginResource>} Returns the list of plugins registered in the exporter
14
- */
15
- getPlugins() {
16
- return this.exporter.plugins;
17
- }
18
-
19
- /**
20
- * Registers a plugin in the exporter
21
- * @param {PluginResource} pluginResource The plugin to be registered
22
- * @returns {void}
23
- */
24
- pushPlugin(pluginResource) {
25
- if (!this.exporter.plugins) {
26
- this.exporter.plugins = [];
27
- }
28
- this.exporter.plugins.push(pluginResource);
29
- }
30
- activatePlugin(pluginId) {
31
- let plugins = this.exporter.plugins;
32
- if (plugins) {
33
- // plugin.active = true;
34
- plugins.forEach(plugin => {
35
- if (plugin.id === pluginId) {
36
- plugin.active = true;
37
- }
38
- });
39
- }
40
- }
41
-
42
-
43
- constructor() {
44
- let defaultExporter = new ConsoleExporter();
45
- this.exporter = defaultExporter;
46
- this.export = (readableSpans, resultCallback) => defaultExporter.export(readableSpans, resultCallback);
47
- this.shutdown = () => defaultExporter.shutdown();
48
- this.forceFlush = () => defaultExporter.forceFlush();
49
- }
50
-
51
- changeExporter(newExporter) {
52
- this.exporter = newExporter;
53
- // OpenTelemetry methods
54
- this.export = (readableSpans, resultCallback) => newExporter.export(readableSpans, resultCallback);
55
- this.shutdown = () => newExporter.shutdown();
56
- this.forceFlush = () => newExporter.forceFlush();
57
- // Other methods should be called directly from the exporter: globalOasTlmConfig.dynamicExporter.exporter.method()
58
- }
59
-
60
- }
61
-
62
- export default DynamicExporter;
1
+ import { ConsoleExporter } from "./consoleExporter.js";
2
+ /**
3
+ * DynamicExporter is a class that can be used to dynamically change the exporter used by OpenTelemetry.
4
+ * This is useful when you want to change the exporter at runtime.
5
+ * Links start, stop and export methods to the Real exporter.
6
+ */
7
+ export class DynamicExporter {
8
+ /**
9
+ * Returns the list of plugins registered in the exporter
10
+ */
11
+ getPlugins() {
12
+ return this.exporter.plugins;
13
+ }
14
+ /**
15
+ * Registers a plugin in the exporter
16
+ */
17
+ pushPlugin(pluginResource) {
18
+ if (!this.exporter.plugins) {
19
+ this.exporter.plugins = [];
20
+ }
21
+ this.exporter.plugins.push(pluginResource);
22
+ }
23
+ activatePlugin(pluginId) {
24
+ const plugins = this.exporter.plugins;
25
+ if (plugins) {
26
+ // plugin.active = true;
27
+ plugins.forEach((plugin) => {
28
+ if (plugin.id === pluginId) {
29
+ plugin.active = true;
30
+ }
31
+ });
32
+ }
33
+ }
34
+ constructor() {
35
+ const defaultExporter = new ConsoleExporter();
36
+ this.exporter = defaultExporter;
37
+ this.export = (readableSpans, resultCallback) => defaultExporter.export(readableSpans, resultCallback);
38
+ this.shutdown = () => defaultExporter.shutdown();
39
+ this.forceFlush = () => defaultExporter.forceFlush();
40
+ }
41
+ changeExporter(newExporter) {
42
+ this.exporter = newExporter;
43
+ // OpenTelemetry methods
44
+ this.export = (readableSpan, resultCallback) => newExporter.export(readableSpan, resultCallback);
45
+ this.shutdown = () => newExporter.shutdown();
46
+ this.forceFlush = () => newExporter.forceFlush();
47
+ // Other methods should be called directly from the exporter: globalOasTlmConfig.dynamicSpanExporter.exporter.method()
48
+ }
49
+ }
50
+ export default DynamicExporter;
@@ -0,0 +1,39 @@
1
+ import './instrumentation/index.js';
2
+ import { globalOasTlmConfig } from './config.js';
3
+ import { Router } from 'express';
4
+ import { InMemoryExporter } from './exporters/InMemoryDbExporter.js';
5
+ import logger from './utils/logger.js';
6
+ import { configureRoutes } from './tlmRoutes.js';
7
+ /**
8
+ * Returns the Oas Telemetry middleware. The parameters are the same as `globalOasTlmConfig`.
9
+ * All parameters are optional. However, either `spec` or `specFileName` must be provided to enable endpoint filtering.
10
+ */
11
+ export default function oasTelemetry(oasTlmInputConfig) {
12
+ const router = Router();
13
+ if (process.env.OASTLM_MODULE_DISABLED === 'true') {
14
+ return router;
15
+ }
16
+ if (oasTlmInputConfig) {
17
+ logger.info("User provided config");
18
+ // Override global config with user provided config
19
+ for (const key in globalOasTlmConfig) {
20
+ globalOasTlmConfig[key] = oasTlmInputConfig[key] ?? globalOasTlmConfig[key];
21
+ }
22
+ }
23
+ logger.info("BaseURL: ", globalOasTlmConfig.baseURL);
24
+ globalOasTlmConfig.dynamicSpanExporter.changeExporter(globalOasTlmConfig.exporter ?? new InMemoryExporter());
25
+ if (globalOasTlmConfig.spec)
26
+ logger.info(`Spec content provided`);
27
+ else {
28
+ if (globalOasTlmConfig.specFileName != "")
29
+ logger.info(`Spec file used for telemetry: ${globalOasTlmConfig.specFileName}`);
30
+ else {
31
+ console.error("No spec available !");
32
+ }
33
+ }
34
+ if (globalOasTlmConfig.autoActivate) {
35
+ globalOasTlmConfig.dynamicSpanExporter.exporter?.start();
36
+ }
37
+ configureRoutes(router);
38
+ return router;
39
+ }
@@ -0,0 +1,26 @@
1
+ // import { NodeSDK } from '@opentelemetry/sdk-node';
2
+ import { resourceFromAttributes } from '@opentelemetry/resources';
3
+ import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
4
+ import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
5
+ import logger from '../utils/logger.js';
6
+ import { initializeLogs } from './logs.js';
7
+ import { initializeTraces } from './traces.js';
8
+ import { registerInstrumentations } from '@opentelemetry/instrumentation';
9
+ import { initializeMetrics } from './metrics.js';
10
+ const oasTelemetryResource = resourceFromAttributes({
11
+ [ATTR_SERVICE_NAME]: 'oas-telemetry-service'
12
+ });
13
+ if (process.env.OASTLM_MODULE_DISABLED !== 'true') {
14
+ initializeTraces(oasTelemetryResource);
15
+ initializeMetrics(oasTelemetryResource);
16
+ initializeLogs(oasTelemetryResource);
17
+ registerInstrumentations({
18
+ instrumentations: [
19
+ new HttpInstrumentation(),
20
+ // new ExpressInstrumentation(),
21
+ ],
22
+ });
23
+ }
24
+ else {
25
+ logger.info('🚫 OASTLM module is disabled, SDKs not initialized.');
26
+ }
@@ -0,0 +1,34 @@
1
+ import { LoggerProvider, SimpleLogRecordProcessor } from '@opentelemetry/sdk-logs';
2
+ import { SeverityNumber } from '@opentelemetry/api-logs';
3
+ import { globalOasTlmConfig } from '../config.js';
4
+ import logger from '../utils/logger.js';
5
+ export function initializeLogs(resource) {
6
+ // Create and configure LoggerProvider
7
+ const logExporter = globalOasTlmConfig.logExporter;
8
+ const logRecordProcessor = new SimpleLogRecordProcessor(logExporter);
9
+ const loggerProvider = new LoggerProvider({ resource: resource, processors: [logRecordProcessor] });
10
+ // Get a logger instance
11
+ const loggerInstance = loggerProvider.getLogger('oas-telemetry'); // Use loggerProvider to get the logger
12
+ // Override console methods to emit logs via OpenTelemetry
13
+ const originalConsoleMethods = {
14
+ log: console.log,
15
+ warn: console.warn,
16
+ error: console.error,
17
+ info: console.info,
18
+ debug: console.debug,
19
+ };
20
+ Object.keys(originalConsoleMethods).forEach((method) => {
21
+ // @ts-expect-error yes
22
+ console[method] = (...args) => {
23
+ loggerInstance.emit({
24
+ severityNumber: SeverityNumber[method.toUpperCase()] || SeverityNumber.INFO,
25
+ severityText: method.toUpperCase(),
26
+ body: args.join(' '),
27
+ attributes: { 'source.source': `console.${method}` },
28
+ });
29
+ // @ts-expect-error yes
30
+ originalConsoleMethods[method](...args);
31
+ };
32
+ });
33
+ logger.info('✅ OpenTelemetry Logs initialized.');
34
+ }
@@ -0,0 +1,18 @@
1
+ import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
2
+ import logger from '../utils/logger.js';
3
+ import { globalOasTlmConfig } from '../config.js';
4
+ import { HostMetrics } from '@opentelemetry/host-metrics';
5
+ export function initializeMetrics(resource) {
6
+ const metricReader = new PeriodicExportingMetricReader({
7
+ // exporter: new ConsoleMetricExporter(),
8
+ exporter: globalOasTlmConfig.metricsExporter,
9
+ exportIntervalMillis: globalOasTlmConfig.metricsExporterInterval
10
+ });
11
+ const meterProvider = new MeterProvider({
12
+ resource: resource,
13
+ readers: [metricReader],
14
+ });
15
+ const hostMetrics = new HostMetrics({ meterProvider });
16
+ hostMetrics.start();
17
+ logger.info('✅ OpenTelemetry Metrics initialized.');
18
+ }
@@ -0,0 +1,12 @@
1
+ import logger from '../utils/logger.js';
2
+ import { NodeTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-node';
3
+ import { globalOasTlmConfig } from '../config.js';
4
+ export function initializeTraces(resource) {
5
+ const tracerProvider = new NodeTracerProvider({
6
+ resource: resource,
7
+ spanProcessors: [new BatchSpanProcessor(globalOasTlmConfig.dynamicSpanExporter)]
8
+ });
9
+ // tracerProvider.addSpanProcessor();
10
+ tracerProvider.register();
11
+ logger.info('✅ OpenTelemetry Traces initialized.');
12
+ }
@@ -1,58 +1,50 @@
1
- import { NodeSDK } from '@opentelemetry/sdk-node';
2
- // import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
3
- import { Resource } from '@opentelemetry/resources';
4
- import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
5
- import { globalOasTlmConfig } from './config.js';
6
- import { getCpuUsageData, getProcessCpuUsageData, getMemoryData, getProcessMemoryData } from './systemMetrics.js'; // Import system metrics functions
7
-
8
- // DynamicExporter allows changing to any exporter at runtime;
9
- const traceExporter = globalOasTlmConfig.dynamicExporter;
10
- // Alternative 1: Using NodeSDK
11
- const sdk = new NodeSDK({
12
- resource: new Resource({
13
- service: 'oas-telemetry-service'
14
- }),
15
- traceExporter,
16
- instrumentations: [new HttpInstrumentation()]
17
- });
18
-
19
-
20
- // Collect and export system metrics
21
- setInterval(() => {
22
- const cpuUsageData = getCpuUsageData();
23
- const processCpuUsageData = getProcessCpuUsageData();
24
- const memoryData = getMemoryData();
25
- const processMemoryData = getProcessMemoryData();
26
-
27
- const metrics = {
28
- timestamp: Date.now(),
29
- cpuUsageData,
30
- processCpuUsageData,
31
- memoryData,
32
- processMemoryData,
33
- };
34
-
35
- // Export the collected metrics using the InMemoryDBMetricsExporter
36
- const inMemoryDbMetricExporter = globalOasTlmConfig.metricsExporter;
37
- inMemoryDbMetricExporter.export(metrics, (result) => {});
38
- }, globalOasTlmConfig.systemMetricsInterval);
39
-
40
- console.log('✅ OpenTelemetry System Metrics initialized.');
41
-
42
- if (process.env.OASTLM_MODULE_DISABLED !== 'true') {
43
- sdk.start()
44
- }
45
-
46
- // Alternative 2:
47
- // const provider = new NodeTracerProvider();
48
- // provider.addSpanProcessor(new SimpleSpanProcessor(traceExporter));
49
-
50
- // if (process.env.OASTLM_MODULE_DISABLED !== 'true') {
51
- // provider.register();
52
- // registerInstrumentations({
53
- // instrumentations: [
54
- // new HttpInstrumentation(),
55
- // new ExpressInstrumentation(),
56
- // ],
57
- // });
58
- // }
1
+ import { NodeSDK } from '@opentelemetry/sdk-node';
2
+ // import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
3
+ import { Resource } from '@opentelemetry/resources';
4
+ import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
5
+ import { globalOasTlmConfig } from './config.js';
6
+ import { getCpuUsageData, getProcessCpuUsageData, getMemoryData, getProcessMemoryData } from './systemMetrics.js'; // Import system metrics functions
7
+ import logger from './utils/logger.js';
8
+ // DynamicExporter allows changing to any exporter at runtime;
9
+ const dynamicSpanExporter = globalOasTlmConfig.dynamicSpanExporter;
10
+ // Alternative 1: Using NodeSDK
11
+ const sdk = new NodeSDK({
12
+ resource: new Resource({
13
+ service: 'oas-telemetry-service'
14
+ }),
15
+ traceExporter: dynamicSpanExporter,
16
+ instrumentations: [new HttpInstrumentation()]
17
+ });
18
+ // Collect and export system metrics
19
+ setInterval(() => {
20
+ const cpuUsageData = getCpuUsageData();
21
+ const processCpuUsageData = getProcessCpuUsageData();
22
+ const memoryData = getMemoryData();
23
+ const processMemoryData = getProcessMemoryData();
24
+ const metrics = {
25
+ timestamp: Date.now(),
26
+ cpuUsageData,
27
+ processCpuUsageData,
28
+ memoryData,
29
+ processMemoryData,
30
+ };
31
+ // Export the collected metrics using the InMemoryDBMetricsExporter
32
+ const inMemoryDbMetricExporter = globalOasTlmConfig.metricsExporter;
33
+ inMemoryDbMetricExporter.export(metrics, () => { });
34
+ }, globalOasTlmConfig.systemMetricsInterval);
35
+ logger.info('✅ OpenTelemetry System Metrics initialized.');
36
+ if (process.env.OASTLM_MODULE_DISABLED !== 'true') {
37
+ sdk.start();
38
+ }
39
+ // Alternative 2:
40
+ // const provider = new NodeTracerProvider();
41
+ // provider.addSpanProcessor(new SimpleSpanProcessor(traceExporter));
42
+ // if (process.env.OASTLM_MODULE_DISABLED !== 'true') {
43
+ // provider.register();
44
+ // registerInstrumentations({
45
+ // instrumentations: [
46
+ // new HttpInstrumentation(),
47
+ // new ExpressInstrumentation(),
48
+ // ],
49
+ // });
50
+ // }
@@ -0,0 +1,82 @@
1
+ import { cpus, totalmem, freemem } from 'os';
2
+ const MILLISECOND = 1 / 1e3;
3
+ const MICROSECOND = 1 / 1e6;
4
+ let prevOsData = {
5
+ time: Date.now(),
6
+ cpus: cpus(),
7
+ };
8
+ export function getCpuUsageData() {
9
+ const currentTime = Date.now();
10
+ const timeElapsed = currentTime - prevOsData.time;
11
+ const currentOsData = { time: currentTime, cpus: cpus() };
12
+ const usageData = currentOsData.cpus.map((cpu, cpuNumber) => {
13
+ const prevTimes = prevOsData.cpus[cpuNumber].times;
14
+ const currTimes = cpu.times;
15
+ const idle = currTimes.idle * MILLISECOND;
16
+ const user = currTimes.user * MILLISECOND;
17
+ const system = currTimes.sys * MILLISECOND;
18
+ const interrupt = currTimes.irq * MILLISECOND;
19
+ const nice = currTimes.nice * MILLISECOND;
20
+ const idleP = (currTimes.idle - prevTimes.idle) / timeElapsed;
21
+ const userP = (currTimes.user - prevTimes.user) / timeElapsed;
22
+ const systemP = (currTimes.sys - prevTimes.sys) / timeElapsed;
23
+ const interruptP = (currTimes.irq - prevTimes.irq) / timeElapsed;
24
+ const niceP = (currTimes.nice - prevTimes.nice) / timeElapsed;
25
+ return {
26
+ cpuNumber: String(cpuNumber),
27
+ idle,
28
+ user,
29
+ system,
30
+ interrupt,
31
+ nice,
32
+ userP,
33
+ systemP,
34
+ idleP,
35
+ interruptP,
36
+ niceP,
37
+ };
38
+ });
39
+ prevOsData = currentOsData;
40
+ return usageData;
41
+ }
42
+ let prevProcData = {
43
+ time: Date.now(),
44
+ usage: process.cpuUsage(),
45
+ };
46
+ export function getProcessCpuUsageData() {
47
+ const currentTime = Date.now();
48
+ const currentUsage = process.cpuUsage();
49
+ const prevUsage = prevProcData.usage;
50
+ const timeElapsed = (currentTime - prevProcData.time) * 1000;
51
+ const cpusTimeElapsed = timeElapsed * prevOsData.cpus.length;
52
+ const user = currentUsage.user * MICROSECOND;
53
+ const system = currentUsage.system * MICROSECOND;
54
+ const userP = (currentUsage.user - prevUsage.user) / cpusTimeElapsed;
55
+ const systemP = (currentUsage.system - prevUsage.system) / cpusTimeElapsed;
56
+ prevProcData = { time: currentTime, usage: currentUsage };
57
+ return {
58
+ user,
59
+ system,
60
+ userP,
61
+ systemP,
62
+ };
63
+ }
64
+ export function getMemoryData() {
65
+ const total = totalmem();
66
+ const free = freemem();
67
+ const used = total - free;
68
+ const freeP = free / total;
69
+ const usedP = used / total;
70
+ return {
71
+ used,
72
+ free,
73
+ usedP,
74
+ freeP,
75
+ };
76
+ }
77
+ export function getProcessMemoryData() {
78
+ if (process.memoryUsage().rss) {
79
+ return process.memoryUsage().rss;
80
+ }
81
+ return 0;
82
+ }
@@ -0,0 +1,68 @@
1
+ import OpenAI from 'openai';
2
+ import dotenv from 'dotenv';
3
+ import { tools, availableTools } from './tools.js';
4
+ import logger from '../utils/logger.js';
5
+ dotenv.config();
6
+ let openai;
7
+ try {
8
+ openai = new OpenAI({
9
+ apiKey: process.env.OASTLM_AI_OPENAI_API_KEY,
10
+ dangerouslyAllowBrowser: true,
11
+ });
12
+ }
13
+ catch {
14
+ openai = null;
15
+ }
16
+ const messages = [
17
+ {
18
+ role: "assistant",
19
+ content: "You are a helpful telemetry assistant. Only use the functions you have been provided with. If the question is not related to the functions, respond with 'I cannot help with that.'. If you need to call to other agents, do so using the tools provided."
20
+ },
21
+ ];
22
+ async function agent(userInput) {
23
+ messages.push({
24
+ role: "user",
25
+ content: userInput,
26
+ });
27
+ for (let i = 0; i < 5; i++) {
28
+ const response = await (openai?.chat?.completions?.create?.({
29
+ model: process.env.OASTLM_AI_OPENAI_MODEL_NAME || "gpt-4o-mini",
30
+ messages: messages,
31
+ tools: tools,
32
+ }));
33
+ const { finish_reason, message } = response.choices[0];
34
+ if (finish_reason === "tool_calls" && message.tool_calls) {
35
+ logger.debug("Tool calls detected:", message.tool_calls);
36
+ const results = [];
37
+ for (const toolCall of message.tool_calls) {
38
+ const functionName = toolCall.function.name;
39
+ const functionToCall = availableTools[functionName];
40
+ const functionArgs = JSON.parse(toolCall.function.arguments);
41
+ const functionArgsArr = Object.values(functionArgs);
42
+ // @ts-expect-error yes
43
+ // eslint-disable-next-line prefer-spread
44
+ const functionResponse = await functionToCall.apply(null, functionArgsArr);
45
+ results.push({
46
+ name: functionName,
47
+ response: functionResponse,
48
+ });
49
+ }
50
+ const resultMessage = results.map(({ name, response }) => `Result from "${name}":\n${JSON.stringify(response, null, 2)}`).join("\n\n");
51
+ messages.push({
52
+ role: "function",
53
+ name: "multiple_tool_calls",
54
+ content: resultMessage,
55
+ });
56
+ }
57
+ else if (finish_reason === "stop") {
58
+ messages.push(message);
59
+ return message;
60
+ }
61
+ }
62
+ return { content: "Se alcanzó el número máximo de iteraciones sin una respuesta adecuada. Intenta con una consulta más específica." };
63
+ }
64
+ export async function getAgentResponse(question) {
65
+ const response = await agent(question);
66
+ logger.debug("Response from agent:", response);
67
+ return response.content;
68
+ }
@@ -0,0 +1,45 @@
1
+ import { getAgentResponse } from './agent.js';
2
+ import { setKnownMicroservices, getKnownMicroservices } from './knownMicroservices.js';
3
+ import logger from '../utils/logger.js';
4
+ export const answerQuestion = async (req, res) => {
5
+ try {
6
+ const { question } = req.body;
7
+ if (!question)
8
+ res.status(400).json({ error: 'Missing question' });
9
+ const answer = await getAgentResponse(question);
10
+ res.json({ answer });
11
+ }
12
+ catch (error) {
13
+ logger.error(error);
14
+ res.status(500).json({ error: 'Internal error' });
15
+ }
16
+ };
17
+ export const setKnownMicroservicesHandler = (req, res) => {
18
+ try {
19
+ const { microservices } = req.body;
20
+ if (!Array.isArray(microservices)) {
21
+ res.status(400).json({ error: 'Invalid microservices format. Expected an array.' });
22
+ return;
23
+ }
24
+ setKnownMicroservices(microservices);
25
+ res.json({
26
+ message: "Microservices configuration updated successfully.",
27
+ knownMicroservices: getKnownMicroservices(),
28
+ note: "In the future, OAS-Telemetry will support autodiscovery, making this configuration unnecessary.",
29
+ });
30
+ }
31
+ catch (error) {
32
+ logger.error(error);
33
+ res.status(500).json({ error: 'Internal error' });
34
+ }
35
+ };
36
+ export const getKnownMicroservicesHandler = (req, res) => {
37
+ try {
38
+ const microservices = getKnownMicroservices();
39
+ res.json({ knownMicroservices: microservices });
40
+ }
41
+ catch (error) {
42
+ logger.error(error);
43
+ res.status(500).json({ error: 'Internal error' });
44
+ }
45
+ };
@@ -0,0 +1,7 @@
1
+ import { Router } from 'express';
2
+ import { answerQuestion, setKnownMicroservicesHandler, getKnownMicroservicesHandler } from './aiController.js';
3
+ export const aiRoutes = Router();
4
+ aiRoutes.post('/chat', answerQuestion);
5
+ aiRoutes.post('/microservices', setKnownMicroservicesHandler); // New route for configuring microservices
6
+ aiRoutes.get('/microservices', getKnownMicroservicesHandler); // Route to retrieve the list of known microservices
7
+ export default aiRoutes;
@@ -0,0 +1,5 @@
1
+ let knownMicroservices = null;
2
+ export const getKnownMicroservices = () => knownMicroservices || [];
3
+ export const setKnownMicroservices = (microservices) => {
4
+ knownMicroservices = microservices;
5
+ };