mirror of
https://github.com/centreon/centreon-plugins.git
synced 2025-07-25 06:35:38 +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 lib::{r_snmp_bulk_walk, SnmpResult};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::collections::{BTreeMap, HashMap};
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone, Copy)]
|
#[derive(Deserialize, Debug, Clone, Copy)]
|
||||||
enum Operation {
|
enum Operation {
|
||||||
@ -60,8 +59,103 @@ pub struct CmdResult {
|
|||||||
pub output: String,
|
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 {
|
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 agregation = ("", 0, Operation::None);
|
||||||
let mut res: Option<(&str, SnmpResult)> = None;
|
let mut res: Option<(&str, SnmpResult)> = None;
|
||||||
for (idx, entry) in self.leaf.entries.iter().enumerate() {
|
for (idx, entry) in self.leaf.entries.iter().enumerate() {
|
||||||
@ -78,26 +172,24 @@ impl Command {
|
|||||||
}
|
}
|
||||||
match res {
|
match res {
|
||||||
Some(r) => {
|
Some(r) => {
|
||||||
let mut values: Vec<f32> = Vec::new();
|
let mut values: Vec<(String, f32)> = Vec::new();
|
||||||
let mut labels: Vec<String> = Vec::new();
|
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
r.1.variables.iter().for_each(|v| {
|
r.1.variables.iter().for_each(|v| {
|
||||||
values.push(v.value.parse().unwrap());
|
|
||||||
let label = r.0.replace("{idx}", &idx.to_string());
|
let label = r.0.replace("{idx}", &idx.to_string());
|
||||||
labels.push(label);
|
values.push((label, v.value.parse().unwrap()));
|
||||||
idx += 1;
|
idx += 1;
|
||||||
});
|
});
|
||||||
let count = values.len();
|
let count = values.len();
|
||||||
let ag = match agregation.2 {
|
let ag = match agregation.2 {
|
||||||
Operation::Average => {
|
Operation::Average => {
|
||||||
let sum: f32 = values.iter().sum();
|
let sum: f32 = values.iter().map(|(_, v)| v).sum();
|
||||||
Some((agregation.0, agregation.1, sum / values.len() as f32))
|
let avg = sum / values.len() as f32;
|
||||||
|
Some((agregation.0, agregation.1, avg))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let metrics = self.build_metrics(&labels, &values, &ag);
|
let (metrics, status) = build_metrics(&values, &ag, &ext);
|
||||||
let status = self.build_status();
|
let output = self.build_output(count, status, &metrics, &ag, &ext);
|
||||||
let output = self.build_output(count, status, &metrics, &ag);
|
|
||||||
return CmdResult { status, output };
|
return CmdResult { status, output };
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@ -109,16 +201,13 @@ impl Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_status(&self) -> i32 {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_output(
|
fn build_output(
|
||||||
&self,
|
&self,
|
||||||
count: usize,
|
count: usize,
|
||||||
status: i32,
|
status: i32,
|
||||||
metrics: &Vec<(String, f32)>,
|
metrics: &Vec<(String, f32, &Option<String>, &Option<String>)>,
|
||||||
ag: &Option<(&str, usize, f32)>,
|
ag: &Option<(&str, usize, f32)>,
|
||||||
|
ext: &CommandExt,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut retval = self
|
let mut retval = self
|
||||||
.leaf
|
.leaf
|
||||||
@ -142,12 +231,20 @@ impl Command {
|
|||||||
retval += " |";
|
retval += " |";
|
||||||
match &self.leaf.data {
|
match &self.leaf.data {
|
||||||
Some(d) => {
|
Some(d) => {
|
||||||
metrics.iter().for_each(|(k, v)| {
|
metrics.iter().for_each(|(k, v, w, c)| {
|
||||||
retval += format!(
|
retval += format!(
|
||||||
" {}={}{};;;{};{}",
|
" {}={}{};{};{};{};{}",
|
||||||
k,
|
k,
|
||||||
v,
|
v,
|
||||||
d.uom,
|
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 {
|
match d.min {
|
||||||
Some(m) => m.to_string(),
|
Some(m) => m.to_string(),
|
||||||
None => "".to_string(),
|
None => "".to_string(),
|
||||||
@ -161,40 +258,24 @@ impl Command {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
metrics.iter().for_each(|(k, v)| {
|
metrics.iter().for_each(|(k, v, w, c)| {
|
||||||
retval += format!(" {}={}", k, v).as_str();
|
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
|
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;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
|
||||||
mod lib;
|
|
||||||
mod generic;
|
mod generic;
|
||||||
|
mod lib;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use generic::{Command, CommandExt};
|
||||||
use lib::r_snmp_get;
|
use lib::r_snmp_get;
|
||||||
use serde_json::Result;
|
use serde_json::Result;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use generic::{Command};
|
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(version, about)]
|
#[command(version, about)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
/// Hostname to operate on
|
/// Hostname to operate on
|
||||||
#[arg(long, short='H')]
|
#[arg(long, short = 'H')]
|
||||||
hostname: String,
|
hostname: String,
|
||||||
|
|
||||||
#[arg(long, short, default_value_t = 161)]
|
#[arg(long, short, default_value_t = 161)]
|
||||||
port: u16,
|
port: u16,
|
||||||
|
|
||||||
#[arg(long, short='v')]
|
#[arg(long, short = 'v')]
|
||||||
snmp_version: String,
|
snmp_version: String,
|
||||||
|
|
||||||
#[arg(long, short)]
|
#[arg(long, short)]
|
||||||
@ -34,15 +34,25 @@ struct Cli {
|
|||||||
|
|
||||||
#[arg(long, short)]
|
#[arg(long, short)]
|
||||||
json_conf: String,
|
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> {
|
fn json_to_command(file_name: &str) -> Result<Command> {
|
||||||
|
|
||||||
// Transform content of the file into a string
|
// 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,
|
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());
|
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 url = format!("{}:{}", cli.hostname, cli.port);
|
||||||
let cmd = json_to_command(&cli.json_conf);
|
let cmd = json_to_command(&cli.json_conf);
|
||||||
let cmd = cmd.unwrap();
|
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);
|
println!("{}", result.output);
|
||||||
std::process::exit(result.status);
|
std::process::exit(result.status);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user