feat: Disk-Space Banner im Diagnostic mit Cleanup-Command zum Kopieren
Server:
- checkDiskSpace() prueft alle 30s 'df -B1 /shared' (zeigt Host-Disk
da /shared ein Volume auf dem Docker-FS ist)
- 4 Stufen: ok (<70%), info (70%), warn (85%), critical (95%)
- Broadcastet disk_status nur bei Aenderung (Level oder Prozent)
- currentDiskStatus wird gecached → neu verbundene Clients bekommen
den aktuellen Stand sofort beim 'init'
UI:
- Sticky Banner ganz oben, versteckt wenn Disk ok
- Farbe nach Level: gelb (info), orange (warn), rot (critical)
- Zeigt Prozent, Used/Total/Avail in GB, konkrete Situation
- Cleanup-Command als monospace Code mit Copy-Button ('docker system
prune -a --volumes -f') — Click auf Code oder Button kopiert ins
Clipboard, Fallback auf Range-Selektion
- 'Schliessen' Button fuer temporaeres Ausblenden (kommt aber wieder
bei naechster Aenderung)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1148,6 +1148,53 @@ function updateAgentActivity() {
|
||||
watchdogWarned = false;
|
||||
}
|
||||
|
||||
// ── Disk-Space Monitor ───────────────────────────────
|
||||
// Prueft regelmaessig die Host-Disk (via gemountetem /shared) und
|
||||
// broadcastet bei kritischen Schwellwerten ein disk_status Event.
|
||||
let lastDiskStatus = null;
|
||||
let currentDiskStatus = null; // Vollstaendig fuer neu verbundene Clients
|
||||
function checkDiskSpace() {
|
||||
const { exec } = require("child_process");
|
||||
exec("df -B1 /shared", (err, stdout) => {
|
||||
if (err) return;
|
||||
const lines = stdout.trim().split("\n");
|
||||
if (lines.length < 2) return;
|
||||
const cols = lines[1].split(/\s+/);
|
||||
// Filesystem Size Used Avail Use% MountedOn
|
||||
const total = parseInt(cols[1], 10);
|
||||
const used = parseInt(cols[2], 10);
|
||||
const avail = parseInt(cols[3], 10);
|
||||
if (!total) return;
|
||||
const pct = Math.round((used / total) * 100);
|
||||
let level = "ok";
|
||||
if (pct >= 95) level = "critical";
|
||||
else if (pct >= 85) level = "warn";
|
||||
else if (pct >= 70) level = "info";
|
||||
const status = {
|
||||
type: "disk_status",
|
||||
level,
|
||||
percent: pct,
|
||||
usedBytes: used,
|
||||
totalBytes: total,
|
||||
availBytes: avail,
|
||||
};
|
||||
currentDiskStatus = status;
|
||||
// Nur broadcasten wenn sich was geaendert hat (oder alle 60s Refresh)
|
||||
const key = `${level}-${pct}`;
|
||||
if (lastDiskStatus !== key) {
|
||||
lastDiskStatus = key;
|
||||
broadcast(status);
|
||||
if (level !== "ok") {
|
||||
log(level === "critical" ? "error" : "warn", "server",
|
||||
`Disk ${pct}% belegt (${(used/1024/1024/1024).toFixed(1)}GB von ${(total/1024/1024/1024).toFixed(1)}GB)`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// Beim Start + alle 30s
|
||||
setTimeout(checkDiskSpace, 2000);
|
||||
setInterval(checkDiskSpace, 30000);
|
||||
|
||||
// Watchdog prüft alle 30s ob ARIA nach einer gesendeten Nachricht reagiert
|
||||
setInterval(async () => {
|
||||
if (pendingMessageTime === 0) return; // Keine Nachricht gesendet
|
||||
@@ -1281,6 +1328,8 @@ wss.on("connection", (ws) => {
|
||||
browserClients.add(ws);
|
||||
// Initialen State + letzte Logs senden
|
||||
ws.send(JSON.stringify({ type: "init", state, logs: logs.slice(-100) }));
|
||||
// Letzten Disk-Status mitgeben damit der Client sofort weiss wie's um Platz steht
|
||||
if (currentDiskStatus) ws.send(JSON.stringify(currentDiskStatus));
|
||||
|
||||
ws.on("message", (raw) => {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user