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}