diff --git a/experimental/examples/new-disk.json b/experimental/examples/new-disk.json index 98056f355..293f33266 100644 --- a/experimental/examples/new-disk.json +++ b/experimental/examples/new-disk.json @@ -25,6 +25,7 @@ "max": 100 }, { + "prefix": "{disk.label}", "name": "disk.usage.bytes", "value": "{disk.used} * {disk.allocationUnits}", "uom": "B", diff --git a/experimental/src/compute/mod.rs b/experimental/src/compute/mod.rs index 060bc6912..b5f3b7d27 100644 --- a/experimental/src/compute/mod.rs +++ b/experimental/src/compute/mod.rs @@ -21,6 +21,9 @@ pub struct Metric { pub min: Option, pub max_expr: Option, pub max: Option, + pub threshold_suffix: Option, + pub warning: Option, + pub critical: Option, } #[derive(Deserialize, Debug)] diff --git a/experimental/src/generic/mod.rs b/experimental/src/generic/mod.rs index b80dbffb9..e542d11df 100644 --- a/experimental/src/generic/mod.rs +++ b/experimental/src/generic/mod.rs @@ -110,6 +110,34 @@ fn compute_status(value: f64, warn: &Option, crit: &Option) -> S } impl Command { + pub fn add_warning(&mut self, name: &str, value: String) { + if let Some(metric) = + self.compute + .metrics + .iter_mut() + .find(|metric| match &metric.threshold_suffix { + Some(suffix) => suffix == name, + None => false, + }) + { + metric.warning = Some(value); + } + } + + pub fn add_critical(&mut self, name: &str, value: String) { + if let Some(metric) = + self.compute + .metrics + .iter_mut() + .find(|metric| match &metric.threshold_suffix { + Some(suffix) => suffix == name, + None => false, + }) + { + metric.critical = Some(value); + } + } + pub fn execute( &self, target: &str, @@ -151,11 +179,28 @@ impl Command { let mut my_res = SnmpResult::new(HashMap::new()); for metric in self.compute.metrics.iter() { let value = &metric.value; - let min = metric.min; - let max = metric.max; let parser = Parser::new(&collect); let value = parser.eval(value).unwrap(); + let min = if let Some(min_expr) = metric.min_expr.as_ref() { + parser.eval(&min_expr).unwrap() + } else if let Some(min_value) = metric.min { + ExprResult::Number(min_value) + } else { + ExprResult::Empty + }; + let max = if let Some(max_expr) = metric.max_expr.as_ref() { + parser.eval(&max_expr).unwrap() + } else if let Some(max_value) = metric.max { + ExprResult::Number(max_value) + } else { + ExprResult::Empty + }; + let compute_threshold = |idx: usize, expr: &ExprResult| match &expr { + ExprResult::Number(value) => Some(*value), + ExprResult::Vector(v) => Some(v[idx]), + _ => None, + }; match &value { ExprResult::Vector(v) => { let prefix_str = match &metric.prefix { @@ -177,8 +222,8 @@ impl Command { let m = Perfdata { name, value: *item, - min, - max, + min: compute_threshold(i, &min), + max: compute_threshold(i, &max), }; trace!("New metric '{}' with value {:?}", m.name, m.value); metrics.push(m); @@ -198,8 +243,8 @@ impl Command { let m = Perfdata { name, value: *s, - min, - max, + min: compute_threshold(0, &min), + max: compute_threshold(0, &max), }; trace!("New metric '{}' with value {:?}", m.name, m.value); metrics.push(m); diff --git a/experimental/src/main.rs b/experimental/src/main.rs index 66f930f17..3403d93b4 100644 --- a/experimental/src/main.rs +++ b/experimental/src/main.rs @@ -15,44 +15,14 @@ mod snmp; use generic::Command; use lalrpop_util::lalrpop_mod; -use log::{debug, info, trace}; +use lexopt::Arg; +use log::{debug, trace}; use serde_json::Result; +use std::collections::HashMap; use std::fs; lalrpop_mod!(grammar); -#[derive(Debug)] -//#[command(version, about)] -struct Cli { - /// Hostname to operate on - //#[arg(long, short = 'H', default_value = "localhost")] - hostname: String, - - //#[arg(long, short, default_value_t = 161)] - port: u16, - - //#[arg(long, short = 'v', default_value = "2c")] - snmp_version: String, - - //#[arg(long, short, default_value = "public")] - community: String, - - //#[arg(long, short)] - json_conf: String, - - //#[arg(long, short)] - warning_core: Option, - - //#[arg(long, short = 'C')] - critical_core: Option, - - //#[arg(long, short = 'a')] - warning_agregation: Option, - - //#[arg(long, short = 'b')] - critical_agregation: Option, -} - fn json_to_command(file_name: &str) -> Result { // Transform content of the file into a string let contents = match fs::read_to_string(file_name) { @@ -76,7 +46,7 @@ fn main() { let mut port = 161; let mut snmp_version = "2c".to_string(); let mut snmp_community = "public".to_string(); - let mut json = None; + let mut cmd: Option = None; loop { let arg = parser.next(); match arg { @@ -91,8 +61,17 @@ fn main() { trace!("port: {}", port); } Short('j') | Long("json") => { - json = Some(parser.value().unwrap().into_string().unwrap()); + let json = Some(parser.value().unwrap().into_string().unwrap()); + let json = json.unwrap(); trace!("json: {:?}", json); + let res_cmd = json_to_command(&json); + cmd = Some(match res_cmd { + Ok(c) => c, + Err(err) => { + println!("json_to_command error: {:?}", err); + std::process::exit(3); + } + }); } Short('v') | Long("snmp-version") => { snmp_version = parser.value().unwrap().into_string().unwrap(); @@ -102,8 +81,34 @@ fn main() { snmp_community = parser.value().unwrap().into_string().unwrap(); trace!("snmp_community: {}", snmp_community); } - _ => { - debug!("other unknown argument"); + t => { + if let Arg::Long(name) = t { + if name.starts_with("warning-") { + let wmetric = name[8..].to_string(); + let value = parser.value().unwrap().into_string().unwrap(); + match cmd.as_mut() { + Some(ref mut cmd) => { + cmd.add_warning(&wmetric, value); + } + None => { + println!("json is empty"); + std::process::exit(3); + } + } + } else if name.starts_with("critical-") { + let cmetric = name[9..].to_string(); + let value = parser.value().unwrap().into_string().unwrap(); + match cmd.as_mut() { + Some(ref mut cmd) => { + cmd.add_critical(&cmetric, value); + } + None => { + println!("json is empty"); + std::process::exit(3); + } + } + } + } } }, None => { @@ -118,21 +123,14 @@ fn main() { } let url = format!("{}:{}", hostname, port); - if json.is_none() { - println!("json is empty"); - std::process::exit(3); - } + let result = match cmd { + Some(ref cmd) => cmd.execute(&url, &snmp_version, &snmp_community), + None => { + println!("json is empty"); + std::process::exit(3); + } + }; - let json = json.unwrap(); - let cmd = json_to_command(&json); - let cmd = cmd.unwrap(); - //let ext = CommandExt { - // warning_core: cli.warning_core, - // critical_core: cli.critical_core, - // warning_agregation: cli.warning_agregation, - // critical_agregation: cli.critical_agregation, - //}; - let result = cmd.execute(&url, &snmp_version, &snmp_community); //println!("{}", result.output); //std::process::exit(result.status as i32); }