i3status_rs/blocks/load.rs
1//! System load average
2//!
3//! # Configuration
4//!
5//! Key | Values | Default
6//! -----------|---------------------------------------------------------------------------------------|--------
7//! `format` | A string to customise the output of this block. See below for available placeholders. | `" $icon $1m.eng(w:4) "`
8//! `interval` | Update interval in seconds | `3`
9//! `info` | Minimum load, where state is set to info | `0.3`
10//! `warning` | Minimum load, where state is set to warning | `0.6`
11//! `critical` | Minimum load, where state is set to critical | `0.9`
12//!
13//! Placeholder | Value | Type | Unit
14//! -------------|------------------------|--------|-----
15//! `icon` | A static icon | Icon | -
16//! `1m` | 1 minute load average | Number | -
17//! `5m` | 5 minute load average | Number | -
18//! `15m` | 15 minute load average | Number | -
19//!
20//! # Example
21//!
22//! ```toml
23//! [[block]]
24//! block = "load"
25//! format = " $icon 1min avg: $1m.eng(w:4) "
26//! interval = 1
27//! ```
28//!
29//! # Icons Used
30//! - `cogs`
31
32use super::prelude::*;
33use crate::util;
34
35#[derive(Deserialize, Debug, SmartDefault)]
36#[serde(deny_unknown_fields, default)]
37pub struct Config {
38 pub format: FormatConfig,
39 #[default(3.into())]
40 pub interval: Seconds,
41 #[default(0.3)]
42 pub info: f64,
43 #[default(0.6)]
44 pub warning: f64,
45 #[default(0.9)]
46 pub critical: f64,
47}
48
49pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
50 let format = config.format.with_default(" $icon $1m.eng(w:4) ")?;
51
52 // borrowed from https://docs.rs/cpuinfo/0.1.1/src/cpuinfo/count/logical.rs.html#4-6
53 let logical_cores = util::read_file("/proc/cpuinfo")
54 .await
55 .error("Your system doesn't support /proc/cpuinfo")?
56 .lines()
57 .filter(|l| l.starts_with("processor"))
58 .count();
59
60 loop {
61 let loadavg = util::read_file("/proc/loadavg")
62 .await
63 .error("Your system does not support reading the load average from /proc/loadavg")?;
64 let mut values = loadavg.split(' ');
65 let m1: f64 = values
66 .next()
67 .and_then(|x| x.parse().ok())
68 .error("bad /proc/loadavg file")?;
69 let m5: f64 = values
70 .next()
71 .and_then(|x| x.parse().ok())
72 .error("bad /proc/loadavg file")?;
73 let m15: f64 = values
74 .next()
75 .and_then(|x| x.parse().ok())
76 .error("bad /proc/loadavg file")?;
77
78 let mut widget = Widget::new().with_format(format.clone());
79 widget.state = match m1 / logical_cores as f64 {
80 x if x > config.critical => State::Critical,
81 x if x > config.warning => State::Warning,
82 x if x > config.info => State::Info,
83 _ => State::Idle,
84 };
85 widget.set_values(map! {
86 "icon" => Value::icon("cogs"),
87 "1m" => Value::number(m1),
88 "5m" => Value::number(m5),
89 "15m" => Value::number(m15),
90 });
91 api.set_widget(widget)?;
92
93 select! {
94 _ = sleep(config.interval.0) => (),
95 _ = api.wait_for_update_request() => (),
96 }
97 }
98}