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; +}