redbear-power: clear PkgW status, remove redundant per-CPU PkgW column

- app.rs: rapl_status field shows 'n/a (run as root)' or
  'n/a (unsupported)' or 'sampling...' depending on state
- render.rs: header PkgW shows rapl_status when unavailable;
  removed per-CPU PkgW column (package power is socket-wide)
This commit is contained in:
2026-06-28 18:51:09 +03:00
parent 03fd3a0690
commit dbb7bf74e9
2 changed files with 15 additions and 9 deletions
@@ -153,6 +153,8 @@ pub meminfo: crate::meminfo::MemInfo,
pub pkg_power_w: Option<f64>,
/// Previous RAPL energy reading for delta computation.
rapl_prev: Option<(u64, std::time::Instant)>,
/// Why RAPL package power is unavailable (empty if working).
pub rapl_status: String,
/// Per-PID IO rate history (normalized KiB/s samples,
/// 0..=255 against the per-history max). Used by the
/// Process tab to render a small sparkline per process.
@@ -395,6 +397,7 @@ impl App {
folded: std::collections::BTreeSet::new(),
pkg_power_w: None,
rapl_prev: None,
rapl_status: "probing...".into(),
io_history: std::collections::BTreeMap::new(),
last_clicked_cpu: None,
sort_ascending: false,
@@ -662,10 +665,19 @@ impl App {
self.rapl_prev = Some(next);
if w > 0.0 {
self.pkg_power_w = Some(w);
self.rapl_status.clear();
}
} else {
self.rapl_prev = Some(curr);
self.rapl_status = "sampling...".into();
}
} else if self.msr_available {
// MSR device exists but we can't read it (permission denied).
// RAPL sysfs also needs root on Linux.
self.rapl_status = "n/a (run as root)".into();
} else {
// No MSR device at all — RAPL unsupported (QEMU, old CPU).
self.rapl_status = "n/a (unsupported)".into();
}
// Re-read cpufreq state (catches external governor changes).
self.cpufreq.refresh();
@@ -9,7 +9,7 @@
//! │ MSR / Daemons / │ │ ... │
//! └─────────────────────┘ └────────────┘
//! ┌─ Per-CPU ───────────────┐
//! │ CPU Freq PkgW Temp │
//! │ CPU Freq Temp │
//! │ 0 2400 15.0 72▏▌·· │
//! │ 1 2400 15.0 70▏▎·· │
//! └────────────────────────┘
@@ -180,8 +180,8 @@ pub fn render_header<'a>(app: &'a App, focused: bool) -> Paragraph<'a> {
"PkgW: ".set_style(theme::LABEL),
app.pkg_power_w
.map(|w| format!("{w:.1} W"))
.unwrap_or_else(|| "n/a".into())
.set_style(theme::VALUE),
.unwrap_or_else(|| app.rapl_status.clone())
.set_style(if app.pkg_power_w.is_some() { theme::VALUE } else { theme::VALUE_OFF }),
" ".into(),
"P-state source: ".set_style(theme::LABEL),
app.pss_source.as_str().into(),
@@ -1407,7 +1407,6 @@ pub fn render_cpu_table<'a>(
let header = Row::new(vec![
"CPU".set_style(theme::LABEL),
"Freq/MHz".set_style(theme::LABEL),
"PkgW".set_style(theme::LABEL),
"Temp°C bar".set_style(theme::LABEL),
"P-state".set_style(theme::LABEL),
"State".set_style(theme::LABEL),
@@ -1449,10 +1448,6 @@ pub fn render_cpu_table<'a>(
let color = theme::flags_color(cpu.critical, cpu.prochot, cpu.power_limit);
Cell::from(flags.clone().set_style(Style::new().fg(color)))
};
let pkgw_cell: Cell = match cpu.current_power_mw {
Some(w) => Cell::from(format!("{:.1}", w as f64 / 1000.0).set_style(theme::VALUE)),
None => Cell::from("n/a".set_style(theme::VALUE_OFF)),
};
let load_label = format!("{:.0}%", cpu.load_pct);
let lcolor = theme::load_color(cpu.load_pct);
let spark_text = if cpu.load_history.is_empty() {
@@ -1468,7 +1463,6 @@ pub fn render_cpu_table<'a>(
Row::new(vec![
Cell::from(format!("{}{}", cpuid::core_type_label(cpu.core_type), cpu.id).set_style(theme::VALUE)),
Cell::from(freq.set_style(theme::VALUE)),
pkgw_cell,
temp_cell,
Cell::from(pstate.set_style(theme::VALUE)),
Cell::from(cpu.state_label().set_style(theme::VALUE)),