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

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 (158) hide show
  1. package/.env.example +50 -17
  2. package/README.md +244 -239
  3. package/dist/cjs/config/bootConfig.cjs +18 -0
  4. package/dist/cjs/config/config.cjs +145 -0
  5. package/dist/cjs/config/config.types.cjs +5 -0
  6. package/dist/cjs/index.cjs +19 -25
  7. package/dist/cjs/{tlmRoutes.cjs → routesManager.cjs} +28 -21
  8. package/dist/cjs/{exporters/InMemoryLogRecordExporter.cjs → telemetry/custom-implementations/exporters/InMemoryDbLogExporter.cjs} +42 -19
  9. package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.cjs +97 -0
  10. package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.cjs +118 -0
  11. package/dist/cjs/telemetry/custom-implementations/exporters/PluginLogExporter.cjs +45 -0
  12. package/dist/cjs/telemetry/custom-implementations/exporters/PluginMetricExporter.cjs +46 -0
  13. package/dist/cjs/telemetry/custom-implementations/exporters/PluginSpanExporter.cjs +61 -0
  14. package/dist/cjs/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.cjs +70 -0
  15. package/dist/cjs/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.cjs +70 -0
  16. package/dist/cjs/{utils → telemetry/custom-implementations/utils}/circular.cjs +39 -49
  17. package/dist/cjs/telemetry/custom-implementations/wrappers.cjs +175 -0
  18. package/dist/cjs/telemetry/initializeTelemetry.cjs +74 -0
  19. package/dist/cjs/telemetry/telemetryConfigurator.cjs +84 -0
  20. package/dist/cjs/telemetry/telemetryRegistry.cjs +40 -0
  21. package/dist/cjs/tlm-ai/agent.cjs +82 -63
  22. package/dist/cjs/tlm-ai/aiController.cjs +5 -4
  23. package/dist/cjs/tlm-ai/aiRoutes.cjs +9 -6
  24. package/dist/cjs/tlm-ai/tools.cjs +16 -9
  25. package/dist/cjs/tlm-auth/authController.cjs +14 -15
  26. package/dist/cjs/tlm-auth/authMiddleware.cjs +11 -10
  27. package/dist/cjs/tlm-auth/authRoutes.cjs +9 -7
  28. package/dist/cjs/tlm-log/logController.cjs +45 -18
  29. package/dist/cjs/tlm-log/logRoutes.cjs +16 -11
  30. package/dist/cjs/tlm-metric/metricsController.cjs +37 -12
  31. package/dist/cjs/tlm-metric/metricsRoutes.cjs +16 -11
  32. package/dist/cjs/tlm-plugin/pluginController.cjs +114 -75
  33. package/dist/cjs/tlm-plugin/pluginProcess.cjs +108 -0
  34. package/dist/cjs/tlm-plugin/pluginRoutes.cjs +11 -6
  35. package/dist/cjs/tlm-plugin/pluginService.cjs +79 -0
  36. package/dist/cjs/tlm-trace/traceController.cjs +54 -45
  37. package/dist/cjs/tlm-trace/traceRoutes.cjs +16 -11
  38. package/dist/cjs/tlm-ui/uiRoutes.cjs +26 -20
  39. package/dist/cjs/tlm-util/utilController.cjs +8 -9
  40. package/dist/cjs/tlm-util/utilRoutes.cjs +22 -19
  41. package/dist/cjs/types/index.cjs +0 -1
  42. package/dist/cjs/utils/logger.cjs +3 -5
  43. package/dist/cjs/utils/regexUtils.cjs +27 -0
  44. package/dist/esm/config/bootConfig.js +11 -0
  45. package/dist/esm/config/config.js +126 -0
  46. package/dist/esm/index.js +18 -29
  47. package/dist/esm/{tlmRoutes.js → routesManager.js} +27 -22
  48. package/dist/esm/{exporters/InMemoryLogRecordExporter.js → telemetry/custom-implementations/exporters/InMemoryDbLogExporter.js} +31 -17
  49. package/dist/esm/{exporters/InMemoryDBMetricsExporter.js → telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.js} +31 -17
  50. package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.js +105 -0
  51. package/dist/esm/telemetry/custom-implementations/exporters/PluginLogExporter.js +36 -0
  52. package/dist/esm/telemetry/custom-implementations/exporters/PluginMetricExporter.js +35 -0
  53. package/dist/esm/telemetry/custom-implementations/exporters/PluginSpanExporter.js +52 -0
  54. package/dist/esm/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.js +64 -0
  55. package/dist/esm/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.js +64 -0
  56. package/dist/esm/telemetry/custom-implementations/utils/circular.js +76 -0
  57. package/dist/esm/telemetry/custom-implementations/wrappers.js +163 -0
  58. package/dist/esm/telemetry/initializeTelemetry.js +71 -0
  59. package/dist/esm/telemetry/telemetryConfigurator.js +74 -0
  60. package/dist/esm/telemetry/telemetryRegistry.js +34 -0
  61. package/dist/esm/tlm-ai/agent.js +77 -59
  62. package/dist/esm/tlm-ai/aiController.js +5 -4
  63. package/dist/esm/tlm-ai/aiRoutes.js +7 -5
  64. package/dist/esm/tlm-ai/tools.js +18 -9
  65. package/dist/esm/tlm-auth/authController.js +9 -10
  66. package/dist/esm/tlm-auth/authMiddleware.js +10 -9
  67. package/dist/esm/tlm-auth/authRoutes.js +8 -6
  68. package/dist/esm/tlm-log/logController.js +36 -16
  69. package/dist/esm/tlm-log/logRoutes.js +15 -11
  70. package/dist/esm/tlm-metric/metricsController.js +29 -10
  71. package/dist/esm/tlm-metric/metricsRoutes.js +15 -11
  72. package/dist/esm/tlm-plugin/pluginController.js +112 -77
  73. package/dist/esm/tlm-plugin/pluginProcess.js +101 -0
  74. package/dist/esm/tlm-plugin/pluginRoutes.js +10 -6
  75. package/dist/esm/tlm-plugin/pluginService.js +73 -0
  76. package/dist/esm/tlm-trace/traceController.js +40 -35
  77. package/dist/esm/tlm-trace/traceRoutes.js +15 -11
  78. package/dist/esm/tlm-ui/uiRoutes.js +24 -19
  79. package/dist/esm/tlm-util/utilController.js +8 -9
  80. package/dist/esm/tlm-util/utilRoutes.js +17 -15
  81. package/dist/esm/types/index.js +0 -1
  82. package/dist/esm/utils/logger.js +3 -4
  83. package/dist/esm/utils/regexUtils.js +23 -0
  84. package/dist/types/config/bootConfig.d.ts +5 -0
  85. package/dist/types/config/config.d.ts +858 -0
  86. package/dist/types/config/config.types.d.ts +34 -0
  87. package/dist/types/index.d.ts +5 -4
  88. package/dist/types/routesManager.d.ts +3 -0
  89. package/dist/types/{exporters/InMemoryLogRecordExporter.d.ts → telemetry/custom-implementations/exporters/InMemoryDbLogExporter.d.ts} +6 -6
  90. package/dist/types/{exporters/InMemoryDBMetricsExporter.d.ts → telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.d.ts} +7 -7
  91. package/dist/types/{exporters/InMemoryDbExporter.d.ts → telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.d.ts} +9 -9
  92. package/dist/types/telemetry/custom-implementations/exporters/PluginLogExporter.d.ts +8 -0
  93. package/dist/types/telemetry/custom-implementations/exporters/PluginMetricExporter.d.ts +12 -0
  94. package/dist/types/telemetry/custom-implementations/exporters/PluginSpanExporter.d.ts +14 -0
  95. package/dist/types/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.d.ts +32 -0
  96. package/dist/types/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.d.ts +34 -0
  97. package/dist/types/telemetry/custom-implementations/utils/circular.d.ts +27 -0
  98. package/dist/types/telemetry/custom-implementations/wrappers.d.ts +52 -0
  99. package/dist/types/telemetry/initializeTelemetry.d.ts +1 -0
  100. package/dist/types/telemetry/telemetryConfigurator.d.ts +2 -0
  101. package/dist/types/telemetry/telemetryRegistry.d.ts +20 -0
  102. package/dist/types/tlm-ai/agent.d.ts +2 -1
  103. package/dist/types/tlm-ai/aiController.d.ts +4 -3
  104. package/dist/types/tlm-ai/aiRoutes.d.ts +2 -2
  105. package/dist/types/tlm-ai/tools.d.ts +3 -1
  106. package/dist/types/tlm-auth/authController.d.ts +4 -3
  107. package/dist/types/tlm-auth/authMiddleware.d.ts +2 -1
  108. package/dist/types/tlm-auth/authRoutes.d.ts +2 -2
  109. package/dist/types/tlm-log/logController.d.ts +1 -0
  110. package/dist/types/tlm-log/logRoutes.d.ts +2 -2
  111. package/dist/types/tlm-metric/metricsController.d.ts +1 -0
  112. package/dist/types/tlm-metric/metricsRoutes.d.ts +2 -2
  113. package/dist/types/tlm-plugin/pluginController.d.ts +4 -1
  114. package/dist/types/tlm-plugin/pluginProcess.d.ts +1 -0
  115. package/dist/types/tlm-plugin/pluginRoutes.d.ts +1 -2
  116. package/dist/types/tlm-plugin/pluginService.d.ts +24 -0
  117. package/dist/types/tlm-trace/traceController.d.ts +7 -6
  118. package/dist/types/tlm-trace/traceRoutes.d.ts +2 -2
  119. package/dist/types/tlm-ui/uiRoutes.d.ts +1 -2
  120. package/dist/types/tlm-util/utilController.d.ts +2 -1
  121. package/dist/types/tlm-util/utilRoutes.d.ts +2 -2
  122. package/dist/types/types/index.d.ts +17 -47
  123. package/dist/types/utils/regexUtils.d.ts +1 -0
  124. package/dist/ui/assets/index-BzIdRox6.js +1733 -0
  125. package/dist/ui/assets/index-CkoHzrrt.css +1 -0
  126. package/dist/ui/index.html +3 -3
  127. package/dist/ui/oas-tlm.svg +185 -0
  128. package/package.json +12 -7
  129. package/dist/cjs/config.cjs +0 -31
  130. package/dist/cjs/exporters/InMemoryDBMetricsExporter.cjs +0 -74
  131. package/dist/cjs/exporters/InMemoryDbExporter.cjs +0 -102
  132. package/dist/cjs/exporters/consoleExporter.cjs +0 -47
  133. package/dist/cjs/exporters/dynamicExporter.cjs +0 -57
  134. package/dist/cjs/instrumentation/index.cjs +0 -28
  135. package/dist/cjs/instrumentation/logs.cjs +0 -46
  136. package/dist/cjs/instrumentation/metrics.cjs +0 -27
  137. package/dist/cjs/instrumentation/traces.cjs +0 -19
  138. package/dist/esm/config.js +0 -20
  139. package/dist/esm/exporters/InMemoryDbExporter.js +0 -102
  140. package/dist/esm/exporters/consoleExporter.js +0 -38
  141. package/dist/esm/exporters/dynamicExporter.js +0 -50
  142. package/dist/esm/instrumentation/index.js +0 -26
  143. package/dist/esm/instrumentation/logs.js +0 -34
  144. package/dist/esm/instrumentation/metrics.js +0 -18
  145. package/dist/esm/instrumentation/traces.js +0 -12
  146. package/dist/esm/utils/circular.js +0 -84
  147. package/dist/types/config.d.ts +0 -6
  148. package/dist/types/exporters/consoleExporter.d.ts +0 -13
  149. package/dist/types/exporters/dynamicExporter.d.ts +0 -25
  150. package/dist/types/instrumentation/logs.d.ts +0 -1
  151. package/dist/types/instrumentation/metrics.d.ts +0 -1
  152. package/dist/types/instrumentation/traces.d.ts +0 -1
  153. package/dist/types/tlmRoutes.d.ts +0 -2
  154. package/dist/types/utils/circular.d.ts +0 -31
  155. package/dist/ui/assets/index-BNhZBPi2.css +0 -1
  156. package/dist/ui/assets/index-DxGAMrAl.js +0 -401
  157. package/dist/ui/vite.svg +0 -1
  158. /package/dist/{types/instrumentation/index.d.ts → esm/config/config.types.js} +0 -0
