@oas-tools/oas-telemetry 0.7.1 → 0.8.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/.env.example +21 -2
- package/README.md +1 -2
- package/dist/cjs/config/bootConfig.cjs +19 -14
- package/dist/cjs/config/config.cjs +112 -125
- package/dist/cjs/config/config.types.cjs +1 -4
- package/dist/cjs/docs/openapi.yaml +158 -4
- package/dist/cjs/index.cjs +27 -30
- package/dist/cjs/routesManager.cjs +62 -70
- package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbLogExporter.cjs +202 -190
- package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.cjs +204 -99
- package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.cjs +152 -116
- package/dist/cjs/telemetry/custom-implementations/instrumentations/logsInstrumentation.cjs +92 -0
- package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/Chunk.cjs +159 -0
- package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/Series.cjs +168 -0
- package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/SeriesRegistry.cjs +389 -0
- package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/types.cjs +2 -0
- package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/utils.cjs +77 -0
- package/dist/cjs/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.cjs +65 -63
- package/dist/cjs/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.cjs +63 -62
- package/dist/cjs/telemetry/custom-implementations/utils/circular.cjs +47 -47
- package/dist/cjs/telemetry/custom-implementations/utils/storagePath.cjs +39 -0
- package/dist/cjs/telemetry/custom-implementations/wrappers.cjs +141 -138
- package/dist/cjs/telemetry/initializeTelemetry.cjs +35 -91
- package/dist/cjs/telemetry/telemetryConfigurator.cjs +70 -72
- package/dist/cjs/telemetry/telemetryRegistry.cjs +45 -31
- package/dist/cjs/tlm-ai/agent.cjs +49 -64
- package/dist/cjs/tlm-ai/aiController.cjs +54 -76
- package/dist/cjs/tlm-ai/aiRoutes.cjs +17 -20
- package/dist/cjs/tlm-ai/aiService.cjs +91 -95
- package/dist/cjs/tlm-ai/tools.cjs +177 -174
- package/dist/cjs/tlm-auth/authController.cjs +80 -123
- package/dist/cjs/tlm-auth/authMiddleware.cjs +25 -30
- package/dist/cjs/tlm-auth/authRoutes.cjs +11 -14
- package/dist/cjs/tlm-log/logController.cjs +171 -116
- package/dist/cjs/tlm-log/logRoutes.cjs +20 -20
- package/dist/cjs/tlm-metric/metricsController.cjs +211 -121
- package/dist/cjs/tlm-metric/metricsRoutes.cjs +23 -20
- package/dist/cjs/tlm-plugin/pluginController.cjs +128 -140
- package/dist/cjs/tlm-plugin/pluginProcess.cjs +89 -94
- package/dist/cjs/tlm-plugin/pluginRoutes.cjs +11 -14
- package/dist/cjs/tlm-plugin/pluginService.cjs +73 -74
- package/dist/cjs/tlm-trace/traceController.cjs +169 -117
- package/dist/cjs/tlm-trace/traceRoutes.cjs +20 -20
- package/dist/cjs/tlm-ui/uiRoutes.cjs +63 -32
- package/dist/cjs/tlm-util/utilController.cjs +68 -70
- package/dist/cjs/tlm-util/utilRoutes.cjs +51 -63
- package/dist/cjs/types/index.cjs +2 -5
- package/dist/cjs/utils/logger.cjs +38 -43
- package/dist/cjs/utils/regexUtils.cjs +22 -22
- package/dist/esm/config/bootConfig.js +6 -0
- package/dist/esm/config/config.js +1 -2
- package/dist/esm/docs/openapi.yaml +158 -4
- package/dist/esm/index.js +9 -8
- package/dist/esm/routesManager.js +6 -10
- package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbLogExporter.js +47 -8
- package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.js +164 -48
- package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.js +69 -29
- package/dist/esm/telemetry/custom-implementations/instrumentations/logsInstrumentation.js +85 -0
- package/dist/esm/telemetry/custom-implementations/metrics/tsdb/Chunk.js +155 -0
- package/dist/esm/telemetry/custom-implementations/metrics/tsdb/Series.js +164 -0
- package/dist/esm/telemetry/custom-implementations/metrics/tsdb/SeriesRegistry.js +382 -0
- package/dist/esm/telemetry/custom-implementations/metrics/tsdb/types.js +1 -0
- package/dist/esm/telemetry/custom-implementations/metrics/tsdb/utils.js +74 -0
- package/dist/esm/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.js +2 -1
- package/dist/esm/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.js +1 -1
- package/dist/esm/telemetry/custom-implementations/utils/storagePath.js +33 -0
- package/dist/esm/telemetry/custom-implementations/wrappers.js +5 -2
- package/dist/esm/telemetry/initializeTelemetry.js +27 -69
- package/dist/esm/telemetry/telemetryConfigurator.js +42 -40
- package/dist/esm/telemetry/telemetryRegistry.js +12 -1
- package/dist/esm/tlm-ai/agent.js +5 -3
- package/dist/esm/tlm-ai/aiController.js +3 -3
- package/dist/esm/tlm-ai/aiService.js +6 -2
- package/dist/esm/tlm-ai/tools.js +5 -9
- package/dist/esm/tlm-auth/authController.js +3 -2
- package/dist/esm/tlm-log/logController.js +84 -4
- package/dist/esm/tlm-log/logRoutes.js +5 -2
- package/dist/esm/tlm-metric/metricsController.js +172 -49
- package/dist/esm/tlm-metric/metricsRoutes.js +10 -4
- package/dist/esm/tlm-plugin/pluginController.js +6 -11
- package/dist/esm/tlm-plugin/pluginService.js +2 -4
- package/dist/esm/tlm-trace/traceController.js +102 -16
- package/dist/esm/tlm-trace/traceRoutes.js +5 -2
- package/dist/esm/tlm-ui/uiRoutes.js +5 -5
- package/dist/esm/tlm-util/utilController.js +3 -9
- package/dist/esm/tlm-util/utilRoutes.js +2 -2
- package/dist/types/config/bootConfig.d.ts +4 -0
- package/dist/types/config/config.d.ts +36 -7
- package/dist/types/config/config.types.d.ts +6 -0
- package/dist/types/index.d.ts +2 -3
- package/dist/types/telemetry/custom-implementations/exporters/InMemoryDbLogExporter.d.ts +4 -1
- package/dist/types/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.d.ts +60 -15
- package/dist/types/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.d.ts +9 -4
- package/dist/types/telemetry/custom-implementations/instrumentations/logsInstrumentation.d.ts +23 -0
- package/dist/types/telemetry/custom-implementations/metrics/tsdb/Chunk.d.ts +49 -0
- package/dist/types/telemetry/custom-implementations/metrics/tsdb/Series.d.ts +67 -0
- package/dist/types/telemetry/custom-implementations/metrics/tsdb/SeriesRegistry.d.ts +69 -0
- package/dist/types/telemetry/custom-implementations/metrics/tsdb/types.d.ts +68 -0
- package/dist/types/telemetry/custom-implementations/metrics/tsdb/utils.d.ts +21 -0
- package/dist/types/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.d.ts +2 -2
- package/dist/types/telemetry/custom-implementations/utils/storagePath.d.ts +12 -0
- package/dist/types/telemetry/custom-implementations/wrappers.d.ts +1 -1
- package/dist/types/telemetry/telemetryConfigurator.d.ts +1 -1
- package/dist/types/telemetry/telemetryRegistry.d.ts +8 -0
- package/dist/types/tlm-ai/agent.d.ts +1 -1
- package/dist/types/tlm-ai/aiService.d.ts +1 -1
- package/dist/types/tlm-log/logController.d.ts +2 -0
- package/dist/types/tlm-metric/metricsController.d.ts +16 -2
- package/dist/types/tlm-trace/traceController.d.ts +3 -1
- package/dist/types/types/index.d.ts +2 -2
- package/dist/ui/assets/{ApiDocsPage-C_VVPPHa.js → ApiDocsPage-BFUrXE5F.js} +2 -2
- package/dist/ui/assets/CollapsibleCard-STA1GVQO.js +1 -0
- package/dist/ui/assets/DevToolsPage-BRSfZqO_.js +1 -0
- package/dist/ui/assets/LandingPage-DzeDy7q7.js +6 -0
- package/dist/ui/assets/LogsPage-BeiFrV2X.js +1 -0
- package/dist/ui/assets/{NotFoundPage-B3quk3P1.js → NotFoundPage-fRNOatbM.js} +1 -1
- package/dist/ui/assets/PluginCreatePage-Ch_RXsdf.js +50 -0
- package/dist/ui/assets/PluginPage-Cl65ZZ_n.js +27 -0
- package/dist/ui/assets/TraceSpansPage-BoK4M5Hh.js +6 -0
- package/dist/ui/assets/VirtualizedListPanel-zcj0v7DL.js +16 -0
- package/dist/ui/assets/alert-BkNVKxJN.js +1133 -0
- package/dist/ui/assets/badge-CN7FeufU.js +1 -0
- package/dist/ui/assets/{chevron-down-CPsvsmqj.js → chevron-down-CG--ounh.js} +1 -1
- package/dist/ui/assets/{chevron-up-Df9jMo1X.js → chevron-up-B6tzMAOm.js} +1 -1
- package/dist/ui/assets/{circle-alert-DOPQPvU8.js → circle-alert-BDF8Tq9y.js} +1 -1
- package/dist/ui/assets/dialog-BrpWNk36.js +15 -0
- package/dist/ui/assets/index-6xOVKwKn.js +305 -0
- package/dist/ui/assets/index-D6f1KjWV.css +1 -0
- package/dist/ui/assets/index-D96rVSkR.js +1 -0
- package/dist/ui/assets/info-99kuqpbx.js +6 -0
- package/dist/ui/assets/{input-Dzvg_ZEZ.js → input-B-01QDg_.js} +1 -1
- package/dist/ui/assets/label-CQLeZjM1.js +1 -0
- package/dist/ui/assets/{loader-circle-CrvlRy5o.js → loader-circle-BoDGk-BO.js} +1 -1
- package/dist/ui/assets/{loginPage-qa4V-B70.js → loginPage-8F4EEd1B.js} +1 -1
- package/dist/ui/assets/metrics-page-D1GxaB_c.css +1 -0
- package/dist/ui/assets/metrics-page-DPtteXqY.js +31 -0
- package/dist/ui/assets/popover-DS_8DYYt.js +11 -0
- package/dist/ui/assets/select-DYjegiXi.js +6 -0
- package/dist/ui/assets/separator-DGsRxIrl.js +6 -0
- package/dist/ui/assets/severityOptions-DEOvJqC9.js +11 -0
- package/dist/ui/assets/square-pen-DPhgYz6O.js +6 -0
- package/dist/ui/assets/switch-Di9NJH2A.js +1 -0
- package/dist/ui/assets/trace-DJq1miYa.js +1 -0
- package/dist/ui/assets/upload-BiLTpCnX.js +11 -0
- package/dist/ui/assets/{utilService-DNyqzwj0.js → utilService-CNZOmadC.js} +1 -1
- package/dist/ui/assets/wand-sparkles-CPoBNFFg.js +6 -0
- package/dist/ui/index.html +2 -2
- package/package.json +44 -48
- package/dist/ui/assets/CollapsibleCard-B3KR_8mL.js +0 -1
- package/dist/ui/assets/DevToolsPage-OyZcDcmw.js +0 -1
- package/dist/ui/assets/LandingPage-CppFBA6K.js +0 -6
- package/dist/ui/assets/LogsPage-9Fq8GArS.js +0 -26
- package/dist/ui/assets/PluginCreatePage-X_aCH4t4.js +0 -50
- package/dist/ui/assets/PluginPage-DMDSihrZ.js +0 -27
- package/dist/ui/assets/alert-jQ9HCPIf.js +0 -1133
- package/dist/ui/assets/badge-CNq0-mH5.js +0 -1
- package/dist/ui/assets/card-DFAwwhN3.js +0 -1
- package/dist/ui/assets/index-BkD6DijD.js +0 -15
- package/dist/ui/assets/index-CERGVYZK.js +0 -292
- package/dist/ui/assets/index-CSIPf9qw.css +0 -1
- package/dist/ui/assets/label-DuVnkZ4q.js +0 -1
- package/dist/ui/assets/select-DhS8YUtJ.js +0 -1
- package/dist/ui/assets/separator-isK4chBP.js +0 -6
- package/dist/ui/assets/severityOptions-O38dSOfk.js +0 -11
- package/dist/ui/assets/switch-Z3mImG9n.js +0 -1
- package/dist/ui/assets/tabs-_77MUUQe.js +0 -16
- package/dist/ui/assets/upload-C1LT4Gkb.js +0 -16
|
@@ -1,37 +1,60 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { BatchLogRecordProcessor as LogBatchLogRecordProcessor, SimpleLogRecordProcessor as LogSimpleLogRecordProcessor } from '@opentelemetry/sdk-logs';
|
|
2
|
+
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
|
|
3
|
+
import { BatchSpanProcessor as TraceBatchSpanProcessor, SimpleSpanProcessor as TraceSimpleSpanProcessor } from '@opentelemetry/sdk-trace-node';
|
|
3
4
|
import logger from '../utils/logger.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { HostMetrics } from '@opentelemetry/host-metrics';
|
|
5
|
+
import { inMemoryDbLogExporter, inMemoryDbMetricExporter, inMemoryDbSpanExporter, instrumentations, multiLogExporter, multiSpanExporter, oasTelemetryResource } from './telemetryRegistry.js';
|
|
6
|
+
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
7
7
|
import { bootEnvVariables } from '../config/bootConfig.js';
|
|
8
8
|
import { pluginService } from '../tlm-plugin/pluginService.js';
|
|
9
|
-
export
|
|
9
|
+
export function configureTelemetry(oasTlmConfig) {
|
|
10
|
+
logger.info("🚀 Configuring Telemetry...");
|
|
11
|
+
if (oasTlmConfig.instrumentations) {
|
|
12
|
+
instrumentations.push(...oasTlmConfig.instrumentations);
|
|
13
|
+
}
|
|
10
14
|
configurePlugins(oasTlmConfig);
|
|
11
|
-
configureTraces(oasTlmConfig);
|
|
12
|
-
configureMetrics(oasTlmConfig);
|
|
13
|
-
configureLogs(oasTlmConfig);
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
const mainTraceProcessor = configureTraces(oasTlmConfig);
|
|
16
|
+
const mainMetricReader = configureMetrics(oasTlmConfig);
|
|
17
|
+
const mainLogProcessor = configureLogs(oasTlmConfig);
|
|
18
|
+
const sdk = new NodeSDK({
|
|
19
|
+
instrumentations: instrumentations,
|
|
20
|
+
resource: oasTelemetryResource,
|
|
21
|
+
traceExporter: inMemoryDbSpanExporter,
|
|
22
|
+
spanProcessors: [mainTraceProcessor, ...oasTlmConfig.traces.extraProcessors || []],
|
|
23
|
+
metricReaders: [mainMetricReader, ...(oasTlmConfig.metrics.extraReaders || [])],
|
|
24
|
+
logRecordProcessors: [mainLogProcessor, ...oasTlmConfig.logs.extraProcessors || []],
|
|
25
|
+
});
|
|
26
|
+
sdk.start();
|
|
27
|
+
logger.info("✅ Node SDK started with telemetry configuration");
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
16
30
|
function configurePlugins(oasTlmConfig) {
|
|
17
31
|
pluginService.enabled = oasTlmConfig.plugins.enabled;
|
|
18
32
|
}
|
|
19
33
|
function configureTraces(oasTlmConfig) {
|
|
20
34
|
// TRACES CONFIGURATION
|
|
21
35
|
// [OT]Provider -> [OT]SpanProcessor(multiSpan) -> n Processors(eg mainProcessor, extra) -> 1 SpanExporter
|
|
22
|
-
inMemoryDbSpanExporter.baseUrl = oasTlmConfig.general.baseUrl; // TODO this will be done with filters
|
|
23
36
|
inMemoryDbSpanExporter.retentionTimeInSeconds = oasTlmConfig.traces.memoryExporter.retentionTimeSeconds;
|
|
24
37
|
inMemoryDbSpanExporter.setEnabledValue(oasTlmConfig.traces.memoryExporter.enabled);
|
|
25
38
|
const mainExporter = multiSpanExporter;
|
|
26
|
-
let mainProcessor = new
|
|
39
|
+
let mainProcessor = new TraceBatchSpanProcessor(mainExporter);
|
|
27
40
|
if (bootEnvVariables.OASTLM_BOOT_ENV !== 'production') {
|
|
28
41
|
logger.info('Not in production, using SimpleSpanProcessor for traces');
|
|
29
|
-
mainProcessor = new
|
|
42
|
+
mainProcessor = new TraceSimpleSpanProcessor(mainExporter);
|
|
30
43
|
}
|
|
31
44
|
mainExporter.addExporters(inMemoryDbSpanExporter); // Main exporter have at least the in-memory exporter used by the traces controller
|
|
32
45
|
mainExporter.addExporters(oasTlmConfig.traces.extraExporters);
|
|
33
|
-
|
|
34
|
-
|
|
46
|
+
return mainProcessor;
|
|
47
|
+
}
|
|
48
|
+
function configureMetrics(oasTlmConfig) {
|
|
49
|
+
// METRICS CONFIGURATION
|
|
50
|
+
inMemoryDbMetricExporter.setEnabledValue(oasTlmConfig.metrics.memoryExporter.enabled);
|
|
51
|
+
inMemoryDbMetricExporter.retentionTimeInSeconds = oasTlmConfig.metrics.memoryExporter.retentionTimeSeconds;
|
|
52
|
+
const mainReader = new PeriodicExportingMetricReader({
|
|
53
|
+
exporter: inMemoryDbMetricExporter,
|
|
54
|
+
exportIntervalMillis: oasTlmConfig.metrics.mainMetricReaderOptions.exportIntervalMillis,
|
|
55
|
+
metricProducers: oasTlmConfig.metrics.mainMetricReaderOptions.metricProducers
|
|
56
|
+
});
|
|
57
|
+
return mainReader;
|
|
35
58
|
}
|
|
36
59
|
function configureLogs(oasTlmConfig) {
|
|
37
60
|
// LOGS CONFIGURATION
|
|
@@ -39,33 +62,12 @@ function configureLogs(oasTlmConfig) {
|
|
|
39
62
|
inMemoryDbLogExporter.setEnabledValue(oasTlmConfig.logs.memoryExporter.enabled);
|
|
40
63
|
inMemoryDbLogExporter.retentionTimeInSeconds = oasTlmConfig.logs.memoryExporter.retentionTimeSeconds;
|
|
41
64
|
const mainExporter = multiLogExporter;
|
|
42
|
-
let mainProcessor = new
|
|
65
|
+
let mainProcessor = new LogBatchLogRecordProcessor(mainExporter);
|
|
43
66
|
if (bootEnvVariables.OASTLM_BOOT_ENV !== 'production') {
|
|
44
67
|
logger.info('Not in production, using SimpleLogRecordProcessor for logs');
|
|
45
|
-
mainProcessor = new
|
|
68
|
+
mainProcessor = new LogSimpleLogRecordProcessor(mainExporter);
|
|
46
69
|
}
|
|
47
70
|
mainExporter.addExporters(inMemoryDbLogExporter); // Main exporter have at least the in-memory exporter used by the logs controller
|
|
48
71
|
mainExporter.addExporters(oasTlmConfig.logs.extraExporters);
|
|
49
|
-
|
|
50
|
-
dynamicMultiLogProcessor.addProcessors(oasTlmConfig.logs.extraProcessors);
|
|
51
|
-
}
|
|
52
|
-
function configureMetrics(oasTlmConfig) {
|
|
53
|
-
// METRICS CONFIGURATION
|
|
54
|
-
// [CUSTOM]MeterProvider -> n [OTel]MetricReader -> (0-1) MetricExporter (only if push-based reader)
|
|
55
|
-
inMemoryDbMetricExporter.setEnabledValue(oasTlmConfig.metrics.memoryExporter.enabled);
|
|
56
|
-
inMemoryDbMetricExporter.retentionTimeInSeconds = oasTlmConfig.metrics.memoryExporter.retentionTimeSeconds;
|
|
57
|
-
const mainReader = new PeriodicExportingMetricReader({
|
|
58
|
-
exporter: inMemoryDbMetricExporter,
|
|
59
|
-
exportIntervalMillis: oasTlmConfig.metrics.mainMetricReaderOptions.exportIntervalMillis,
|
|
60
|
-
metricProducers: oasTlmConfig.metrics.mainMetricReaderOptions.metricProducers
|
|
61
|
-
});
|
|
62
|
-
const meterProvider = new MeterProvider({
|
|
63
|
-
resource: oasTelemetryResource,
|
|
64
|
-
readers: [mainReader, ...oasTlmConfig.metrics.extraReaders],
|
|
65
|
-
views: oasTlmConfig.metrics.extraViews || []
|
|
66
|
-
});
|
|
67
|
-
// TODO maybe hostMetrics are too much, consider using only a subset of them.
|
|
68
|
-
const hostMetrics = new HostMetrics({ meterProvider: meterProvider });
|
|
69
|
-
// AFTER adding all readers, start the instrumentations
|
|
70
|
-
hostMetrics.start();
|
|
72
|
+
return mainProcessor;
|
|
71
73
|
}
|
|
@@ -8,6 +8,15 @@ import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
|
|
|
8
8
|
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
9
9
|
import { bootEnvVariables } from "../config/bootConfig.js";
|
|
10
10
|
// GLOBAL REGISTRY of telemetry components, used by SDKs and controllers.
|
|
11
|
+
let _bootInitialized = false;
|
|
12
|
+
let _telemetryConfigured = false;
|
|
13
|
+
let _router = undefined;
|
|
14
|
+
export function isBootInitialized() { return _bootInitialized; }
|
|
15
|
+
export function setBootInitialized(v) { _bootInitialized = v; }
|
|
16
|
+
export function isTelemetryConfigured() { return _telemetryConfigured; }
|
|
17
|
+
export function setTelemetryConfigured(v) { _telemetryConfigured = v; }
|
|
18
|
+
export function setTelemetryRouter(router) { _router = router; }
|
|
19
|
+
export function getTelemetryRouter() { return _router; }
|
|
11
20
|
export const oasTelemetryResource = resourceFromAttributes({
|
|
12
21
|
[ATTR_SERVICE_NAME]: bootEnvVariables.OASTLM_BOOT_SERVICE_NAME
|
|
13
22
|
});
|
|
@@ -22,7 +31,7 @@ export const dynamicMultiSpanProcessor = new DynamicMultiSpanProcessor();
|
|
|
22
31
|
export const inMemoryDbLogExporter = new InMemoryDbLogExporter();
|
|
23
32
|
export const multiLogExporter = new EnablerMultiLogExporter();
|
|
24
33
|
export const dynamicMultiLogProcessor = new DynamicMultiLogRecordProcessor();
|
|
25
|
-
//
|
|
34
|
+
// For custom log instrumentation, and lib logging
|
|
26
35
|
export const originalConsoleMethods = {
|
|
27
36
|
log: console.log,
|
|
28
37
|
warn: console.warn,
|
|
@@ -35,3 +44,5 @@ export const originalConsoleMethods = {
|
|
|
35
44
|
export const inMemoryDbMetricExporter = new InMemoryDbMetricExporter();
|
|
36
45
|
// Readers and their exporters cannot be grouped together in a MultiReader or similar construct
|
|
37
46
|
// due to differences in aggregation temporality and aggregation selection.
|
|
47
|
+
// INSTRUMENTATIONS -----------------------------------------------------------------------
|
|
48
|
+
export const instrumentations = [];
|
package/dist/esm/tlm-ai/agent.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { tools, availableTools } from './tools.js';
|
|
2
2
|
import logger from '../utils/logger.js';
|
|
3
|
-
export async function agent(openai, messages, model = "gpt-3.5-turbo"
|
|
3
|
+
export async function agent(openai, messages, model = "gpt-3.5-turbo") {
|
|
4
4
|
for (let i = 0; i < 5; i++) {
|
|
5
5
|
const modelResponse = await openai.chat.completions.create({
|
|
6
6
|
model,
|
|
@@ -12,11 +12,13 @@ export async function agent(openai, messages, model = "gpt-3.5-turbo", extraProm
|
|
|
12
12
|
logger.debug("Tool calls detected:", message.tool_calls);
|
|
13
13
|
const results = [];
|
|
14
14
|
for (const toolCall of message.tool_calls) {
|
|
15
|
+
// Type guard for tool_calls
|
|
16
|
+
if (toolCall.type !== 'function' || !toolCall.function)
|
|
17
|
+
continue;
|
|
15
18
|
const functionName = toolCall.function.name;
|
|
16
19
|
const functionToCall = availableTools[functionName];
|
|
17
20
|
const functionArgs = JSON.parse(toolCall.function.arguments);
|
|
18
21
|
const functionArgsArr = Object.values(functionArgs);
|
|
19
|
-
// @ts-expect-error yes
|
|
20
22
|
// eslint-disable-next-line prefer-spread
|
|
21
23
|
const functionResponse = await functionToCall.apply(null, functionArgsArr);
|
|
22
24
|
results.push({
|
|
@@ -26,7 +28,7 @@ export async function agent(openai, messages, model = "gpt-3.5-turbo", extraProm
|
|
|
26
28
|
}
|
|
27
29
|
const resultMessage = results.map(({ name, response }, idx) => {
|
|
28
30
|
const toolCall = message.tool_calls?.[idx];
|
|
29
|
-
const params = toolCall ? JSON.parse(toolCall.function.arguments) : {};
|
|
31
|
+
const params = toolCall && toolCall.type === 'function' && toolCall.function ? JSON.parse(toolCall.function.arguments) : {};
|
|
30
32
|
return `Tool "${name}" called with parameters:\n${JSON.stringify(params, null, 2)}\nResult:\n${JSON.stringify(response, null, 2)}`;
|
|
31
33
|
}).join("\n\n");
|
|
32
34
|
messages.push({
|
|
@@ -20,7 +20,7 @@ export async function listConversations(req, res) {
|
|
|
20
20
|
}
|
|
21
21
|
export async function getConversationHistory(req, res) {
|
|
22
22
|
try {
|
|
23
|
-
const
|
|
23
|
+
const conversationId = req.params.conversationId;
|
|
24
24
|
const conversation = getAiService().getConversation(conversationId);
|
|
25
25
|
if (!conversation) {
|
|
26
26
|
res.status(404).json({ error: 'Not found' });
|
|
@@ -34,7 +34,7 @@ export async function getConversationHistory(req, res) {
|
|
|
34
34
|
}
|
|
35
35
|
export async function deleteConversation(req, res) {
|
|
36
36
|
try {
|
|
37
|
-
const
|
|
37
|
+
const conversationId = req.params.conversationId;
|
|
38
38
|
const deleted = getAiService().deleteConversation(conversationId);
|
|
39
39
|
if (!deleted) {
|
|
40
40
|
res.status(404).json({ error: 'Not found' });
|
|
@@ -48,7 +48,7 @@ export async function deleteConversation(req, res) {
|
|
|
48
48
|
}
|
|
49
49
|
export async function sendMessage(req, res) {
|
|
50
50
|
try {
|
|
51
|
-
const
|
|
51
|
+
const conversationId = req.params.conversationId;
|
|
52
52
|
const { content } = req.body;
|
|
53
53
|
if (!content) {
|
|
54
54
|
res.status(400).json({ error: 'Missing content' });
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import OpenAI from 'openai';
|
|
2
2
|
import { agent } from './agent.js';
|
|
3
3
|
class AIService {
|
|
4
|
+
config;
|
|
5
|
+
conversations = new Map();
|
|
6
|
+
openai;
|
|
7
|
+
model;
|
|
8
|
+
extraPrompts;
|
|
4
9
|
constructor(config) {
|
|
5
10
|
this.config = config;
|
|
6
|
-
this.conversations = new Map();
|
|
7
11
|
this.openai = new OpenAI({
|
|
8
12
|
apiKey: this.config.apiKey,
|
|
9
13
|
});
|
|
@@ -47,7 +51,7 @@ class AIService {
|
|
|
47
51
|
// Use the agent function with tools
|
|
48
52
|
// Internaly pushes new messages to conversation.messages
|
|
49
53
|
const currentMessagesCount = conversation.messages.length;
|
|
50
|
-
await agent(this.openai, conversation.messages, model || this.model
|
|
54
|
+
await agent(this.openai, conversation.messages, model || this.model);
|
|
51
55
|
// Return the last assistant message (the one just added by agent)
|
|
52
56
|
const generatedMessages = conversation.messages.slice(currentMessagesCount);
|
|
53
57
|
return generatedMessages;
|
package/dist/esm/tlm-ai/tools.js
CHANGED
|
@@ -3,14 +3,10 @@ import { inMemoryDbLogExporter, inMemoryDbMetricExporter, inMemoryDbSpanExporter
|
|
|
3
3
|
const getTraces = async (searchInput) => {
|
|
4
4
|
logger.debug("getTraces called with searchInput:", searchInput);
|
|
5
5
|
try {
|
|
6
|
-
const search = searchInput
|
|
7
|
-
const traces = await
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
reject(err);
|
|
11
|
-
else
|
|
12
|
-
resolve(docs);
|
|
13
|
-
});
|
|
6
|
+
const search = searchInput ? JSON.parse(searchInput) : {};
|
|
7
|
+
const traces = await inMemoryDbSpanExporter.find({
|
|
8
|
+
query: search,
|
|
9
|
+
limit: 1000
|
|
14
10
|
});
|
|
15
11
|
const simplifiedTraces = getSimplifiedTraces(traces);
|
|
16
12
|
logger.debug(`Searching for traces with searchInput: ${JSON.stringify(search)}`);
|
|
@@ -38,7 +34,7 @@ const getLogs = async (startDate, endDate) => {
|
|
|
38
34
|
const logs = (await inMemoryDbLogExporter.find({
|
|
39
35
|
query: nedbQuery,
|
|
40
36
|
messageSearch: null,
|
|
41
|
-
limit:
|
|
37
|
+
limit: 1000 // or any appropriate limit
|
|
42
38
|
})) || [];
|
|
43
39
|
logger.debug(`Found ${logs.length} logs in the specified range.`);
|
|
44
40
|
const simplifiedLogs = getSimplifiedLogs(logs);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import jwt from 'jsonwebtoken';
|
|
2
2
|
import logger from '../utils/logger.js';
|
|
3
|
+
import { bootEnvVariables } from '../config/bootConfig.js';
|
|
3
4
|
function generateAccessToken(secret, expiresIn) {
|
|
4
5
|
return jwt.sign({ type: "access" }, secret, { expiresIn: Math.floor(expiresIn / 1000) });
|
|
5
6
|
}
|
|
@@ -28,7 +29,7 @@ export const getLogin = (oasTlmConfig) => (req, res) => {
|
|
|
28
29
|
httpOnly: true,
|
|
29
30
|
secure: process.env.NODE_ENV === "production",
|
|
30
31
|
sameSite: "lax",
|
|
31
|
-
path:
|
|
32
|
+
path: bootEnvVariables.OASTLM_BOOT_BASE_URL + "/auth/refresh"
|
|
32
33
|
});
|
|
33
34
|
res.status(200).json({ valid: true, message: "Login successful" });
|
|
34
35
|
return;
|
|
@@ -46,7 +47,7 @@ export const getLogout = (oasTlmConfig) => (req, res) => {
|
|
|
46
47
|
return;
|
|
47
48
|
}
|
|
48
49
|
res.clearCookie('oas-tlm-access-token', { path: '/' });
|
|
49
|
-
res.clearCookie('oas-tlm-refresh-token', { path:
|
|
50
|
+
res.clearCookie('oas-tlm-refresh-token', { path: bootEnvVariables.OASTLM_BOOT_BASE_URL + '/auth/refresh' });
|
|
50
51
|
res.status(200).json({ valid: true, message: "Logged out" });
|
|
51
52
|
};
|
|
52
53
|
export const getRefresh = (oasTlmConfig) => (req, res) => {
|
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
import { inMemoryDbLogExporter } from '../telemetry/telemetryRegistry.js';
|
|
2
2
|
import logger from '../utils/logger.js';
|
|
3
3
|
import { convertRegexRecursively } from '../utils/regexUtils.js';
|
|
4
|
+
/**
|
|
5
|
+
* Parse NDJSON import data
|
|
6
|
+
* Each line must be a valid JSON object
|
|
7
|
+
* @param body - Request body (raw string)
|
|
8
|
+
* @returns Array of log objects
|
|
9
|
+
*/
|
|
10
|
+
function parseImportData(body) {
|
|
11
|
+
if (typeof body !== 'string') {
|
|
12
|
+
throw new Error('Import must be NDJSON format (plain text with one JSON object per line)');
|
|
13
|
+
}
|
|
14
|
+
const lines = body.split('\n').filter((line) => line.trim());
|
|
15
|
+
return lines.map((line, index) => {
|
|
16
|
+
try {
|
|
17
|
+
return JSON.parse(line);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
logger.error(`Failed to parse NDJSON line ${index + 1}: ${line}`);
|
|
21
|
+
throw new Error(`Invalid JSON on line ${index + 1}`);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
4
25
|
export const findLogs = async (req, res) => {
|
|
5
26
|
const body = req.body || {};
|
|
6
27
|
const messageSearch = body.textSearch || null;
|
|
@@ -27,7 +48,8 @@ export const findLogs = async (req, res) => {
|
|
|
27
48
|
};
|
|
28
49
|
const docs = await inMemoryDbLogExporter.find(findConfig);
|
|
29
50
|
res.send({
|
|
30
|
-
|
|
51
|
+
logsCount: docs.length,
|
|
52
|
+
logs: docs,
|
|
31
53
|
});
|
|
32
54
|
}
|
|
33
55
|
catch (err) {
|
|
@@ -40,14 +62,13 @@ export const resetLogs = (req, res) => {
|
|
|
40
62
|
res.send('Logs reset');
|
|
41
63
|
};
|
|
42
64
|
export const insertLogsToDb = async (req, res) => {
|
|
43
|
-
const jsonContent = req.body.logs;
|
|
65
|
+
const jsonContent = (req.body || {}).logs;
|
|
44
66
|
const resetData = req.query.reset === 'true';
|
|
45
67
|
if (!Array.isArray(jsonContent)) {
|
|
46
68
|
res.status(400).send({ error: 'Invalid data format.' });
|
|
47
69
|
return;
|
|
48
70
|
}
|
|
49
71
|
const cleanedLogs = jsonContent.map((log) => {
|
|
50
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
51
72
|
const { _id, ...rest } = log; // Remove _id if it exists
|
|
52
73
|
return rest; // Return the cleaned log object
|
|
53
74
|
});
|
|
@@ -74,6 +95,41 @@ export const insertLogsToDb = async (req, res) => {
|
|
|
74
95
|
res.status(500).send({ error: 'Failed to reset and insert data', details: err.message });
|
|
75
96
|
}
|
|
76
97
|
};
|
|
98
|
+
export const importLogs = async (req, res) => {
|
|
99
|
+
const resetData = req.query.reset === 'true';
|
|
100
|
+
try {
|
|
101
|
+
// Parse NDJSON format
|
|
102
|
+
const logs = parseImportData(req.body);
|
|
103
|
+
if (logs.length === 0) {
|
|
104
|
+
res.status(400).send({ error: 'No valid logs found in import data' });
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const cleanedLogs = logs.map((log) => {
|
|
108
|
+
const { _id, ...rest } = log; // Remove _id if it exists
|
|
109
|
+
return rest;
|
|
110
|
+
});
|
|
111
|
+
let message = '';
|
|
112
|
+
if (resetData) {
|
|
113
|
+
inMemoryDbLogExporter.reset();
|
|
114
|
+
message += 'Logs Database reset. ';
|
|
115
|
+
}
|
|
116
|
+
await new Promise((resolve, reject) => {
|
|
117
|
+
inMemoryDbLogExporter.insert(cleanedLogs, (err, newDocs) => {
|
|
118
|
+
if (err) {
|
|
119
|
+
logger.error('Error importing logs:', err);
|
|
120
|
+
return reject(err);
|
|
121
|
+
}
|
|
122
|
+
resolve(newDocs);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
message += `Imported ${cleanedLogs.length} logs.`;
|
|
126
|
+
res.send({ message, ImportedLogsCount: cleanedLogs.length });
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
logger.error('Import failed:', err);
|
|
130
|
+
res.status(400).send({ error: 'Failed to import logs', details: err.message });
|
|
131
|
+
}
|
|
132
|
+
};
|
|
77
133
|
export const startLogs = (req, res) => {
|
|
78
134
|
inMemoryDbLogExporter.enable();
|
|
79
135
|
res.send('Log collection started');
|
|
@@ -87,7 +143,7 @@ export const statusLogs = (req, res) => {
|
|
|
87
143
|
res.send({ active: isRunning });
|
|
88
144
|
};
|
|
89
145
|
export const setLogRetentionTime = (req, res) => {
|
|
90
|
-
const retentionTimeInSeconds = req.body.retentionTimeInSeconds;
|
|
146
|
+
const retentionTimeInSeconds = (req.body || {}).retentionTimeInSeconds;
|
|
91
147
|
if (typeof retentionTimeInSeconds !== 'number' || retentionTimeInSeconds <= 0) {
|
|
92
148
|
res.status(400).send({ error: 'Invalid retention time. Must be a positive number.' });
|
|
93
149
|
return;
|
|
@@ -99,3 +155,27 @@ export const getLogRetentionTime = (req, res) => {
|
|
|
99
155
|
const retentionTimeInSeconds = inMemoryDbLogExporter.retentionTimeInSeconds || 0;
|
|
100
156
|
res.send({ retentionTimeInSeconds: retentionTimeInSeconds });
|
|
101
157
|
};
|
|
158
|
+
export const exportLogs = async (req, res) => {
|
|
159
|
+
try {
|
|
160
|
+
// Get ALL logs without practical limit
|
|
161
|
+
const findConfig = {
|
|
162
|
+
query: {},
|
|
163
|
+
messageSearch: null,
|
|
164
|
+
sortOrder: { timestamp: -1 }
|
|
165
|
+
};
|
|
166
|
+
const docs = await inMemoryDbLogExporter.find(findConfig);
|
|
167
|
+
const timestamp = new Date().toISOString().slice(0, 19).replace(/[-T:]/g, '');
|
|
168
|
+
res.setHeader('Content-Type', 'application/x-ndjson');
|
|
169
|
+
res.setHeader('Content-Disposition', `attachment; filename="logs-${timestamp}.ndjson"`);
|
|
170
|
+
res.setHeader('Transfer-Encoding', 'chunked');
|
|
171
|
+
// Stream as NDJSON (one JSON object per line)
|
|
172
|
+
docs.forEach(doc => {
|
|
173
|
+
res.write(JSON.stringify(doc) + '\n');
|
|
174
|
+
});
|
|
175
|
+
res.end();
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
logger.error('Failed to export logs:', err);
|
|
179
|
+
res.status(500).send({ error: 'Failed to export logs', details: err.message });
|
|
180
|
+
}
|
|
181
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Router } from 'express';
|
|
2
|
-
import { startLogs, stopLogs, statusLogs, resetLogs, findLogs, insertLogsToDb, setLogRetentionTime, getLogRetentionTime } from './logController.js';
|
|
1
|
+
import { Router, text } from 'express';
|
|
2
|
+
import { startLogs, stopLogs, statusLogs, resetLogs, findLogs, insertLogsToDb, importLogs, setLogRetentionTime, getLogRetentionTime, exportLogs } from './logController.js';
|
|
3
3
|
export const getLogRoutes = () => {
|
|
4
4
|
const router = Router();
|
|
5
5
|
// Logs Control
|
|
@@ -9,6 +9,9 @@ export const getLogRoutes = () => {
|
|
|
9
9
|
router.post('/reset', resetLogs);
|
|
10
10
|
router.post('/retention-time', setLogRetentionTime);
|
|
11
11
|
router.get('/retention-time', getLogRetentionTime);
|
|
12
|
+
router.get('/export', exportLogs);
|
|
13
|
+
// Use text middleware for import to handle NDJSON format
|
|
14
|
+
router.post('/import', text({ type: 'application/x-ndjson', limit: '500mb' }), importLogs);
|
|
12
15
|
router.get('/', findLogs);
|
|
13
16
|
router.post('/', insertLogsToDb);
|
|
14
17
|
router.post('/find', findLogs);
|