load configuration file

This commit is contained in:
Ondrej Novak 2026-06-19 23:23:20 +02:00
parent 6d3f360012
commit fe3cbc7fc3
Signed by: handy
SSH Key Fingerprint: SHA256:jlNm8ijkaMl4X7+nn3zBFTJufdQgT4unKJoZVH6kYTM
6 changed files with 167 additions and 71 deletions

108
Cargo.lock generated
View File

@ -313,6 +313,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]] [[package]]
name = "exr" name = "exr"
version = "1.74.0" version = "1.74.0"
@ -516,6 +522,12 @@ dependencies = [
"zerocopy", "zerocopy",
] ]
[[package]]
name = "hashbrown"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]] [[package]]
name = "image" name = "image"
version = "0.25.10" version = "0.25.10"
@ -576,6 +588,16 @@ version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" 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]] [[package]]
name = "interpolate_name" name = "interpolate_name"
version = "0.2.4" version = "0.2.4"
@ -1187,6 +1209,45 @@ dependencies = [
"version-compare", "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]] [[package]]
name = "shlex" name = "shlex"
version = "1.3.0" version = "1.3.0"
@ -1284,6 +1345,45 @@ dependencies = [
"zune-jpeg", "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]] [[package]]
name = "transpose" name = "transpose"
version = "0.2.3" version = "0.2.3"
@ -1391,6 +1491,8 @@ dependencies = [
"imageproc", "imageproc",
"protocol", "protocol",
"regex", "regex",
"serde",
"toml",
] ]
[[package]] [[package]]
@ -1409,6 +1511,12 @@ dependencies = [
"safe_arch", "safe_arch",
] ]
[[package]]
name = "winnow"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"
[[package]] [[package]]
name = "wit-bindgen" name = "wit-bindgen"
version = "0.51.0" version = "0.51.0"

View File

@ -7,6 +7,7 @@ use imageproc::{
use crate::Container; use crate::Container;
pub struct StackedConfig { pub struct StackedConfig {
pub name: String,
pub width_px_per_sample: u32, pub width_px_per_sample: u32,
pub height_px: u32, pub height_px: u32,
pub series: Vec<StackedSeriesConfig>, pub series: Vec<StackedSeriesConfig>,

View File

@ -8,3 +8,5 @@ draw = { version = "0.1.0", path = "../draw" }
imageproc = { version = "0.26.1", features = ["display-window"] } imageproc = { version = "0.26.1", features = ["display-window"] }
protocol = { path = "../protocol" } protocol = { path = "../protocol" }
regex = "1.12.3" regex = "1.12.3"
serde = { version = "1.0.228", features = ["derive"] }
toml = { version = "1.1.2", features = ["serde", "parse"] }

View File

@ -1,9 +1,13 @@
use regex::Regex; use std::fs;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
pub struct Config { pub struct Config {
pub graphs: Vec<GraphConfig>, pub graph: Vec<GraphConfig>,
} }
#[derive(Debug, Deserialize)]
pub struct GraphConfig { pub struct GraphConfig {
pub name: String, pub name: String,
pub width_px: u16, pub width_px: u16,
@ -12,8 +16,14 @@ pub struct GraphConfig {
pub series: Vec<SeriesConfig>, pub series: Vec<SeriesConfig>,
} }
#[derive(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<Regex>, pub metrics: Vec<String>,
}
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")
} }

View File

@ -2,77 +2,21 @@ mod config;
mod observables; mod observables;
mod runner; mod runner;
use config::{Config, GraphConfig, SeriesConfig}; use config::parse;
use draw::{StackedConfig, StackedSeriesConfig}; use protocol::Protocol;
use observables::{Observable, ObservableCollection};
use protocol::{Protocol, ProtocolError};
use regex::Regex;
use std::{thread, time}; use std::{thread, time};
use crate::runner::{Graph, Runner}; 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() { fn main() {
if let Ok(mut proto) = Protocol::new("/var/run/collectd-unixsock") { if let Ok(mut proto) = Protocol::new("/var/run/collectd-unixsock") {
let config = create_debug_config(); let config = parse("config.toml");
let cfg = StackedConfig { let graphs = config
height_px: config.graphs[0].height_px as u32, .graph
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() .iter()
.map(|s| StackedSeriesConfig { color: s.color }) .map(|g| Graph::new(g, &mut proto))
.collect(), .collect();
};
let observables = config.graphs[0]
.series
.iter()
.map(|s| Observable::discover(&mut proto, &s.name, &s.metrics))
.collect::<Result<Vec<Observable>, ProtocolError>>()
.unwrap();
let collection = ObservableCollection::new(observables);
let graphs = vec![Graph::new(cfg, collection)];
let mut runner = Runner::new(graphs, proto); let mut runner = Runner::new(graphs, proto);
loop { loop {

View File

@ -1,9 +1,13 @@
use core::fmt; use core::fmt;
use draw::{StackedConfig, StackedSeries, stacked}; use draw::{StackedConfig, StackedSeries, StackedSeriesConfig, stacked};
use protocol::Protocol; use protocol::{Protocol, ProtocolError};
use regex::Regex;
use crate::observables::ObservableCollection; use crate::{
config::GraphConfig,
observables::{Observable, ObservableCollection},
};
pub struct Graph { pub struct Graph {
pub observable: ObservableCollection, pub observable: ObservableCollection,
@ -11,10 +15,37 @@ pub struct Graph {
} }
impl 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::<Result<Vec<Observable>, ProtocolError>>()
.expect("Could not discover required metrics"),
);
Graph { Graph {
series: StackedSeries::new(stacked_config),
observable: observable, observable: observable,
series: StackedSeries::new(config),
} }
} }
} }