allow reading arbitrary value

This commit is contained in:
Ondrej Novak 2026-06-24 23:47:07 +02:00
parent da931f031b
commit bb41643e49
Signed by: handy
SSH Key Fingerprint: SHA256:jlNm8ijkaMl4X7+nn3zBFTJufdQgT4unKJoZVH6kYTM
3 changed files with 108 additions and 13 deletions

View File

@ -17,14 +17,86 @@ pub struct GraphConfig {
pub series: Vec<SeriesConfig>, pub series: Vec<SeriesConfig>,
} }
#[derive(PartialEq, Debug, Deserialize)]
pub struct MetricSpecification {
pub name: String,
pub value: String,
}
#[derive(Debug, Deserialize)] #[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<Vec<MetricSpecification>, D::Error>
where
D: serde::Deserializer<'de>,
{
let inputs = Vec::<MetricInput>::deserialize(deserializer)?;
Ok(inputs.into_iter().map(|m| m.into_metric()).collect())
}
#[derive(PartialEq, Debug, Deserialize)]
pub struct SeriesConfig { pub struct SeriesConfig {
pub name: String, pub name: String,
pub color: (u8, u8, u8), pub color: (u8, u8, u8),
pub metrics: Vec<String>,
#[serde(deserialize_with = "deserialize_metrics")]
pub metrics: Vec<MetricSpecification>,
} }
pub fn parse(path: &str) -> Config { pub fn parse(path: &str) -> Config {
let file = fs::read_to_string(path).expect("Could not open configuration file"); let file = fs::read_to_string(path).expect("Could not open configuration file");
toml::from_str(&file).expect("Could not parse 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);
}
}

View File

@ -1,21 +1,51 @@
use protocol::{Protocol, ProtocolError}; use protocol::{Protocol, ProtocolError};
use regex::Regex; use regex::Regex;
use crate::config::MetricSpecification;
pub struct Observable { pub struct Observable {
pub name: String, pub name: String,
metrics: Vec<String>, metrics: Vec<Metric>,
}
struct MetricRegex {
pub name_regex: Regex,
pub value: String,
}
struct Metric {
pub metric_name: String,
pub value_name: String,
} }
impl Observable { impl Observable {
pub fn discover( pub fn discover(
proto: &mut Protocol, proto: &mut Protocol,
name: &str, name: &str,
includes: &Vec<Regex>, includes: &Vec<MetricSpecification>,
) -> Result<Observable, ProtocolError> { ) -> Result<Observable, ProtocolError> {
let all_values = proto.list()?; let all_values = proto.list()?;
let regexes: Vec<MetricRegex> = includes
.iter()
.map(|i| MetricRegex {
name_regex: Regex::new(&i.name).unwrap(),
value: i.value.to_string(),
})
.collect();
let filtered_values = all_values let filtered_values = all_values
.into_iter() .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(); .collect();
Ok(Observable { Ok(Observable {
@ -28,7 +58,7 @@ impl Observable {
let results = self let results = self
.metrics .metrics
.iter() .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::<Result<Vec<f32>, ProtocolError>>()?; .collect::<Result<Vec<f32>, ProtocolError>>()?;
Ok(results.into_iter().sum::<f32>()) Ok(results.into_iter().sum::<f32>())

View File

@ -2,7 +2,6 @@ use core::fmt;
use draw::{StackedConfig, StackedSeries, StackedSeriesConfig, stacked}; use draw::{StackedConfig, StackedSeries, StackedSeriesConfig, stacked};
use protocol::{Protocol, ProtocolError}; use protocol::{Protocol, ProtocolError};
use regex::Regex;
use crate::{ use crate::{
config::GraphConfig, config::GraphConfig,
@ -33,13 +32,7 @@ impl Graph {
config config
.series .series
.iter() .iter()
.map(|s| { .map(|s| Observable::discover(proto, &s.name, &s.metrics))
Observable::discover(
proto,
&s.name,
&s.metrics.iter().map(|m| Regex::new(&m).unwrap()).collect(),
)
})
.collect::<Result<Vec<Observable>, ProtocolError>>() .collect::<Result<Vec<Observable>, ProtocolError>>()
.expect("Could not discover required metrics"), .expect("Could not discover required metrics"),
); );