@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.
Files changed (167) hide show
  1. package/.env.example +21 -2
  2. package/README.md +1 -2
  3. package/dist/cjs/config/bootConfig.cjs +19 -14
  4. package/dist/cjs/config/config.cjs +112 -125
  5. package/dist/cjs/config/config.types.cjs +1 -4
  6. package/dist/cjs/docs/openapi.yaml +158 -4
  7. package/dist/cjs/index.cjs +27 -30
  8. package/dist/cjs/routesManager.cjs +62 -70
  9. package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbLogExporter.cjs +202 -190
  10. package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.cjs +204 -99
  11. package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.cjs +152 -116
  12. package/dist/cjs/telemetry/custom-implementations/instrumentations/logsInstrumentation.cjs +92 -0
  13. package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/Chunk.cjs +159 -0
  14. package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/Series.cjs +168 -0
  15. package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/SeriesRegistry.cjs +389 -0
  16. package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/types.cjs +2 -0
  17. package/dist/cjs/telemetry/custom-implementations/metrics/tsdb/utils.cjs +77 -0
  18. package/dist/cjs/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.cjs +65 -63
  19. package/dist/cjs/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.cjs +63 -62
  20. package/dist/cjs/telemetry/custom-implementations/utils/circular.cjs +47 -47
  21. package/dist/cjs/telemetry/custom-implementations/utils/storagePath.cjs +39 -0
  22. package/dist/cjs/telemetry/custom-implementations/wrappers.cjs +141 -138
  23. package/dist/cjs/telemetry/initializeTelemetry.cjs +35 -91
  24. package/dist/cjs/telemetry/telemetryConfigurator.cjs +70 -72
  25. package/dist/cjs/telemetry/telemetryRegistry.cjs +45 -31
  26. package/dist/cjs/tlm-ai/agent.cjs +49 -64
  27. package/dist/cjs/tlm-ai/aiController.cjs +54 -76
  28. package/dist/cjs/tlm-ai/aiRoutes.cjs +17 -20
  29. package/dist/cjs/tlm-ai/aiService.cjs +91 -95
  30. package/dist/cjs/tlm-ai/tools.cjs +177 -174
  31. package/dist/cjs/tlm-auth/authController.cjs +80 -123
  32. package/dist/cjs/tlm-auth/authMiddleware.cjs +25 -30
  33. package/dist/cjs/tlm-auth/authRoutes.cjs +11 -14
  34. package/dist/cjs/tlm-log/logController.cjs +171 -116
  35. package/dist/cjs/tlm-log/logRoutes.cjs +20 -20
  36. package/dist/cjs/tlm-metric/metricsController.cjs +211 -121
  37. package/dist/cjs/tlm-metric/metricsRoutes.cjs +23 -20
  38. package/dist/cjs/tlm-plugin/pluginController.cjs +128 -140
  39. package/dist/cjs/tlm-plugin/pluginProcess.cjs +89 -94
  40. package/dist/cjs/tlm-plugin/pluginRoutes.cjs +11 -14
  41. package/dist/cjs/tlm-plugin/pluginService.cjs +73 -74
  42. package/dist/cjs/tlm-trace/traceController.cjs +169 -117
  43. package/dist/cjs/tlm-trace/traceRoutes.cjs +20 -20
  44. package/dist/cjs/tlm-ui/uiRoutes.cjs +63 -32
  45. package/dist/cjs/tlm-util/utilController.cjs +68 -70
  46. package/dist/cjs/tlm-util/utilRoutes.cjs +51 -63
  47. package/dist/cjs/types/index.cjs +2 -5
  48. package/dist/cjs/utils/logger.cjs +38 -43
  49. package/dist/cjs/utils/regexUtils.cjs +22 -22
  50. package/dist/esm/config/bootConfig.js +6 -0
  51. package/dist/esm/config/config.js +1 -2
  52. package/dist/esm/docs/openapi.yaml +158 -4
  53. package/dist/esm/index.js +9 -8
  54. package/dist/esm/routesManager.js +6 -10
  55. package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbLogExporter.js +47 -8
  56. package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.js +164 -48
  57. package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.js +69 -29
  58. package/dist/esm/telemetry/custom-implementations/instrumentations/logsInstrumentation.js +85 -0
  59. package/dist/esm/telemetry/custom-implementations/metrics/tsdb/Chunk.js +155 -0
  60. package/dist/esm/telemetry/custom-implementations/metrics/tsdb/Series.js +164 -0
  61. package/dist/esm/telemetry/custom-implementations/metrics/tsdb/SeriesRegistry.js +382 -0
  62. package/dist/esm/telemetry/custom-implementations/metrics/tsdb/types.js +1 -0
  63. package/dist/esm/telemetry/custom-implementations/metrics/tsdb/utils.js +74 -0
  64. package/dist/esm/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.js +2 -1
  65. package/dist/esm/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.js +1 -1
  66. package/dist/esm/telemetry/custom-implementations/utils/storagePath.js +33 -0
  67. package/dist/esm/telemetry/custom-implementations/wrappers.js +5 -2
  68. package/dist/esm/telemetry/initializeTelemetry.js +27 -69
  69. package/dist/esm/telemetry/telemetryConfigurator.js +42 -40
  70. package/dist/esm/telemetry/telemetryRegistry.js +12 -1
  71. package/dist/esm/tlm-ai/agent.js +5 -3
  72. package/dist/esm/tlm-ai/aiController.js +3 -3
  73. package/dist/esm/tlm-ai/aiService.js +6 -2
  74. package/dist/esm/tlm-ai/tools.js +5 -9
  75. package/dist/esm/tlm-auth/authController.js +3 -2
  76. package/dist/esm/tlm-log/logController.js +84 -4
  77. package/dist/esm/tlm-log/logRoutes.js +5 -2
  78. package/dist/esm/tlm-metric/metricsController.js +172 -49
  79. package/dist/esm/tlm-metric/metricsRoutes.js +10 -4
  80. package/dist/esm/tlm-plugin/pluginController.js +6 -11
  81. package/dist/esm/tlm-plugin/pluginService.js +2 -4
  82. package/dist/esm/tlm-trace/traceController.js +102 -16
  83. package/dist/esm/tlm-trace/traceRoutes.js +5 -2
  84. package/dist/esm/tlm-ui/uiRoutes.js +5 -5
  85. package/dist/esm/tlm-util/utilController.js +3 -9
  86. package/dist/esm/tlm-util/utilRoutes.js +2 -2
  87. package/dist/types/config/bootConfig.d.ts +4 -0
  88. package/dist/types/config/config.d.ts +36 -7
  89. package/dist/types/config/config.types.d.ts +6 -0
  90. package/dist/types/index.d.ts +2 -3
  91. package/dist/types/telemetry/custom-implementations/exporters/InMemoryDbLogExporter.d.ts +4 -1
  92. package/dist/types/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.d.ts +60 -15
  93. package/dist/types/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.d.ts +9 -4
  94. package/dist/types/telemetry/custom-implementations/instrumentations/logsInstrumentation.d.ts +23 -0
  95. package/dist/types/telemetry/custom-implementations/metrics/tsdb/Chunk.d.ts +49 -0
  96. package/dist/types/telemetry/custom-implementations/metrics/tsdb/Series.d.ts +67 -0
  97. package/dist/types/telemetry/custom-implementations/metrics/tsdb/SeriesRegistry.d.ts +69 -0
  98. package/dist/types/telemetry/custom-implementations/metrics/tsdb/types.d.ts +68 -0
  99. package/dist/types/telemetry/custom-implementations/metrics/tsdb/utils.d.ts +21 -0
  100. package/dist/types/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.d.ts +2 -2
  101. package/dist/types/telemetry/custom-implementations/utils/storagePath.d.ts +12 -0
  102. package/dist/types/telemetry/custom-implementations/wrappers.d.ts +1 -1
  103. package/dist/types/telemetry/telemetryConfigurator.d.ts +1 -1
  104. package/dist/types/telemetry/telemetryRegistry.d.ts +8 -0
  105. package/dist/types/tlm-ai/agent.d.ts +1 -1
  106. package/dist/types/tlm-ai/aiService.d.ts +1 -1
  107. package/dist/types/tlm-log/logController.d.ts +2 -0
  108. package/dist/types/tlm-metric/metricsController.d.ts +16 -2
  109. package/dist/types/tlm-trace/traceController.d.ts +3 -1
  110. package/dist/types/types/index.d.ts +2 -2
  111. package/dist/ui/assets/{ApiDocsPage-C_VVPPHa.js → ApiDocsPage-BFUrXE5F.js} +2 -2
  112. package/dist/ui/assets/CollapsibleCard-STA1GVQO.js +1 -0
  113. package/dist/ui/assets/DevToolsPage-BRSfZqO_.js +1 -0
  114. package/dist/ui/assets/LandingPage-DzeDy7q7.js +6 -0
  115. package/dist/ui/assets/LogsPage-BeiFrV2X.js +1 -0
  116. package/dist/ui/assets/{NotFoundPage-B3quk3P1.js → NotFoundPage-fRNOatbM.js} +1 -1
  117. package/dist/ui/assets/PluginCreatePage-Ch_RXsdf.js +50 -0
  118. package/dist/ui/assets/PluginPage-Cl65ZZ_n.js +27 -0
  119. package/dist/ui/assets/TraceSpansPage-BoK4M5Hh.js +6 -0
  120. package/dist/ui/assets/VirtualizedListPanel-zcj0v7DL.js +16 -0
  121. package/dist/ui/assets/alert-BkNVKxJN.js +1133 -0
  122. package/dist/ui/assets/badge-CN7FeufU.js +1 -0
  123. package/dist/ui/assets/{chevron-down-CPsvsmqj.js → chevron-down-CG--ounh.js} +1 -1
  124. package/dist/ui/assets/{chevron-up-Df9jMo1X.js → chevron-up-B6tzMAOm.js} +1 -1
  125. package/dist/ui/assets/{circle-alert-DOPQPvU8.js → circle-alert-BDF8Tq9y.js} +1 -1
  126. package/dist/ui/assets/dialog-BrpWNk36.js +15 -0
  127. package/dist/ui/assets/index-6xOVKwKn.js +305 -0
  128. package/dist/ui/assets/index-D6f1KjWV.css +1 -0
  129. package/dist/ui/assets/index-D96rVSkR.js +1 -0
  130. package/dist/ui/assets/info-99kuqpbx.js +6 -0
  131. package/dist/ui/assets/{input-Dzvg_ZEZ.js → input-B-01QDg_.js} +1 -1
  132. package/dist/ui/assets/label-CQLeZjM1.js +1 -0
  133. package/dist/ui/assets/{loader-circle-CrvlRy5o.js → loader-circle-BoDGk-BO.js} +1 -1
  134. package/dist/ui/assets/{loginPage-qa4V-B70.js → loginPage-8F4EEd1B.js} +1 -1
  135. package/dist/ui/assets/metrics-page-D1GxaB_c.css +1 -0
  136. package/dist/ui/assets/metrics-page-DPtteXqY.js +31 -0
  137. package/dist/ui/assets/popover-DS_8DYYt.js +11 -0
  138. package/dist/ui/assets/select-DYjegiXi.js +6 -0
  139. package/dist/ui/assets/separator-DGsRxIrl.js +6 -0
  140. package/dist/ui/assets/severityOptions-DEOvJqC9.js +11 -0
  141. package/dist/ui/assets/square-pen-DPhgYz6O.js +6 -0
  142. package/dist/ui/assets/switch-Di9NJH2A.js +1 -0
  143. package/dist/ui/assets/trace-DJq1miYa.js +1 -0
  144. package/dist/ui/assets/upload-BiLTpCnX.js +11 -0
  145. package/dist/ui/assets/{utilService-DNyqzwj0.js → utilService-CNZOmadC.js} +1 -1
  146. package/dist/ui/assets/wand-sparkles-CPoBNFFg.js +6 -0
  147. package/dist/ui/index.html +2 -2
  148. package/package.json +44 -48
  149. package/dist/ui/assets/CollapsibleCard-B3KR_8mL.js +0 -1
  150. package/dist/ui/assets/DevToolsPage-OyZcDcmw.js +0 -1
  151. package/dist/ui/assets/LandingPage-CppFBA6K.js +0 -6
  152. package/dist/ui/assets/LogsPage-9Fq8GArS.js +0 -26
  153. package/dist/ui/assets/PluginCreatePage-X_aCH4t4.js +0 -50
  154. package/dist/ui/assets/PluginPage-DMDSihrZ.js +0 -27
  155. package/dist/ui/assets/alert-jQ9HCPIf.js +0 -1133
  156. package/dist/ui/assets/badge-CNq0-mH5.js +0 -1
  157. package/dist/ui/assets/card-DFAwwhN3.js +0 -1
  158. package/dist/ui/assets/index-BkD6DijD.js +0 -15
  159. package/dist/ui/assets/index-CERGVYZK.js +0 -292
  160. package/dist/ui/assets/index-CSIPf9qw.css +0 -1
  161. package/dist/ui/assets/label-DuVnkZ4q.js +0 -1
  162. package/dist/ui/assets/select-DhS8YUtJ.js +0 -1
  163. package/dist/ui/assets/separator-isK4chBP.js +0 -6
  164. package/dist/ui/assets/severityOptions-O38dSOfk.js +0 -11
  165. package/dist/ui/assets/switch-Z3mImG9n.js +0 -1
  166. package/dist/ui/assets/tabs-_77MUUQe.js +0 -16
  167. package/dist/ui/assets/upload-C1LT4Gkb.js +0 -16
