From a84fa76c979ac70c08514d8ba03f690e8acbcd35 Mon Sep 17 00:00:00 2001 From: Vijit Singh Date: Thu, 4 Jun 2026 08:33:12 -0500 Subject: [PATCH] dashboard: low-disk warning badge in the header (#138) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The data filesystem fills as the chains grow and logs accumulate, and a full disk corrupts monerod's DB mid-write. Disk usage is already collected and shown as a bar, but the bar is easy to miss — add a prominent top-bar badge: a `warn` at 85% used and a `bad` critical alert at 95%, on both the sync and main screens (build_badges feeds both). Thresholds live in config (DISK_WARN_PERCENT / DISK_CRITICAL_PERCENT). Tests: critical / warn / ample / missing-data cases for the badge. Dashboard suite 421 passed, 93% coverage. CHANGELOG updated. Co-Authored-By: Claude Opus 4.8 --- CHANGELOG.md | 3 +++ .../dashboard/mining_dashboard/config/config.py | 7 +++++++ build/dashboard/mining_dashboard/web/views.py | 13 ++++++++++++- build/dashboard/tests/web/test_views.py | 17 +++++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73b872e..66d0df7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,9 @@ per the process in [`docs/releasing.md`](docs/releasing.md). (`3333`) is published on (default `0.0.0.0`; set a LAN IP or `127.0.0.1` to narrow it). - Liveness healthcheck for the p2pool container (probes the stratum port), so a stalled p2pool is now visible in `pithead status` and the dashboard. +- Low-disk warning badge in the dashboard header (#138): a heads-up at 85% used of the data + filesystem and a prominent critical alert at 95%, on both the sync and main screens — the disk + bar alone is easy to miss, and a full data disk corrupts the Monero database mid-write. ### Changed diff --git a/build/dashboard/mining_dashboard/config/config.py b/build/dashboard/mining_dashboard/config/config.py index d4f8093..7aa4c3a 100644 --- a/build/dashboard/mining_dashboard/config/config.py +++ b/build/dashboard/mining_dashboard/config/config.py @@ -9,6 +9,13 @@ DISK_PATH = '/data' DB_FILE_PATH = os.path.join(DISK_PATH, "mining_data.db") +# Low-disk warning thresholds (% used of the data filesystem), surfaced as a top-bar badge (#138): +# a heads-up at WARN, a prominent critical alert near full. The chains keep growing and a full data +# disk corrupts monerod's DB mid-write, so this is a runtime guard distinct from the setup-time +# pre-flight estimate. (The disk *bar* uses its own colour thresholds; these gate the badge.) +DISK_WARN_PERCENT = 85 +DISK_CRITICAL_PERCENT = 95 + # --- Data Source File Paths --- # File paths for JSON metrics generated by local collectors STRATUM_STATS_PATH = f"{BASE_STATS_DIR}/local/stratum" diff --git a/build/dashboard/mining_dashboard/web/views.py b/build/dashboard/mining_dashboard/web/views.py index a96b700..94e8b28 100644 --- a/build/dashboard/mining_dashboard/web/views.py +++ b/build/dashboard/mining_dashboard/web/views.py @@ -15,7 +15,7 @@ import bisect import logging -from mining_dashboard.config.config import HOST_IP, UPDATE_INTERVAL +from mining_dashboard.config.config import HOST_IP, UPDATE_INTERVAL, DISK_WARN_PERCENT, DISK_CRITICAL_PERCENT from mining_dashboard.helper.utils import ( format_hashrate, format_duration, format_time_abs, is_ip_address, detect_host_ipv4, ) @@ -561,6 +561,17 @@ def build_badges(data, metrics, mode_variant): elif metrics.monero_mode == "Full": badges.append({"text": "XMR Full", "variant": "outline", "title": "Monero blockchain is full (not pruned)"}) + # Low-disk badge (Issue #138). The data filesystem fills as the chains grow and logs accumulate; + # a full disk corrupts monerod's DB mid-write. The disk *bar* shows the percentage, but it's easy + # to miss — surface a prominent top-bar badge near full, on both the sync and main screens. + disk_percent = (data.get('system', {}).get('disk', {}) or {}).get('percent', 0) or 0 + if disk_percent >= DISK_CRITICAL_PERCENT: + badges.append({"text": f"⚠ Disk {disk_percent:.0f}% full", "variant": "bad", + "title": "The data disk is almost full — free space now; a full disk can corrupt the Monero database."}) + elif disk_percent >= DISK_WARN_PERCENT: + badges.append({"text": f"Disk {disk_percent:.0f}% full", "variant": "warn", + "title": "The data disk is filling up — free space or move a data_dir before it runs out."}) + return badges diff --git a/build/dashboard/tests/web/test_views.py b/build/dashboard/tests/web/test_views.py index c0d89db..6b27908 100644 --- a/build/dashboard/tests/web/test_views.py +++ b/build/dashboard/tests/web/test_views.py @@ -368,6 +368,23 @@ def test_no_prune_badge_when_unknown(self): out = build_badges({}, _metrics(monero_mode="Unknown"), "ok") assert not any("XMR" in b["text"] for b in out) + def test_disk_badge_critical(self): + out = build_badges({"system": {"disk": {"percent": 96}}}, _metrics(), "ok") + assert any(b["variant"] == "bad" and "Disk 96% full" in b["text"] for b in out) + + def test_disk_badge_warn(self): + out = build_badges({"system": {"disk": {"percent": 88}}}, _metrics(), "ok") + assert any(b["variant"] == "warn" and "Disk 88% full" in b["text"] for b in out) + + def test_no_disk_badge_when_ample(self): + out = build_badges({"system": {"disk": {"percent": 50}}}, _metrics(), "ok") + assert not any("Disk" in b["text"] for b in out) + + def test_no_disk_badge_when_missing(self): + # No system/disk data (e.g. an early poll) must not emit a spurious or crashing badge. + out = build_badges({}, _metrics(), "ok") + assert not any("Disk" in b["text"] for b in out) + # --- System (presentation thresholds) -------------------------------------------------