@@ -0,0 +1,101 @@
1
+ // pluginProcess.js
2
+ // Runs inside a child process, isolated from the main app
3
+ // @ts-expect-error no types
4
+ import { importFromString, requireFromString } from "import-from-string";
5
+ import { installDependencies } from "dynamic-installer";
6
+ let plugin;
7
+ const log = (...args) => {
8
+ console.log(`[PluginProcess:${process.pid}]`, ...args);
9
+ };
10
+ process.on("message", async (msg) => {
11
+ if (msg.type === "load") {
12
+ try {
13
+ const pluginResource = normalizePluginResource(msg.pluginResource);
14
+ if (pluginResource.install && Array.isArray(pluginResource.install.dependencies) && pluginResource.install.dependencies.length > 0) {
15
+ log("Installing dependencies for plugin: " + pluginResource.name);
16
+ const dependenciesStatus = await installDependencies(pluginResource.install);
17
+ if (!dependenciesStatus.success) {
18
+ if (pluginResource.install.ignoreErrors === true) {
19
+ log(`Warning: Error installing dependencies: ${JSON.stringify(dependenciesStatus.details)}`);
20
+ }
21
+ else {
22
+ process.send?.({ event: "error", error: `Error installing dependencies: ${JSON.stringify(dependenciesStatus.details)}` });
23
+ return;
24
+ }
25
+ }
26
+ }
27
+ let module;
28
+ if (pluginResource?.moduleFormat?.toLowerCase() === "esm") {
29
+ module = await importFromString(pluginResource.sourceCode);
30
+ }
31
+ else {
32
+ module = await requireFromString(pluginResource.sourceCode);
33
+ }
34
+ plugin = module.default?.plugin ?? module.plugin;
35
+ if (!plugin)
36
+ throw new Error("Plugin must export a valid 'plugin' object");
37
+ for (const fn of ["load", "isConfigured"]) {
38
+ if (typeof plugin[fn] !== "function") {
39
+ throw new Error(`Plugin is missing required function "${fn}"`);
40
+ }
41
+ }
42
+ await plugin.load(pluginResource.config);
43
+ if (!plugin.isConfigured()) {
44
+ throw new Error("Plugin could not be configured");
45
+ }
46
+ process.send?.({ event: "loaded", name: pluginResource.name || pluginResource.id || "unknown" });
47
+ }
48
+ catch (err) {
49
+ process.send?.({ event: "error", error: err.message });
50
+ process.exit(1);
51
+ }
52
+ }
53
+ // Forward log/metric/trace calls
54
+ if (msg.type === "newLog" && plugin?.newLog) {
55
+ plugin.newLog(msg.payload);
56
+ }
57
+ if (msg.type === "newMetric" && plugin?.newMetric) {
58
+ plugin.newMetric(msg.payload);
59
+ }
60
+ if (msg.type === "newTrace" && plugin?.newTrace) {
61
+ plugin.newTrace(msg.payload);
62
+ }
63
+ if (msg.type === "unload") {
64
+ if (plugin && typeof plugin.unload === "function") {
65
+ await plugin.unload();
66
+ }
67
+ process.send?.({ event: "unloaded" });
68
+ process.exit(0);
69
+ }
70
+ });
71
+ function normalizePluginResource(raw) {
72
+ let resource = raw;
73
+ // case: received as stringified JSON
74
+ if (typeof raw === "string") {
75
+ try {
76
+ resource = JSON.parse(raw);
77
+ }
78
+ catch (err) {
79
+ throw new Error("Invalid pluginResource JSON: " + err.message);
80
+ }
81
+ }
82
+ // normalize install
83
+ if (typeof resource.install === "string") {
84
+ try {
85
+ resource.install = JSON.parse(resource.install);
86
+ }
87
+ catch (err) {
88
+ throw new Error("Invalid install JSON: " + err.message);
89
+ }
90
+ }
91
+ // normalize config
92
+ if (typeof resource.config === "string") {
93
+ try {
94
+ resource.config = JSON.parse(resource.config);
95
+ }
96
+ catch (err) {
97
+ throw new Error("Invalid config JSON: " + err.message);
98
+ }
99
+ }
100
+ return resource;
101
+ }
@@ -1,7 +1,11 @@
1
1
  import { Router } from 'express';
