@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.
- package/README.md +442 -442
- package/dist/{config.cjs → cjs/config.cjs} +6 -7
- package/dist/{exporters → cjs/exporters}/InMemoryDBMetricsExporter.cjs +5 -40
- package/dist/cjs/exporters/InMemoryDbExporter.cjs +87 -0
- package/dist/cjs/exporters/InMemoryLogRecordExporter.cjs +110 -0
- package/dist/{exporters → cjs/exporters}/consoleExporter.cjs +2 -7
- package/dist/{exporters → cjs/exporters}/dynamicExporter.cjs +12 -19
- package/dist/cjs/index.cjs +43 -0
- package/dist/cjs/instrumentation/index.cjs +28 -0
- package/dist/cjs/instrumentation/logs.cjs +46 -0
- package/dist/cjs/instrumentation/metrics.cjs +27 -0
- package/dist/cjs/instrumentation/traces.cjs +19 -0
- package/dist/{openTelemetry.cjs → cjs/openTelemetry.cjs} +6 -8
- package/dist/{systemMetrics.cjs → cjs/systemMetrics.cjs} +7 -7
- package/dist/cjs/tlm-ai/agent.cjs +79 -0
- package/dist/cjs/tlm-ai/aiController.cjs +69 -0
- package/dist/cjs/tlm-ai/aiRoutes.cjs +13 -0
- package/dist/cjs/tlm-ai/knownMicroservices.cjs +13 -0
- package/dist/cjs/tlm-ai/tools.cjs +504 -0
- package/dist/{routes/authRoutes.cjs → cjs/tlm-auth/authController.cjs} +21 -28
- package/dist/{middleware → cjs/tlm-auth}/authMiddleware.cjs +1 -1
- package/dist/cjs/tlm-auth/authRoutes.cjs +14 -0
- package/dist/cjs/tlm-log/logController.cjs +55 -0
- package/dist/cjs/tlm-log/logRoutes.cjs +13 -0
- package/dist/{routes → cjs/tlm-metric}/metricsRoutes.cjs +1 -2
- package/dist/{controllers → cjs/tlm-plugin}/pluginController.cjs +31 -41
- package/dist/cjs/tlm-plugin/pluginRoutes.cjs +13 -0
- package/dist/{controllers/telemetryController.cjs → cjs/tlm-trace/traceController.cjs} +8 -19
- package/dist/cjs/tlm-trace/traceRoutes.cjs +17 -0
- package/dist/cjs/tlm-ui/uiController.cjs +27 -0
- package/dist/cjs/tlm-ui/uiRoutes.cjs +31 -0
- package/dist/cjs/tlm-util/utilController.cjs +63 -0
- package/dist/cjs/tlm-util/utilRoutes.cjs +12 -0
- package/dist/cjs/tlmRoutes.cjs +79 -0
- package/dist/cjs/types/index.cjs +8 -0
- package/dist/cjs/utils/circular.cjs +90 -0
- package/dist/cjs/utils/logger.cjs +28 -0
- package/{src → dist/esm}/config.js +20 -23
- package/{src → dist/esm}/exporters/InMemoryDBMetricsExporter.js +57 -111
- package/dist/esm/exporters/InMemoryDbExporter.js +87 -0
- package/dist/esm/exporters/InMemoryLogRecordExporter.js +95 -0
- package/{src → dist/esm}/exporters/consoleExporter.js +38 -47
- package/{src → dist/esm}/exporters/dynamicExporter.js +50 -62
- package/dist/esm/index.js +39 -0
- package/dist/esm/instrumentation/index.js +26 -0
- package/dist/esm/instrumentation/logs.js +34 -0
- package/dist/esm/instrumentation/metrics.js +18 -0
- package/dist/esm/instrumentation/traces.js +12 -0
- package/{src → dist/esm}/openTelemetry.js +50 -58
- package/dist/esm/systemMetrics.js +82 -0
- package/dist/esm/tlm-ai/agent.js +68 -0
- package/dist/esm/tlm-ai/aiController.js +45 -0
- package/dist/esm/tlm-ai/aiRoutes.js +7 -0
- package/dist/esm/tlm-ai/knownMicroservices.js +5 -0
- package/dist/esm/tlm-ai/tools.js +490 -0
- package/dist/esm/tlm-auth/authController.js +41 -0
- package/{src/middleware → dist/esm/tlm-auth}/authMiddleware.js +12 -14
- package/dist/esm/tlm-auth/authRoutes.js +7 -0
- package/dist/esm/tlm-log/logController.js +36 -0
- package/dist/esm/tlm-log/logRoutes.js +7 -0
- package/{src/controllers → dist/esm/tlm-metric}/metricsController.js +28 -30
- package/{src/routes → dist/esm/tlm-metric}/metricsRoutes.js +8 -15
- package/{src/controllers → dist/esm/tlm-plugin}/pluginController.js +103 -115
- package/dist/esm/tlm-plugin/pluginRoutes.js +7 -0
- package/dist/esm/tlm-trace/traceController.js +54 -0
- package/dist/esm/tlm-trace/traceRoutes.js +11 -0
- package/dist/esm/tlm-ui/uiController.js +20 -0
- package/dist/esm/tlm-ui/uiRoutes.js +23 -0
- package/dist/esm/tlm-util/utilController.js +57 -0
- package/dist/esm/tlm-util/utilRoutes.js +6 -0
- package/dist/esm/tlmRoutes.js +72 -0
- package/dist/esm/types/index.js +4 -0
- package/dist/esm/utils/circular.js +84 -0
- package/dist/esm/utils/logger.js +19 -0
- package/dist/types/config.d.ts +6 -0
- package/dist/types/exporters/InMemoryDBMetricsExporter.d.ts +15 -0
- package/dist/types/exporters/InMemoryDbExporter.d.ts +24 -0
- package/dist/types/exporters/InMemoryLogRecordExporter.d.ts +27 -0
- package/dist/types/exporters/consoleExporter.d.ts +13 -0
- package/dist/types/exporters/dynamicExporter.d.ts +25 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/instrumentation/index.d.ts +1 -0
- package/dist/types/instrumentation/logs.d.ts +1 -0
- package/dist/types/instrumentation/metrics.d.ts +1 -0
- package/dist/types/instrumentation/traces.d.ts +1 -0
- package/dist/types/openTelemetry.d.ts +1 -0
- package/dist/types/systemMetrics.d.ts +26 -0
- package/dist/types/tlm-ai/agent.d.ts +1 -0
- package/dist/types/tlm-ai/aiController.d.ts +4 -0
- package/dist/types/tlm-ai/aiRoutes.d.ts +2 -0
- package/dist/types/tlm-ai/knownMicroservices.d.ts +6 -0
- package/dist/types/tlm-ai/tools.d.ts +45 -0
- package/dist/types/tlm-auth/authController.d.ts +4 -0
- package/dist/types/tlm-auth/authMiddleware.d.ts +2 -0
- package/dist/types/tlm-auth/authRoutes.d.ts +2 -0
- package/dist/types/tlm-log/logController.d.ts +4 -0
- package/dist/types/tlm-log/logRoutes.d.ts +2 -0
- package/dist/types/tlm-metric/metricsController.d.ts +4 -0
- package/dist/types/tlm-metric/metricsRoutes.d.ts +2 -0
- package/dist/types/tlm-plugin/pluginController.d.ts +3 -0
- package/dist/types/tlm-plugin/pluginRoutes.d.ts +2 -0
- package/dist/types/tlm-trace/traceController.d.ts +7 -0
- package/dist/types/tlm-trace/traceRoutes.d.ts +2 -0
- package/dist/types/tlm-ui/uiController.d.ts +8 -0
- package/dist/types/tlm-ui/uiRoutes.d.ts +2 -0
- package/dist/types/tlm-util/utilController.d.ts +3 -0
- package/dist/types/tlm-util/utilRoutes.d.ts +2 -0
- package/dist/types/tlmRoutes.d.ts +2 -0
- package/dist/types/types/index.d.ts +56 -0
- package/dist/types/utils/circular.d.ts +31 -0
- package/dist/types/utils/logger.d.ts +9 -0
- package/dist/ui/assets/index-BNhZBPi2.css +1 -0
- package/dist/ui/assets/index-DxGAMrAl.js +401 -0
- package/dist/ui/index.html +14 -0
- package/dist/ui/vite.svg +1 -0
- package/package.json +80 -77
- package/dist/controllers/uiController.cjs +0 -78
- package/dist/exporters/InMemoryDbExporter.cjs +0 -178
- package/dist/index.cjs +0 -110
- package/dist/routes/telemetryRoutes.cjs +0 -31
- package/dist/services/uiService.cjs +0 -1520
- package/src/controllers/telemetryController.js +0 -69
- package/src/controllers/uiController.js +0 -69
- package/src/dev/ui/login.html +0 -32
- package/src/exporters/InMemoryDbExporter.js +0 -181
- package/src/index.js +0 -114
- package/src/routes/authRoutes.js +0 -53
- package/src/routes/telemetryRoutes.js +0 -38
- package/src/services/uiService.js +0 -1520
- package/src/systemMetrics.js +0 -102
- /package/dist/{controllers → cjs/tlm-metric}/metricsController.cjs +0 -0
|
@@ -1,47 +1,38 @@
|
|
|
1
|
-
export class ConsoleExporter {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
console.log("
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
this.
|
|
46
|
-
this.
|
|
47
|
-
|
|
48
|
-
|
|
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
|
|
10
|
-
// Alternative 1: Using NodeSDK
|
|
11
|
-
const sdk = new NodeSDK({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (process.env.OASTLM_MODULE_DISABLED !== 'true') {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
//
|
|
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;
|