From 73c860c5306165869ab710b5386eda3db58f6d52 Mon Sep 17 00:00:00 2001 From: KingKDot Date: Fri, 1 May 2026 19:13:11 -0500 Subject: [PATCH] better history for metrics --- Overlord-Server/public/assets/metrics.js | 22 +++++++++++++++++-- Overlord-Server/src/main-server.ts | 15 ++++++++++++- Overlord-Server/src/metrics.test.ts | 4 ++-- Overlord-Server/src/metrics.ts | 19 ++++++++++++++-- .../src/server/routes/misc-routes.ts | 2 -- go.work.sum | 1 + 6 files changed, 54 insertions(+), 9 deletions(-) diff --git a/Overlord-Server/public/assets/metrics.js b/Overlord-Server/public/assets/metrics.js index 7dab008..d1573d6 100644 --- a/Overlord-Server/public/assets/metrics.js +++ b/Overlord-Server/public/assets/metrics.js @@ -30,12 +30,16 @@ function initCharts() { backgroundColor: "rgba(96, 165, 250, 0.1)", fill: true, tension: 0.4, + pointRadius: 0, + pointHoverRadius: 4, + borderWidth: 2, }, ], }, options: { responsive: true, maintainAspectRatio: false, + animation: false, plugins: { legend: { display: false }, tooltip: { @@ -53,7 +57,12 @@ function initCharts() { grid: { color: "rgba(100, 116, 139, 0.1)" }, }, x: { - ticks: { color: "#94a3b8", maxTicksLimit: 10 }, + ticks: { + color: "#94a3b8", + maxTicksLimit: 6, + autoSkip: true, + maxRotation: 0, + }, grid: { color: "rgba(100, 116, 139, 0.1)" }, }, }, @@ -72,12 +81,16 @@ function initCharts() { backgroundColor: "rgba(192, 132, 252, 0.1)", fill: true, tension: 0.4, + pointRadius: 0, + pointHoverRadius: 4, + borderWidth: 2, }, ], }, options: { responsive: true, maintainAspectRatio: false, + animation: false, plugins: { legend: { display: false }, tooltip: { @@ -95,7 +108,12 @@ function initCharts() { grid: { color: "rgba(100, 116, 139, 0.1)" }, }, x: { - ticks: { color: "#94a3b8", maxTicksLimit: 10 }, + ticks: { + color: "#94a3b8", + maxTicksLimit: 6, + autoSkip: true, + maxRotation: 0, + }, grid: { color: "rgba(100, 116, 139, 0.1)" }, }, }, diff --git a/Overlord-Server/src/main-server.ts b/Overlord-Server/src/main-server.ts index f2800de..0646f9f 100644 --- a/Overlord-Server/src/main-server.ts +++ b/Overlord-Server/src/main-server.ts @@ -5,7 +5,7 @@ import { fileURLToPath } from "url"; import path from "path"; import fs from "fs/promises"; import { existsSync } from "node:fs"; -import { upsertClientRow, setOnlineState, listClients, markAllClientsOffline, getBuild, getBuildByTag, getAllBuilds, deleteExpiredBuilds, deleteBuild, getNotificationScreenshot, clearNotificationScreenshots, deleteClientRow, getClientIp, banIp, isIpBanned, clientExists, deleteExpiredSharedFiles, getChatHistory, insertChatMessage, getOnlineClientCountForUser, deleteExpiredChatMessages, recordBuildClaim } from "./db"; +import { upsertClientRow, setOnlineState, listClients, markAllClientsOffline, getBuild, getBuildByTag, getAllBuilds, deleteExpiredBuilds, deleteBuild, getNotificationScreenshot, clearNotificationScreenshots, deleteClientRow, getClientIp, banIp, isIpBanned, clientExists, deleteExpiredSharedFiles, getChatHistory, insertChatMessage, getOnlineClientCountForUser, deleteExpiredChatMessages, recordBuildClaim, getClientMetricsSummary } from "./db"; import { handleFrame, handleHello, handlePing, handlePong } from "./wsHandlers"; import { getMessageByteLength, getMaxPayloadLimit, isAllowedClientMessageType } from "./wsValidation"; import { ClientInfo, ClientRole } from "./types"; @@ -140,6 +140,19 @@ import type { SocketData } from "./sessions/types"; import { SERVER_VERSION } from "./version"; +metrics.setSnapshotEnricher((snapshot) => { + const summary = getClientMetricsSummary(); + snapshot.clients.total = summary.total; + snapshot.clients.online = summary.online; + snapshot.clients.offline = summary.total - summary.online; + snapshot.clients.byOS = summary.byOS; + snapshot.clients.byCountry = summary.byCountry; + snapshot.sessions.console = sessionManager.getConsoleSessionCount(); + snapshot.sessions.remoteDesktop = sessionManager.getRdSessionCount(); + snapshot.sessions.fileBrowser = sessionManager.getFileBrowserSessionCount(); + snapshot.sessions.process = sessionManager.getProcessSessionCount(); +}); + const config = loadConfig(); const isAuthorizedAgent = (req: Request, url: URL) => isAuthorizedAgentRequest(req, url, config.auth.agentToken); diff --git a/Overlord-Server/src/metrics.test.ts b/Overlord-Server/src/metrics.test.ts index 3710f70..cd0195b 100644 --- a/Overlord-Server/src/metrics.test.ts +++ b/Overlord-Server/src/metrics.test.ts @@ -178,13 +178,13 @@ describe("MetricsCollector", () => { }); test("history is capped at maxHistoryPoints", () => { - for (let i = 0; i < 100; i++) { + for (let i = 0; i < 4500; i++) { const snap = metrics.getSnapshot(); metrics.recordHistoryEntry(snap); } const history = metrics.getHistory(); - expect(history.length).toBeLessThanOrEqual(60); + expect(history.length).toBeLessThanOrEqual(4320); }); test("getHistory returns a copy", () => { diff --git a/Overlord-Server/src/metrics.ts b/Overlord-Server/src/metrics.ts index 4ceea69..b699256 100644 --- a/Overlord-Server/src/metrics.ts +++ b/Overlord-Server/src/metrics.ts @@ -94,7 +94,8 @@ class MetricsCollector { private receivedPerSecond: number = 0; private history: MetricsHistory[] = []; - private maxHistoryPoints: number = 60; + private maxHistoryPoints: number = 4320; + private snapshotEnricher: ((snapshot: MetricsSnapshot) => void) | null = null; private pingValues: number[] = []; private maxPingHistory: number = 1000; @@ -205,7 +206,21 @@ class MetricsCollector { return { min, max, avg, count: this.pingValues.length }; } - private recordHistory() {} + setSnapshotEnricher(fn: ((snapshot: MetricsSnapshot) => void) | null): void { + this.snapshotEnricher = fn; + } + + private recordHistory() { + const snapshot = this.getSnapshot(); + if (this.snapshotEnricher) { + try { + this.snapshotEnricher(snapshot); + } catch (err) { + console.error("metrics snapshot enricher failed:", err); + } + } + this.recordHistoryEntry(snapshot); + } private trackEventLoopDelay() { const intervalMs = 1000; diff --git a/Overlord-Server/src/server/routes/misc-routes.ts b/Overlord-Server/src/server/routes/misc-routes.ts index 70bb0cd..2a31f54 100644 --- a/Overlord-Server/src/server/routes/misc-routes.ts +++ b/Overlord-Server/src/server/routes/misc-routes.ts @@ -54,8 +54,6 @@ export async function handleMiscRoutes( snapshot.sessions.fileBrowser = deps.getFileBrowserSessionCount(); snapshot.sessions.process = deps.getProcessSessionCount(); - metrics.recordHistoryEntry(snapshot); - const history = metrics.getHistory(); return new Response(JSON.stringify({ snapshot, history }), { diff --git a/go.work.sum b/go.work.sum index 4aca735..6d4a6de 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,5 +1,6 @@ github.com/gen2brain/x264-go/x264c v0.0.0-20221204084822-82ee2951dea2 h1:4GzTsZK/uG+tHvWR2ORcTCGTC4+mgOPhkUdz/Ro9alg= github.com/gen2brain/x264-go/x264c v0.0.0-20221204084822-82ee2951dea2/go.mod h1:MUMv+ZURlTO3qH8QAt2gxiIY5X4NMaxObz2ImZOMvyA= +golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=