diff --git a/Cargo.lock b/Cargo.lock index 86d41c8..2fd7449 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -313,6 +313,12 @@ dependencies = [ "syn", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "exr" version = "1.74.0" @@ -516,6 +522,12 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + [[package]] name = "image" version = "0.25.10" @@ -576,6 +588,16 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "interpolate_name" version = "0.2.4" @@ -1187,6 +1209,45 @@ dependencies = [ "version-compare", ] +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + [[package]] name = "shlex" version = "1.3.0" @@ -1284,6 +1345,45 @@ dependencies = [ "zune-jpeg", ] +[[package]] +name = "toml" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + [[package]] name = "transpose" version = "0.2.3" @@ -1391,6 +1491,8 @@ dependencies = [ "imageproc", "protocol", "regex", + "serde", + "toml", ] [[package]] @@ -1409,6 +1511,12 @@ dependencies = [ "safe_arch", ] +[[package]] +name = "winnow" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" + [[package]] name = "wit-bindgen" version = "0.51.0" diff --git a/draw/src/stacked.rs b/draw/src/stacked.rs index 09818a7..0871cbf 100644 --- a/draw/src/stacked.rs +++ b/draw/src/stacked.rs @@ -7,6 +7,7 @@ use imageproc::{ use crate::Container; pub struct StackedConfig { + pub name: String, pub width_px_per_sample: u32, pub height_px: u32, pub series: Vec, diff --git a/waybar-collectd/Cargo.toml b/waybar-collectd/Cargo.toml index 76575d2..b12d9da 100644 --- a/waybar-collectd/Cargo.toml +++ b/waybar-collectd/Cargo.toml @@ -8,3 +8,5 @@ draw = { version = "0.1.0", path = "../draw" } imageproc = { version = "0.26.1", features = ["display-window"] } protocol = { path = "../protocol" } regex = "1.12.3" +serde = { version = "1.0.228", features = ["derive"] } +toml = { version = "1.1.2", features = ["serde", "parse"] } diff --git a/waybar-collectd/src/config.rs b/waybar-collectd/src/config.rs index c10dd4c..44ec344 100644 --- a/waybar-collectd/src/config.rs +++ b/waybar-collectd/src/config.rs @@ -1,9 +1,13 @@ -use regex::Regex; +use std::fs; +use serde::Deserialize; + +#[derive(Debug, Deserialize)] pub struct Config { - pub graphs: Vec, + pub graph: Vec, } +#[derive(Debug, Deserialize)] pub struct GraphConfig { pub name: String, pub width_px: u16, @@ -12,8 +16,14 @@ pub struct GraphConfig { pub series: Vec, } +#[derive(Debug, Deserialize)] pub struct SeriesConfig { pub name: String, pub color: (u8, u8, u8), - pub metrics: Vec, + pub metrics: Vec, +} + +pub fn parse(path: &str) -> Config { + let file = fs::read_to_string(path).expect("Could not open configuration file"); + toml::from_str(&file).expect("Could not parse configuration file") } diff --git a/waybar-collectd/src/main.rs b/waybar-collectd/src/main.rs index 97cf1ea..66db3b5 100644 --- a/waybar-collectd/src/main.rs +++ b/waybar-collectd/src/main.rs @@ -2,77 +2,21 @@ mod config; mod observables; mod runner; -use config::{Config, GraphConfig, SeriesConfig}; -use draw::{StackedConfig, StackedSeriesConfig}; -use observables::{Observable, ObservableCollection}; -use protocol::{Protocol, ProtocolError}; -use regex::Regex; +use config::parse; +use protocol::Protocol; use std::{thread, time}; use crate::runner::{Graph, Runner}; -fn create_debug_config() -> Config { - let load_regexes = vec![Regex::new(".*\\/cpu-[0-9]+\\/cpu-(nice|steal|system|user)").unwrap()]; - let iowait_regexes = vec![Regex::new(".*\\/cpu-[0-9]+\\/cpu-wait").unwrap()]; - let irq_regexes = vec![Regex::new(".*\\/cpu-[0-9]+\\/cpu-(interrupt|softirq)").unwrap()]; - let idle_regexes = vec![Regex::new(".*\\/cpu-[0-9]+\\/cpu-idle").unwrap()]; - let series = vec![ - SeriesConfig { - name: "load".to_string(), - color: (2, 154, 219), - metrics: load_regexes, - }, - SeriesConfig { - name: "io wait".to_string(), - color: (68, 200, 229), - metrics: iowait_regexes, - }, - SeriesConfig { - name: "irq".to_string(), - color: (143, 232, 252), - metrics: irq_regexes, - }, - SeriesConfig { - name: "idle".to_string(), - color: (0, 0, 0), - metrics: idle_regexes, - }, - ]; - let graphs = vec![GraphConfig { - name: "cpu load".to_string(), - width_px: 480, - height_px: 98, - samples: 60, - series: series, - }]; - - Config { graphs: graphs } -} - fn main() { if let Ok(mut proto) = Protocol::new("/var/run/collectd-unixsock") { - let config = create_debug_config(); + let config = parse("config.toml"); - let cfg = StackedConfig { - height_px: config.graphs[0].height_px as u32, - max_samples: config.graphs[0].samples as u32, - width_px_per_sample: (config.graphs[0].width_px / config.graphs[0].samples) as u32, - series: config.graphs[0] - .series - .iter() - .map(|s| StackedSeriesConfig { color: s.color }) - .collect(), - }; - - let observables = config.graphs[0] - .series + let graphs = config + .graph .iter() - .map(|s| Observable::discover(&mut proto, &s.name, &s.metrics)) - .collect::, ProtocolError>>() - .unwrap(); - let collection = ObservableCollection::new(observables); - let graphs = vec![Graph::new(cfg, collection)]; - + .map(|g| Graph::new(g, &mut proto)) + .collect(); let mut runner = Runner::new(graphs, proto); loop { diff --git a/waybar-collectd/src/runner.rs b/waybar-collectd/src/runner.rs index 5e12786..b1b256c 100644 --- a/waybar-collectd/src/runner.rs +++ b/waybar-collectd/src/runner.rs @@ -1,9 +1,13 @@ use core::fmt; -use draw::{StackedConfig, StackedSeries, stacked}; -use protocol::Protocol; +use draw::{StackedConfig, StackedSeries, StackedSeriesConfig, stacked}; +use protocol::{Protocol, ProtocolError}; +use regex::Regex; -use crate::observables::ObservableCollection; +use crate::{ + config::GraphConfig, + observables::{Observable, ObservableCollection}, +}; pub struct Graph { pub observable: ObservableCollection, @@ -11,10 +15,37 @@ pub struct Graph { } impl Graph { - pub fn new(config: StackedConfig, observable: ObservableCollection) -> Graph { + pub fn new(config: &GraphConfig, proto: &mut Protocol) -> Graph { + let stacked_config = StackedConfig { + name: config.name.to_string(), + height_px: config.height_px as u32, + max_samples: config.samples as u32, + width_px_per_sample: (config.width_px / config.samples) as u32, + series: config + .series + .iter() + .map(|s| StackedSeriesConfig { color: s.color }) + .collect(), + }; + + let observable = ObservableCollection::new( + config + .series + .iter() + .map(|s| { + Observable::discover( + proto, + &s.name, + &s.metrics.iter().map(|m| Regex::new(&m).unwrap()).collect(), + ) + }) + .collect::, ProtocolError>>() + .expect("Could not discover required metrics"), + ); + Graph { + series: StackedSeries::new(stacked_config), observable: observable, - series: StackedSeries::new(config), } } }