feat: Live-Metriken via WebSockets (Phase 3)
This commit is contained in:
+14
-1
@@ -4,9 +4,10 @@ Greift lokal auf psutil und sysfs zu.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import asyncio
|
||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends
|
from fastapi import APIRouter, Depends, WebSocket, WebSocketDisconnect
|
||||||
from auth import auth
|
from auth import auth
|
||||||
|
|
||||||
router = APIRouter(prefix="/api/system", dependencies=[Depends(auth)])
|
router = APIRouter(prefix="/api/system", dependencies=[Depends(auth)])
|
||||||
@@ -89,3 +90,15 @@ def system_status():
|
|||||||
},
|
},
|
||||||
"gpu_temp": temps["gpu"]
|
"gpu_temp": temps["gpu"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@router.websocket("/stream")
|
||||||
|
async def system_stream(websocket: WebSocket):
|
||||||
|
await websocket.accept()
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
# Sende Live-Daten alle 500ms
|
||||||
|
data = system_status()
|
||||||
|
await websocket.send_json(data)
|
||||||
|
await asyncio.sleep(0.5)
|
||||||
|
except WebSocketDisconnect:
|
||||||
|
pass
|
||||||
|
|||||||
+20
-5
@@ -72,9 +72,24 @@ async function pollJobs() {
|
|||||||
catch { /* still */ }
|
catch { /* still */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pollSystem() {
|
function connectSystemStream() {
|
||||||
try { applySystem(await api("/api/system/status")); }
|
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||||
catch { /* still */ }
|
const wsUrl = `${protocol}//${window.location.host}/api/system/stream`;
|
||||||
|
const ws = new WebSocket(wsUrl);
|
||||||
|
|
||||||
|
ws.onmessage = (e) => {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(e.data);
|
||||||
|
applySystem(data);
|
||||||
|
} catch (err) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onclose = () => {
|
||||||
|
// Bei Verbindungsabbruch nach 3 Sekunden erneut versuchen
|
||||||
|
setTimeout(connectSystemStream, 3000);
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onerror = () => ws.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Boot ----
|
// ---- Boot ----
|
||||||
@@ -106,8 +121,8 @@ document.addEventListener("mc:refresh", pollStatus);
|
|||||||
|
|
||||||
pollStatus();
|
pollStatus();
|
||||||
pollJobs();
|
pollJobs();
|
||||||
pollSystem();
|
connectSystemStream();
|
||||||
|
|
||||||
setInterval(tickClock, 1000);
|
setInterval(tickClock, 1000);
|
||||||
setInterval(pollStatus, 3000);
|
setInterval(pollStatus, 3000);
|
||||||
setInterval(pollJobs, 1500);
|
setInterval(pollJobs, 1500);
|
||||||
setInterval(pollSystem, 2000);
|
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ function kvRow(k, v, cls = "") {
|
|||||||
return `<div class="kv-row"><span class="kv-k">${k}</span><span class="kv-v ${cls}">${v}</span></div>`;
|
return `<div class="kv-row"><span class="kv-k">${k}</span><span class="kv-v ${cls}">${v}</span></div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chart-Daten (letzte 60 Sekunden, je 3s Polling = 20 Punkte)
|
// Chart-Daten (letzte 30 Sekunden, je 0.5s Stream = 60 Punkte)
|
||||||
const hist = { cpu: [], ram: [], gpu: [] };
|
const hist = { cpu: [], ram: [], gpu: [] };
|
||||||
const MAX_HIST = 20;
|
const MAX_HIST = 60;
|
||||||
|
|
||||||
function renderSys() {
|
function renderSys() {
|
||||||
if (!SYS) return;
|
if (!SYS) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user