Repository navigation
Expand file tree
/
Copy pathindex.js
More file actions
123 lines (107 loc) · 3.02 KB
/
Copy pathindex.js
File metadata and controls
123 lines (107 loc) · 3.02 KB
1
2
3
4
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
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
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
const prometheusClient = require('prom-client');
const {
Counter, Gauge, Histogram, register: defaultRegister, Registry, Summary,
} = prometheusClient;
const defaultOptions = {
addRouteMetrics: true,
collectDefaultMetrics: true,
authorization: null,
};
let metrics = {};
let register = null;
const toSnakeCase = (string) => string.toLowerCase()
.replace(/[^a-z]+/ig, ' ')
.trim()
.replace(/\s/ig, '_');
const getMetric = (type, name, options) => {
if (!name) {
throw new Error('The name of the metric is missing');
}
const snakeCaseName = toSnakeCase(name);
const metric = metrics[snakeCaseName];
if (metric) {
return metric;
}
switch (type) {
case 'counter':
metrics[snakeCaseName] = new Counter({
name: snakeCaseName,
help: snakeCaseName,
registers: [register],
...(options.labelNames && {
labelNames: options.labelNames,
}),
});
break;
case 'gauge':
metrics[snakeCaseName] = new Gauge({
name: snakeCaseName,
help: snakeCaseName,
registers: [register],
});
break;
case 'histogram':
metrics[snakeCaseName] = new Histogram({
name: snakeCaseName,
help: snakeCaseName,
registers: [register],
});
break;
case 'summary':
metrics[snakeCaseName] = new Summary({
name: snakeCaseName,
help: snakeCaseName,
percentiles: [0.1, 0.5, 0.9, 0.99],
maxAgeSeconds: 600,
ageBuckets: 5,
registers: [register],
});
break;
// no default
}
return metrics[snakeCaseName];
};
const getGauge = (name, labelNames) => getMetric('gauge', name, { labelNames });
const getCounter = (name, labelNames) => getMetric('counter', name, { labelNames });
const getHistogram = (name) => getMetric('histogram', name);
const getSummary = (name) => getMetric('summary', name);
const initPrometheus = (app, parameterOptions) => {
if (!app) {
throw new Error('Missing express express app parameter.');
}
const options = { ...defaultOptions, ...parameterOptions };
defaultRegister.clear();
register = new Registry();
metrics = {};
if (options.collectDefaultMetrics) {
prometheusClient.collectDefaultMetrics({ register });
}
app.get('/metrics', async (_, res) => {
try {
res.set('Content-Type', register.contentType);
res.send(await register.metrics());
} catch (err) {
res.sendStatus(500);
}
});
if (options.addRouteMetrics) {
app.use((req, res, next) => {
req.startTime = Date.now();
req.on('close', () => {
const code = `${`${res.statusCode}`[0]}00`;
const path = `${req.method} ${(req.route && req.route.path) || 'No path'}`;
const elapsedTime = Date.now() - req.startTime;
getCounter(`${path} status code`, ['code']).inc({ code });
getSummary(`${path} response time`).observe(elapsedTime);
});
next();
});
}
};
module.exports = {
initPrometheus,
getCounter,
getGauge,
getHistogram,
getSummary,
};