better history for metrics
This commit is contained in:
@@ -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)" },
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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", () => {
|
||||
|
||||
@@ -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 }), {
|
||||
|
||||
@@ -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=
|
||||
|
||||
Reference in New Issue
Block a user