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