120 lines
4.4 KiB
Rust
120 lines
4.4 KiB
Rust
use crate::structs::v3::MetricOutput;
|
|
use serde_json::{Map, Value};
|
|
use prometheus::Gauge;
|
|
use tracing::error;
|
|
use prometheus::{opts, GaugeVec, core::Collector};
|
|
use tracing::{debug, trace};
|
|
|
|
#[derive(Debug)]
|
|
pub enum MetricsValueType {
|
|
Number,
|
|
Array,
|
|
TaggedArray,
|
|
ArrayOfStrings,
|
|
None,
|
|
}
|
|
|
|
pub struct MetricsProcesser;
|
|
|
|
|
|
impl MetricsProcesser {
|
|
pub fn get_type_of_value(metrics: &MetricOutput) -> MetricsValueType {
|
|
trace!("defining metric type");
|
|
if Self::is_number(metrics) {
|
|
debug!("processing Number");
|
|
return MetricsValueType::Number;
|
|
}
|
|
else if Self::is_array(metrics) {
|
|
if Self::is_tagged_array(metrics) {
|
|
debug!("processing TaggedArray");
|
|
return MetricsValueType::TaggedArray;
|
|
}
|
|
if Self::is_array_of_string_values(metrics) {
|
|
debug!("processing ArrayOfStrings");
|
|
return MetricsValueType::ArrayOfStrings;
|
|
}
|
|
debug!("processing Array");
|
|
return MetricsValueType::Array;
|
|
}
|
|
debug!("processing undefined type");
|
|
MetricsValueType::None
|
|
}
|
|
|
|
// TODO: i64 and f63 support
|
|
pub fn gauge_from_number(
|
|
metric: &MetricOutput,
|
|
metric_name: &str,
|
|
metric_desc: &str,
|
|
prefix: &str
|
|
) -> Option<Box<dyn Collector>> {
|
|
trace!("fn gauge_from_number is running");
|
|
if let Some(status) = metric.status {
|
|
if let Some(device) = metric.device {
|
|
if let Some(source_id) = &metric.source_id {
|
|
let vec = GaugeVec::new(opts!(format!("{}_{}", prefix, metric.name), metric_desc), &["status", "device", "source_id"]).unwrap();
|
|
vec.with_label_values(&[&status.to_string(), &device.to_string(), &source_id.to_string()]).set(metric.value.as_f64().unwrap_or_else(|| 0.0));
|
|
debug!("processed metric: {:?}", &vec);
|
|
return Some(Box::new(vec));
|
|
}
|
|
else {
|
|
let vec = GaugeVec::new(opts!(format!("{}_{}", prefix, metric.name), metric_desc), &["status", "device"]).unwrap();
|
|
vec.with_label_values(&[&status.to_string(), &device.to_string()]).set(metric.value.as_f64().unwrap_or_else(|| 0.0));
|
|
debug!("processed metric: {:?}", &vec);
|
|
return Some(Box::new(vec));
|
|
}
|
|
} else {
|
|
let vec = GaugeVec::new(opts!(format!("{}_{}", prefix, metric.name), metric_desc), &["status"]).unwrap();
|
|
vec.with_label_values(&[&status.to_string()]).set(metric.value.as_f64().unwrap_or_else(|| 0.0));
|
|
debug!("processed metric: {:?}", &vec);
|
|
return Some(Box::new(vec));
|
|
}
|
|
}
|
|
|
|
let gauge = Gauge::new(
|
|
format!("{}_{}", prefix, metric.name),
|
|
metric_desc
|
|
);
|
|
|
|
match gauge {
|
|
Ok(gauge) => {
|
|
let val = match metric.value.as_number() {
|
|
Some(val) => {
|
|
val.as_f64().unwrap_or_else(||
|
|
0.0
|
|
)
|
|
},
|
|
None => {
|
|
error!("Cannot convert {} metric value to f64 type. Value was set to 0.0", &metric_name);
|
|
0.0
|
|
},
|
|
};
|
|
gauge.set(val);
|
|
debug!("processed metric: {:?}", &gauge);
|
|
return Some(Box::new(gauge));
|
|
},
|
|
Err(er) => error!("Cannot create Gauge metric {} due to {}", &metric_name, er),
|
|
}
|
|
None
|
|
}
|
|
pub fn is_array_of_string_values(metrics: &MetricOutput) -> bool {
|
|
let arr = metrics.value.clone();
|
|
let arr = arr.as_array().unwrap();
|
|
let map: Map<String, Value> = serde_json::from_value(
|
|
arr[0].clone()
|
|
).unwrap();
|
|
map.values()
|
|
.all(|val| val.is_string())
|
|
}
|
|
fn is_array(metrics: &MetricOutput) -> bool {
|
|
metrics.value.is_array()
|
|
}
|
|
fn is_tagged_array(metrics: &MetricOutput) -> bool {
|
|
let arr = metrics.value.as_array().unwrap();
|
|
let map: Map<String, Value> = serde_json::from_value(arr[0].clone()).unwrap();
|
|
map.len() > 1
|
|
}
|
|
fn is_number(metrics: &MetricOutput) -> bool {
|
|
metrics
|
|
.value.is_number()
|
|
}
|
|
} |