feat: display system swap usage in the TUI memory section (#226)
Surface swap usage in the interactive view so users can spot swap pressure at a glance. This is most important on Apple Silicon, where an over-sized model or mismatched inference-engine parameters spill unified memory into swap and silently degrade throughput. The data plumbing was already in place — `MemoryInfo` carries `swap_{total,used,free}_bytes` across every platform and the Prometheus exporter already publishes `all_smi_swap_*` series — but the TUI never rendered them.
UI changes:
- `print_memory_info` now draws a second `Swap` bar directly below the existing `Mem` bar whenever `swap_total_bytes > 0`. The bar is hidden on hosts with no swap so non-swap deployments stay visually uncluttered, mirroring the API exporter guard at `src/api/metrics/memory.rs:76`.
- The swap segment switches color from magenta (idle: swap exists but is unused) to red (active: `swap_used_bytes > 0`) so active swap pressure is immediately distinguishable — the core signal requested in the issue.
- `BarSegment` gains `swap_used` (Magenta) and `swap_used_active` (Red) helpers alongside the existing `memory_used`/`memory_buffers`/`memory_cache` constructors.
- The help overlay's resource-gauge legend documents the new Swap row with the same colored-keyword styling as the Memory row.
Cluster/remote mode plumbing:
The Prometheus metrics parser previously routed only `memory_*` lines into the per-host memory accumulator. `swap_*` lines were silently dropped, which would have left every cluster-mode `MemoryInfo` row with `swap_total_bytes == 0` and the new UI inert against real remote hosts. Routing now accepts both prefixes, the field map gains `swap_{total,used,free}_bytes`, and a new `test_parse_swap_metrics` test covers the round-trip.
Mock server:
The Apple Silicon and NVIDIA mock templates previously hardcoded swap to zero and did not emit `all_smi_swap_*` series at all, so the new UI could not be demoed via `all-smi-mock-server`. Both templates now seed realistic non-zero swap (4 GB on Apple Silicon with non-zero usage, 32 GB on NVIDIA with variable usage), and the template builders emit `all_smi_swap_{total,used,free}_bytes` series guarded by the same `swap_total_bytes > 0` condition as the real exporter. Three new mock-template tests cover emission-when-present, omission-when-zero, and placeholder resolution.
Tests:
- `memory_renderer`: five new tests covering swap-row visible when total > 0, hidden when total == 0, visible-with-idle-bar when total > 0 but used == 0, red ANSI SGR present when actively swapping, and no panic at narrow terminal widths.
- `metrics_parser`: extended `test_parse_memory_metrics` to assert that absent swap series leave the swap fields at zero, plus a new `test_parse_swap_metrics` that asserts the swap series populate the same `MemoryInfo` row as the matching memory series.
- `nvidia` mock template: three new tests for swap emission/omission and placeholder resolution.
Verification: `cargo check --lib --tests`, `cargo clippy --lib --tests -- -D warnings`, `cargo fmt --check`, and targeted `cargo test --lib ui::renderers::memory_renderer` / `cargo test --lib network::metrics_parser` / `cargo test --features mock --bin all-smi-mock-server mock::templates::nvidia` all pass. J
Jeongkyu Shin committed
7ee76050955dbf9f76c15507c6bab22d11400603
Parent: 92c82fa
Committed by GitHub <noreply@github.com>
on 5/24/2026, 6:39:23 AM