mirror of
https://github.com/centreon/centreon-plugins.git
synced 2025-07-23 21:55:16 +02:00
enh(experimental): thresholds taken into acount
This commit is contained in:
parent
a2c0e7530b
commit
0a21a2e8fa
@ -3,7 +3,6 @@ extern crate serde_json;
|
||||
|
||||
use lib::{r_snmp_bulk_walk, SnmpResult};
|
||||
use serde::Deserialize;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
#[derive(Deserialize, Debug, Clone, Copy)]
|
||||
enum Operation {
|
||||
@ -60,8 +59,103 @@ pub struct CmdResult {
|
||||
pub output: String,
|
||||
}
|
||||
|
||||
pub struct CommandExt {
|
||||
pub warning_core: Option<String>,
|
||||
pub critical_core: Option<String>,
|
||||
pub warning_agregation: Option<String>,
|
||||
pub critical_agregation: Option<String>,
|
||||
}
|
||||
|
||||
fn compute_status(value: f32, warn: &Option<String>, crit: &Option<String>) -> i32 {
|
||||
if let Some(c) = crit {
|
||||
let crit = c.parse().unwrap();
|
||||
if value > crit {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
if let Some(w) = warn {
|
||||
let warn = w.parse().unwrap();
|
||||
if value > warn {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
fn build_status(metrics: &Vec<(String, f32, i32)>) -> i32 {
|
||||
let mut retval = 0;
|
||||
metrics.iter().for_each(|(_, _, s)| {
|
||||
if *s > retval {
|
||||
retval = *s;
|
||||
if retval == 2 {
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
return retval;
|
||||
}
|
||||
|
||||
fn build_metrics<'a>(
|
||||
values: &Vec<(String, f32)>,
|
||||
ag: &Option<(&str, usize, f32)>,
|
||||
ext: &'a CommandExt,
|
||||
) -> (
|
||||
Vec<(String, f32, &'a Option<String>, &'a Option<String>)>,
|
||||
i32,
|
||||
) {
|
||||
let mut metrics: Vec<(String, f32, &Option<String>, &Option<String>)> = Vec::new();
|
||||
let mut status = 0;
|
||||
match ag {
|
||||
Some(a) => {
|
||||
// The agregation is located in first place
|
||||
if a.1 == 0 {
|
||||
let w = &ext.warning_agregation;
|
||||
let c = &ext.critical_agregation;
|
||||
let current_status =
|
||||
compute_status(a.2, &ext.warning_agregation, &ext.critical_agregation);
|
||||
metrics.push((a.0.to_string(), a.2, w, c));
|
||||
if current_status > status {
|
||||
status = current_status;
|
||||
}
|
||||
}
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
values.iter().enumerate().for_each(|(i, v)| {
|
||||
let current_status = compute_status(v.1, &ext.warning_core, &ext.critical_core);
|
||||
metrics.push((
|
||||
values[i].0.clone(),
|
||||
v.1,
|
||||
&ext.warning_core,
|
||||
&ext.critical_core,
|
||||
));
|
||||
if current_status > status {
|
||||
status = current_status;
|
||||
}
|
||||
});
|
||||
match ag {
|
||||
Some(a) => {
|
||||
if a.1 > 0 {
|
||||
let current_status =
|
||||
compute_status(a.2, &ext.warning_agregation, &ext.critical_agregation);
|
||||
metrics.push((
|
||||
a.0.to_string(),
|
||||
a.2,
|
||||
&ext.warning_agregation,
|
||||
&ext.critical_agregation,
|
||||
));
|
||||
if current_status > status {
|
||||
status = current_status;
|
||||
}
|
||||
}
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
(metrics, status)
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub fn execute(&self, target: &str) -> CmdResult {
|
||||
pub fn execute(&self, target: &str, ext: &CommandExt) -> CmdResult {
|
||||
let mut agregation = ("", 0, Operation::None);
|
||||
let mut res: Option<(&str, SnmpResult)> = None;
|
||||
for (idx, entry) in self.leaf.entries.iter().enumerate() {
|
||||
@ -78,26 +172,24 @@ impl Command {
|
||||
}
|
||||
match res {
|
||||
Some(r) => {
|
||||
let mut values: Vec<f32> = Vec::new();
|
||||
let mut labels: Vec<String> = Vec::new();
|
||||
let mut values: Vec<(String, f32)> = Vec::new();
|
||||
let mut idx = 0;
|
||||
r.1.variables.iter().for_each(|v| {
|
||||
values.push(v.value.parse().unwrap());
|
||||
let label = r.0.replace("{idx}", &idx.to_string());
|
||||
labels.push(label);
|
||||
values.push((label, v.value.parse().unwrap()));
|
||||
idx += 1;
|
||||
});
|
||||
let count = values.len();
|
||||
let ag = match agregation.2 {
|
||||
Operation::Average => {
|
||||
let sum: f32 = values.iter().sum();
|
||||
Some((agregation.0, agregation.1, sum / values.len() as f32))
|
||||
let sum: f32 = values.iter().map(|(_, v)| v).sum();
|
||||
let avg = sum / values.len() as f32;
|
||||
Some((agregation.0, agregation.1, avg))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
let metrics = self.build_metrics(&labels, &values, &ag);
|
||||
let status = self.build_status();
|
||||
let output = self.build_output(count, status, &metrics, &ag);
|
||||
let (metrics, status) = build_metrics(&values, &ag, &ext);
|
||||
let output = self.build_output(count, status, &metrics, &ag, &ext);
|
||||
return CmdResult { status, output };
|
||||
}
|
||||
None => {
|
||||
@ -109,16 +201,13 @@ impl Command {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_status(&self) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
fn build_output(
|
||||
&self,
|
||||
count: usize,
|
||||
status: i32,
|
||||
metrics: &Vec<(String, f32)>,
|
||||
metrics: &Vec<(String, f32, &Option<String>, &Option<String>)>,
|
||||
ag: &Option<(&str, usize, f32)>,
|
||||
ext: &CommandExt,
|
||||
) -> String {
|
||||
let mut retval = self
|
||||
.leaf
|
||||
@ -142,12 +231,20 @@ impl Command {
|
||||
retval += " |";
|
||||
match &self.leaf.data {
|
||||
Some(d) => {
|
||||
metrics.iter().for_each(|(k, v)| {
|
||||
metrics.iter().for_each(|(k, v, w, c)| {
|
||||
retval += format!(
|
||||
" {}={}{};;;{};{}",
|
||||
" {}={}{};{};{};{};{}",
|
||||
k,
|
||||
v,
|
||||
d.uom,
|
||||
match w {
|
||||
Some(m) => m.to_string(),
|
||||
None => "".to_string(),
|
||||
},
|
||||
match c {
|
||||
Some(m) => m.to_string(),
|
||||
None => "".to_string(),
|
||||
},
|
||||
match d.min {
|
||||
Some(m) => m.to_string(),
|
||||
None => "".to_string(),
|
||||
@ -161,40 +258,24 @@ impl Command {
|
||||
});
|
||||
}
|
||||
None => {
|
||||
metrics.iter().for_each(|(k, v)| {
|
||||
retval += format!(" {}={}", k, v).as_str();
|
||||
metrics.iter().for_each(|(k, v, w, c)| {
|
||||
retval += format!(
|
||||
" {}={};{};{}",
|
||||
k,
|
||||
v,
|
||||
match w {
|
||||
Some(v) => v.to_string(),
|
||||
None => "".to_string(),
|
||||
},
|
||||
match c {
|
||||
Some(v) => v.to_string(),
|
||||
None => "".to_string(),
|
||||
}
|
||||
)
|
||||
.as_str();
|
||||
});
|
||||
}
|
||||
};
|
||||
retval
|
||||
}
|
||||
|
||||
fn build_metrics(
|
||||
&self,
|
||||
labels: &Vec<String>,
|
||||
values: &Vec<f32>,
|
||||
ag: &Option<(&str, usize, f32)>,
|
||||
) -> Vec<(String, f32)> {
|
||||
let mut metrics: Vec<(String, f32)> = Vec::new();
|
||||
match ag {
|
||||
Some(a) => {
|
||||
if a.1 == 0 {
|
||||
metrics.push((a.0.to_string(), a.2));
|
||||
}
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
values.iter().enumerate().for_each(|(i, v)| {
|
||||
metrics.push((labels[i].clone(), *v));
|
||||
});
|
||||
match ag {
|
||||
Some(a) => {
|
||||
if a.1 > 0 {
|
||||
metrics.push((a.0.to_string(), a.2));
|
||||
}
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
metrics
|
||||
}
|
||||
}
|
||||
|
@ -7,26 +7,26 @@ extern crate regex;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
|
||||
mod lib;
|
||||
mod generic;
|
||||
mod lib;
|
||||
|
||||
use clap::Parser;
|
||||
use generic::{Command, CommandExt};
|
||||
use lib::r_snmp_get;
|
||||
use serde_json::Result;
|
||||
use std::fs;
|
||||
use generic::{Command};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about)]
|
||||
struct Cli {
|
||||
/// Hostname to operate on
|
||||
#[arg(long, short='H')]
|
||||
#[arg(long, short = 'H')]
|
||||
hostname: String,
|
||||
|
||||
#[arg(long, short, default_value_t = 161)]
|
||||
port: u16,
|
||||
|
||||
#[arg(long, short='v')]
|
||||
#[arg(long, short = 'v')]
|
||||
snmp_version: String,
|
||||
|
||||
#[arg(long, short)]
|
||||
@ -34,15 +34,25 @@ struct Cli {
|
||||
|
||||
#[arg(long, short)]
|
||||
json_conf: String,
|
||||
|
||||
#[arg(long, short)]
|
||||
warning_core: Option<String>,
|
||||
|
||||
#[arg(long, short = 'C')]
|
||||
critical_core: Option<String>,
|
||||
|
||||
#[arg(long, short = 'a')]
|
||||
warning_agregation: Option<String>,
|
||||
|
||||
#[arg(long, short = 'b')]
|
||||
critical_agregation: Option<String>,
|
||||
}
|
||||
|
||||
fn json_to_command(file_name: &str) -> Result<Command> {
|
||||
|
||||
// Transform content of the file into a string
|
||||
let contents = match fs::read_to_string(file_name)
|
||||
{
|
||||
let contents = match fs::read_to_string(file_name) {
|
||||
Ok(ret) => ret,
|
||||
Err(err) => panic!("Could not deserialize the file, error code: {}", err)
|
||||
Err(err) => panic!("Could not deserialize the file, error code: {}", err),
|
||||
};
|
||||
|
||||
let module: Result<Command> = serde_json::from_str(&contents.as_str());
|
||||
@ -54,7 +64,13 @@ fn main() {
|
||||
let url = format!("{}:{}", cli.hostname, cli.port);
|
||||
let cmd = json_to_command(&cli.json_conf);
|
||||
let cmd = cmd.unwrap();
|
||||
let result = cmd.execute(&url);
|
||||
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, &ext);
|
||||
println!("{}", result.output);
|
||||
std::process::exit(result.status);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user