2
- import { listPlugins, registerPlugin } from './pluginController.js';
3
- export const pluginRoutes = Router();
4
- // Plugins
5
- pluginRoutes.get('/plugins', listPlugins);
6
- pluginRoutes.post('/plugins', registerPlugin);
7
- export default pluginRoutes;
2
+ import { listPlugins, registerPlugin, activatePlugin, deactivatePlugin, deletePlugin } from './pluginController.js';
3
+ export const getPluginRoutes = () => {
4
+ const router = Router();
5
+ router.get('/', listPlugins);
6
+ router.post('/', registerPlugin);
7
+ router.post('/:id/activate', activatePlugin);
8
+ router.post('/:id/deactivate', deactivatePlugin);
9
+ router.delete('/:id', deletePlugin);
10
+ return router;
11
+ };
@@ -0,0 +1,73 @@
1
+ import logger from "../utils/logger.js";
2
+ class PluginService {
3
+ constructor() {
4
+ this.plugins = [];
5
+ }
6
+ getPlugins() {
7
+ return this.plugins;
8
+ }
9
+ pushPlugin(plugin) {
10
+ this.plugins.push(plugin);
11
+ }
12
+ activatePlugin(pluginId) {
13
+ const plugin = this.plugins.find((p) => p.id === pluginId);
14
+ if (plugin) {
15
+ plugin.active = true;
16
+ }
17
+ }
18
+ deactivatePlugin(pluginId) {
19
+ const plugin = this.plugins.find((p) => p.id === pluginId);
20
+ if (plugin) {
21
+ plugin.active = false;
22
+ }
23
+ }
24
+ deletePlugin(pluginId) {
25
+ const plugin = this.plugins.find((p) => p.id === pluginId);
26
+ if (plugin?.process && !plugin.process.killed) {
27
+ plugin.process.kill(1);
28
+ }
29
+ this.plugins = this.plugins.filter((p) => p.id !== pluginId);
30
+ }
31
+ broadcastToPlugins(type, payload) {
32
+ this.plugins.forEach((plugin, i) => {
33
+ if (!plugin.active)
34
+ return;
35
+ if (plugin.process) {
36
+ if (plugin.process.connected) {
37
+ try {
38
+ plugin.process.send({ type, payload });
39
+ logger.debug(`Sent ${type} to child-process plugin <${plugin.name}> (#${i})`);
40
+ }
41
+ catch (err) {
42
+ logger.error(`Failed to send ${type} to plugin <${plugin.name}> (#${i}):`, err);
43
+ }
44
+ }
45
+ else {
46
+ logger.warn(`Plugin <${plugin.name}> (#${i}) is not connected. Skipping ${type}.`);
47
+ }
48
+ }
49
+ else {
50
+ logger.debug(`Plugin <${plugin.name}> does not implement ${type}. Skipping.`);
51
+ }
52
+ });
53
+ }
54
+ /**
55
+ * Broadcast a new metric to all active plugins
56
+ */
57
+ broadcastMetric(metric) {
58
+ this.broadcastToPlugins("newMetric", metric);
59
+ }
60
+ /**
61
+ * Broadcast a new log to all active plugins
62
+ */
63
+ broadcastLog(log) {
64
+ this.broadcastToPlugins("newLog", log);
65
+ }
66
+ /**
67
+ * Broadcast a new trace to all active plugins
68
+ */
69
+ broadcastTrace(trace) {
70
+ this.broadcastToPlugins("newTrace", trace);
71
+ }
72
+ }
73
+ export const pluginService = new PluginService();
@@ -1,52 +1,48 @@
1
- import { globalOasTlmConfig } from '../config.js';
2
- export const startTelemetry = (req, res) => {
3
- globalOasTlmConfig.dynamicSpanExporter.exporter.start();
4
- res.send('Telemetry started');
1
+ import { inMemoryDbSpanExporter } from '../telemetry/telemetryRegistry.js';
2
+ import { convertRegexRecursively } from '../utils/regexUtils.js';
3
+ export const startTraces = (req, res) => {
4
+ inMemoryDbSpanExporter.enable();
5
+ res.send('Traces started');
5
6
  };
6
- export const stopTelemetry = (req, res) => {
7
- globalOasTlmConfig.dynamicSpanExporter.exporter.stop();
8
- res.send('Telemetry stopped');
7
+ export const stopTraces = (req, res) => {
8
+ inMemoryDbSpanExporter.disable();
9
+ res.send('Traces stopped');
9
10
  };
10
- export const statusTelemetry = (req, res) => {
11
- const isRunning = globalOasTlmConfig.dynamicSpanExporter.exporter.isRunning() || false;
11
+ export const statusTraces = (req, res) => {
12
+ const isRunning = inMemoryDbSpanExporter.isEnabled() || false;
12
13
  res.send({ active: isRunning });
13
14
  };
14
- export const resetTelemetry = (req, res) => {
15
- globalOasTlmConfig.dynamicSpanExporter.exporter.reset();
16
- res.send('Telemetry reset');
15
+ export const resetTraces = (req, res) => {
16
+ inMemoryDbSpanExporter.reset();
17
+ res.send('Traces reset');
17
18
  };
18
- export const listTelemetry = async (req, res) => {
19
+ export const listTraces = async (req, res) => {
19
20
  try {
20
- const spans = await globalOasTlmConfig.dynamicSpanExporter.exporter.getFinishedSpans();
21
+ const spans = inMemoryDbSpanExporter.getFinishedSpans();
21
22
  res.send({ spansCount: spans.length, spans: spans });
22
23
  }
23
24
  catch (err) {
24
25
  console.error(err);
25
- res.status(500).send({ error: 'Failed to list telemetry data' });
26
+ res.status(500).send({ error: 'Failed to list traces data' });
26
27
  }
27
28
  };
28
- export const findTelemetry = (req, res) => {
29
+ export const findTraces = (req, res) => {
29
30
  const body = req.body;
30
- const search = body?.search ? body.search : {};
31
- if (body?.flags?.containsRegex) {
32
- try {
33
- //@ts-expect-error yes
34
- body.config?.regexIds?.forEach(regexId => {
35
- if (search[regexId])
36
- search[regexId] = new RegExp(search[regexId]);
37
- });
38
- }
39
- catch (e) {
40
- console.error(e);
41
- res.status(404).send({ spansCount: 0, spans: [], error: e });
42
- return;
43
- }
31
+ const query = body?.query ? body.query : {};
32
+ let processedQuery;
33
+ try {
34
+ processedQuery = convertRegexRecursively(query);
44
35
  }
45
- globalOasTlmConfig.dynamicSpanExporter.exporter.find(search, (err, docs) => {
36
+ catch (error) {
37
+ console.error(error.message);
38
+ res.status(400).send({ error: error.message });
39
+ return; // Exit if invalid regex was encountered
40
+ }
41
+ inMemoryDbSpanExporter.find(processedQuery, (err, docs) => {
46
42
  if (err) {
47
43
  console.error(err);
48
- res.status(404).send({ spansCount: 0, spans: [], error: err });
49
- return;
44
+ res.status(404).send({ spansCount: 0, spans: [], error: err.message });
45
+ return; // Exit the function to prevent further execution
50
46
  }
51
47
  const spans = docs;
52
48
  res.send({ spansCount: spans.length, spans: spans });
@@ -67,11 +63,11 @@ export const insertTracesToDb = async (req, res) => {
67
63
  try {
68
64
  let message = '';
69
65
  if (resetData) {
70
- globalOasTlmConfig.dynamicSpanExporter.exporter.reset();
66
+ inMemoryDbSpanExporter.reset();
71
67
  message += 'Traces Database reset. ';
72
68
  }
73
69
  await new Promise((resolve, reject) => {
74
- globalOasTlmConfig.dynamicSpanExporter.exporter.insert(cleanedTraces, (err, newDocs) => {
70
+ inMemoryDbSpanExporter.insert(cleanedTraces, (err, newDocs) => {
75
71
  if (err) {
76
72
  console.error('Error inserting traces:', err);
77
73
  return reject(err);
@@ -87,3 +83,12 @@ export const insertTracesToDb = async (req, res) => {
87
83
  res.status(500).send({ error: 'Failed to reset and insert data', details: err.message });
88
84
  }
89
85
  };
86
+ export const setRetentionTimeTraces = (req, res) => {
87
+ const retentionTime = req.body.retentionTime;
88
+ if (typeof retentionTime !== 'number' || retentionTime <= 0) {
89
+ res.status(400).send({ error: 'Invalid retention time. Must be a positive number.' });
90
+ return;
91
+ }
92
+ inMemoryDbSpanExporter.retentionTimeInSeconds = retentionTime;
93
+ res.send({ message: `Retention time set to ${retentionTime} seconds.` });
94
+ };
@@ -1,12 +1,16 @@
1
1
  import { Router } from 'express';
2
- import { startTelemetry, stopTelemetry, statusTelemetry, resetTelemetry, listTelemetry, findTelemetry, insertTracesToDb } from './traceController.js';
3
- export const traceRoutes = Router();
4
- traceRoutes.get('/', listTelemetry);
5
- traceRoutes.post('/', insertTracesToDb);
6
- traceRoutes.post('/find', findTelemetry);
7
- // Telemetry Control
8
- traceRoutes.get('/start', startTelemetry);
9
- traceRoutes.get('/stop', stopTelemetry);
10
- traceRoutes.get('/status', statusTelemetry);
11
- traceRoutes.get('/reset', resetTelemetry);
12
- export default traceRoutes;
2
+ import { startTraces, stopTraces, statusTraces, resetTraces, listTraces, findTraces, insertTracesToDb, setRetentionTimeTraces } from './traceController.js';
3
+ export const getTraceRoutes = () => {
4
+ const router = Router();
5
+ // Telemetry Control
6
+ router.post('/start', startTraces);
7
+ router.post('/stop', stopTraces);
8
+ router.get('/status', statusTraces);
9
+ router.post('/reset', resetTraces);
10
+ router.get('/', listTraces);
11
+ router.post('/', insertTracesToDb);
12
+ router.post('/find', findTraces);
13
+ router.post('/retention-time', setRetentionTimeTraces);
14
+ return router;
15
+ };
16
+ export default getTraceRoutes;
@@ -2,22 +2,27 @@ import express, { Router } from 'express';
2
2
  import path from 'path';
3
3
  import { fileURLToPath } from 'url';
4
4
  import logger from '../utils/logger.js';
5
- let relativePath = '../../ui';
6
- if (process.env.OASTLM_ENV === 'development') {
7
- relativePath = '../../dist/ui';
8
- logger.warn('🚧 This process is serving the OASTLM UI from the build directory, but you are in development mode. For live updates, run the React app separately and access it at http://localhost:5173/.');
9
- }
10
- const customFilename = fileURLToPath(import.meta.url);
11
- const customDirname = path.dirname(customFilename);
12
- const staticFilesPath = path.join(customDirname, relativePath);
13
- export const uiRoutes = Router();
14
- // This only works once the app is built: src/ --> dist/esm/
15
- // This file: dist/esm/routes/
16
- // UI bundle: dist/ui/
17
- // For development, the UI is served separately.
18
- uiRoutes.use(express.static(staticFilesPath));
19
- uiRoutes.get('*', (_req, res) => {
20
- // Serve the index.html file for all routes
21
- res.sendFile(path.join(staticFilesPath, 'index.html'));
22
- });
23
- export default uiRoutes;
5
+ import { bootEnvVariables } from '../config/bootConfig.js';
6
+ export const getUIRoutes = () => {
7
+ // This is when this file is in /dist
8
+ let relativePath = '../../ui';
9
+ // This is when this file in in /src
10
+ if (bootEnvVariables.OASTLM_BOOT_ENV === 'development') {
11
+ relativePath = '../../dist/ui';
12
+ logger.warn('🚧 This process is serving the OASTLM UI from the build directory, but you are in development mode. For live updates, run the React app separately and access it at http://localhost:5173/.');
13
+ }
14
+ const customFilename = fileURLToPath(import.meta.url);
15
+ const customDirname = path.dirname(customFilename);
16
+ const staticFilesPath = path.join(customDirname, relativePath);
17
+ const router = Router();
18
+ // This only works once the app is built: src/ --> dist/esm/
19
+ // This file: dist/esm/routes/
20
+ // UI bundle: dist/ui/
21
+ // For development, the UI is served separately.
22
+ router.use(express.static(staticFilesPath));
23
+ router.get('*', (_req, res) => {
24
+ // Serve the index.html file for all routes
25
+ res.sendFile(path.join(staticFilesPath, 'index.html'));
26
+ });
27
+ return router;
28
+ };
@@ -1,13 +1,12 @@
1
- import { globalOasTlmConfig } from '../config.js';
2
1
  import { readFileSync } from 'fs';
3
2
  import path from 'path';
4
3
  import yaml from 'js-yaml';
5
4
  import v8 from 'node:v8';
6
- export const specLoader = (_req, res) => {
7
- if (globalOasTlmConfig.specFileName) {
5
+ export const specLoader = (_req, res, oasTlmConfig) => {
6
+ if (oasTlmConfig.general.specFileName) {
8
7
  try {
9
- const data = readFileSync(globalOasTlmConfig.specFileName, { encoding: 'utf8', flag: 'r' });
10
- const extension = path.extname(globalOasTlmConfig.specFileName);
8
+ const data = readFileSync(oasTlmConfig.general.specFileName, { encoding: 'utf8', flag: 'r' });
9
+ const extension = path.extname(oasTlmConfig.general.specFileName);
11
10
  let json = data;
12
11
  if (extension == "yaml")
13
12
  //@ts-expect-error yes
@@ -16,17 +15,17 @@ export const specLoader = (_req, res) => {
16
15
  res.send(json);
17
16
  }
18
17
  catch (e) {
19
- console.error(`ERROR loading spec file ${globalOasTlmConfig.specFileName}: ${e}`);
18
+ console.error(`ERROR loading spec file ${oasTlmConfig.general.specFileName}: ${e}`);
20
19
  }
21
20
  }
22
- else if (globalOasTlmConfig.spec) {
21
+ else if (oasTlmConfig.general.spec) {
23
22
  let spec = null;
24
23
  try {
25
- spec = JSON.parse(globalOasTlmConfig.spec);
24
+ spec = JSON.parse(oasTlmConfig.general.spec);
26
25
  }
27
26
  catch (ej) {
28
27
  try {
29
- spec = JSON.stringify(yaml.load(globalOasTlmConfig.spec), null, 2);
28
+ spec = JSON.stringify(yaml.load(oasTlmConfig.general.spec), null, 2);
30
29
  }
31
30
  catch (ey) {
32
31
  console.error(`Error parsing spec: ${ej} - ${ey}`);
@@ -1,17 +1,19 @@
1
1
  import { Router } from 'express';
2
2
  import { specLoader, heapStats } from './utilController.js';
3
- export const utilsRoutes = Router();
4
- utilsRoutes.get('/spec', specLoader);
5
- utilsRoutes.get('/heapStats', heapStats);
6
- utilsRoutes.get('/generateLog', (req, res) => {
7
- const log = req.query.log || 'Default log message';
8
- console.log('Generated log:', log);
9
- res.send({ message: 'Log generated', log: log });
10
- });
11
- utilsRoutes.get('/wait/:seconds?', async (req, res) => {
12
- const seconds = parseInt(req.params.seconds ?? "1", 10);
13
- const waitTime = isNaN(seconds) ? 1 : seconds;
14
- await new Promise(resolve => setTimeout(resolve, waitTime * 1000));
15
- res.send({ waited: waitTime });
16
- });
17
- export default utilsRoutes;
3
+ export const getUtilsRoutes = (oasTlmConfig) => {
4
+ const router = Router();
5
+ router.get('/spec', (req, res) => specLoader(req, res, oasTlmConfig));
6
+ router.get('/heapStats', heapStats);
7
+ router.get('/generateLog', (req, res) => {
8
+ const log = req.query.log || 'Default log message';
9
+ console.log(log);
10
+ res.send({ message: 'Log generated', log: log });
11
+ });
12
+ router.get('/wait/:seconds?', async (req, res) => {
13
+ const seconds = parseInt(req.params.seconds ?? "1", 10);
14
+ const waitTime = isNaN(seconds) ? 1 : seconds;
15
+ await new Promise(resolve => setTimeout(resolve, waitTime * 1000));
16
+ res.send({ waited: waitTime });
17
+ });
18
+ return router;
19
+ };
@@ -1,4 +1,3 @@
1
1
  ;
2
2
  ;
3
- ;
4
3
  export {};
@@ -1,8 +1,7 @@
1
- import dotenv from 'dotenv';
2
- dotenv.config();
1
+ import { bootEnvVariables } from "../config/bootConfig.js";
3
2
  const LOG_LEVELS = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE'];
4
- const currentLogLevel = (process.env.OASTLM_LOG_LEVEL || 'INFO').toUpperCase();
5
- const serviceName = process.env.OASTLM_SERVICE_NAME || 'OAS-TLM';
3
+ const currentLogLevel = (bootEnvVariables.OASTLM_BOOT_LOG_LEVEL || 'INFO').toUpperCase();
4
+ const serviceName = 'OAS-Telemetry';
6
5
  function log(level, ...messages) {
7
6
  if (LOG_LEVELS.indexOf(level) >= LOG_LEVELS.indexOf(currentLogLevel)) {
8
7
  const timestamp = new Date().toISOString();
@@ -0,0 +1,23 @@
1
+ export const convertRegexRecursively = (obj) => {
2
+ if (Array.isArray(obj)) {
3
+ return obj.map(convertRegexRecursively);
4
+ }
5
+ else if (obj && typeof obj === 'object') {
6
+ const newObj = {};
7
+ for (const key of Object.keys(obj)) {
8
+ if (key === '$regex' && typeof obj[key] === 'string') {
9
+ try {
10
+ return new RegExp(obj[key]);
11
+ }
12
+ catch {
13
+ throw new Error(`Invalid regex value "${obj[key]}"`);
14
+ }
15
+ }
16
+ else {
17
+ newObj[key] = convertRegexRecursively(obj[key]);
18
+ }
19
+ }
20
+ return newObj;
21
+ }
22
+ return obj;
23
+ };
@@ -0,0 +1,5 @@
1
+ export declare const bootEnvVariables: {
2
+ OASTLM_BOOT_ENV: string;
3
+ OASTLM_BOOT_MODULE_DISABLED: boolean;
4
+ OASTLM_BOOT_LOG_LEVEL: string;
5
+ };