Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ per the process in [`docs/releasing.md`](docs/releasing.md).
- `pithead doctor` now checks that Docker is enabled to start at boot (systemd) and warns if not —
`restart: unless-stopped` only brings the stack back after a reboot when the daemon does too,
which matters for an unattended miner (#137).
- 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

Expand Down
7 changes: 7 additions & 0 deletions build/dashboard/mining_dashboard/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
13 changes: 12 additions & 1 deletion build/dashboard/mining_dashboard/web/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
Expand Down Expand Up @@ -567,6 +567,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


Expand Down
17 changes: 17 additions & 0 deletions build/dashboard/tests/web/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,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) -------------------------------------------------

Expand Down
Loading