various: deprecate %cpu-usage; add new variables#56
Conversation
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Id8593744f5c1b4a862ff9d516570a1986a6a6964
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ie65f50fae6ca27a115b12c3d04c7032f6a6a6964
…bles Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Idf55162fa903329d659caac19bbe92e86a6a6964
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I3d5a06963de7b1f485861ce77607d2226a6a6964
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Id94264310cd7f9ccde4a7d1edd162e336a6a6964
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ia2809ab13363fa591132631f3956579a6a6a6964
7209726 to
0fea2d2
Compare
%cpu-usage; add new variables%cpu-usage; add new variables
Adds `%cpu-core-count`, `?lid-closed`, `$battery-cycles` and `%battery-health` variables. Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I513545b3c54aa7d725423896a295532a6a6a6964
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ic792e0ccffd71f3229c03f91572c72006a6a6964
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ifd02e5852dcfff8720ba3f631c47d00d6a6a6964
| // SW_LID is bit 0 in the capabilities bitmask | ||
| // The state file shows the current state of switches as a hex bitmask | ||
| // If bit 0 is set, the lid is closed | ||
| if let Ok(caps) = u64::from_str_radix(sw_caps.trim(), 16) { | ||
| self.lid_closed = (caps & 0x1) != 0; | ||
| log::debug!( | ||
| "lid state from input device {path}: {state}", | ||
| path = entry_path.display(), | ||
| state = if self.lid_closed { "closed" } else { "open" } | ||
| ); |
There was a problem hiding this comment.
I don't know how this holds up against different systems. Will need to investigate.
| // Battery health as a percentage (0-100) | ||
| // Some systems report this as capacity_level or health | ||
| self.health = if let Some(health) = | ||
| fs::read_n::<u64>(self.path.join("health")) | ||
| .with_context(|| format!("failed to read {self} health"))? | ||
| { | ||
| Some(health as f64 / 100.0) | ||
| } else { | ||
| // Try to calculate health from energy_full vs energy_full_design | ||
| let energy_full = fs::read_n::<u64>(self.path.join("energy_full")) | ||
| .with_context(|| format!("failed to read {self} energy_full"))?; | ||
|
|
||
| let energy_full_design = | ||
| fs::read_n::<u64>(self.path.join("energy_full_design")) | ||
| .with_context(|| { | ||
| format!("failed to read {self} energy_full_design") | ||
| })?; | ||
|
|
||
| match (energy_full, energy_full_design) { | ||
| (Some(full), Some(design)) if design > 0 => { | ||
| Some(full as f64 / design as f64) | ||
| }, | ||
| _ => None, | ||
| } | ||
| }; |
There was a problem hiding this comment.
Like we do for paths, we might want to classify those paths depending on the vendor. It's really difficult to support various vendors without diving into the kernel code, which is very time consuming. Though, I don't like assuming things either.
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ie8f136a922eebace444a8b40cebd7eac6a6a6964
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: If2d8e55a400a7a52903752fb480728056a6a6964
Now computed on-demand from `state.cpus`` during expression evaluation rather than stored as pre-computed fields in `EvalState`. Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ifeb78acbb2f8c28468b6bcc912f88b556a6a6964
I guess this was bound to happen and now I feel stupid for wasting my time with the static expressions earlier. This commit adds `load-average-since` that computers average load from the CPU log over a configurable duration, similiar to `cpu-usage-since`. Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I95a9e5dca7a34da5395ade1d6deb25a76a6a6964
I've changed cycles to cycle paths via search & replace previously so it accidentally regressed the path. This fixes the incorrect sysfs path from "cycles" to "cycle_count" for reading battery cycle count on Linux systems. Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ia801fe84abb87cbfbf5e14be14eeab566a6a6964
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I99b2146dfff44569fd90436a836692476a6a6964
Adds new expression variants:
- `BatteryCyclesFor { name }` - cycle count for specific battery
- `BatteryHealthFor { name }` - health for specific battery
- `IsBatteryAvailable { value }` - predicate to check battery existence
Those eplace the aggregated-only `battery_cycles` and `battery_health`.
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I736448f3e8a73a6a90538cd99af188996a6a6964
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ibaeb1235a15aebe0450f6f056c6a9c966a6a6964
| *value == T::default() | ||
| } | ||
|
|
||
| fn find_battery<'a>( |
There was a problem hiding this comment.
This should really be inlined, or defined inside the fn that uses it
There was a problem hiding this comment.
It can be moved to eval but I reckon we'll need it elsewhere if we end up adding more battery-specific expressions. For now I'm moving it but I strongly suspect it'll be moved out eventually.
| pub frequency_available: bool, | ||
| pub turbo_available: bool, | ||
|
|
||
| pub cpu_usage: f64, |
| let max = state | ||
| .cpus | ||
| .iter() | ||
| .filter_map(|cpu| cpu.frequency_mhz_maximum) |
There was a problem hiding this comment.
I'm pretty sure this is the hardware limit. We have no field for software, add cpu.frequency_mhz_software_cap
|
|
||
| CpuCoreCount => Number(state.cpus.len() as f64), | ||
|
|
||
| LoadAverageSince { duration } => { |
There was a problem hiding this comment.
duration should be an Expr so people can do ifs etc inside. We have .try_into_string as well.
| let batteries: Vec<_> = self | ||
| .power_supplies | ||
| .iter() | ||
| .filter(|ps| ps.type_ == "Battery" && !ps.is_from_peripheral) | ||
| .collect(); |
There was a problem hiding this comment.
Can't this use the find_batteries? Also, you don't seem to be checking is_from_peripheral in that fn def, I wonder if the disparity is a good idea
| let entry = match entry { | ||
| Ok(entry) => entry, | ||
| Err(error) => { | ||
| log::debug!("failed to read input device entry: {error}"); | ||
| continue; | ||
| }, | ||
| }; |
There was a problem hiding this comment.
This can be a let Ok(...) = ... else { log; continue; };
| }; | ||
|
|
||
| // Look for lid switch input device | ||
| if name.trim() == "Lid Switch" { |
There was a problem hiding this comment.
let "Lid Switch" = name.trim() else { log; continue; };
if body here
Adds a few new system variables per #45. New variables:
%cpu-core-count- Number of CPU cores$load-average-sinceSystem load average over a given duration?lid-closed- Boolean for lid state$hour-of-day- Current hour (0-23) based on local time$battery-cycles- Battery cycle count%battery-health- Battery health percentageNotes:
%cpu-usageis now fully deprecated. Updated example config with best-case examples I can think of. Could be optimized further if we decide to actually benchmark power consumption on a live system.Like we do for CPU usage, it's worth adding support for measuring load average over certain durations rather than just fixed 1m, 5m and 15m averages.
$cpu-scaling-minimumis not added, because minimum should be always 0. Maximum is what we'll want to use to infer system "capability". I cannot think of a single case where it will not be 0.?$hour-of-dayis added despite my belief that it'll be obsoleted by the D-Bus interface. It's a trivial addition, and I'd rather not curse people with D-Bus for something so trivial. It's good for some basic rules, and of trivial cost.I'm not particularly proud of the battery aggregation. This'll need to be polished to support per-battery supports.