feat: live system metrics (CPU, RAM, Disk, GPU, Temp)

This commit is contained in:
Hitonabi
2026-06-20 21:19:58 +02:00
parent 6c0ba255fe
commit 08eab95178
6 changed files with 125 additions and 4 deletions
+13
View File
@@ -13,6 +13,7 @@ import jobs from "./panels/jobs.js";
const panels = [overview, models, maintenance, jobs];
let lastJobs = [];
let lastSystem = null;
// ---- Topbar / Alert aus dem Status ableiten ----
function applyStatus(s) {
@@ -40,6 +41,11 @@ function applyJobs(jobs) {
for (const p of panels) p.onJobs?.(lastJobs);
}
function applySystem(sys) {
lastSystem = sys;
for (const p of panels) p.onSystem?.(sys);
}
function showAlert(html, warn) {
const a = $("#alert");
a.className = "alert" + (warn ? " warn" : "");
@@ -58,6 +64,11 @@ async function pollJobs() {
catch { /* still */ }
}
async function pollSystem() {
try { applySystem(await api("/api/system/status")); }
catch { /* still */ }
}
// ---- Boot ----
function bootToken() {
const i = $("#token");
@@ -76,6 +87,8 @@ document.addEventListener("mc:refresh", pollStatus);
pollStatus();
pollJobs();
pollSystem();
setInterval(tickClock, 1000);
setInterval(pollStatus, 3000);
setInterval(pollJobs, 1500);
setInterval(pollSystem, 3000);
+18 -3
View File
@@ -5,6 +5,7 @@ import { $, icon, esc } from "../core/ui.js";
let S = null; // letzter Status
let J = []; // letzte Job-Liste
let SYS = null; // letzte System-Auslastung
const RUNNING = new Set(["running", "ready", "loading", "starting"]);
@@ -52,6 +53,9 @@ function kpi(cls, title, ic, value, sub) {
function renderKpis() {
const c = counts();
const sysV = SYS ? `${SYS.cpu.percent.toFixed(0)}<small>% CPU</small>` : "n/a";
const sysS = SYS ? `${SYS.ram.percent.toFixed(0)}% RAM, ${SYS.gpu_temp ? SYS.gpu_temp.toFixed(0)+'°C' : SYS.cpu.temp ? SYS.cpu.temp.toFixed(0)+'°C' : ''}` : "bald · Live-Auslastung";
$("#kpis").innerHTML =
kpi(c.swap ? "green" : "red", "llama-swap", "swap",
c.swap ? "Online" : "Offline", "Transport-Status") +
@@ -59,7 +63,7 @@ function renderKpis() {
`${c.running}<small>/${c.total}</small>`, "aktiv / gesamt") +
kpi("purple", "Jobs", "layers", c.jobsRun, "laufend") +
kpi(c.jobsErr ? "red" : "muted", "Fehler", "alert", c.jobsErr, "in der Aktivität") +
kpi("muted", "System-Last", "gauge", "n/a", "bald · Live-Auslastung");
kpi(SYS ? "blue" : "muted", "System-Last", "gauge", sysV, sysS);
}
function kvRow(k, v, cls = "") {
@@ -68,6 +72,16 @@ function kvRow(k, v, cls = "") {
function renderHealth() {
const c = counts();
let sysRow = kvRow("Auslastung (RAM/GPU/Disk)", "folgt", "na");
if (SYS) {
const gb = b => (b / 1024 / 1024 / 1024).toFixed(1);
const ram = `${gb(SYS.ram.used)}GB / ${gb(SYS.ram.total)}GB`;
const gpu = (SYS.gpu && SYS.gpu.vram.total) ? `${gb(SYS.gpu.vram.used + SYS.gpu.gtt.used)}GB / ${gb(SYS.gpu.vram.total + SYS.gpu.gtt.total)}GB` : "";
const disk = `${SYS.disk.percent.toFixed(0)}%`;
sysRow = kvRow("Auslastung (RAM/GPU/Disk)", `${ram} | ${gpu} | ${disk}`);
}
$("#health").innerHTML = `
<div class="card-h"><h3>Stack-Gesundheit</h3>
<span class="meta ${c.swap ? "ok" : ""}">${c.swap ? "Connected" : "Offline"}</span></div>
@@ -77,7 +91,7 @@ function renderHealth() {
${kvRow("Aktiv", c.running, c.running ? "ok" : "")}
${kvRow("Jobs (laufend)", c.jobsRun)}
${kvRow("Fehler", c.jobsErr, c.jobsErr ? "bad" : "")}
${kvRow("Auslastung (RAM/GPU/Disk)", "folgt", "na")}
${sysRow}
</div>`;
}
@@ -113,5 +127,6 @@ function renderAll() { renderHero(); renderKpis(); renderHealth(); renderModels(
function mount() { renderAll(); }
function onStatus(s) { S = s; renderAll(); }
function onJobs(jobs) { J = jobs || []; renderHero(); renderKpis(); renderHealth(); }
function onSystem(sys) { SYS = sys; renderKpis(); renderHealth(); }
export default { id: "overview", mount, onStatus, onJobs };
export default { id: "overview", mount, onStatus, onJobs, onSystem };