allow reading arbitrary value
This commit is contained in:
parent
da931f031b
commit
bb41643e49
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>())
|
||||||
|
|
|
||||||
|
|
@ -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"),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue