@oas-tools/oas-telemetry 0.7.0-alpha.0 → 0.7.0-alpha.2
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 +26 -0
- package/NOTICE +8 -0
- package/README.md +76 -18
- package/dist/cjs/exporters/InMemoryDBMetricsExporter.cjs +10 -2
- package/dist/cjs/exporters/InMemoryDbExporter.cjs +16 -1
- package/dist/cjs/exporters/InMemoryLogRecordExporter.cjs +51 -15
- package/dist/cjs/tlm-ai/tools.cjs +2 -2
- package/dist/cjs/tlm-log/logController.cjs +69 -3
- package/dist/cjs/tlm-log/logRoutes.cjs +6 -1
- package/dist/cjs/tlm-metric/metricsController.cjs +69 -3
- package/dist/cjs/tlm-metric/metricsRoutes.cjs +4 -0
- package/dist/cjs/tlm-trace/traceController.cjs +51 -2
- package/dist/cjs/tlm-trace/traceRoutes.cjs +1 -0
- package/dist/cjs/tlm-util/utilRoutes.cjs +16 -0
- package/dist/cjs/tlmRoutes.cjs +3 -1
- package/dist/esm/exporters/InMemoryDBMetricsExporter.js +10 -2
- package/dist/esm/exporters/InMemoryDbExporter.js +16 -1
- package/dist/esm/exporters/InMemoryLogRecordExporter.js +46 -11
- package/dist/esm/tlm-ai/tools.js +2 -2
- package/dist/esm/tlm-log/logController.js +48 -1
- package/dist/esm/tlm-log/logRoutes.js +7 -2
- package/dist/esm/tlm-metric/metricsController.js +48 -1
- package/dist/esm/tlm-metric/metricsRoutes.js +5 -1
- package/dist/esm/tlm-trace/traceController.js +35 -0
- package/dist/esm/tlm-trace/traceRoutes.js +2 -1
- package/dist/esm/tlm-util/utilRoutes.js +11 -0
- package/dist/esm/tlmRoutes.js +1 -1
- package/dist/types/exporters/InMemoryDBMetricsExporter.d.ts +6 -0
- package/dist/types/exporters/InMemoryDbExporter.d.ts +6 -0
- package/dist/types/exporters/InMemoryLogRecordExporter.d.ts +7 -1
- package/dist/types/tlm-log/logController.d.ts +4 -0
- package/dist/types/tlm-metric/metricsController.d.ts +4 -0
- package/dist/types/tlm-trace/traceController.d.ts +1 -0
- package/package.json +3 -1
- package/dist/cjs/openTelemetry.cjs +0 -56
- package/dist/cjs/systemMetrics.cjs +0 -97
- package/dist/cjs/tlm-ui/uiController.cjs +0 -27
- package/dist/esm/openTelemetry.js +0 -50
- package/dist/esm/systemMetrics.js +0 -82
- package/dist/esm/tlm-ui/uiController.js +0 -20
- package/dist/types/openTelemetry.d.ts +0 -1
- package/dist/types/systemMetrics.d.ts +0 -26
- package/dist/types/tlm-ui/uiController.d.ts +0 -8
package/dist/cjs/tlmRoutes.cjs
CHANGED
|
@@ -32,7 +32,9 @@ const configureRoutes = router => {
|
|
|
32
32
|
if (req.body !== undefined) {
|
|
33
33
|
return next(); // Already parsed, no need to parse again.
|
|
34
34
|
}
|
|
35
|
-
return (0, _express.json)(
|
|
35
|
+
return (0, _express.json)({
|
|
36
|
+
limit: '10mb'
|
|
37
|
+
})(req, res, next);
|
|
36
38
|
});
|
|
37
39
|
const allAuthMiddlewares = getWrappedMiddlewares(() => _config.globalOasTlmConfig.authEnabled, [(0, _cookieParser.default)(), _authRoutes.default, _authMiddleware.authMiddleware]);
|
|
38
40
|
const baseURL = _config.globalOasTlmConfig.baseURL;
|
|
@@ -9,8 +9,8 @@ export class InMemoryDBMetricsExporter {
|
|
|
9
9
|
export(metrics, resultCallback) {
|
|
10
10
|
try {
|
|
11
11
|
if (!this._stopped) {
|
|
12
|
-
|
|
13
|
-
const cleanMetrics = applyNesting(
|
|
12
|
+
const scopeMetrics = metrics?.scopeMetrics;
|
|
13
|
+
const cleanMetrics = applyNesting(scopeMetrics);
|
|
14
14
|
this._metrics.insert(cleanMetrics, (err, _newDoc) => {
|
|
15
15
|
if (err) {
|
|
16
16
|
console.error('Insertion Error:', err);
|
|
@@ -54,4 +54,12 @@ export class InMemoryDBMetricsExporter {
|
|
|
54
54
|
getFinishedMetrics() {
|
|
55
55
|
return this._metrics.getAllData();
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Inserts metrics into the in-memory database.
|
|
59
|
+
* @param metrics - The metrics to insert.
|
|
60
|
+
* @param callback - The callback to execute after insertion.
|
|
61
|
+
*/
|
|
62
|
+
insert(metrics, callback) {
|
|
63
|
+
this._metrics.insert(metrics, callback);
|
|
64
|
+
}
|
|
57
65
|
}
|
|
@@ -3,6 +3,7 @@ import { ExportResultCode } from '@opentelemetry/core';
|
|
|
3
3
|
import dataStore from '@seald-io/nedb';
|
|
4
4
|
import logger from '../utils/logger.js';
|
|
5
5
|
import { applyNesting, removeCircularRefs } from '../utils/circular.js';
|
|
6
|
+
import { globalOasTlmConfig } from '../config.js';
|
|
6
7
|
export class InMemoryExporter {
|
|
7
8
|
constructor() {
|
|
8
9
|
// Overrided by dynamic exporter
|
|
@@ -18,7 +19,13 @@ export class InMemoryExporter {
|
|
|
18
19
|
const cleanSpans = readableSpans
|
|
19
20
|
.map(nestedSpan => removeCircularRefs(nestedSpan)) // to avoid JSON parsing error
|
|
20
21
|
.map(span => applyNesting(span)) // to avoid dot notation in keys (neDB does not support dot notation in keys)
|
|
21
|
-
.filter(span =>
|
|
22
|
+
.filter(span => {
|
|
23
|
+
const target = span?.attributes?.http?.target; // Exclude spans where target includes 'telemetry' but NOT 'telemetry/utils'
|
|
24
|
+
if (target && target.includes(globalOasTlmConfig.baseURL)) {
|
|
25
|
+
return target.includes(globalOasTlmConfig.baseURL + '/utils');
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
});
|
|
22
29
|
// Insert spans into the in-memory database
|
|
23
30
|
this._spans.insert(cleanSpans, (err, _newDoc) => {
|
|
24
31
|
// p = {name, plugin
|
|
@@ -84,4 +91,12 @@ export class InMemoryExporter {
|
|
|
84
91
|
return this._spans.getAllData();
|
|
85
92
|
}
|
|
86
93
|
;
|
|
94
|
+
/**
|
|
95
|
+
* Inserts spans into the in-memory database.
|
|
96
|
+
* @param spans - The spans to insert.
|
|
97
|
+
* @param callback - The callback to execute after insertion.
|
|
98
|
+
*/
|
|
99
|
+
insert(spans, callback) {
|
|
100
|
+
this._spans.insert(spans, callback);
|
|
101
|
+
}
|
|
87
102
|
}
|
|
@@ -11,6 +11,7 @@ export class InMemoryLogRecordExporter {
|
|
|
11
11
|
storeFields: ['_id'],
|
|
12
12
|
idField: '_id',
|
|
13
13
|
});
|
|
14
|
+
this._stopped = false;
|
|
14
15
|
}
|
|
15
16
|
/*
|
|
16
17
|
* SUPER WARNING:
|
|
@@ -24,6 +25,10 @@ export class InMemoryLogRecordExporter {
|
|
|
24
25
|
* @param resultCallback
|
|
25
26
|
*/
|
|
26
27
|
export(logs, resultCallback) {
|
|
28
|
+
if (this._stopped) {
|
|
29
|
+
resultCallback({ code: ExportResultCode.SUCCESS });
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
27
32
|
const logsToInsert = logs.map(logRecord => {
|
|
28
33
|
// Remove circular references first, then apply nesting, then export info
|
|
29
34
|
const formattedLog = this._formatLogRecord(logRecord);
|
|
@@ -31,16 +36,7 @@ export class InMemoryLogRecordExporter {
|
|
|
31
36
|
const nestedLog = applyNesting(cleanedLog);
|
|
32
37
|
return nestedLog;
|
|
33
38
|
});
|
|
34
|
-
this.
|
|
35
|
-
if (err) {
|
|
36
|
-
console.dir(err);
|
|
37
|
-
resultCallback({ code: ExportResultCode.FAILED });
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
// console.dir(newDocs, { depth: 3 });
|
|
41
|
-
newDocs.forEach((doc) => this._miniSearch.add(doc));
|
|
42
|
-
resultCallback({ code: ExportResultCode.SUCCESS });
|
|
43
|
-
});
|
|
39
|
+
this._insertLogs(logsToInsert, resultCallback);
|
|
44
40
|
}
|
|
45
41
|
reset() {
|
|
46
42
|
this._db = new Datastore();
|
|
@@ -67,7 +63,33 @@ export class InMemoryLogRecordExporter {
|
|
|
67
63
|
}
|
|
68
64
|
this._db.find(query, callback);
|
|
69
65
|
}
|
|
70
|
-
|
|
66
|
+
insert(data, callback) {
|
|
67
|
+
this._insertLogs(data, (result) => {
|
|
68
|
+
if (result.code === ExportResultCode.SUCCESS) {
|
|
69
|
+
this._db.find({}, (err, docs) => {
|
|
70
|
+
if (err) {
|
|
71
|
+
console.dir(err);
|
|
72
|
+
callback(err, []);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
callback(null, docs);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
callback(new Error('Failed to insert logs'), []);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
start() {
|
|
84
|
+
this._stopped = false;
|
|
85
|
+
}
|
|
86
|
+
stop() {
|
|
87
|
+
this._stopped = true;
|
|
88
|
+
}
|
|
89
|
+
isRunning() {
|
|
90
|
+
return !this._stopped;
|
|
91
|
+
}
|
|
92
|
+
getFinishedLogs() {
|
|
71
93
|
return this._db.getAllData();
|
|
72
94
|
}
|
|
73
95
|
/**
|
|
@@ -92,4 +114,17 @@ export class InMemoryLogRecordExporter {
|
|
|
92
114
|
attributes: logRecord.attributes,
|
|
93
115
|
};
|
|
94
116
|
}
|
|
117
|
+
_insertLogs(logsToInsert, resultCallback) {
|
|
118
|
+
this._db.insert(logsToInsert, (err, newDocs) => {
|
|
119
|
+
if (err) {
|
|
120
|
+
console.dir(err);
|
|
121
|
+
resultCallback({ code: ExportResultCode.FAILED });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
// console.dir(newDocs, { depth: 3 });
|
|
125
|
+
newDocs.forEach((doc) => this._miniSearch.add(doc));
|
|
126
|
+
resultCallback({ code: ExportResultCode.SUCCESS });
|
|
127
|
+
});
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
95
130
|
}
|
package/dist/esm/tlm-ai/tools.js
CHANGED
|
@@ -42,7 +42,7 @@ const getLogs = async (startDate, endDate) => {
|
|
|
42
42
|
}
|
|
43
43
|
const logs = [];
|
|
44
44
|
await new Promise((resolve, reject) => {
|
|
45
|
-
globalOasTlmConfig.
|
|
45
|
+
globalOasTlmConfig.logExporter.find(nedbQuery, null, (err, docs) => {
|
|
46
46
|
if (err) {
|
|
47
47
|
reject(err);
|
|
48
48
|
}
|
|
@@ -402,7 +402,7 @@ function getSimplifiedMetrics(metrics) {
|
|
|
402
402
|
// @ts-expect-error index signature
|
|
403
403
|
cpuUtilization[state] = stateSums[state] / stateCounts[state];
|
|
404
404
|
}
|
|
405
|
-
cpuCount = Math.max(...metric.dataPoints.map((dp) => parseInt(dp.attributes?.system?.cpu?.
|
|
405
|
+
cpuCount = Math.max(...metric.dataPoints.map((dp) => parseInt(dp.attributes?.system?.cpu?.logical_number || 0, 10))) + 1;
|
|
406
406
|
}
|
|
407
407
|
if (name === 'system.memory.usage') {
|
|
408
408
|
for (const dp of metric.dataPoints) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { globalOasTlmConfig } from '../config.js';
|
|
2
2
|
export const listLogs = async (req, res) => {
|
|
3
3
|
try {
|
|
4
|
-
const logs = globalOasTlmConfig.logExporter.
|
|
4
|
+
const logs = globalOasTlmConfig.logExporter.getFinishedLogs();
|
|
5
5
|
res.send({ logsCount: logs.length, logs: logs });
|
|
6
6
|
}
|
|
7
7
|
catch (err) {
|
|
@@ -34,3 +34,50 @@ export const resetLogs = (req, res) => {
|
|
|
34
34
|
globalOasTlmConfig.logExporter.reset();
|
|
35
35
|
res.send('Logs reset');
|
|
36
36
|
};
|
|
37
|
+
export const insertLogsToDb = async (req, res) => {
|
|
38
|
+
const jsonContent = req.body.logs;
|
|
39
|
+
const resetData = req.query.reset === 'true';
|
|
40
|
+
if (!Array.isArray(jsonContent)) {
|
|
41
|
+
res.status(400).send({ error: 'Invalid data format. Expected an array of JSON objects.' });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const cleanedLogs = jsonContent.map((log) => {
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
46
|
+
const { _id, ...rest } = log; // Remove _id if it exists
|
|
47
|
+
return rest; // Return the cleaned log object
|
|
48
|
+
});
|
|
49
|
+
try {
|
|
50
|
+
let message = '';
|
|
51
|
+
if (resetData) {
|
|
52
|
+
globalOasTlmConfig.logExporter.reset();
|
|
53
|
+
message += 'Logs Database reset. ';
|
|
54
|
+
}
|
|
55
|
+
await new Promise((resolve, reject) => {
|
|
56
|
+
globalOasTlmConfig.logExporter.insert(cleanedLogs, (err, newDocs) => {
|
|
57
|
+
if (err) {
|
|
58
|
+
console.error('Error inserting logs:', err);
|
|
59
|
+
return reject(err);
|
|
60
|
+
}
|
|
61
|
+
resolve(newDocs);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
message += `Inserted ${cleanedLogs.length} logs.`;
|
|
65
|
+
res.send({ message, InsertedLogsCount: cleanedLogs.length });
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
console.error(err);
|
|
69
|
+
res.status(500).send({ error: 'Failed to reset and insert data', details: err.message });
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
export const startLogs = (req, res) => {
|
|
73
|
+
globalOasTlmConfig.logExporter.start();
|
|
74
|
+
res.send('Log collection started');
|
|
75
|
+
};
|
|
76
|
+
export const stopLogs = (req, res) => {
|
|
77
|
+
globalOasTlmConfig.logExporter.stop();
|
|
78
|
+
res.send('Log collection stopped');
|
|
79
|
+
};
|
|
80
|
+
export const statusLogs = (req, res) => {
|
|
81
|
+
const isRunning = globalOasTlmConfig.logExporter.isRunning() || false;
|
|
82
|
+
res.send({ active: isRunning });
|
|
83
|
+
};
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
-
import { listLogs, findLogs,
|
|
2
|
+
import { startLogs, stopLogs, statusLogs, resetLogs, listLogs, findLogs, insertLogsToDb } from './logController.js';
|
|
3
3
|
export const logRoutes = Router();
|
|
4
|
+
// Logs Control
|
|
5
|
+
logRoutes.get('/start', startLogs);
|
|
6
|
+
logRoutes.get('/stop', stopLogs);
|
|
7
|
+
logRoutes.get('/status', statusLogs);
|
|
8
|
+
logRoutes.get('/reset', resetLogs);
|
|
4
9
|
logRoutes.get('/', listLogs);
|
|
10
|
+
logRoutes.post('/', insertLogsToDb);
|
|
5
11
|
logRoutes.post('/find', findLogs);
|
|
6
|
-
logRoutes.get('/reset', resetLogs);
|
|
7
12
|
export default logRoutes;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { globalOasTlmConfig } from '../config.js';
|
|
2
2
|
export const listMetrics = async (req, res) => {
|
|
3
3
|
try {
|
|
4
|
-
const metrics =
|
|
4
|
+
const metrics = globalOasTlmConfig.metricsExporter.getFinishedMetrics();
|
|
5
5
|
res.send({ metricsCount: metrics.length, metrics: metrics });
|
|
6
6
|
}
|
|
7
7
|
catch (err) {
|
|
@@ -26,3 +26,50 @@ export const resetMetrics = (req, res) => {
|
|
|
26
26
|
globalOasTlmConfig.metricsExporter.reset();
|
|
27
27
|
res.send('Metrics reset');
|
|
28
28
|
};
|
|
29
|
+
export const insertMetricsToDb = async (req, res) => {
|
|
30
|
+
const jsonContent = req.body.metrics;
|
|
31
|
+
const resetData = req.query.reset === 'true';
|
|
32
|
+
if (!Array.isArray(jsonContent)) {
|
|
33
|
+
res.status(400).send({ error: 'Invalid data format. Expected an array of JSON objects.' });
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const cleanedMetrics = jsonContent.map((metric) => {
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
38
|
+
const { _id, ...rest } = metric; // Remove _id if it exists
|
|
39
|
+
return rest; // Return the cleaned metric object
|
|
40
|
+
});
|
|
41
|
+
try {
|
|
42
|
+
let message = '';
|
|
43
|
+
if (resetData) {
|
|
44
|
+
globalOasTlmConfig.metricsExporter.reset();
|
|
45
|
+
message += 'Metrics Database reset. ';
|
|
46
|
+
}
|
|
47
|
+
await new Promise((resolve, reject) => {
|
|
48
|
+
globalOasTlmConfig.metricsExporter.insert(cleanedMetrics, (err, newDocs) => {
|
|
49
|
+
if (err) {
|
|
50
|
+
console.error('Error inserting metrics:', err);
|
|
51
|
+
return reject(err);
|
|
52
|
+
}
|
|
53
|
+
resolve(newDocs);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
message += `Inserted ${cleanedMetrics.length} metrics.`;
|
|
57
|
+
res.send({ message, InsertedMetricsCount: cleanedMetrics.length });
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
console.error(err);
|
|
61
|
+
res.status(500).send({ error: 'Failed to reset and insert data', details: err.message });
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
export const startMetrics = (req, res) => {
|
|
65
|
+
globalOasTlmConfig.metricsExporter.start();
|
|
66
|
+
res.send('Metrics collection started');
|
|
67
|
+
};
|
|
68
|
+
export const stopMetrics = (req, res) => {
|
|
69
|
+
globalOasTlmConfig.metricsExporter.stop();
|
|
70
|
+
res.send('Metrics collection stopped');
|
|
71
|
+
};
|
|
72
|
+
export const statusMetrics = (req, res) => {
|
|
73
|
+
const isRunning = globalOasTlmConfig.metricsExporter.isRunning() || false;
|
|
74
|
+
res.send({ active: isRunning });
|
|
75
|
+
};
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
-
import { listMetrics, findMetrics, resetMetrics } from './metricsController.js';
|
|
2
|
+
import { listMetrics, findMetrics, resetMetrics, insertMetricsToDb, startMetrics, stopMetrics, statusMetrics } from './metricsController.js';
|
|
3
3
|
export const metricsRoutes = Router();
|
|
4
4
|
// Metrics Control
|
|
5
5
|
metricsRoutes.get('/', listMetrics);
|
|
6
|
+
metricsRoutes.post('/', insertMetricsToDb);
|
|
6
7
|
metricsRoutes.post('/find', findMetrics);
|
|
7
8
|
metricsRoutes.get('/reset', resetMetrics);
|
|
9
|
+
metricsRoutes.get('/start', startMetrics);
|
|
10
|
+
metricsRoutes.get('/stop', stopMetrics);
|
|
11
|
+
metricsRoutes.get('/status', statusMetrics);
|
|
8
12
|
export default metricsRoutes;
|
|
@@ -52,3 +52,38 @@ export const findTelemetry = (req, res) => {
|
|
|
52
52
|
res.send({ spansCount: spans.length, spans: spans });
|
|
53
53
|
});
|
|
54
54
|
};
|
|
55
|
+
export const insertTracesToDb = async (req, res) => {
|
|
56
|
+
const jsonContent = req.body.spans;
|
|
57
|
+
const resetData = req.query.reset === 'true';
|
|
58
|
+
if (!Array.isArray(jsonContent)) {
|
|
59
|
+
res.status(400).send({ error: 'Invalid data format. Expected an array of JSON objects.' });
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const cleanedTraces = jsonContent.map((trace) => {
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
64
|
+
const { _id, ...rest } = trace; // Remove _id if it exists
|
|
65
|
+
return rest; // Return the cleaned trace object
|
|
66
|
+
});
|
|
67
|
+
try {
|
|
68
|
+
let message = '';
|
|
69
|
+
if (resetData) {
|
|
70
|
+
globalOasTlmConfig.dynamicSpanExporter.exporter.reset();
|
|
71
|
+
message += 'Traces Database reset. ';
|
|
72
|
+
}
|
|
73
|
+
await new Promise((resolve, reject) => {
|
|
74
|
+
globalOasTlmConfig.dynamicSpanExporter.exporter.insert(cleanedTraces, (err, newDocs) => {
|
|
75
|
+
if (err) {
|
|
76
|
+
console.error('Error inserting traces:', err);
|
|
77
|
+
return reject(err);
|
|
78
|
+
}
|
|
79
|
+
resolve(newDocs);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
message += `Inserted ${cleanedTraces.length} traces.`;
|
|
83
|
+
res.send({ message, InsertedTracesCount: cleanedTraces.length });
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
console.error(err);
|
|
87
|
+
res.status(500).send({ error: 'Failed to reset and insert data', details: err.message });
|
|
88
|
+
}
|
|
89
|
+
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
-
import { startTelemetry, stopTelemetry, statusTelemetry, resetTelemetry, listTelemetry, findTelemetry } from './traceController.js';
|
|
2
|
+
import { startTelemetry, stopTelemetry, statusTelemetry, resetTelemetry, listTelemetry, findTelemetry, insertTracesToDb } from './traceController.js';
|
|
3
3
|
export const traceRoutes = Router();
|
|
4
4
|
traceRoutes.get('/', listTelemetry);
|
|
5
|
+
traceRoutes.post('/', insertTracesToDb);
|
|
5
6
|
traceRoutes.post('/find', findTelemetry);
|
|
6
7
|
// Telemetry Control
|
|
7
8
|
traceRoutes.get('/start', startTelemetry);
|
|
@@ -3,4 +3,15 @@ import { specLoader, heapStats } from './utilController.js';
|
|
|
3
3
|
export const utilsRoutes = Router();
|
|
4
4
|
utilsRoutes.get('/spec', specLoader);
|
|
5
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
|
+
});
|
|
6
17
|
export default utilsRoutes;
|
package/dist/esm/tlmRoutes.js
CHANGED
|
@@ -24,7 +24,7 @@ export const configureRoutes = (router) => {
|
|
|
24
24
|
if (req.body !== undefined) {
|
|
25
25
|
return next(); // Already parsed, no need to parse again.
|
|
26
26
|
}
|
|
27
|
-
return json()(req, res, next);
|
|
27
|
+
return json({ limit: '10mb' })(req, res, next);
|
|
28
28
|
});
|
|
29
29
|
const allAuthMiddlewares = getWrappedMiddlewares(() => globalOasTlmConfig.authEnabled, [cookieParser(), authRoutes, authMiddleware]);
|
|
30
30
|
const baseURL = globalOasTlmConfig.baseURL;
|
|
@@ -12,4 +12,10 @@ export declare class InMemoryDBMetricsExporter {
|
|
|
12
12
|
find(search: any, callback: any): void;
|
|
13
13
|
reset(): void;
|
|
14
14
|
getFinishedMetrics(): import("@seald-io/nedb").Document<Record<string, any>>[];
|
|
15
|
+
/**
|
|
16
|
+
* Inserts metrics into the in-memory database.
|
|
17
|
+
* @param metrics - The metrics to insert.
|
|
18
|
+
* @param callback - The callback to execute after insertion.
|
|
19
|
+
*/
|
|
20
|
+
insert(metrics: any[], callback: (err: any, newDocs: any[]) => void): void;
|
|
15
21
|
}
|
|
@@ -21,4 +21,10 @@ export declare class InMemoryExporter implements OasTlmExporter {
|
|
|
21
21
|
find(search: any, callback: any): void;
|
|
22
22
|
reset(): void;
|
|
23
23
|
getFinishedSpans(): import("@seald-io/nedb").Document<Record<string, any>>[];
|
|
24
|
+
/**
|
|
25
|
+
* Inserts spans into the in-memory database.
|
|
26
|
+
* @param spans - The spans to insert.
|
|
27
|
+
* @param callback - The callback to execute after insertion.
|
|
28
|
+
*/
|
|
29
|
+
insert(spans: any[], callback: (err: any, newDocs: any[]) => void): void;
|
|
24
30
|
}
|
|
@@ -3,6 +3,7 @@ import { ReadableLogRecord, LogRecordExporter } from '@opentelemetry/sdk-logs';
|
|
|
3
3
|
export declare class InMemoryLogRecordExporter implements LogRecordExporter {
|
|
4
4
|
private _db;
|
|
5
5
|
private _miniSearch;
|
|
6
|
+
private _stopped;
|
|
6
7
|
constructor();
|
|
7
8
|
/**
|
|
8
9
|
* Export logs.
|
|
@@ -16,7 +17,11 @@ export declare class InMemoryLogRecordExporter implements LogRecordExporter {
|
|
|
16
17
|
*/
|
|
17
18
|
shutdown(): Promise<void>;
|
|
18
19
|
find(query: any, messageSearch: string | null, callback: (err: any, docs: any) => void): void;
|
|
19
|
-
|
|
20
|
+
insert(data: any[], callback: (err: any, newDocs: any[]) => void): void;
|
|
21
|
+
start(): void;
|
|
22
|
+
stop(): void;
|
|
23
|
+
isRunning(): boolean;
|
|
24
|
+
getFinishedLogs(): any[];
|
|
20
25
|
/**
|
|
21
26
|
* @copyright The OpenTelemetry Authors
|
|
22
27
|
* @license Apache-2.0
|
|
@@ -24,4 +29,5 @@ export declare class InMemoryLogRecordExporter implements LogRecordExporter {
|
|
|
24
29
|
* @param logRecord
|
|
25
30
|
*/
|
|
26
31
|
private _formatLogRecord;
|
|
32
|
+
private _insertLogs;
|
|
27
33
|
}
|
|
@@ -2,3 +2,7 @@ import { Request, Response } from 'express';
|
|
|
2
2
|
export declare const listLogs: (req: Request, res: Response) => Promise<void>;
|
|
3
3
|
export declare const findLogs: (req: Request, res: Response) => Promise<void>;
|
|
4
4
|
export declare const resetLogs: (req: Request, res: Response) => void;
|
|
5
|
+
export declare const insertLogsToDb: (req: Request, res: Response) => Promise<void>;
|
|
6
|
+
export declare const startLogs: (req: Request, res: Response) => void;
|
|
7
|
+
export declare const stopLogs: (req: Request, res: Response) => void;
|
|
8
|
+
export declare const statusLogs: (req: Request, res: Response) => void;
|
|
@@ -2,3 +2,7 @@ import { Request, Response } from 'express';
|
|
|
2
2
|
export declare const listMetrics: (req: Request, res: Response) => Promise<void>;
|
|
3
3
|
export declare const findMetrics: (req: Request, res: Response) => void;
|
|
4
4
|
export declare const resetMetrics: (req: Request, res: Response) => void;
|
|
5
|
+
export declare const insertMetricsToDb: (req: Request, res: Response) => Promise<void>;
|
|
6
|
+
export declare const startMetrics: (req: Request, res: Response) => void;
|
|
7
|
+
export declare const stopMetrics: (req: Request, res: Response) => void;
|
|
8
|
+
export declare const statusMetrics: (req: Request, res: Response) => void;
|
|
@@ -5,3 +5,4 @@ export declare const statusTelemetry: (req: Request, res: Response) => void;
|
|
|
5
5
|
export declare const resetTelemetry: (req: Request, res: Response) => void;
|
|
6
6
|
export declare const listTelemetry: (req: Request, res: Response) => Promise<void>;
|
|
7
7
|
export declare const findTelemetry: (req: Request, res: Response) => void;
|
|
8
|
+
export declare const insertTracesToDb: (req: Request, res: Response) => Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oas-tools/oas-telemetry",
|
|
3
|
-
"version": "0.7.0-alpha.
|
|
3
|
+
"version": "0.7.0-alpha.2",
|
|
4
4
|
"description": "Automatically collects and stores telemetry data in memory using OpenTelemetry. Just import the Express middleware to access it through the built-in REST API or web UI—no extra setup required.",
|
|
5
5
|
"author": "Manuel Otero",
|
|
6
6
|
"contributors": [
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"lint": "eslint --ext .ts . --fix"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
|
+
".env.example",
|
|
23
|
+
"NOTICE",
|
|
22
24
|
"dist"
|
|
23
25
|
],
|
|
24
26
|
"main": "./dist/cjs/index.cjs",
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _sdkNode = require("@opentelemetry/sdk-node");
|
|
4
|
-
var _resources = require("@opentelemetry/resources");
|
|
5
|
-
var _instrumentationHttp = require("@opentelemetry/instrumentation-http");
|
|
6
|
-
var _config = require("./config.cjs");
|
|
7
|
-
var _systemMetrics = require("./systemMetrics.cjs");
|
|
8
|
-
var _logger = _interopRequireDefault(require("./utils/logger.cjs"));
|
|
9
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
-
// import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
|
|
11
|
-
|
|
12
|
-
// Import system metrics functions
|
|
13
|
-
|
|
14
|
-
// DynamicExporter allows changing to any exporter at runtime;
|
|
15
|
-
const dynamicSpanExporter = _config.globalOasTlmConfig.dynamicSpanExporter;
|
|
16
|
-
// Alternative 1: Using NodeSDK
|
|
17
|
-
const sdk = new _sdkNode.NodeSDK({
|
|
18
|
-
resource: new _resources.Resource({
|
|
19
|
-
service: 'oas-telemetry-service'
|
|
20
|
-
}),
|
|
21
|
-
traceExporter: dynamicSpanExporter,
|
|
22
|
-
instrumentations: [new _instrumentationHttp.HttpInstrumentation()]
|
|
23
|
-
});
|
|
24
|
-
// Collect and export system metrics
|
|
25
|
-
setInterval(() => {
|
|
26
|
-
const cpuUsageData = (0, _systemMetrics.getCpuUsageData)();
|
|
27
|
-
const processCpuUsageData = (0, _systemMetrics.getProcessCpuUsageData)();
|
|
28
|
-
const memoryData = (0, _systemMetrics.getMemoryData)();
|
|
29
|
-
const processMemoryData = (0, _systemMetrics.getProcessMemoryData)();
|
|
30
|
-
const metrics = {
|
|
31
|
-
timestamp: Date.now(),
|
|
32
|
-
cpuUsageData,
|
|
33
|
-
processCpuUsageData,
|
|
34
|
-
memoryData,
|
|
35
|
-
processMemoryData
|
|
36
|
-
};
|
|
37
|
-
// Export the collected metrics using the InMemoryDBMetricsExporter
|
|
38
|
-
const inMemoryDbMetricExporter = _config.globalOasTlmConfig.metricsExporter;
|
|
39
|
-
inMemoryDbMetricExporter.export(metrics, () => {});
|
|
40
|
-
}, _config.globalOasTlmConfig.systemMetricsInterval);
|
|
41
|
-
_logger.default.info('✅ OpenTelemetry System Metrics initialized.');
|
|
42
|
-
if (process.env.OASTLM_MODULE_DISABLED !== 'true') {
|
|
43
|
-
sdk.start();
|
|
44
|
-
}
|
|
45
|
-
// Alternative 2:
|
|
46
|
-
// const provider = new NodeTracerProvider();
|
|
47
|
-
// provider.addSpanProcessor(new SimpleSpanProcessor(traceExporter));
|
|
48
|
-
// if (process.env.OASTLM_MODULE_DISABLED !== 'true') {
|
|
49
|
-
// provider.register();
|
|
50
|
-
// registerInstrumentations({
|
|
51
|
-
// instrumentations: [
|
|
52
|
-
// new HttpInstrumentation(),
|
|
53
|
-
// new ExpressInstrumentation(),
|
|
54
|
-
// ],
|
|
55
|
-
// });
|
|
56
|
-
// }
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.getCpuUsageData = getCpuUsageData;
|
|
7
|
-
exports.getMemoryData = getMemoryData;
|
|
8
|
-
exports.getProcessCpuUsageData = getProcessCpuUsageData;
|
|
9
|
-
exports.getProcessMemoryData = getProcessMemoryData;
|
|
10
|
-
var _os = require("os");
|
|
11
|
-
const MILLISECOND = 1 / 1e3;
|
|
12
|
-
const MICROSECOND = 1 / 1e6;
|
|
13
|
-
let prevOsData = {
|
|
14
|
-
time: Date.now(),
|
|
15
|
-
cpus: (0, _os.cpus)()
|
|
16
|
-
};
|
|
17
|
-
function getCpuUsageData() {
|
|
18
|
-
const currentTime = Date.now();
|
|
19
|
-
const timeElapsed = currentTime - prevOsData.time;
|
|
20
|
-
const currentOsData = {
|
|
21
|
-
time: currentTime,
|
|
22
|
-
cpus: (0, _os.cpus)()
|
|
23
|
-
};
|
|
24
|
-
const usageData = currentOsData.cpus.map((cpu, cpuNumber) => {
|
|
25
|
-
const prevTimes = prevOsData.cpus[cpuNumber].times;
|
|
26
|
-
const currTimes = cpu.times;
|
|
27
|
-
const idle = currTimes.idle * MILLISECOND;
|
|
28
|
-
const user = currTimes.user * MILLISECOND;
|
|
29
|
-
const system = currTimes.sys * MILLISECOND;
|
|
30
|
-
const interrupt = currTimes.irq * MILLISECOND;
|
|
31
|
-
const nice = currTimes.nice * MILLISECOND;
|
|
32
|
-
const idleP = (currTimes.idle - prevTimes.idle) / timeElapsed;
|
|
33
|
-
const userP = (currTimes.user - prevTimes.user) / timeElapsed;
|
|
34
|
-
const systemP = (currTimes.sys - prevTimes.sys) / timeElapsed;
|
|
35
|
-
const interruptP = (currTimes.irq - prevTimes.irq) / timeElapsed;
|
|
36
|
-
const niceP = (currTimes.nice - prevTimes.nice) / timeElapsed;
|
|
37
|
-
return {
|
|
38
|
-
cpuNumber: String(cpuNumber),
|
|
39
|
-
idle,
|
|
40
|
-
user,
|
|
41
|
-
system,
|
|
42
|
-
interrupt,
|
|
43
|
-
nice,
|
|
44
|
-
userP,
|
|
45
|
-
systemP,
|
|
46
|
-
idleP,
|
|
47
|
-
interruptP,
|
|
48
|
-
niceP
|
|
49
|
-
};
|
|
50
|
-
});
|
|
51
|
-
prevOsData = currentOsData;
|
|
52
|
-
return usageData;
|
|
53
|
-
}
|
|
54
|
-
let prevProcData = {
|
|
55
|
-
time: Date.now(),
|
|
56
|
-
usage: process.cpuUsage()
|
|
57
|
-
};
|
|
58
|
-
function getProcessCpuUsageData() {
|
|
59
|
-
const currentTime = Date.now();
|
|
60
|
-
const currentUsage = process.cpuUsage();
|
|
61
|
-
const prevUsage = prevProcData.usage;
|
|
62
|
-
const timeElapsed = (currentTime - prevProcData.time) * 1000;
|
|
63
|
-
const cpusTimeElapsed = timeElapsed * prevOsData.cpus.length;
|
|
64
|
-
const user = currentUsage.user * MICROSECOND;
|
|
65
|
-
const system = currentUsage.system * MICROSECOND;
|
|
66
|
-
const userP = (currentUsage.user - prevUsage.user) / cpusTimeElapsed;
|
|
67
|
-
const systemP = (currentUsage.system - prevUsage.system) / cpusTimeElapsed;
|
|
68
|
-
prevProcData = {
|
|
69
|
-
time: currentTime,
|
|
70
|
-
usage: currentUsage
|
|
71
|
-
};
|
|
72
|
-
return {
|
|
73
|
-
user,
|
|
74
|
-
system,
|
|
75
|
-
userP,
|
|
76
|
-
systemP
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
function getMemoryData() {
|
|
80
|
-
const total = (0, _os.totalmem)();
|
|
81
|
-
const free = (0, _os.freemem)();
|
|
82
|
-
const used = total - free;
|
|
83
|
-
const freeP = free / total;
|
|
84
|
-
const usedP = used / total;
|
|
85
|
-
return {
|
|
86
|
-
used,
|
|
87
|
-
free,
|
|
88
|
-
usedP,
|
|
89
|
-
freeP
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
function getProcessMemoryData() {
|
|
93
|
-
if (process.memoryUsage().rss) {
|
|
94
|
-
return process.memoryUsage().rss;
|
|
95
|
-
}
|
|
96
|
-
return 0;
|
|
97
|
-
}
|