From 71657a013b0e9ab7389c49291fcd463fdd8856c8 Mon Sep 17 00:00:00 2001
From: Bernd Storath <999999bst@gmail.com>
Date: Mon, 10 Feb 2025 13:18:44 +0100
Subject: [PATCH] rewrite prometheus and json metric endpoints
---
src/app/components/ClientCard/Avatar.vue | 8 ++-
src/server/routes/metrics/index.get.ts | 4 --
src/server/routes/metrics/json.get.ts | 32 +++++++++
src/server/routes/metrics/prometheus.get.ts | 67 +++++++++++++++++++
src/server/utils/metrics.ts | 74 ---------------------
src/shared/utils/time.ts | 10 +++
6 files changed, 114 insertions(+), 81 deletions(-)
delete mode 100644 src/server/routes/metrics/index.get.ts
create mode 100644 src/server/routes/metrics/prometheus.get.ts
delete mode 100644 src/server/utils/metrics.ts
create mode 100644 src/shared/utils/time.ts
diff --git a/src/app/components/ClientCard/Avatar.vue b/src/app/components/ClientCard/Avatar.vue
index 2f3cfd06..319fd7dc 100644
--- a/src/app/components/ClientCard/Avatar.vue
+++ b/src/app/components/ClientCard/Avatar.vue
@@ -6,9 +6,11 @@
{
- setHeader(event, 'Content-Type', 'text/plain');
- return getPrometheusResponse();
-});
diff --git a/src/server/routes/metrics/json.get.ts b/src/server/routes/metrics/json.get.ts
index e89e64b8..e06569a1 100644
--- a/src/server/routes/metrics/json.get.ts
+++ b/src/server/routes/metrics/json.get.ts
@@ -1,3 +1,35 @@
export default defineMetricsHandler('prometheus', async () => {
return getMetricsJSON();
});
+
+async function getMetricsJSON() {
+ const clients = await WireGuard.getClients();
+ let wireguardPeerCount = 0;
+ let wireguardEnabledPeersCount = 0;
+ let wireguardConnectedPeersCount = 0;
+ for (const client of clients) {
+ wireguardPeerCount++;
+ if (client.enabled === true) {
+ wireguardEnabledPeersCount++;
+ }
+ if (isPeerConnected(client)) {
+ wireguardConnectedPeersCount++;
+ }
+ }
+ return {
+ wireguard_configured_peers: wireguardPeerCount,
+ wireguard_enabled_peers: wireguardEnabledPeersCount,
+ wireguard_connected_peers: wireguardConnectedPeersCount,
+ clients: clients.map((client) => ({
+ name: client.name,
+ enabled: client.enabled,
+ ipv4Address: client.ipv4Address,
+ ipv6Address: client.ipv6Address,
+ publicKey: client.publicKey,
+ endpoint: client.endpoint,
+ latestHandshakeAt: client.latestHandshakeAt,
+ transferRx: client.transferRx,
+ transferTx: client.transferTx,
+ })),
+ };
+}
diff --git a/src/server/routes/metrics/prometheus.get.ts b/src/server/routes/metrics/prometheus.get.ts
new file mode 100644
index 00000000..762e6663
--- /dev/null
+++ b/src/server/routes/metrics/prometheus.get.ts
@@ -0,0 +1,67 @@
+export default defineMetricsHandler('prometheus', async ({ event }) => {
+ setHeader(event, 'Content-Type', 'text/plain');
+ return getPrometheusResponse();
+});
+
+async function getPrometheusResponse() {
+ const clients = await WireGuard.getClients();
+ let wireguardPeerCount = 0;
+ let wireguardEnabledPeersCount = 0;
+ let wireguardConnectedPeersCount = 0;
+ const wireguardSentBytes = [];
+ const wireguardReceivedBytes = [];
+ const wireguardLatestHandshakeSeconds = [];
+ for (const client of clients) {
+ wireguardPeerCount++;
+ if (client.enabled === true) {
+ wireguardEnabledPeersCount++;
+ }
+
+ if (isPeerConnected(client)) {
+ wireguardConnectedPeersCount++;
+ }
+
+ const id = `interface="wg0",enabled="${client.enabled}",ipv4Address="${client.ipv4Address}",ipv6Address="${client.ipv6Address}",name="${client.name}"`;
+
+ wireguardSentBytes.push(
+ `wireguard_sent_bytes{${id}} ${client.transferTx ?? 0}`
+ );
+ wireguardReceivedBytes.push(
+ `wireguard_received_bytes{${id}} ${client.transferRx ?? 0}`
+ );
+ // TODO: if latestHandshakeAt is null this would result in client showing as online?
+ wireguardLatestHandshakeSeconds.push(
+ `wireguard_latest_handshake_seconds{${id}} ${client.latestHandshakeAt ? (Date.now() - client.latestHandshakeAt.getTime()) / 1000 : 0}`
+ );
+ }
+
+ const returnText = [
+ '# HELP wg-easy and wireguard metrics',
+ '',
+ '# HELP wireguard_configured_peers',
+ '# TYPE wireguard_configured_peers gauge',
+ `wireguard_configured_peers{interface="wg0"} ${wireguardPeerCount}`,
+ '',
+ '# HELP wireguard_enabled_peers',
+ '# TYPE wireguard_enabled_peers gauge',
+ `wireguard_enabled_peers{interface="wg0"} ${wireguardEnabledPeersCount}`,
+ '',
+ '# HELP wireguard_connected_peers',
+ '# TYPE wireguard_connected_peers gauge',
+ `wireguard_connected_peers{interface="wg0"} ${wireguardConnectedPeersCount}`,
+ '',
+ '# HELP wireguard_sent_bytes Bytes sent to the peer',
+ '# TYPE wireguard_sent_bytes counter',
+ `${wireguardSentBytes.join('\n')}`,
+ '',
+ '# HELP wireguard_received_bytes Bytes received from the peer',
+ '# TYPE wireguard_received_bytes counter',
+ `${wireguardReceivedBytes.join('\n')}`,
+ '',
+ '# HELP wireguard_latest_handshake_seconds UNIX timestamp seconds of the last handshake',
+ '# TYPE wireguard_latest_handshake_seconds gauge',
+ `${wireguardLatestHandshakeSeconds.join('\n')}`,
+ ];
+
+ return returnText.join('\n');
+}
diff --git a/src/server/utils/metrics.ts b/src/server/utils/metrics.ts
deleted file mode 100644
index 9c007c66..00000000
--- a/src/server/utils/metrics.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-// TODO: rewrite
-
-export async function getPrometheusResponse() {
- const clients = await WireGuard.getClients();
- let wireguardPeerCount = 0;
- let wireguardEnabledPeersCount = 0;
- let wireguardConnectedPeersCount = 0;
- let wireguardSentBytes = '';
- let wireguardReceivedBytes = '';
- let wireguardLatestHandshakeSeconds = '';
- for (const client of clients) {
- wireguardPeerCount++;
- if (client.enabled === true) {
- wireguardEnabledPeersCount++;
- }
- if (client.endpoint !== null) {
- wireguardConnectedPeersCount++;
- }
- wireguardSentBytes += `wireguard_sent_bytes{interface="wg0",enabled="${client.enabled}",ipv4Address="${client.ipv4Address}",ipv6Address="${client.ipv6Address}",name="${client.name}"} ${Number(client.transferTx)}\n`;
- wireguardReceivedBytes += `wireguard_received_bytes{interface="wg0",enabled="${client.enabled}",ipv4Address="${client.ipv4Address}",ipv6Address="${client.ipv6Address}",name="${client.name}"} ${Number(client.transferRx)}\n`;
- wireguardLatestHandshakeSeconds += `wireguard_latest_handshake_seconds{interface="wg0",enabled="${client.enabled}",ipv4Address="${client.ipv4Address}",ipv6Address="${client.ipv6Address}",name="${client.name}"} ${client.latestHandshakeAt ? (new Date().getTime() - new Date(client.latestHandshakeAt).getTime()) / 1000 : 0}\n`;
- }
-
- let returnText = '# HELP wg-easy and wireguard metrics\n';
-
- returnText += '\n# HELP wireguard_configured_peers\n';
- returnText += '# TYPE wireguard_configured_peers gauge\n';
- returnText += `wireguard_configured_peers{interface="wg0"} ${wireguardPeerCount}\n`;
-
- returnText += '\n# HELP wireguard_enabled_peers\n';
- returnText += '# TYPE wireguard_enabled_peers gauge\n';
- returnText += `wireguard_enabled_peers{interface="wg0"} ${wireguardEnabledPeersCount}\n`;
-
- returnText += '\n# HELP wireguard_connected_peers\n';
- returnText += '# TYPE wireguard_connected_peers gauge\n';
- returnText += `wireguard_connected_peers{interface="wg0"} ${wireguardConnectedPeersCount}\n`;
-
- returnText += '\n# HELP wireguard_sent_bytes Bytes sent to the peer\n';
- returnText += '# TYPE wireguard_sent_bytes counter\n';
- returnText += `${wireguardSentBytes}`;
-
- returnText +=
- '\n# HELP wireguard_received_bytes Bytes received from the peer\n';
- returnText += '# TYPE wireguard_received_bytes counter\n';
- returnText += `${wireguardReceivedBytes}`;
-
- returnText +=
- '\n# HELP wireguard_latest_handshake_seconds UNIX timestamp seconds of the last handshake\n';
- returnText += '# TYPE wireguard_latest_handshake_seconds gauge\n';
- returnText += `${wireguardLatestHandshakeSeconds}`;
-
- return returnText;
-}
-
-export async function getMetricsJSON() {
- const clients = await WireGuard.getClients();
- let wireguardPeerCount = 0;
- let wireguardEnabledPeersCount = 0;
- let wireguardConnectedPeersCount = 0;
- for (const client of clients) {
- wireguardPeerCount++;
- if (client.enabled === true) {
- wireguardEnabledPeersCount++;
- }
- if (client.endpoint !== null) {
- wireguardConnectedPeersCount++;
- }
- }
- return {
- wireguard_configured_peers: wireguardPeerCount,
- wireguard_enabled_peers: wireguardEnabledPeersCount,
- wireguard_connected_peers: wireguardConnectedPeersCount,
- };
-}
diff --git a/src/shared/utils/time.ts b/src/shared/utils/time.ts
new file mode 100644
index 00000000..3d4085e4
--- /dev/null
+++ b/src/shared/utils/time.ts
@@ -0,0 +1,10 @@
+export function isPeerConnected(client: { latestHandshakeAt: Date | null }) {
+ if (!client.latestHandshakeAt) {
+ return false;
+ }
+
+ const lastHandshakeMs = Date.now() - client.latestHandshakeAt.getTime();
+
+ // connected if last handshake was less than 10 minutes ago
+ return lastHandshakeMs < 1000 * 60 * 10;
+}