@oas-tools/oas-telemetry 0.2.0 → 0.2.1
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/LICENSE +200 -200
- package/README.md +133 -133
- package/dist/exporters/InMemoryDbExporter.cjs +72 -12
- package/dist/index.cjs +35 -21
- package/dist/ui.cjs +648 -539
- package/package.json +63 -63
- package/src/exporters/InMemoryDbExporter.js +154 -89
- package/src/index.js +197 -190
- package/src/telemetry.js +25 -25
- package/src/ui.js +887 -777
package/src/index.js
CHANGED
|
@@ -1,190 +1,197 @@
|
|
|
1
|
-
// telemetryMiddleware.js
|
|
2
|
-
import { inMemoryExporter } from './telemetry.js';
|
|
3
|
-
import { Router } from 'express';
|
|
4
|
-
import v8 from 'v8';
|
|
5
|
-
import {readFileSync,existsSync} from 'fs';
|
|
6
|
-
import path from 'path';
|
|
7
|
-
import yaml from 'js-yaml';
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
router.get(baseURL,
|
|
47
|
-
router.get(baseURL+"/
|
|
48
|
-
router.get(baseURL+"/
|
|
49
|
-
router.get(baseURL+"/
|
|
50
|
-
router.
|
|
51
|
-
router.get(baseURL+"/
|
|
52
|
-
|
|
53
|
-
router
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
<li><a href="/telemetry/
|
|
66
|
-
<li
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
res.send(
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
res.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
res.send(
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
1
|
+
// telemetryMiddleware.js
|
|
2
|
+
import { inMemoryExporter } from './telemetry.js';
|
|
3
|
+
import { Router } from 'express';
|
|
4
|
+
import v8 from 'v8';
|
|
5
|
+
import { readFileSync, existsSync } from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import yaml from 'js-yaml';
|
|
8
|
+
import ui from './ui.js'
|
|
9
|
+
|
|
10
|
+
let baseURL = '/telemetry';
|
|
11
|
+
|
|
12
|
+
let telemetryConfig = {
|
|
13
|
+
exporter: inMemoryExporter,
|
|
14
|
+
specFileName: ""
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default function oasTelemetry(tlConfig) {
|
|
18
|
+
if (tlConfig) {
|
|
19
|
+
console.log('Telemetry config provided');
|
|
20
|
+
telemetryConfig = tlConfig;
|
|
21
|
+
if (telemetryConfig.exporter == undefined)
|
|
22
|
+
telemetryConfig.exporter = inMemoryExporter;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (telemetryConfig.spec)
|
|
26
|
+
console.log(`Spec content provided`);
|
|
27
|
+
else {
|
|
28
|
+
if (telemetryConfig.specFileName != "")
|
|
29
|
+
console.log(`Spec file used for telemetry: ${telemetryConfig.specFileName}`);
|
|
30
|
+
else {
|
|
31
|
+
console.log("No spec available !");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
const router = Router();
|
|
38
|
+
|
|
39
|
+
//const baseURL = telemetryConfig.baseURL;
|
|
40
|
+
|
|
41
|
+
router.get(baseURL, mainPage);
|
|
42
|
+
router.get(baseURL + "/detail/*", detailPage);
|
|
43
|
+
router.get(baseURL + "/spec", specLoader);
|
|
44
|
+
router.get(baseURL + "/api", apiPage);
|
|
45
|
+
router.get(baseURL + "/start", startTelemetry);
|
|
46
|
+
router.get(baseURL + "/stop", stopTelemetry);
|
|
47
|
+
router.get(baseURL + "/status", statusTelemetry);
|
|
48
|
+
router.get(baseURL + "/reset", resetTelemetry);
|
|
49
|
+
router.get(baseURL + "/list", listTelemetry);
|
|
50
|
+
router.post(baseURL + "/find", findTelemetry);
|
|
51
|
+
router.get(baseURL + "/heapStats", heapStats);
|
|
52
|
+
|
|
53
|
+
return router;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const apiPage = (req, res) => {
|
|
57
|
+
let text = `
|
|
58
|
+
<h1>Telemetry API routes:</h1>
|
|
59
|
+
<ul>
|
|
60
|
+
<li><a href="/telemetry/start">/telemetry/start</a></li>
|
|
61
|
+
<li><a href="/telemetry/stop">/telemetry/stop</a></li>
|
|
62
|
+
<li><a href="/telemetry/status">/telemetry/status</a></li>
|
|
63
|
+
<li><a href="/telemetry/reset">/telemetry/reset</a></li>
|
|
64
|
+
<li><a href="/telemetry/list">/telemetry/list</a></li>
|
|
65
|
+
<li><a href="/telemetry/heapStats">/telemetry/heapStats</a></li>
|
|
66
|
+
<li>/telemetry/find [POST]</li>
|
|
67
|
+
</ul>
|
|
68
|
+
`;
|
|
69
|
+
res.send(text);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const mainPage = (req, res) => {
|
|
73
|
+
res.set('Content-Type', 'text/html');
|
|
74
|
+
res.send(ui().main);
|
|
75
|
+
}
|
|
76
|
+
const detailPage = (req, res) => {
|
|
77
|
+
res.set('Content-Type', 'text/html');
|
|
78
|
+
res.send(ui().detail);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const specLoader = (req, res) => {
|
|
82
|
+
if (telemetryConfig.specFileName) {
|
|
83
|
+
try {
|
|
84
|
+
const data = readFileSync(telemetryConfig.specFileName,
|
|
85
|
+
{ encoding: 'utf8', flag: 'r' });
|
|
86
|
+
|
|
87
|
+
const extension = path.extname(telemetryConfig.specFileName);
|
|
88
|
+
|
|
89
|
+
let json = data;
|
|
90
|
+
|
|
91
|
+
if (extension == yaml)
|
|
92
|
+
json = JSON.stringify(yaml.SafeLoad(data), null, 2);
|
|
93
|
+
|
|
94
|
+
res.setHeader('Content-Type', 'application/json');
|
|
95
|
+
res.send(json);
|
|
96
|
+
|
|
97
|
+
} catch (e) {
|
|
98
|
+
console.error(`ERROR loading spec file ${telemetryConfig.specFileName}: ${e}`)
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
if (telemetryConfig.spec) {
|
|
102
|
+
let spec = false;
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
spec = JSON.parse(telemetryConfig.spec);
|
|
106
|
+
} catch (ej) {
|
|
107
|
+
try {
|
|
108
|
+
spec = JSON.stringify(yaml.load(telemetryConfig.spec), null, 2);
|
|
109
|
+
} catch (ey) {
|
|
110
|
+
console.error(`Error parsing spec: ${ej} - ${ey}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (!spec) {
|
|
115
|
+
res.status(404);
|
|
116
|
+
} else {
|
|
117
|
+
res.setHeader('Content-Type', 'application/json');
|
|
118
|
+
res.send(spec);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
const startTelemetry = (req, res) => {
|
|
127
|
+
telemetryConfig.exporter.start();
|
|
128
|
+
res.send('Telemetry started');
|
|
129
|
+
}
|
|
130
|
+
const stopTelemetry = (req, res) => {
|
|
131
|
+
telemetryConfig.exporter.stop();
|
|
132
|
+
|
|
133
|
+
res.send('Telemetry stopped');
|
|
134
|
+
}
|
|
135
|
+
const statusTelemetry = (req, res) => {
|
|
136
|
+
const status = !telemetryConfig.exporter._stopped || false;
|
|
137
|
+
res.send({ active: status });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
const resetTelemetry = (req, res) => {
|
|
142
|
+
telemetryConfig.exporter.reset();
|
|
143
|
+
res.send('Telemetry reset');
|
|
144
|
+
}
|
|
145
|
+
const listTelemetry = (req, res) => {
|
|
146
|
+
const spansDB = telemetryConfig.exporter.getFinishedSpans();
|
|
147
|
+
spansDB.find({}, (err, docs) => {
|
|
148
|
+
if (err) {
|
|
149
|
+
console.error(err);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const spans = docs;
|
|
153
|
+
res.send({ spansCount: spans.length, spans: spans });
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const findTelemetry = (req, res) => {
|
|
158
|
+
const spansDB = telemetryConfig.exporter.getFinishedSpans();
|
|
159
|
+
const body = req.body;
|
|
160
|
+
const search = body?.search ? body.search : {};
|
|
161
|
+
if (body?.flags?.containsRegex) {
|
|
162
|
+
try {
|
|
163
|
+
body.config?.regexIds?.forEach(regexId => {
|
|
164
|
+
search[regexId] = new RegExp(search[regexId]);
|
|
165
|
+
});
|
|
166
|
+
} catch (e) {
|
|
167
|
+
console.error(e);
|
|
168
|
+
res.status(404).send({ spansCount: 0, spans: [], error: e });
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
spansDB.find(search, (err, docs) => {
|
|
172
|
+
if (err) {
|
|
173
|
+
console.error(err);
|
|
174
|
+
res.status(404).send({ spansCount: 0, spans: [], error: err });
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const spans = docs;
|
|
179
|
+
res.send({ spansCount: spans.length, spans: spans });
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const heapStats = (req, res) => {
|
|
185
|
+
var heapStats = v8.getHeapStatistics();
|
|
186
|
+
|
|
187
|
+
// Round stats to MB
|
|
188
|
+
var roundedHeapStats = Object.getOwnPropertyNames(heapStats).reduce(function (map, stat) {
|
|
189
|
+
map[stat] = Math.round((heapStats[stat] / 1024 / 1024) * 1000) / 1000;
|
|
190
|
+
return map;
|
|
191
|
+
}, {});
|
|
192
|
+
roundedHeapStats['units'] = 'MB';
|
|
193
|
+
|
|
194
|
+
res.send(roundedHeapStats);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
|
package/src/telemetry.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// tracing.js
|
|
4
|
-
|
|
5
|
-
'use strict'
|
|
6
|
-
|
|
7
|
-
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
8
|
-
// import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
|
|
9
|
-
import { Resource } from '@opentelemetry/resources';
|
|
10
|
-
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
|
|
11
|
-
import { InMemoryExporter } from './exporters/InMemoryDbExporter.js';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// Create an in-memory span exporter
|
|
15
|
-
export const inMemoryExporter = new InMemoryExporter();
|
|
16
|
-
|
|
17
|
-
const traceExporter = inMemoryExporter;
|
|
18
|
-
const sdk = new NodeSDK({
|
|
19
|
-
resource: new Resource(),
|
|
20
|
-
traceExporter,
|
|
21
|
-
instrumentations: [new HttpInstrumentation()]
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
sdk.start()
|
|
25
|
-
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
// tracing.js
|
|
4
|
+
|
|
5
|
+
'use strict'
|
|
6
|
+
|
|
7
|
+
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
8
|
+
// import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
|
|
9
|
+
import { Resource } from '@opentelemetry/resources';
|
|
10
|
+
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
|
|
11
|
+
import { InMemoryExporter } from './exporters/InMemoryDbExporter.js';
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
// Create an in-memory span exporter
|
|
15
|
+
export const inMemoryExporter = new InMemoryExporter();
|
|
16
|
+
|
|
17
|
+
const traceExporter = inMemoryExporter;
|
|
18
|
+
const sdk = new NodeSDK({
|
|
19
|
+
resource: new Resource(),
|
|
20
|
+
traceExporter,
|
|
21
|
+
instrumentations: [new HttpInstrumentation()]
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
sdk.start()
|
|
25
|
+
|