Skip to content

Commit 15475d6

Browse files
authored
Merge pull request #687 from gnmyt/features/prometheus
🔥 Prometheus Endpunkt hinzugefügt
2 parents fe1b90e + 750afb5 commit 15475d6

File tree

7 files changed

+131
-0
lines changed

7 files changed

+131
-0
lines changed

README.de.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ MySpeed ist eine Speedtest-Analyse-Software, welche die Geschwindigkeit deines I
2525
- 🗄️ Füge mehrere Server direkt zu einer MySpeed-Instanz hinzu
2626
- 🩺 Es lassen sich Healthchecks konfigurieren, welche dich bei Fehlern oder Ausfällen über E-Mail, Signal, WhatsApp oder Telegram benachrichtigen können
2727
- 📆 Testergebnisse lassen sich bis zu 30 Tage lang speichern
28+
- 🔥 Unterstützung für Prometheus und Grafana
29+
- 🗳️ Wähle zwischen Ookla, LibreSpeed und Cloudflare Speedtest-Servern
2830
- 💁 Erfahre mehr zu MySpeed auf unserer [Website](https://myspeed.dev)
2931

3032
### ⬇️ Installation

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ MySpeed is a speed test analysis software that records your internet speed for u
2525
- 🗄️ Add multiple servers directly to a MySpeed instance
2626
- 🩺 Configure health checks to notify you via email, Signal, WhatsApp, or Telegram in case of errors or downtime
2727
- 📆 Test results can be stored for up to 30 days
28+
- 🔥 Support for Prometheus and Grafana
29+
- 🗳️ Choose between Ookla, LibreSpeed and Cloudflare speed test servers
2830
- 💁 Learn more about MySpeed on our [website](https://myspeed.dev)
2931

3032
### ⬇️ Installation

package-lock.json

Lines changed: 61 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"express": "^4.19.2",
1818
"mysql2": "^3.9.7",
1919
"node-schedule": "^2.1.1",
20+
"prom-client": "^15.1.2",
2021
"sequelize": "^6.37.3",
2122
"sqlite3": "^5.1.7",
2223
"tmp": "^0.2.3"

server/controller/speedtests.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,19 @@ module.exports.removeOld = async () => {
144144
}
145145
});
146146
return true;
147+
}
148+
149+
module.exports.getLatest = async () => {
150+
let latest = await tests.findOne({order: [["created", "DESC"]]});
151+
if (latest.error === null) delete latest.error;
152+
if (latest.resultId === null) delete latest.resultId;
153+
return latest;
154+
}
155+
156+
module.exports.getLatest = async () => {
157+
let latest = await tests.findOne({order: [["created", "DESC"]]});
158+
if (latest === null) return undefined;
159+
if (latest.error === null) delete latest.error;
160+
if (latest.resultId === null) delete latest.resultId;
161+
return latest;
147162
}

server/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ app.use("/api/storage", require('./routes/storage'));
2424
app.use("/api/recommendations", require('./routes/recommendations'));
2525
app.use("/api/nodes", require('./routes/nodes'));
2626
app.use("/api/integrations", require('./routes/integrations'));
27+
app.use("/api/prometheus", require('./routes/prometheus'));
2728
app.use("/api*", (req, res) => res.status(404).json({message: "Route not found"}));
2829

2930
if (process.env.NODE_ENV === 'production') {

server/routes/prometheus.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
const express = require('express');
2+
const app = express.Router();
3+
const testController = require('../controller/speedtests');
4+
const promClient = require('prom-client');
5+
const config = require('../controller/config');
6+
const bcrypt = require('bcrypt');
7+
8+
const pingGauge = new promClient.Gauge({name: 'myspeed_ping', help: 'Current ping in ms'});
9+
const downloadGauge = new promClient.Gauge({name: 'myspeed_download', help: 'Current download speed in Mbps'});
10+
const uploadGauge = new promClient.Gauge({name: 'myspeed_upload', help: 'Current upload speed in Mbps'});
11+
const currentServerGauge = new promClient.Gauge({name: 'myspeed_server', help: 'Current server ID',});
12+
const timeGauge = new promClient.Gauge({name: 'myspeed_time', help: 'Time of the test'});
13+
14+
app.get('/metrics', async (req, res) => {
15+
let passwordHash = await config.getValue("password");
16+
17+
if (passwordHash !== "none") {
18+
if (!req.headers.authorization || req.headers.authorization.indexOf('Basic ') === -1) {
19+
res.setHeader('WWW-Authenticate', 'Basic realm="User Visible Realm"');
20+
return res.status(401).end('Unauthorized');
21+
}
22+
23+
const base64Credentials = req.headers.authorization.split(' ')[1];
24+
const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
25+
const [username, password] = credentials.split(':');
26+
27+
if (username !== "prometheus" || !bcrypt.compareSync(password, passwordHash)) {
28+
res.setHeader('WWW-Authenticate', 'Basic realm="User Visible Realm"');
29+
return res.status(401).end('Unauthorized');
30+
}
31+
}
32+
33+
const latest = await testController.getLatest();
34+
if (!latest) return res.status(500).end('No test found');
35+
36+
if (latest.error || latest.ping === -1)
37+
return res.status(500).end('Error in the latest test');
38+
39+
pingGauge.set(latest.ping);
40+
downloadGauge.set(latest.download);
41+
uploadGauge.set(latest.upload);
42+
currentServerGauge.set(latest.serverId);
43+
timeGauge.set(latest.time);
44+
45+
res.set('Content-Type', promClient.register.contentType);
46+
res.end(await promClient.register.metrics());
47+
});
48+
49+
module.exports = app;

0 commit comments

Comments
 (0)