@@ -1,37 +1,60 @@
1
- import { BatchSpanProcessor, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node';
2
- import { dynamicMultiLogProcessor, dynamicMultiSpanProcessor, inMemoryDbLogExporter, inMemoryDbMetricExporter, inMemoryDbSpanExporter, multiLogExporter, multiSpanExporter, oasTelemetryResource } from './telemetryRegistry.js';
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 { BatchLogRecordProcessor, SimpleLogRecordProcessor } from '@opentelemetry/sdk-logs';
5
- import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
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 const configureTelemetry = (oasTlmConfig) => {
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
- logger.info("✅ Telemetry configured successfully. All exporters are ready");
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 BatchSpanProcessor(mainExporter);
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 SimpleSpanProcessor(mainExporter);
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
- dynamicMultiSpanProcessor.addProcessors(mainProcessor);
34
- dynamicMultiSpanProcessor.addProcessors(oasTlmConfig.traces.extraProcessors);
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 BatchLogRecordProcessor(mainExporter);
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 SimpleLogRecordProcessor(mainExporter);
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
- dynamicMultiLogProcessor.addProcessors(mainProcessor);
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
- // Override console methods to emit logs via OpenTelemetry, like an instrumentation
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 = [];
@@ -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", extraPrompts = []) {
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 { conversationId } = req.params;
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 { conversationId } = req.params;
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 { conversationId } = req.params;
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, this.extraPrompts);
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;
@@ -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 new Promise((resolve, reject) => {
8
- inMemoryDbSpanExporter.find(search, (err, docs) => {
9
- if (err)
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: 50 // or any appropriate 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: oasTlmConfig.general.baseUrl + "/auth/refresh"
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: oasTlmConfig.general.baseUrl + '/auth/refresh' });
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
- items: docs,
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);