mirror of
https://github.com/centreon/centreon-plugins.git
synced 2025-07-29 16:45:04 +02:00
enh(generic-snmp): new ast object
This commit is contained in:
parent
1ecfbb7d11
commit
ef7dffae3d
267
experimental/src/compute/ast.rs
Normal file
267
experimental/src/compute/ast.rs
Normal file
@ -0,0 +1,267 @@
|
||||
use snmp::{SnmpItem, SnmpResult};
|
||||
use std::str;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Expr<'input> {
|
||||
Id(&'input [u8]),
|
||||
Number(f64),
|
||||
OpPlus(Box<Expr<'input>>, Box<Expr<'input>>),
|
||||
OpMinus(Box<Expr<'input>>, Box<Expr<'input>>),
|
||||
OpStar(Box<Expr<'input>>, Box<Expr<'input>>),
|
||||
OpSlash(Box<Expr<'input>>, Box<Expr<'input>>),
|
||||
Fn(Func, Box<Expr<'input>>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Func {
|
||||
Average,
|
||||
Min,
|
||||
Max,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ExprResult {
|
||||
Vector(Vec<f64>),
|
||||
Scalar(f64),
|
||||
}
|
||||
|
||||
impl std::ops::Add for ExprResult {
|
||||
type Output = ExprResult;
|
||||
|
||||
fn add(self, other: Self) -> Self::Output {
|
||||
match (self, other) {
|
||||
(ExprResult::Scalar(a), ExprResult::Scalar(b)) => ExprResult::Scalar(a + b),
|
||||
(ExprResult::Vector(a), ExprResult::Vector(b)) => {
|
||||
let len_a = a.len();
|
||||
let len_b = b.len();
|
||||
if len_a == len_b {
|
||||
let mut result = Vec::with_capacity(len_a);
|
||||
for i in 0..len_a {
|
||||
result.push(a[i] + b[i]);
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
} else {
|
||||
if len_a > len_b {
|
||||
let mut result = a.clone();
|
||||
for (idx, value) in b.iter().enumerate() {
|
||||
result[idx] += value;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
} else {
|
||||
let mut result = b.clone();
|
||||
for (idx, value) in a.iter().enumerate() {
|
||||
result[idx] += value;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
(ExprResult::Scalar(a), ExprResult::Vector(b)) => {
|
||||
let mut result = b.clone();
|
||||
for value in result.iter_mut() {
|
||||
*value += a;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
}
|
||||
(ExprResult::Vector(a), ExprResult::Scalar(b)) => {
|
||||
let mut result = a.clone();
|
||||
for value in result.iter_mut() {
|
||||
*value += b;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Sub for ExprResult {
|
||||
type Output = ExprResult;
|
||||
|
||||
fn sub(self, other: Self) -> Self::Output {
|
||||
match (self, other) {
|
||||
(ExprResult::Scalar(a), ExprResult::Scalar(b)) => ExprResult::Scalar(a - b),
|
||||
(ExprResult::Vector(a), ExprResult::Vector(b)) => {
|
||||
let len_a = a.len();
|
||||
let len_b = b.len();
|
||||
if len_a == len_b {
|
||||
let mut result = Vec::with_capacity(len_a);
|
||||
for i in 0..len_a {
|
||||
result.push(a[i] - b[i]);
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
} else {
|
||||
if len_a > len_b {
|
||||
let mut result = a.clone();
|
||||
for (idx, value) in b.iter().enumerate() {
|
||||
result[idx] -= value;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
} else {
|
||||
let mut result = b.clone();
|
||||
for (idx, value) in a.iter().enumerate() {
|
||||
result[idx] -= value;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
(ExprResult::Scalar(a), ExprResult::Vector(b)) => {
|
||||
let mut result = vec![0_f64; b.len()];
|
||||
for (idx, value) in result.iter_mut().enumerate() {
|
||||
*value = a - b[idx];
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
}
|
||||
(ExprResult::Vector(a), ExprResult::Scalar(b)) => {
|
||||
let mut result = a.clone();
|
||||
for value in result.iter_mut() {
|
||||
*value -= b;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul for ExprResult {
|
||||
type Output = ExprResult;
|
||||
|
||||
fn mul(self, other: Self) -> Self::Output {
|
||||
match (self, other) {
|
||||
(ExprResult::Scalar(a), ExprResult::Scalar(b)) => ExprResult::Scalar(a * b),
|
||||
(ExprResult::Vector(a), ExprResult::Vector(b)) => {
|
||||
let len_a = a.len();
|
||||
let len_b = b.len();
|
||||
if len_a == len_b {
|
||||
let mut result = Vec::with_capacity(len_a);
|
||||
for i in 0..len_a {
|
||||
result.push(a[i] * b[i]);
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
} else {
|
||||
if len_a > len_b {
|
||||
let mut result = a.clone();
|
||||
for (idx, value) in b.iter().enumerate() {
|
||||
result[idx] *= value;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
} else {
|
||||
let mut result = b.clone();
|
||||
for (idx, value) in a.iter().enumerate() {
|
||||
result[idx] *= value;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
(ExprResult::Scalar(a), ExprResult::Vector(b)) => {
|
||||
let mut result = b.clone();
|
||||
for value in result.iter_mut() {
|
||||
*value *= a;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
}
|
||||
(ExprResult::Vector(a), ExprResult::Scalar(b)) => {
|
||||
let mut result = a.clone();
|
||||
for value in result.iter_mut() {
|
||||
*value *= b;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Div for ExprResult {
|
||||
type Output = ExprResult;
|
||||
|
||||
fn div(self, other: Self) -> Self::Output {
|
||||
match (self, other) {
|
||||
(ExprResult::Scalar(a), ExprResult::Scalar(b)) => ExprResult::Scalar(a / b),
|
||||
(ExprResult::Vector(a), ExprResult::Vector(b)) => {
|
||||
let len_a = a.len();
|
||||
let len_b = b.len();
|
||||
if len_a == len_b {
|
||||
let mut result = Vec::with_capacity(len_a);
|
||||
for i in 0..len_a {
|
||||
result.push(a[i] / b[i]);
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
} else {
|
||||
if len_a > len_b {
|
||||
let mut result = a.clone();
|
||||
for (idx, value) in b.iter().enumerate() {
|
||||
result[idx] /= value;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
} else {
|
||||
let mut result = b.clone();
|
||||
for (idx, value) in a.iter().enumerate() {
|
||||
result[idx] /= value;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
(ExprResult::Scalar(a), ExprResult::Vector(b)) => {
|
||||
let mut result = vec![0_f64; b.len()];
|
||||
for (idx, value) in result.iter_mut().enumerate() {
|
||||
*value = a / b[idx];
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
}
|
||||
(ExprResult::Vector(a), ExprResult::Scalar(b)) => {
|
||||
let mut result = a.clone();
|
||||
for value in result.iter_mut() {
|
||||
*value /= b;
|
||||
}
|
||||
ExprResult::Vector(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'input> Expr<'input> {
|
||||
pub fn eval(&self, collect: &Vec<SnmpResult>) -> ExprResult {
|
||||
match self {
|
||||
Expr::Number(n) => ExprResult::Scalar(*n),
|
||||
Expr::Id(key) => {
|
||||
for result in collect {
|
||||
let k = str::from_utf8(key).unwrap();
|
||||
let item = &result.items[k];
|
||||
match item {
|
||||
SnmpItem::Nbr(n) => {
|
||||
if n.len() == 1 {
|
||||
return ExprResult::Scalar(n[0]);
|
||||
} else {
|
||||
return ExprResult::Vector(n.clone());
|
||||
}
|
||||
}
|
||||
_ => panic!("Should be a number"),
|
||||
}
|
||||
}
|
||||
ExprResult::Scalar(0.0)
|
||||
}
|
||||
Expr::OpPlus(left, right) => left.eval(collect) + right.eval(collect),
|
||||
Expr::OpMinus(left, right) => left.eval(collect) - right.eval(collect),
|
||||
Expr::OpStar(left, right) => left.eval(collect) * right.eval(collect),
|
||||
Expr::OpSlash(left, right) => left.eval(collect) / right.eval(collect),
|
||||
Expr::Fn(func, expr) => {
|
||||
let v = expr.eval(collect);
|
||||
match func {
|
||||
Func::Average => v,
|
||||
Func::Min => v,
|
||||
Func::Max => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval_as_str(&self) -> &[u8] {
|
||||
if let Expr::Id(id) = self {
|
||||
return id;
|
||||
} else {
|
||||
return b"Bad value";
|
||||
}
|
||||
}
|
||||
}
|
@ -4,20 +4,23 @@ use std::str;
|
||||
pub type Spanned<Tok, Loc, Error> = Result<(Loc, Tok, Loc), Error>;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Tok {
|
||||
Num(f32),
|
||||
Id,
|
||||
pub enum Tok<'input> {
|
||||
Num(f64),
|
||||
Id(&'input [u8]),
|
||||
OpStar,
|
||||
OpSlash,
|
||||
OpPlus,
|
||||
OpMinus,
|
||||
LParen,
|
||||
RParen,
|
||||
LBrace,
|
||||
RBrace,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum LexicalError {
|
||||
NotPossible,
|
||||
UnmatchedBrace,
|
||||
// Not possible
|
||||
}
|
||||
|
||||
@ -35,8 +38,9 @@ impl<'input> Lexer<'input> {
|
||||
}
|
||||
}
|
||||
|
||||
fn number(&mut self, start: usize, chars: &[u8]) -> Option<Spanned<Tok, usize, LexicalError>> {
|
||||
fn number(&mut self, start: usize) -> Option<Spanned<Tok<'input>, usize, LexicalError>> {
|
||||
// Consume digits and decimal points
|
||||
let chars = self.chars.as_bytes();
|
||||
let mut end = start;
|
||||
let mut done = false;
|
||||
for c in chars[(start + 1)..].iter() {
|
||||
@ -59,22 +63,19 @@ impl<'input> Lexer<'input> {
|
||||
self.offset = end;
|
||||
let value = str::from_utf8(&chars[start..end])
|
||||
.unwrap_or("Bad value")
|
||||
.parse::<f32>()
|
||||
.parse::<f64>()
|
||||
.unwrap_or(0.0);
|
||||
Some(Ok((start, Tok::Num(value), end)))
|
||||
}
|
||||
|
||||
fn identifier(
|
||||
&mut self,
|
||||
start: usize,
|
||||
chars: &[u8],
|
||||
) -> Option<Spanned<Tok, usize, LexicalError>> {
|
||||
fn identifier(&mut self, start: usize) -> Option<Spanned<Tok<'input>, usize, LexicalError>> {
|
||||
// Consume identifier
|
||||
let chars = self.chars.as_bytes();
|
||||
let mut end = start;
|
||||
let mut done = false;
|
||||
for c in chars[(start + 1)..].iter() {
|
||||
end += 1;
|
||||
if !c.is_ascii_alphanumeric() && *c != b'_' {
|
||||
if !c.is_ascii_alphanumeric() && *c != b'_' && *c != b'.' {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
@ -89,12 +90,12 @@ impl<'input> Lexer<'input> {
|
||||
str::from_utf8(&chars[start..end]).unwrap_or("Bad value")
|
||||
);
|
||||
self.offset = end;
|
||||
Some(Ok((start, Tok::Id, end)))
|
||||
Some(Ok((start, Tok::Id(&chars[start..end]), end)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'input> Iterator for Lexer<'input> {
|
||||
type Item = Spanned<Tok, usize, LexicalError>;
|
||||
type Item = Spanned<Tok<'input>, usize, LexicalError>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
for (i, c) in self.chars.as_bytes().iter().enumerate().skip(self.offset) {
|
||||
@ -124,12 +125,20 @@ impl<'input> Iterator for Lexer<'input> {
|
||||
self.offset = i + 1;
|
||||
return Some(Ok((i, Tok::RParen, i + 1)));
|
||||
}
|
||||
b'{' => {
|
||||
self.offset = i + 1;
|
||||
return Some(Ok((i, Tok::LBrace, i + 1)));
|
||||
}
|
||||
b'}' => {
|
||||
self.offset = i + 1;
|
||||
return Some(Ok((i, Tok::RBrace, i + 1)));
|
||||
}
|
||||
b'0'..=b'9' => {
|
||||
// Consume digits and decimal points
|
||||
return self.number(i, &self.chars.as_bytes());
|
||||
return self.number(i);
|
||||
}
|
||||
b'a'..=b'z' | b'A'..=b'Z' | b'_' => {
|
||||
return self.identifier(i, &self.chars.as_bytes());
|
||||
return self.identifier(i);
|
||||
}
|
||||
_ => {
|
||||
// Unknown character
|
||||
@ -151,9 +160,9 @@ mod Test {
|
||||
fn test_lexer_num_id_num() {
|
||||
let input = "123 abc 456";
|
||||
let mut lexer = Lexer::new(input);
|
||||
assert_eq!(lexer.next(), Some(Ok((0, Tok::Num(123_f32), 3))));
|
||||
assert_eq!(lexer.next(), Some(Ok((4, Tok::Id, 7))));
|
||||
assert_eq!(lexer.next(), Some(Ok((8, Tok::Num(456_f32), 11))));
|
||||
assert_eq!(lexer.next(), Some(Ok((0, Tok::Num(123_f64), 3))));
|
||||
assert_eq!(lexer.next(), Some(Ok((4, Tok::Id(b"abc"), 7))));
|
||||
assert_eq!(lexer.next(), Some(Ok((8, Tok::Num(456_f64), 11))));
|
||||
assert_eq!(lexer.next(), None);
|
||||
}
|
||||
|
||||
@ -161,20 +170,20 @@ mod Test {
|
||||
fn test_lexer_id_num_id() {
|
||||
let input = "abc 123 def";
|
||||
let mut lexer = Lexer::new(input);
|
||||
assert_eq!(lexer.next(), Some(Ok((0, Tok::Id, 3))));
|
||||
assert_eq!(lexer.next(), Some(Ok((4, Tok::Num(123_f32), 7))));
|
||||
assert_eq!(lexer.next(), Some(Ok((8, Tok::Id, 11))));
|
||||
assert_eq!(lexer.next(), Some(Ok((0, Tok::Id(b"abc"), 3))));
|
||||
assert_eq!(lexer.next(), Some(Ok((4, Tok::Num(123_f64), 7))));
|
||||
assert_eq!(lexer.next(), Some(Ok((8, Tok::Id(b"def"), 11))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lexer_num_op() {
|
||||
let input = "1+2*3";
|
||||
let mut lexer = Lexer::new(input);
|
||||
assert_eq!(lexer.next(), Some(Ok((0, Tok::Num(1_f32), 1))));
|
||||
assert_eq!(lexer.next(), Some(Ok((0, Tok::Num(1_f64), 1))));
|
||||
assert_eq!(lexer.next(), Some(Ok((1, Tok::OpPlus, 2))));
|
||||
assert_eq!(lexer.next(), Some(Ok((2, Tok::Num(2_f32), 3))));
|
||||
assert_eq!(lexer.next(), Some(Ok((2, Tok::Num(2_f64), 3))));
|
||||
assert_eq!(lexer.next(), Some(Ok((3, Tok::OpStar, 4))));
|
||||
assert_eq!(lexer.next(), Some(Ok((4, Tok::Num(3_f32), 5))));
|
||||
assert_eq!(lexer.next(), Some(Ok((4, Tok::Num(3_f64), 5))));
|
||||
assert_eq!(lexer.next(), None);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
pub mod ast;
|
||||
pub mod lexer;
|
||||
|
||||
use lalrpop_util::lalrpop_mod;
|
||||
use self::ast::ExprResult;
|
||||
use self::lexer::{LexicalError, Tok};
|
||||
use lalrpop_util::{lalrpop_mod, ParseError};
|
||||
use serde::Deserialize;
|
||||
use snmp::SnmpResult;
|
||||
|
||||
@ -10,10 +13,10 @@ lalrpop_mod!(grammar);
|
||||
pub struct Metric {
|
||||
pub name: String,
|
||||
pub prefix: Option<String>,
|
||||
value: String,
|
||||
pub value: String,
|
||||
uom: Option<String>,
|
||||
min: Option<f32>,
|
||||
max: Option<f32>,
|
||||
min: Option<f64>,
|
||||
max: Option<f64>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
@ -35,8 +38,19 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval(&self, expr: &str) -> f32 {
|
||||
2.0_f32
|
||||
pub fn eval(
|
||||
&self,
|
||||
expr: &'a str,
|
||||
) -> Result<ExprResult, ParseError<usize, Tok<'a>, LexicalError>> {
|
||||
let lexer = lexer::Lexer::new(expr);
|
||||
let res = self.parser.parse(lexer);
|
||||
match res {
|
||||
Ok(res) => {
|
||||
let res = res.eval(self.collect);
|
||||
Ok(res)
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +62,7 @@ mod Test {
|
||||
let lexer = lexer::Lexer::new("123");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap() == 123_f32);
|
||||
assert!(res.unwrap().eval() == 123_f32);
|
||||
let lexer = lexer::Lexer::new("123");
|
||||
assert!(grammar::ExprParser::new().parse(lexer).is_ok());
|
||||
let lexer = lexer::Lexer::new("(((123))");
|
||||
@ -61,27 +75,27 @@ mod Test {
|
||||
let lexer = lexer::Lexer::new("1 + 2");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap() == 3_f32);
|
||||
assert!(res.unwrap().eval() == 3_f32);
|
||||
|
||||
let lexer = lexer::Lexer::new("1 + 2 - 3");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap() == 0_f32);
|
||||
assert!(res.unwrap().eval() == 0_f32);
|
||||
|
||||
let lexer = lexer::Lexer::new("1 - 2 + 3");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap() == 2_f32);
|
||||
assert!(res.unwrap().eval() == 2_f32);
|
||||
|
||||
let lexer = lexer::Lexer::new("1 - (2 + 3)");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap() == -4_f32);
|
||||
assert!(res.unwrap().eval() == -4_f32);
|
||||
|
||||
let lexer = lexer::Lexer::new("1 - (2 + (3 - (4 + (5 - (6 + 7)))))");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap() == -8_f32);
|
||||
assert!((res.unwrap()).eval() == -8_f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -89,27 +103,27 @@ mod Test {
|
||||
let lexer = lexer::Lexer::new("2 * 3");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap() == 6_f32);
|
||||
assert!(res.unwrap().eval() == 6_f32);
|
||||
|
||||
let lexer = lexer::Lexer::new("1 + 2 * 3");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap() == 7_f32);
|
||||
assert!(res.unwrap().eval() == 7_f32);
|
||||
|
||||
let lexer = lexer::Lexer::new("(1 + 2) * 3");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap() == 9_f32);
|
||||
assert!(res.unwrap().eval() == 9_f32);
|
||||
|
||||
let lexer = lexer::Lexer::new("2 * 3 * 4");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap() == 24_f32);
|
||||
assert!(res.unwrap().eval() == 24_f32);
|
||||
|
||||
let lexer = lexer::Lexer::new("2 * 3 / 2");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap() == 3_f32);
|
||||
assert!(res.unwrap().eval() == 3_f32);
|
||||
|
||||
// We have an issue with 2/0, I know it but we'll fix it later.
|
||||
}
|
||||
@ -119,7 +133,20 @@ mod Test {
|
||||
let lexer = lexer::Lexer::new("1 + (3 + 2 * 3) / 3");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap() == 4_f32);
|
||||
assert!(res.unwrap().eval() == 4_f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn identifier() {
|
||||
let lexer = lexer::Lexer::new("{abc} + 1");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_ok());
|
||||
println!("{:?}", res);
|
||||
assert!(res.unwrap().eval() == 1_f32);
|
||||
|
||||
let lexer = lexer::Lexer::new("abc + 1");
|
||||
let res = grammar::ExprParser::new().parse(lexer);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -4,7 +4,7 @@ extern crate serde_json;
|
||||
use compute::{Compute, Parser};
|
||||
use serde::Deserialize;
|
||||
use snmp::{snmp_bulk_get, snmp_bulk_walk, snmp_bulk_walk_with_labels};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum Status {
|
||||
@ -56,7 +56,7 @@ pub struct Snmp {
|
||||
name: String,
|
||||
oid: String,
|
||||
query: QueryType,
|
||||
labels: Option<BTreeMap<String, String>>,
|
||||
labels: Option<HashMap<String, String>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
@ -82,7 +82,7 @@ pub struct CommandExt {
|
||||
pub critical_agregation: Option<String>,
|
||||
}
|
||||
|
||||
fn compute_status(value: f32, warn: &Option<String>, crit: &Option<String>) -> Status {
|
||||
fn compute_status(value: f64, warn: &Option<String>, crit: &Option<String>) -> Status {
|
||||
if let Some(c) = crit {
|
||||
let crit = c.parse().unwrap();
|
||||
if value > crit {
|
||||
@ -130,12 +130,20 @@ impl Command {
|
||||
}
|
||||
}
|
||||
|
||||
let p = Parser::new(&collect);
|
||||
for (idx, metric) in self.compute.metrics.iter().enumerate() {
|
||||
for (i, metric) in self.compute.metrics.iter().enumerate() {
|
||||
let name = match &metric.prefix {
|
||||
Some(prefix) => format!("{}#{}", p.eval(prefix), metric.name),
|
||||
None => format!("{}#{}", idx, metric.name),
|
||||
Some(prefix) => {
|
||||
format!("{:?}#{}", prefix, metric.name)
|
||||
}
|
||||
|
||||
None => format!("{}#{}", i, metric.name),
|
||||
};
|
||||
println!("name: {}", name);
|
||||
let value = &metric.value;
|
||||
println!("value: {}", value);
|
||||
let parser = Parser::new(&collect);
|
||||
let value = parser.eval(value).unwrap();
|
||||
println!("value result: {:?}", value);
|
||||
}
|
||||
|
||||
if !to_get.is_empty() {
|
||||
|
@ -1,23 +1,24 @@
|
||||
use std::str::FromStr;
|
||||
use compute::lexer;
|
||||
use compute::ast;
|
||||
|
||||
grammar;
|
||||
grammar<'input>;
|
||||
|
||||
pub Expr: f32 = {
|
||||
<s:Expr> "+" <p:Product> => s + p,
|
||||
<s:Expr> "-" <p:Product> => s - p,
|
||||
<p:Product> => p,
|
||||
pub Expr: Box<ast::Expr<'input>> = {
|
||||
<s:Expr> "+" <p:Product> => Box::new(ast::Expr::OpPlus(<>)),
|
||||
<s:Expr> "-" <p:Product> => Box::new(ast::Expr::OpMinus(<>)),
|
||||
Product,
|
||||
};
|
||||
|
||||
pub Product: f32 = {
|
||||
<s:Product> "*" <v:Term> => s * v,
|
||||
<s:Product> "/" <v:Term> => s / v,
|
||||
<v:Term> => v,
|
||||
pub Product: Box<ast::Expr<'input>> = {
|
||||
<s:Product> "*" <v:Term> => Box::new(ast::Expr::OpStar(<>)),
|
||||
<s:Product> "/" <v:Term> => Box::new(ast::Expr::OpSlash(<>)),
|
||||
<v:Term> => <>,
|
||||
};
|
||||
|
||||
pub Term: f32 = {
|
||||
"num" => <>,
|
||||
"(" <v:Expr> ")" => v,
|
||||
pub Term: Box<ast::Expr<'input>> = {
|
||||
"num" => Box::new(ast::Expr::Number(<>)),
|
||||
"(" <v:Expr> ")" => <>,
|
||||
"{" <"id"> "}" => Box::new(ast::Expr::Id(<>)),
|
||||
};
|
||||
|
||||
extern {
|
||||
@ -26,13 +27,16 @@ extern {
|
||||
|
||||
// ...
|
||||
|
||||
enum lexer::Tok {
|
||||
enum lexer::Tok<'input> {
|
||||
"*" => lexer::Tok::OpStar,
|
||||
"/" => lexer::Tok::OpSlash,
|
||||
"+" => lexer::Tok::OpPlus,
|
||||
"-" => lexer::Tok::OpMinus,
|
||||
"(" => lexer::Tok::LParen,
|
||||
")" => lexer::Tok::RParen,
|
||||
"num" => lexer::Tok::Num(<f32>)
|
||||
"{" => lexer::Tok::LBrace,
|
||||
"}" => lexer::Tok::RBrace,
|
||||
"num" => lexer::Tok::Num(<f64>),
|
||||
"id" => lexer::Tok::Id(<&'input [u8]>),
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ mod compute;
|
||||
mod generic;
|
||||
mod snmp;
|
||||
|
||||
use generic::{Command, CommandExt};
|
||||
use generic::Command;
|
||||
use lalrpop_util::lalrpop_mod;
|
||||
use serde_json::Result;
|
||||
//use snmp::snmp_get;
|
||||
|
@ -11,26 +11,26 @@ use rasn_snmp::v2::VarBind;
|
||||
use rasn_snmp::v2::VarBindValue;
|
||||
use rasn_snmp::v2::{GetBulkRequest, GetNextRequest, GetRequest};
|
||||
use rasn_snmp::v2c::Message;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
use std::net::UdpSocket;
|
||||
|
||||
pub enum ValueType {
|
||||
None(()),
|
||||
Integer(i64),
|
||||
Float(f32),
|
||||
Float(f64),
|
||||
String(String),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SnmpItem {
|
||||
Nbr(Vec<f32>),
|
||||
Nbr(Vec<f64>),
|
||||
Str(Vec<String>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SnmpResult {
|
||||
items: BTreeMap<String, SnmpItem>,
|
||||
pub items: HashMap<String, SnmpItem>,
|
||||
last_oid: Vec<u32>,
|
||||
}
|
||||
|
||||
@ -179,7 +179,7 @@ pub fn snmp_bulk_get<'a>(
|
||||
.collect::<Vec<Vec<u32>>>();
|
||||
|
||||
let mut retval = SnmpResult {
|
||||
items: BTreeMap::new(),
|
||||
items: HashMap::new(),
|
||||
last_oid: Vec::new(),
|
||||
};
|
||||
let mut request_id: i32 = 1;
|
||||
@ -256,7 +256,7 @@ pub fn snmp_bulk_walk<'a>(
|
||||
.collect::<Vec<u32>>();
|
||||
let mut oid_tab = &oid_init;
|
||||
let mut retval = SnmpResult {
|
||||
items: BTreeMap::new(),
|
||||
items: HashMap::new(),
|
||||
last_oid: Vec::new(),
|
||||
};
|
||||
let request_id: i32 = 1;
|
||||
@ -314,7 +314,7 @@ pub fn snmp_bulk_walk_with_labels<'a>(
|
||||
community: &str,
|
||||
oid: &str,
|
||||
snmp_name: &str,
|
||||
labels: &'a BTreeMap<String, String>,
|
||||
labels: &'a HashMap<String, String>,
|
||||
) -> SnmpResult {
|
||||
let oid_init = oid
|
||||
.split('.')
|
||||
@ -323,7 +323,7 @@ pub fn snmp_bulk_walk_with_labels<'a>(
|
||||
|
||||
let mut oid_tab = &oid_init;
|
||||
let mut retval = SnmpResult {
|
||||
items: BTreeMap::new(),
|
||||
items: HashMap::new(),
|
||||
last_oid: Vec::new(),
|
||||
};
|
||||
let request_id: i32 = 1;
|
||||
@ -380,7 +380,7 @@ impl SnmpResult {
|
||||
decoded: Message<Pdus>,
|
||||
oid: &str,
|
||||
snmp_name: &str,
|
||||
labels: &'a BTreeMap<String, String>,
|
||||
labels: &'a HashMap<String, String>,
|
||||
walk: bool,
|
||||
) -> bool {
|
||||
let mut completed = false;
|
||||
@ -461,7 +461,7 @@ impl SnmpResult {
|
||||
ValueType::String(_) => {
|
||||
panic!("Value should be a float");
|
||||
}
|
||||
ValueType::Integer(i) => *i as f32,
|
||||
ValueType::Integer(i) => *i as f64,
|
||||
}),
|
||||
SnmpItem::Str(v) => v.push(match &typ {
|
||||
ValueType::Float(_) => {
|
||||
@ -482,7 +482,7 @@ impl SnmpResult {
|
||||
panic!("Should not arrive");
|
||||
}
|
||||
ValueType::String(s) => SnmpItem::Str(vec![s]),
|
||||
ValueType::Integer(i) => SnmpItem::Nbr(vec![i as f32]),
|
||||
ValueType::Integer(i) => SnmpItem::Nbr(vec![i as f64]),
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -572,7 +572,7 @@ impl SnmpResult {
|
||||
ValueType::String(_) => {
|
||||
panic!("Value should be a float");
|
||||
}
|
||||
ValueType::Integer(i) => *i as f32,
|
||||
ValueType::Integer(i) => *i as f64,
|
||||
}),
|
||||
SnmpItem::Str(v) => v.push(match &typ {
|
||||
ValueType::Float(_) => {
|
||||
@ -593,7 +593,7 @@ impl SnmpResult {
|
||||
panic!("Should not arrive");
|
||||
}
|
||||
ValueType::String(s) => SnmpItem::Str(vec![s]),
|
||||
ValueType::Integer(i) => SnmpItem::Nbr(vec![i as f32]),
|
||||
ValueType::Integer(i) => SnmpItem::Nbr(vec![i as f64]),
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -714,7 +714,7 @@ impl SnmpResult {
|
||||
ValueType::String(_) => {
|
||||
panic!("Value should be a float");
|
||||
}
|
||||
ValueType::Integer(i) => *i as f32,
|
||||
ValueType::Integer(i) => *i as f64,
|
||||
}),
|
||||
SnmpItem::Str(v) => v.push(match &typ {
|
||||
ValueType::Float(_) => {
|
||||
@ -735,7 +735,7 @@ impl SnmpResult {
|
||||
panic!("Should not arrive");
|
||||
}
|
||||
ValueType::String(s) => SnmpItem::Str(vec![s]),
|
||||
ValueType::Integer(i) => SnmpItem::Nbr(vec![i as f32]),
|
||||
ValueType::Integer(i) => SnmpItem::Nbr(vec![i as f64]),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user