From babffee80e1ceb0b10d0bd903150fefedbfe9d17 Mon Sep 17 00:00:00 2001 From: vasilito Date: Tue, 7 Jul 2026 02:12:50 +0300 Subject: [PATCH] redbear-power: add system load average (1/5/15 min) to System panel Reads /proc/loadavg every 4th refresh cycle and displays the three load average values alongside Cores/AvgFreq/MaxTemp/TotalPkg. --- .../system/redbear-power/source/src/app.rs | 25 +++++++++++++++++++ .../system/redbear-power/source/src/render.rs | 5 ++++ 2 files changed, 30 insertions(+) diff --git a/local/recipes/system/redbear-power/source/src/app.rs b/local/recipes/system/redbear-power/source/src/app.rs index e3a2117879..58d1d0b4ff 100644 --- a/local/recipes/system/redbear-power/source/src/app.rs +++ b/local/recipes/system/redbear-power/source/src/app.rs @@ -145,6 +145,7 @@ pub struct App { /// `/proc/stat` (Linux). Read every tick — it's a single /// file read. Fields degrade to `None` when unavailable. pub sched_stats: crate::sched::SchedStats, + pub load_avg: Option<(f64, f64, f64)>, /// When true, render the Process tab as a tree (parents above /// children, prefixed with `├─ ` / `└─ ` connector characters). /// Toggled by the `T` hotkey. Sort modes are honored within @@ -443,6 +444,18 @@ impl App { process_sort: crate::process::SortMode::default(), process_filter: String::new(), sched_stats: crate::sched::SchedStats::default(), + load_avg: std::fs::read_to_string("/proc/loadavg").ok().and_then(|s| { + let parts: Vec<&str> = s.split_whitespace().collect(); + if parts.len() >= 3 { + Some(( + parts[0].parse().ok()?, + parts[1].parse().ok()?, + parts[2].parse().ok()?, + )) + } else { + None + } + }), process_tree: false, show_full_cmdline: false, folded: std::collections::BTreeSet::new(), @@ -557,6 +570,18 @@ impl App { if self.refresh_counter % 4 == 0 { self.meminfo = crate::meminfo::read_meminfo(); self.os_info = crate::meminfo::read_os_info(); + self.load_avg = std::fs::read_to_string("/proc/loadavg").ok().and_then(|s| { + let parts: Vec<&str> = s.split_whitespace().collect(); + if parts.len() >= 3 { + Some(( + parts[0].parse().ok()?, + parts[1].parse().ok()?, + parts[2].parse().ok()?, + )) + } else { + None + } + }); } // Battery state changes continuously on a laptop (capacity drops, diff --git a/local/recipes/system/redbear-power/source/src/render.rs b/local/recipes/system/redbear-power/source/src/render.rs index c45fa3f216..659066cc07 100644 --- a/local/recipes/system/redbear-power/source/src/render.rs +++ b/local/recipes/system/redbear-power/source/src/render.rs @@ -426,6 +426,11 @@ pub fn render_system_panel<'a>(app: &'a App, focused: bool) -> Paragraph<'a> { max_temp.set_style(theme::VALUE), " TotalPkg: ".set_style(theme::LABEL), format!("{total_pkgw:.1} W").set_style(theme::VALUE), + " Load: ".set_style(theme::LABEL), + match app.load_avg { + Some((a, b, c)) => format!("{a:.2} {b:.2} {c:.2}").set_style(theme::VALUE), + None => "n/a".set_style(theme::VALUE_OFF), + }, ])); let any_prochot = app.cpus.iter().any(|c| c.prochot); let any_critical = app.cpus.iter().any(|c| c.critical);