@oas-tools/oas-telemetry 0.7.0-alpha.2 → 0.7.0-alpha.3
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 +50 -17
- package/README.md +242 -240
- package/dist/cjs/config/bootConfig.cjs +18 -0
- package/dist/cjs/config/config.cjs +145 -0
- package/dist/cjs/config/config.types.cjs +5 -0
- package/dist/cjs/index.cjs +19 -25
- package/dist/cjs/{tlmRoutes.cjs → routesManager.cjs} +28 -21
- package/dist/cjs/{exporters/InMemoryLogRecordExporter.cjs → telemetry/custom-implementations/exporters/InMemoryDbLogExporter.cjs} +42 -19
- package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.cjs +97 -0
- package/dist/cjs/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.cjs +118 -0
- package/dist/cjs/telemetry/custom-implementations/exporters/PluginLogExporter.cjs +52 -0
- package/dist/cjs/telemetry/custom-implementations/exporters/PluginMetricExporter.cjs +53 -0
- package/dist/cjs/telemetry/custom-implementations/exporters/PluginSpanExporter.cjs +69 -0
- package/dist/cjs/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.cjs +70 -0
- package/dist/cjs/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.cjs +70 -0
- package/dist/cjs/{utils → telemetry/custom-implementations/utils}/circular.cjs +39 -49
- package/dist/cjs/telemetry/custom-implementations/wrappers.cjs +175 -0
- package/dist/cjs/telemetry/initializeTelemetry.cjs +74 -0
- package/dist/cjs/telemetry/telemetryConfigurator.cjs +84 -0
- package/dist/cjs/telemetry/telemetryRegistry.cjs +40 -0
- package/dist/cjs/tlm-ai/agent.cjs +82 -63
- package/dist/cjs/tlm-ai/aiController.cjs +5 -4
- package/dist/cjs/tlm-ai/aiRoutes.cjs +9 -6
- package/dist/cjs/tlm-ai/tools.cjs +16 -9
- package/dist/cjs/tlm-auth/authController.cjs +14 -15
- package/dist/cjs/tlm-auth/authMiddleware.cjs +11 -10
- package/dist/cjs/tlm-auth/authRoutes.cjs +9 -7
- package/dist/cjs/tlm-log/logController.cjs +45 -18
- package/dist/cjs/tlm-log/logRoutes.cjs +16 -11
- package/dist/cjs/tlm-metric/metricsController.cjs +37 -12
- package/dist/cjs/tlm-metric/metricsRoutes.cjs +16 -11
- package/dist/cjs/tlm-plugin/pluginController.cjs +40 -19
- package/dist/cjs/tlm-plugin/pluginRoutes.cjs +8 -6
- package/dist/cjs/tlm-plugin/pluginService.cjs +25 -0
- package/dist/cjs/tlm-trace/traceController.cjs +54 -45
- package/dist/cjs/tlm-trace/traceRoutes.cjs +16 -11
- package/dist/cjs/tlm-ui/uiRoutes.cjs +26 -20
- package/dist/cjs/tlm-util/utilController.cjs +8 -9
- package/dist/cjs/tlm-util/utilRoutes.cjs +22 -19
- package/dist/cjs/types/index.cjs +0 -1
- package/dist/cjs/utils/logger.cjs +3 -5
- package/dist/cjs/utils/regexUtils.cjs +27 -0
- package/dist/esm/config/bootConfig.js +11 -0
- package/dist/esm/config/config.js +126 -0
- package/dist/esm/index.js +18 -29
- package/dist/esm/{tlmRoutes.js → routesManager.js} +27 -22
- package/dist/esm/{exporters/InMemoryLogRecordExporter.js → telemetry/custom-implementations/exporters/InMemoryDbLogExporter.js} +31 -17
- package/dist/esm/{exporters/InMemoryDBMetricsExporter.js → telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.js} +31 -17
- package/dist/esm/telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.js +105 -0
- package/dist/esm/telemetry/custom-implementations/exporters/PluginLogExporter.js +44 -0
- package/dist/esm/telemetry/custom-implementations/exporters/PluginMetricExporter.js +43 -0
- package/dist/esm/telemetry/custom-implementations/exporters/PluginSpanExporter.js +61 -0
- package/dist/esm/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.js +64 -0
- package/dist/esm/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.js +64 -0
- package/dist/esm/telemetry/custom-implementations/utils/circular.js +76 -0
- package/dist/esm/telemetry/custom-implementations/wrappers.js +163 -0
- package/dist/esm/telemetry/initializeTelemetry.js +71 -0
- package/dist/esm/telemetry/telemetryConfigurator.js +74 -0
- package/dist/esm/telemetry/telemetryRegistry.js +34 -0
- package/dist/esm/tlm-ai/agent.js +77 -59
- package/dist/esm/tlm-ai/aiController.js +5 -4
- package/dist/esm/tlm-ai/aiRoutes.js +7 -5
- package/dist/esm/tlm-ai/tools.js +18 -9
- package/dist/esm/tlm-auth/authController.js +9 -10
- package/dist/esm/tlm-auth/authMiddleware.js +10 -9
- package/dist/esm/tlm-auth/authRoutes.js +8 -6
- package/dist/esm/tlm-log/logController.js +36 -16
- package/dist/esm/tlm-log/logRoutes.js +15 -11
- package/dist/esm/tlm-metric/metricsController.js +29 -10
- package/dist/esm/tlm-metric/metricsRoutes.js +15 -11
- package/dist/esm/tlm-plugin/pluginController.js +40 -19
- package/dist/esm/tlm-plugin/pluginRoutes.js +6 -5
- package/dist/esm/tlm-plugin/pluginService.js +19 -0
- package/dist/esm/tlm-trace/traceController.js +40 -35
- package/dist/esm/tlm-trace/traceRoutes.js +15 -11
- package/dist/esm/tlm-ui/uiRoutes.js +24 -19
- package/dist/esm/tlm-util/utilController.js +8 -9
- package/dist/esm/tlm-util/utilRoutes.js +17 -15
- package/dist/esm/types/index.js +0 -1
- package/dist/esm/utils/logger.js +3 -4
- package/dist/esm/utils/regexUtils.js +23 -0
- package/dist/types/config/bootConfig.d.ts +5 -0
- package/dist/types/config/config.d.ts +253 -0
- package/dist/types/config/config.types.d.ts +34 -0
- package/dist/types/index.d.ts +5 -4
- package/dist/types/routesManager.d.ts +3 -0
- package/dist/types/{exporters/InMemoryLogRecordExporter.d.ts → telemetry/custom-implementations/exporters/InMemoryDbLogExporter.d.ts} +6 -6
- package/dist/types/{exporters/InMemoryDBMetricsExporter.d.ts → telemetry/custom-implementations/exporters/InMemoryDbMetricExporter.d.ts} +7 -7
- package/dist/types/{exporters/InMemoryDbExporter.d.ts → telemetry/custom-implementations/exporters/InMemoryDbSpanExporter.d.ts} +9 -9
- package/dist/types/telemetry/custom-implementations/exporters/PluginLogExporter.d.ts +8 -0
- package/dist/types/telemetry/custom-implementations/exporters/PluginMetricExporter.d.ts +12 -0
- package/dist/types/telemetry/custom-implementations/exporters/PluginSpanExporter.d.ts +14 -0
- package/dist/types/telemetry/custom-implementations/processors/dynamicMultiLogProcessor.d.ts +32 -0
- package/dist/types/telemetry/custom-implementations/processors/dynamicMultiSpanProcessor.d.ts +34 -0
- package/dist/types/telemetry/custom-implementations/utils/circular.d.ts +27 -0
- package/dist/types/telemetry/custom-implementations/wrappers.d.ts +52 -0
- package/dist/types/telemetry/initializeTelemetry.d.ts +1 -0
- package/dist/types/telemetry/telemetryConfigurator.d.ts +2 -0
- package/dist/types/telemetry/telemetryRegistry.d.ts +20 -0
- package/dist/types/tlm-ai/agent.d.ts +2 -1
- package/dist/types/tlm-ai/aiController.d.ts +4 -3
- package/dist/types/tlm-ai/aiRoutes.d.ts +2 -2
- package/dist/types/tlm-ai/tools.d.ts +3 -1
- package/dist/types/tlm-auth/authController.d.ts +4 -3
- package/dist/types/tlm-auth/authMiddleware.d.ts +2 -1
- package/dist/types/tlm-auth/authRoutes.d.ts +2 -2
- package/dist/types/tlm-log/logController.d.ts +1 -0
- package/dist/types/tlm-log/logRoutes.d.ts +2 -2
- package/dist/types/tlm-metric/metricsController.d.ts +1 -0
- package/dist/types/tlm-metric/metricsRoutes.d.ts +2 -2
- package/dist/types/tlm-plugin/pluginRoutes.d.ts +1 -2
- package/dist/types/tlm-plugin/pluginService.d.ts +9 -0
- package/dist/types/tlm-trace/traceController.d.ts +7 -6
- package/dist/types/tlm-trace/traceRoutes.d.ts +2 -2
- package/dist/types/tlm-ui/uiRoutes.d.ts +1 -2
- package/dist/types/tlm-util/utilController.d.ts +2 -1
- package/dist/types/tlm-util/utilRoutes.d.ts +2 -2
- package/dist/types/types/index.d.ts +7 -46
- package/dist/types/utils/regexUtils.d.ts +1 -0
- package/dist/ui/assets/index-D9HsRlaQ.js +437 -0
- package/dist/ui/assets/index-DEyIcKBi.css +1 -0
- package/dist/ui/index.html +3 -3
- package/dist/ui/oas-tlm.svg +185 -0
- package/package.json +12 -7
- package/dist/cjs/config.cjs +0 -31
- package/dist/cjs/exporters/InMemoryDBMetricsExporter.cjs +0 -74
- package/dist/cjs/exporters/InMemoryDbExporter.cjs +0 -102
- package/dist/cjs/exporters/consoleExporter.cjs +0 -47
- package/dist/cjs/exporters/dynamicExporter.cjs +0 -57
- package/dist/cjs/instrumentation/index.cjs +0 -28
- package/dist/cjs/instrumentation/logs.cjs +0 -46
- package/dist/cjs/instrumentation/metrics.cjs +0 -27
- package/dist/cjs/instrumentation/traces.cjs +0 -19
- package/dist/esm/config.js +0 -20
- package/dist/esm/exporters/InMemoryDbExporter.js +0 -102
- package/dist/esm/exporters/consoleExporter.js +0 -38
- package/dist/esm/exporters/dynamicExporter.js +0 -50
- package/dist/esm/instrumentation/index.js +0 -26
- package/dist/esm/instrumentation/logs.js +0 -34
- package/dist/esm/instrumentation/metrics.js +0 -18
- package/dist/esm/instrumentation/traces.js +0 -12
- package/dist/esm/utils/circular.js +0 -84
- package/dist/types/config.d.ts +0 -6
- package/dist/types/exporters/consoleExporter.d.ts +0 -13
- package/dist/types/exporters/dynamicExporter.d.ts +0 -25
- package/dist/types/instrumentation/logs.d.ts +0 -1
- package/dist/types/instrumentation/metrics.d.ts +0 -1
- package/dist/types/instrumentation/traces.d.ts +0 -1
- package/dist/types/tlmRoutes.d.ts +0 -2
- package/dist/types/utils/circular.d.ts +0 -31
- package/dist/ui/assets/index-BNhZBPi2.css +0 -1
- package/dist/ui/assets/index-DxGAMrAl.js +0 -401
- package/dist/ui/vite.svg +0 -1
- /package/dist/{types/instrumentation/index.d.ts → esm/config/config.types.js} +0 -0
|
@@ -3,16 +3,21 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.getTraceRoutes = exports.default = void 0;
|
|
7
7
|
var _express = require("express");
|
|
8
8
|
var _traceController = require("./traceController.cjs");
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
const getTraceRoutes = () => {
|
|
10
|
+
const router = (0, _express.Router)();
|
|
11
|
+
// Telemetry Control
|
|
12
|
+
router.post('/start', _traceController.startTraces);
|
|
13
|
+
router.post('/stop', _traceController.stopTraces);
|
|
14
|
+
router.get('/status', _traceController.statusTraces);
|
|
15
|
+
router.post('/reset', _traceController.resetTraces);
|
|
16
|
+
router.get('/', _traceController.listTraces);
|
|
17
|
+
router.post('/', _traceController.insertTracesToDb);
|
|
18
|
+
router.post('/find', _traceController.findTraces);
|
|
19
|
+
router.post('/retention-time', _traceController.setRetentionTimeTraces);
|
|
20
|
+
return router;
|
|
21
|
+
};
|
|
22
|
+
exports.getTraceRoutes = getTraceRoutes;
|
|
23
|
+
var _default = exports.default = getTraceRoutes;
|
|
@@ -3,29 +3,35 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.getUIRoutes = void 0;
|
|
7
7
|
var _express = _interopRequireWildcard(require("express"));
|
|
8
8
|
var _path = _interopRequireDefault(require("path"));
|
|
9
9
|
var _url = require("url");
|
|
10
10
|
var _logger = _interopRequireDefault(require("../utils/logger.cjs"));
|
|
11
|
+
var _bootConfig = require("../config/bootConfig.cjs");
|
|
11
12
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
13
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
relativePath = '../../
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
14
|
+
const getUIRoutes = () => {
|
|
15
|
+
// This is when this file is in /dist
|
|
16
|
+
let relativePath = '../../ui';
|
|
17
|
+
// This is when this file in in /src
|
|
18
|
+
if (_bootConfig.bootEnvVariables.OASTLM_BOOT_ENV === 'development') {
|
|
19
|
+
relativePath = '../../dist/ui';
|
|
20
|
+
_logger.default.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/.');
|
|
21
|
+
}
|
|
22
|
+
const customFilename = (0, _url.fileURLToPath)(require('url').pathToFileURL(__filename).toString());
|
|
23
|
+
const customDirname = _path.default.dirname(customFilename);
|
|
24
|
+
const staticFilesPath = _path.default.join(customDirname, relativePath);
|
|
25
|
+
const router = (0, _express.Router)();
|
|
26
|
+
// This only works once the app is built: src/ --> dist/esm/
|
|
27
|
+
// This file: dist/esm/routes/
|
|
28
|
+
// UI bundle: dist/ui/
|
|
29
|
+
// For development, the UI is served separately.
|
|
30
|
+
router.use(_express.default.static(staticFilesPath));
|
|
31
|
+
router.get('*', (_req, res) => {
|
|
32
|
+
// Serve the index.html file for all routes
|
|
33
|
+
res.sendFile(_path.default.join(staticFilesPath, 'index.html'));
|
|
34
|
+
});
|
|
35
|
+
return router;
|
|
36
|
+
};
|
|
37
|
+
exports.getUIRoutes = getUIRoutes;
|
|
@@ -4,20 +4,19 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.specLoader = exports.heapStats = void 0;
|
|
7
|
-
var _config = require("../config.cjs");
|
|
8
7
|
var _fs = require("fs");
|
|
9
8
|
var _path = _interopRequireDefault(require("path"));
|
|
10
9
|
var _jsYaml = _interopRequireDefault(require("js-yaml"));
|
|
11
10
|
var _nodeV = _interopRequireDefault(require("node:v8"));
|
|
12
11
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
|
-
const specLoader = (_req, res) => {
|
|
14
|
-
if (
|
|
12
|
+
const specLoader = (_req, res, oasTlmConfig) => {
|
|
13
|
+
if (oasTlmConfig.general.specFileName) {
|
|
15
14
|
try {
|
|
16
|
-
const data = (0, _fs.readFileSync)(
|
|
15
|
+
const data = (0, _fs.readFileSync)(oasTlmConfig.general.specFileName, {
|
|
17
16
|
encoding: 'utf8',
|
|
18
17
|
flag: 'r'
|
|
19
18
|
});
|
|
20
|
-
const extension = _path.default.extname(
|
|
19
|
+
const extension = _path.default.extname(oasTlmConfig.general.specFileName);
|
|
21
20
|
let json = data;
|
|
22
21
|
if (extension == "yaml")
|
|
23
22
|
//@ts-expect-error yes
|
|
@@ -25,15 +24,15 @@ const specLoader = (_req, res) => {
|
|
|
25
24
|
res.setHeader('Content-Type', 'application/json');
|
|
26
25
|
res.send(json);
|
|
27
26
|
} catch (e) {
|
|
28
|
-
console.error(`ERROR loading spec file ${
|
|
27
|
+
console.error(`ERROR loading spec file ${oasTlmConfig.general.specFileName}: ${e}`);
|
|
29
28
|
}
|
|
30
|
-
} else if (
|
|
29
|
+
} else if (oasTlmConfig.general.spec) {
|
|
31
30
|
let spec = null;
|
|
32
31
|
try {
|
|
33
|
-
spec = JSON.parse(
|
|
32
|
+
spec = JSON.parse(oasTlmConfig.general.spec);
|
|
34
33
|
} catch (ej) {
|
|
35
34
|
try {
|
|
36
|
-
spec = JSON.stringify(_jsYaml.default.load(
|
|
35
|
+
spec = JSON.stringify(_jsYaml.default.load(oasTlmConfig.general.spec), null, 2);
|
|
37
36
|
} catch (ey) {
|
|
38
37
|
console.error(`Error parsing spec: ${ej} - ${ey}`);
|
|
39
38
|
}
|
|
@@ -3,26 +3,29 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.getUtilsRoutes = void 0;
|
|
7
7
|
var _express = require("express");
|
|
8
8
|
var _utilController = require("./utilController.cjs");
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
const getUtilsRoutes = oasTlmConfig => {
|
|
10
|
+
const router = (0, _express.Router)();
|
|
11
|
+
router.get('/spec', (req, res) => (0, _utilController.specLoader)(req, res, oasTlmConfig));
|
|
12
|
+
router.get('/heapStats', _utilController.heapStats);
|
|
13
|
+
router.get('/generateLog', (req, res) => {
|
|
14
|
+
const log = req.query.log || 'Default log message';
|
|
15
|
+
console.log(log);
|
|
16
|
+
res.send({
|
|
17
|
+
message: 'Log generated',
|
|
18
|
+
log: log
|
|
19
|
+
});
|
|
18
20
|
});
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
router.get('/wait/:seconds?', async (req, res) => {
|
|
22
|
+
const seconds = parseInt(req.params.seconds ?? "1", 10);
|
|
23
|
+
const waitTime = isNaN(seconds) ? 1 : seconds;
|
|
24
|
+
await new Promise(resolve => setTimeout(resolve, waitTime * 1000));
|
|
25
|
+
res.send({
|
|
26
|
+
waited: waitTime
|
|
27
|
+
});
|
|
26
28
|
});
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
return router;
|
|
30
|
+
};
|
|
31
|
+
exports.getUtilsRoutes = getUtilsRoutes;
|
package/dist/cjs/types/index.cjs
CHANGED
|
@@ -4,12 +4,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
var
|
|
8
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
-
_dotenv.default.config();
|
|
7
|
+
var _bootConfig = require("../config/bootConfig.cjs");
|
|
10
8
|
const LOG_LEVELS = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE'];
|
|
11
|
-
const currentLogLevel = (
|
|
12
|
-
const serviceName =
|
|
9
|
+
const currentLogLevel = (_bootConfig.bootEnvVariables.OASTLM_BOOT_LOG_LEVEL || 'INFO').toUpperCase();
|
|
10
|
+
const serviceName = 'OAS-Telemetry';
|
|
13
11
|
function log(level, ...messages) {
|
|
14
12
|
if (LOG_LEVELS.indexOf(level) >= LOG_LEVELS.indexOf(currentLogLevel)) {
|
|
15
13
|
const timestamp = new Date().toISOString();
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.convertRegexRecursively = void 0;
|
|
7
|
+
const convertRegexRecursively = obj => {
|
|
8
|
+
if (Array.isArray(obj)) {
|
|
9
|
+
return obj.map(convertRegexRecursively);
|
|
10
|
+
} else if (obj && typeof obj === 'object') {
|
|
11
|
+
const newObj = {};
|
|
12
|
+
for (const key of Object.keys(obj)) {
|
|
13
|
+
if (key === '$regex' && typeof obj[key] === 'string') {
|
|
14
|
+
try {
|
|
15
|
+
return new RegExp(obj[key]);
|
|
16
|
+
} catch {
|
|
17
|
+
throw new Error(`Invalid regex value "${obj[key]}"`);
|
|
18
|
+
}
|
|
19
|
+
} else {
|
|
20
|
+
newObj[key] = convertRegexRecursively(obj[key]);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return newObj;
|
|
24
|
+
}
|
|
25
|
+
return obj;
|
|
26
|
+
};
|
|
27
|
+
exports.convertRegexRecursively = convertRegexRecursively;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
3
|
+
dotenv.config();
|
|
4
|
+
}
|
|
5
|
+
// This variables can NOT be configured via oasTelemetry(config)
|
|
6
|
+
// They are used at the import of the library
|
|
7
|
+
export const bootEnvVariables = {
|
|
8
|
+
OASTLM_BOOT_ENV: process.env.OASTLM_BOOT_ENV || process.env.NODE_ENV || 'production',
|
|
9
|
+
OASTLM_BOOT_MODULE_DISABLED: process.env.OASTLM_BOOT_MODULE_DISABLED === 'true',
|
|
10
|
+
OASTLM_BOOT_LOG_LEVEL: process.env.OASTLM_BOOT_LOG_LEVEL || 'INFO',
|
|
11
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import merge from 'lodash.merge';
|
|
2
|
+
// Environment-level config (highest priority)
|
|
3
|
+
// If NOT defined, it should return UNDEFINED so it dose not override the userConfig or defaultConfig.
|
|
4
|
+
// Thats why we use getParsedEnvVar with no default value.
|
|
5
|
+
const loadEnv = () => {
|
|
6
|
+
return {
|
|
7
|
+
general: {
|
|
8
|
+
baseUrl: getParsedEnvVar("OASTLM_CONFIG_GENERAL_BASE_URL"),
|
|
9
|
+
specFileName: getParsedEnvVar("OASTLM_CONFIG_GENERAL_SPEC_FILE_NAME"),
|
|
10
|
+
// spec Not settable via env
|
|
11
|
+
},
|
|
12
|
+
auth: {
|
|
13
|
+
enabled: getParsedEnvVar("OASTLM_CONFIG_AUTH_ENABLED", (v) => v === "true"),
|
|
14
|
+
apiKeyMaxAge: getParsedEnvVar("OASTLM_CONFIG_AUTH_API_KEY_MAX_AGE", (v) => parseInt(v, 10)),
|
|
15
|
+
password: getParsedEnvVar("OASTLM_CONFIG_AUTH_PASSWORD"),
|
|
16
|
+
jwtSecret: getParsedEnvVar("OASTLM_CONFIG_AUTH_JWT_SECRET"),
|
|
17
|
+
},
|
|
18
|
+
traces: {
|
|
19
|
+
memoryExporter: {
|
|
20
|
+
enabled: getParsedEnvVar("OASTLM_CONFIG_TRACES_MEMORY_EXPORTER_ENABLED", (v) => v === "true"),
|
|
21
|
+
retentionTimeSeconds: getParsedEnvVar("OASTLM_CONFIG_TRACES_MEMORY_EXPORTER_RETENTION_TIME_SECONDS", (v) => parseInt(v, 10)),
|
|
22
|
+
// filters NOT settable via env
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
metrics: {
|
|
26
|
+
mainMetricReaderOptions: {
|
|
27
|
+
exportIntervalMillis: getParsedEnvVar("OASTLM_CONFIG_METRICS_MAIN_READER_EXPORT_INTERVAL", (v) => parseInt(v, 10)),
|
|
28
|
+
// metricProducers NOT settable via env
|
|
29
|
+
},
|
|
30
|
+
memoryExporter: {
|
|
31
|
+
enabled: getParsedEnvVar("OASTLM_CONFIG_METRICS_MEMORY_EXPORTER_ENABLED", (v) => v === "true"),
|
|
32
|
+
retentionTimeSeconds: getParsedEnvVar("OASTLM_CONFIG_METRICS_MEMORY_EXPORTER_RETENTION_TIME_SECONDS", (v) => parseInt(v, 10)),
|
|
33
|
+
// filters NOT settable via env
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
logs: {
|
|
37
|
+
memoryExporter: {
|
|
38
|
+
enabled: getParsedEnvVar("OASTLM_CONFIG_LOGS_MEMORY_EXPORTER_ENABLED", (v) => v === "true"),
|
|
39
|
+
retentionTimeSeconds: getParsedEnvVar("OASTLM_CONFIG_LOGS_MEMORY_EXPORTER_RETENTION_TIME_SECONDS", (v) => parseInt(v, 10)),
|
|
40
|
+
// filters NOT settable via env
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
ai: {
|
|
44
|
+
openAIKey: getParsedEnvVar("OASTLM_CONFIG_AI_OPENAI_KEY"),
|
|
45
|
+
openAIModel: getParsedEnvVar("OASTLM_CONFIG_AI_OPENAI_MODEL", (v) => v || "gpt-3.5-turbo"),
|
|
46
|
+
extraContextPrompts: getParsedEnvVar("OASTLM_CONFIG_AI_EXTRA_CONTEXT_PROMPTS", (v) => v ? v.split(',') : []),
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
// This defines de OasTlmConfig type, which is used throughout the library.
|
|
51
|
+
// Please ensure that all possible types are included here, not only the defaults.
|
|
52
|
+
// e.g. .ai.openAIKey: null as string | null, default is null, but can be set to a string.
|
|
53
|
+
// NOTE: Some BOOT environment variables (e.g., OASTLM_BOOT_MODULE_DISABLED) are accessed before this config is loaded.
|
|
54
|
+
// This means certain settings may affect application startup behavior outside of this configuration system.
|
|
55
|
+
export const defaultConfig = {
|
|
56
|
+
general: {
|
|
57
|
+
baseUrl: "/telemetry",
|
|
58
|
+
specFileName: null, // e.g. "oas.json" or null if not provided
|
|
59
|
+
spec: null, // e.g. JSON.stringify(oasSpec) or null if not provided,
|
|
60
|
+
uiPath: "/oas-telemetry-ui", // path to the UI, e.g. "/oas-telemetry-ui" WARN: This must match the UI package's App.tsx "oas-telemetry-ui" path
|
|
61
|
+
},
|
|
62
|
+
auth: {
|
|
63
|
+
enabled: false,
|
|
64
|
+
apiKeyMaxAge: 1000 * 60 * 60, // 1 hour
|
|
65
|
+
password: "oas-telemetry-password",
|
|
66
|
+
jwtSecret: "oas-telemetry-secret",
|
|
67
|
+
},
|
|
68
|
+
ai: {
|
|
69
|
+
openAIKey: null,
|
|
70
|
+
openAIModel: "gpt-3.5-turbo",
|
|
71
|
+
extraContextPrompts: [], // e.g. ["Provide detailed explanations", "Use simple language"]
|
|
72
|
+
},
|
|
73
|
+
traces: {
|
|
74
|
+
extraExporters: [], // e.g. [new ConsoleSpanExporter()]
|
|
75
|
+
extraProcessors: [], // e.g. [new SimpleSpanProcessor(new ConsoleSpanExporter())]
|
|
76
|
+
mainProcessorOptions: {
|
|
77
|
+
config: undefined
|
|
78
|
+
},
|
|
79
|
+
memoryExporter: {
|
|
80
|
+
enabled: true, // auto start exporting.
|
|
81
|
+
retentionTimeSeconds: 60 * 60, // 1 hour
|
|
82
|
+
},
|
|
83
|
+
filters: [], // future feature, currently not used
|
|
84
|
+
},
|
|
85
|
+
metrics: {
|
|
86
|
+
mainMetricReaderOptions: {
|
|
87
|
+
exportIntervalMillis: 1000 * 60, // 60 seconds
|
|
88
|
+
metricProducers: [], // experimental by OpenTelemetry, not used by OAS-TLM yet
|
|
89
|
+
},
|
|
90
|
+
extraReaders: [], // e.g. [new PrometheusExporter()]
|
|
91
|
+
extraViews: [], // e.g. [new MetricView({ name: 'my_metric', labels: ['env'] })]
|
|
92
|
+
memoryExporter: {
|
|
93
|
+
enabled: true,
|
|
94
|
+
retentionTimeSeconds: 60 * 60, // 1 hour
|
|
95
|
+
},
|
|
96
|
+
filters: [], // future feature, currently not used
|
|
97
|
+
},
|
|
98
|
+
logs: {
|
|
99
|
+
extraExporters: [], // e.g. [new ConsoleLogRecordExporter()]
|
|
100
|
+
extraProcessors: [], // e.g. [new SimpleLogRecordProcessor(new ConsoleLogRecordExporter())]
|
|
101
|
+
memoryExporter: {
|
|
102
|
+
enabled: true,
|
|
103
|
+
retentionTimeSeconds: 60 * 60, // 1 hour
|
|
104
|
+
},
|
|
105
|
+
filters: [], // future feature, currently not used
|
|
106
|
+
},
|
|
107
|
+
plugins: {
|
|
108
|
+
enabled: true, // future feature
|
|
109
|
+
extraPlugins: [], // future feature
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
// Helper to get an environment variable with optional transform
|
|
113
|
+
const getParsedEnvVar = (envKey, transform) => {
|
|
114
|
+
const rawValue = process.env[envKey];
|
|
115
|
+
// Treat undefined and "" in env as undefined (skip)
|
|
116
|
+
if (rawValue === undefined || rawValue === "")
|
|
117
|
+
return undefined;
|
|
118
|
+
if (typeof transform === 'function') {
|
|
119
|
+
return transform(rawValue);
|
|
120
|
+
}
|
|
121
|
+
return rawValue;
|
|
122
|
+
};
|
|
123
|
+
export const getConfig = (userConfig, fallbackConfig = defaultConfig, envConfig = loadEnv()) => {
|
|
124
|
+
// environment variables OVERRIDE userConfig OVERRIDE fallbackConfig
|
|
125
|
+
return merge({}, fallbackConfig, userConfig, envConfig);
|
|
126
|
+
};
|
package/dist/esm/index.js
CHANGED
|
@@ -1,39 +1,28 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { Router } from 'express';
|
|
4
|
-
import { InMemoryExporter } from './exporters/InMemoryDbExporter.js';
|
|
1
|
+
import "./config/bootConfig.js"; // Load environment variables before any other imports
|
|
2
|
+
import './telemetry/initializeTelemetry.js'; // Initialize OpenTelemetry instrumentation
|
|
5
3
|
import logger from './utils/logger.js';
|
|
6
|
-
import {
|
|
4
|
+
import { getConfig } from './config/config.js';
|
|
5
|
+
import { Router } from 'express';
|
|
6
|
+
import { configureRoutes } from './routesManager.js';
|
|
7
|
+
import { configureTelemetry } from './telemetry/telemetryConfigurator.js';
|
|
8
|
+
import { bootEnvVariables } from "./config/bootConfig.js";
|
|
7
9
|
/**
|
|
8
|
-
* Returns the
|
|
10
|
+
* Returns the OAS-Telemetry middleware.
|
|
9
11
|
* All parameters are optional. However, either `spec` or `specFileName` must be provided to enable endpoint filtering.
|
|
10
12
|
*/
|
|
11
13
|
export default function oasTelemetry(oasTlmInputConfig) {
|
|
12
14
|
const router = Router();
|
|
13
|
-
|
|
15
|
+
// This environment variable cannot be set via the config object,
|
|
16
|
+
// as it is required to disable OpenTelemetry SDK initialization,
|
|
17
|
+
// which occurs during the first import at the top of this file.
|
|
18
|
+
if (bootEnvVariables.OASTLM_BOOT_MODULE_DISABLED) {
|
|
14
19
|
return router;
|
|
15
20
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
logger.info("BaseURL: ", globalOasTlmConfig.baseURL);
|
|
24
|
-
globalOasTlmConfig.dynamicSpanExporter.changeExporter(globalOasTlmConfig.exporter ?? new InMemoryExporter());
|
|
25
|
-
if (globalOasTlmConfig.spec)
|
|
26
|
-
logger.info(`Spec content provided`);
|
|
27
|
-
else {
|
|
28
|
-
if (globalOasTlmConfig.specFileName != "")
|
|
29
|
-
logger.info(`Spec file used for telemetry: ${globalOasTlmConfig.specFileName}`);
|
|
30
|
-
else {
|
|
31
|
-
console.error("No spec available !");
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
if (globalOasTlmConfig.autoActivate) {
|
|
35
|
-
globalOasTlmConfig.dynamicSpanExporter.exporter?.start();
|
|
36
|
-
}
|
|
37
|
-
configureRoutes(router);
|
|
21
|
+
const oasTlmConfig = getConfig(oasTlmInputConfig);
|
|
22
|
+
logger.info("BaseUrl: ", oasTlmConfig.general.baseUrl);
|
|
23
|
+
if (!oasTlmConfig.general.spec && !oasTlmConfig.general.specFileName)
|
|
24
|
+
logger.warn("No spec provided, endpoint filtering will not be available. Please provide either `spec` or `specFileName` in the configuration.");
|
|
25
|
+
configureTelemetry(oasTlmConfig);
|
|
26
|
+
configureRoutes(router, oasTlmConfig);
|
|
38
27
|
return router;
|
|
39
28
|
}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { json } from "express";
|
|
2
2
|
import logger from "./utils/logger.js";
|
|
3
3
|
import cors from 'cors';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
4
|
+
import { getTraceRoutes } from "./tlm-trace/traceRoutes.js";
|
|
5
|
+
import { getMetricsRoutes } from "./tlm-metric/metricsRoutes.js";
|
|
6
|
+
import { getLogRoutes } from "./tlm-log/logRoutes.js";
|
|
6
7
|
import cookieParser from 'cookie-parser';
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
export const configureRoutes = (router) => {
|
|
15
|
-
if (
|
|
8
|
+
import { getAuthRoutes } from './tlm-auth/authRoutes.js';
|
|
9
|
+
import { getUIRoutes } from './tlm-ui/uiRoutes.js';
|
|
10
|
+
import { getAuthMiddleware } from "./tlm-auth/authMiddleware.js";
|
|
11
|
+
import { getUtilsRoutes } from "./tlm-util/utilRoutes.js";
|
|
12
|
+
import { getAIRoutes } from "./tlm-ai/aiRoutes.js";
|
|
13
|
+
import { bootEnvVariables } from "./config/bootConfig.js";
|
|
14
|
+
import { getPluginRoutes } from "./tlm-plugin/pluginRoutes.js";
|
|
15
|
+
export const configureRoutes = (router, oasTlmConfig) => {
|
|
16
|
+
if (bootEnvVariables.OASTLM_BOOT_ENV === 'development') {
|
|
16
17
|
logger.info("Running in development mode, enabling CORS for all origins");
|
|
17
18
|
router.use(cors({
|
|
18
19
|
origin: '*', // Permitir todas las solicitudes en desarrollo
|
|
@@ -26,19 +27,23 @@ export const configureRoutes = (router) => {
|
|
|
26
27
|
}
|
|
27
28
|
return json({ limit: '10mb' })(req, res, next);
|
|
28
29
|
});
|
|
29
|
-
const allAuthMiddlewares = getWrappedMiddlewares(() =>
|
|
30
|
-
const
|
|
31
|
-
router.use(
|
|
30
|
+
const allAuthMiddlewares = getWrappedMiddlewares(() => oasTlmConfig.auth.enabled, [cookieParser(), getAuthRoutes(oasTlmConfig), getAuthMiddleware(oasTlmConfig)]);
|
|
31
|
+
const baseUrl = oasTlmConfig.general.baseUrl;
|
|
32
|
+
router.use(baseUrl, allAuthMiddlewares);
|
|
33
|
+
router.use(baseUrl + "/traces", getTraceRoutes());
|
|
34
|
+
router.use(baseUrl + "/metrics", getMetricsRoutes());
|
|
35
|
+
router.use(baseUrl + "/logs", getLogRoutes());
|
|
36
|
+
router.use(baseUrl + "/ai", getWrappedMiddlewares(() => oasTlmConfig.ai.openAIKey !== null, [getAIRoutes(oasTlmConfig)]));
|
|
32
37
|
// WARNING: This path must be the same as the one used in the UI package App.tsx "oas-telemetry-ui"
|
|
33
|
-
router.use(
|
|
34
|
-
router.use(
|
|
35
|
-
router.use(
|
|
36
|
-
router.
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
router.use(baseUrl + "/oas-telemetry-ui", getUIRoutes());
|
|
39
|
+
router.use(baseUrl + "/utils", getUtilsRoutes(oasTlmConfig));
|
|
40
|
+
router.use(baseUrl + "/plugins", getPluginRoutes());
|
|
41
|
+
router.get(baseUrl + '/health', (_req, res) => {
|
|
42
|
+
res.status(200).send({ status: 'OK' });
|
|
43
|
+
});
|
|
39
44
|
//redirect to the UI when accessing the base URL
|
|
40
|
-
router.get(
|
|
41
|
-
res.redirect(
|
|
45
|
+
router.get(baseUrl, (req, res) => {
|
|
46
|
+
res.redirect(baseUrl + "/oas-telemetry-ui");
|
|
42
47
|
});
|
|
43
48
|
};
|
|
44
49
|
/**
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { hrTimeToMicroseconds } from '@opentelemetry/core';
|
|
2
2
|
import { ExportResultCode } from '@opentelemetry/core';
|
|
3
|
-
import { removeCircularRefs, applyNesting } from '../utils/circular.js';
|
|
4
3
|
import Datastore from '@seald-io/nedb';
|
|
5
4
|
import MiniSearch from 'minisearch';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
import { applyNesting, removeCircularRefs } from '../utils/circular.js';
|
|
6
|
+
import { Enabler } from '../wrappers.js';
|
|
7
|
+
import logger from '../../../utils/logger.js';
|
|
8
|
+
export class InMemoryDbLogExporter extends Enabler {
|
|
9
|
+
constructor(retentionTimeInSeconds = 3600) {
|
|
10
|
+
super();
|
|
11
|
+
this._retentionTimeInSeconds = retentionTimeInSeconds;
|
|
12
|
+
this._db = new Datastore({ timestampData: true });
|
|
13
|
+
this._db.ensureIndex({ fieldName: 'createdAt' });
|
|
9
14
|
this._miniSearch = new MiniSearch({
|
|
10
15
|
fields: ['body'],
|
|
11
16
|
storeFields: ['_id'],
|
|
12
17
|
idField: '_id',
|
|
13
18
|
});
|
|
14
|
-
this.
|
|
19
|
+
this._startCleanupJob();
|
|
15
20
|
}
|
|
16
21
|
/*
|
|
17
22
|
* SUPER WARNING:
|
|
@@ -25,7 +30,7 @@ export class InMemoryLogRecordExporter {
|
|
|
25
30
|
* @param resultCallback
|
|
26
31
|
*/
|
|
27
32
|
export(logs, resultCallback) {
|
|
28
|
-
if (this.
|
|
33
|
+
if (!this.isEnabled()) {
|
|
29
34
|
resultCallback({ code: ExportResultCode.SUCCESS });
|
|
30
35
|
return;
|
|
31
36
|
}
|
|
@@ -57,7 +62,7 @@ export class InMemoryLogRecordExporter {
|
|
|
57
62
|
if (messageSearch) {
|
|
58
63
|
const searchResults = this._miniSearch.search(messageSearch);
|
|
59
64
|
const ids = searchResults.map((result) => result._id);
|
|
60
|
-
|
|
65
|
+
logger.debug(`MiniSearch found ${ids.length} results for search term "${messageSearch}"`, { depth: 3 });
|
|
61
66
|
// Add MiniSearch results to the query
|
|
62
67
|
query._id = { $in: ids };
|
|
63
68
|
}
|
|
@@ -68,7 +73,7 @@ export class InMemoryLogRecordExporter {
|
|
|
68
73
|
if (result.code === ExportResultCode.SUCCESS) {
|
|
69
74
|
this._db.find({}, (err, docs) => {
|
|
70
75
|
if (err) {
|
|
71
|
-
|
|
76
|
+
logger.debug(err);
|
|
72
77
|
callback(err, []);
|
|
73
78
|
return;
|
|
74
79
|
}
|
|
@@ -80,15 +85,6 @@ export class InMemoryLogRecordExporter {
|
|
|
80
85
|
}
|
|
81
86
|
});
|
|
82
87
|
}
|
|
83
|
-
start() {
|
|
84
|
-
this._stopped = false;
|
|
85
|
-
}
|
|
86
|
-
stop() {
|
|
87
|
-
this._stopped = true;
|
|
88
|
-
}
|
|
89
|
-
isRunning() {
|
|
90
|
-
return !this._stopped;
|
|
91
|
-
}
|
|
92
88
|
getFinishedLogs() {
|
|
93
89
|
return this._db.getAllData();
|
|
94
90
|
}
|
|
@@ -114,6 +110,10 @@ export class InMemoryLogRecordExporter {
|
|
|
114
110
|
attributes: logRecord.attributes,
|
|
115
111
|
};
|
|
116
112
|
}
|
|
113
|
+
set retentionTimeInSeconds(retentionTimeInSeconds) {
|
|
114
|
+
this._retentionTimeInSeconds = retentionTimeInSeconds;
|
|
115
|
+
logger.info(`InMemoryDbLogExporter retention time set to ${this._retentionTimeInSeconds} seconds`);
|
|
116
|
+
}
|
|
117
117
|
_insertLogs(logsToInsert, resultCallback) {
|
|
118
118
|
this._db.insert(logsToInsert, (err, newDocs) => {
|
|
119
119
|
if (err) {
|
|
@@ -127,4 +127,18 @@ export class InMemoryLogRecordExporter {
|
|
|
127
127
|
});
|
|
128
128
|
return;
|
|
129
129
|
}
|
|
130
|
+
_startCleanupJob() {
|
|
131
|
+
const interval = 1000;
|
|
132
|
+
setInterval(() => {
|
|
133
|
+
const expirationDate = new Date(Date.now() - this._retentionTimeInSeconds * 1000);
|
|
134
|
+
this._db.remove({ createdAt: { $lt: expirationDate } }, { multi: true }, (err, numRemoved) => {
|
|
135
|
+
if (err) {
|
|
136
|
+
logger.error('Error in TTL cleanup:', err);
|
|
137
|
+
}
|
|
138
|
+
else if (numRemoved > 0) {
|
|
139
|
+
logger.debug(`TTL cleanup: removed ${numRemoved} expired logs`);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}, interval);
|
|
143
|
+
}
|
|
130
144
|
}
|