better history for metrics

This commit is contained in:
KingKDot
2026-05-01 19:13:11 -05:00
parent 5380282726
commit 73c860c530
6 changed files with 54 additions and 9 deletions
+20 -2
View File
@@ -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)" },
},
},
+14 -1
View File
@@ -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);
+2 -2
View File
@@ -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", () => {
+17 -2
View File
@@ -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;
@@ -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 }), {