summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-02-18 19:39:04 +0200
committerPaul Buetow <pbuetow@mimecast.com>2026-02-18 19:39:04 +0200
commit1e0b0f9e9573d1c6188fc683591e1f8ae044ca1f (patch)
tree023bac27dc261ee546572b6c253e647d6a802d99
parent3cc9d42252b7d5f9c24c10ef748cff1d2e1bbd67 (diff)
Disk I/O: collect stats on remote, dynamic bar count, reset peak on r
- Add M DISKSTATS block to embedded loadbars-remote.sh so disk I/O is collected from /proc/diskstats on remote hosts (was only in scripts/ copy). - Document in countBars that total bars are computed per host (dynamic device count when disk mode is per-device). - Extend r hotkey to reset disk auto-scale peak to 1 MB/s floor when disk bars are on and diskmax is not fixed; update README and help text. Co-authored-by: Cursor <cursoragent@cursor.com>
-rw-r--r--README.md2
-rw-r--r--internal/collector/loadbars-remote.sh12
-rw-r--r--internal/display/display.go15
3 files changed, 26 insertions, 3 deletions
diff --git a/README.md b/README.md
index 9d30b64..1794237 100644
--- a/README.md
+++ b/README.md
@@ -143,7 +143,7 @@ Press these keys while loadbars is running (see also `h` for a short list on std
| **3** / **n** | Toggle network bars (RX/TX summed across all non-lo interfaces per host) |
| **4** / **l** | Toggle load average bars (1-min teal fill, 5-min yellow line, 15-min white line) |
| **5** | Toggle disk I/O bars: aggregate (all devices) → per-device → off → aggregate |
-| **r** | Reset load auto-scale peak to floor (2.0) — has no effect when `loadmax` is fixed |
+| **r** | Reset load auto-scale peak to floor (2.0) and disk auto-scale peak to floor (1 MB/s) — no effect when `loadmax`/`diskmax` is fixed |
| **e** | Toggle extended display (1px peak line on CPU bars: max system+user over last samples) |
| **g** | Toggle global average CPU line (1px red line showing mean CPU usage across all hosts) |
| **i** | Toggle global I/O average line (1px pink line showing mean iowait+IRQ across all hosts) |
diff --git a/internal/collector/loadbars-remote.sh b/internal/collector/loadbars-remote.sh
index 9037ad8..ccdcbe8 100644
--- a/internal/collector/loadbars-remote.sh
+++ b/internal/collector/loadbars-remote.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# loadbars-remote.sh - Emits loadbars protocol (M LOADAVG, M MEMSTATS, M NETSTATS, M CPUSTATS)
+# loadbars-remote.sh - Emits loadbars protocol (M LOADAVG, M MEMSTATS, M NETSTATS, M DISKSTATS, M CPUSTATS)
# for local or remote execution. No Perl required.
# Usage: bash loadbars-remote.sh
# Interval for CPU sampling (seconds)
@@ -26,6 +26,16 @@ while true; do
fi
done < <(tail -n +3 /proc/net/dev 2>/dev/null)
+ # Disk: /proc/diskstats, one line per block device with cumulative counters
+ echo "M DISKSTATS"
+ while IFS= read -r line; do
+ set -- $line
+ # $1=major $2=minor $3=device $4=reads_completed $5=reads_merged
+ # $6=sectors_read $7=ms_reading $8=writes_completed $9=writes_merged
+ # $10=sectors_written $11=ms_writing $12=ios_in_progress $13=ms_io
+ [ -n "$3" ] && echo "$3:rs=${6:-0};ws=${10:-0};rt=${7:-0};wt=${11:-0};io=${13:-0}"
+ done < /proc/diskstats 2>/dev/null
+
# CPU: /proc/stat, 20 times with INTERVAL sleep
echo "M CPUSTATS"
for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
diff --git a/internal/display/display.go b/internal/display/display.go
index 94b4c76..514a62f 100644
--- a/internal/display/display.go
+++ b/internal/display/display.go
@@ -231,6 +231,14 @@ func handleToggleKeys(sym sdl.Keycode, cfg *config.Config, state *runState) {
} else {
fmt.Println("==> Load peak reset ignored (fixed loadmax =", cfg.LoadMax, ")")
}
+ // Reset disk auto-scale peak to the floor when disk bars are on and diskmax is not fixed.
+ if state.diskMode != constants.DiskModeOff && cfg.DiskMax == 0 {
+ const diskPeakFloorBps = 1048576.0 // 1 MB/s, same as in updateDiskPeak
+ state.diskPeak = diskPeakFloorBps
+ fmt.Println("==> Disk peak reset to auto-scale floor (1 MB/s)")
+ } else if state.diskMode != constants.DiskModeOff && cfg.DiskMax > 0 {
+ fmt.Println("==> Disk peak reset ignored (fixed diskmax =", cfg.DiskMax, ")")
+ }
case sdl.K_e:
state.extended = !state.extended
fmt.Println("==> Toggled extended (peak line):", state.extended)
@@ -394,6 +402,10 @@ func drawFrame(renderer *sdl.Renderer, src stats.Source, cfg *config.Config, sta
drawOverlay(renderer, snap, cfg, state)
}
+// countBars returns the total number of bars to display. The total is computed
+// dynamically per snapshot: each host contributes its own CPU/mem/net/load bars
+// plus its own disk device count (so servers with different numbers of devices
+// are all included).
func countBars(snap map[string]*stats.HostStats, cpuMode int, showMem, showNet, showLoad bool, diskMode int) int {
n := 0
for _, host := range sortedHosts(snap) {
@@ -408,6 +420,7 @@ func countBars(snap map[string]*stats.HostStats, cpuMode int, showMem, showNet,
if showLoad {
n++
}
+ // Per-host device count: aggregate=1 bar, devices=whole-disk count, off=0
n += len(sortedDiskNames(h.Disk, diskMode))
}
}
@@ -826,7 +839,7 @@ func drawMemBarSmoothed(renderer *sdl.Renderer, h *stats.HostStats, smoothed *st
}
func printHotkeys() {
- fmt.Println("=> Hotkeys: 1=cores 2/m=mem 3/n=net 4/l=load 5=disk r=reset load peak e=extended g=avg line i=io avg s=separators h=help q=quit w=write config a/y=cpu avg d/c=net avg b/x=disk avg f/v=link scale arrows=resize")
+ fmt.Println("=> Hotkeys: 1=cores 2/m=mem 3/n=net 4/l=load 5=disk r=reset load/disk peak e=extended g=avg line i=io avg s=separators h=help q=quit w=write config a/y=cpu avg d/c=net avg b/x=disk avg f/v=link scale arrows=resize")
}
// scaleLinkUp moves cfg.NetLink to the next higher link speed in linkScales.