From bb41643e4976429a7ed678fb2f1327cea90fbd08 Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Wed, 24 Jun 2026 23:47:07 +0200 Subject: [PATCH] allow reading arbitrary value --- waybar-collectd/src/config.rs | 74 +++++++++++++++++++++++++++++- waybar-collectd/src/observables.rs | 38 +++++++++++++-- waybar-collectd/src/runner.rs | 9 +--- 3 files changed, 108 insertions(+), 13 deletions(-) diff --git a/waybar-collectd/src/config.rs b/waybar-collectd/src/config.rs index edecec3..609bbcf 100644 --- a/waybar-collectd/src/config.rs +++ b/waybar-collectd/src/config.rs @@ -17,14 +17,86 @@ pub struct GraphConfig { pub series: Vec, } +#[derive(PartialEq, Debug, Deserialize)] +pub struct MetricSpecification { + pub name: String, + pub value: String, +} + #[derive(Debug, Deserialize)] +#[serde(untagged)] +enum MetricInput { + String(String), + Struct { name: String, value: String }, +} + +impl MetricInput { + fn into_metric(self) -> MetricSpecification { + match self { + MetricInput::String(name) => MetricSpecification { + name, + value: "value".to_string(), + }, + MetricInput::Struct { name, value } => MetricSpecification { name, value }, + } + } +} + +fn deserialize_metrics<'de, D>(deserializer: D) -> Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + let inputs = Vec::::deserialize(deserializer)?; + Ok(inputs.into_iter().map(|m| m.into_metric()).collect()) +} + +#[derive(PartialEq, Debug, Deserialize)] pub struct SeriesConfig { pub name: String, pub color: (u8, u8, u8), - pub metrics: Vec, + + #[serde(deserialize_with = "deserialize_metrics")] + 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") } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_parse_metrics() { + let parsed: SeriesConfig = toml::from_str( + "name = 'hello world' + color = [0, 0, 0] + metrics = [ + 'm1', + { name = 'm2', value = 'modified'}, + + ]", + ) + .unwrap(); + + let expected_metrics = vec![ + MetricSpecification { + name: "m1".to_string(), + value: "value".to_string(), + }, + MetricSpecification { + name: "m2".to_string(), + value: "modified".to_string(), + }, + ]; + let expected = SeriesConfig { + name: "hello world".to_string(), + color: (0, 0, 0), + metrics: expected_metrics, + }; + + assert_eq!(parsed, expected); + } +} diff --git a/waybar-collectd/src/observables.rs b/waybar-collectd/src/observables.rs index 0465854..9cd161c 100644 --- a/waybar-collectd/src/observables.rs +++ b/waybar-collectd/src/observables.rs @@ -1,21 +1,51 @@ use protocol::{Protocol, ProtocolError}; use regex::Regex; +use crate::config::MetricSpecification; + pub struct Observable { pub name: String, - metrics: Vec, + metrics: Vec, +} + +struct MetricRegex { + pub name_regex: Regex, + pub value: String, +} + +struct Metric { + pub metric_name: String, + pub value_name: String, } impl Observable { pub fn discover( proto: &mut Protocol, name: &str, - includes: &Vec, + includes: &Vec, ) -> Result { let all_values = proto.list()?; + let regexes: Vec = includes + .iter() + .map(|i| MetricRegex { + name_regex: Regex::new(&i.name).unwrap(), + value: i.value.to_string(), + }) + .collect(); let filtered_values = all_values .into_iter() - .filter(|v| includes.iter().any(|i| i.is_match(v))) + .filter_map(|v| { + for r in regexes.iter() { + if r.name_regex.is_match(&v) { + return Some(Metric { + metric_name: v, + value_name: r.value.to_string(), + }); + } + } + + None + }) .collect(); Ok(Observable { @@ -28,7 +58,7 @@ impl Observable { let results = self .metrics .iter() - .map(|f| proto.get(f.into(), "value".to_string())) + .map(|f| proto.get(f.metric_name.to_string(), f.value_name.to_string())) .collect::, ProtocolError>>()?; Ok(results.into_iter().sum::()) diff --git a/waybar-collectd/src/runner.rs b/waybar-collectd/src/runner.rs index 769bdfa..51fdfd0 100644 --- a/waybar-collectd/src/runner.rs +++ b/waybar-collectd/src/runner.rs @@ -2,7 +2,6 @@ use core::fmt; use draw::{StackedConfig, StackedSeries, StackedSeriesConfig, stacked}; use protocol::{Protocol, ProtocolError}; -use regex::Regex; use crate::{ config::GraphConfig, @@ -33,13 +32,7 @@ impl Graph { config .series .iter() - .map(|s| { - Observable::discover( - proto, - &s.name, - &s.metrics.iter().map(|m| Regex::new(&m).unwrap()).collect(), - ) - }) + .map(|s| Observable::discover(proto, &s.name, &s.metrics)) .collect::, ProtocolError>>() .expect("Could not discover required metrics"), );