#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[cfg_attr(
feature = "serialization",
derive(serde::Serialize, serde::Deserialize)
)]
pub enum AlertState {
#[default]
Ok,
Warning,
Critical,
Unknown,
}
impl std::fmt::Display for AlertState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AlertState::Ok => write!(f, "OK"),
AlertState::Warning => write!(f, "WARN"),
AlertState::Critical => write!(f, "CRIT"),
AlertState::Unknown => write!(f, "UNKNOWN"),
}
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(
feature = "serialization",
derive(serde::Serialize, serde::Deserialize)
)]
pub struct AlertThreshold {
pub warning: f64,
pub critical: f64,
}
impl AlertThreshold {
pub fn new(warning: f64, critical: f64) -> Self {
Self { warning, critical }
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(
feature = "serialization",
derive(serde::Serialize, serde::Deserialize)
)]
pub struct AlertMetric {
pub(super) id: String,
name: String,
value: f64,
units: Option<String>,
threshold: AlertThreshold,
pub(super) state: AlertState,
history: Vec<f64>,
max_history: usize,
}
impl AlertMetric {
pub fn new(id: impl Into<String>, name: impl Into<String>, threshold: AlertThreshold) -> Self {
let mut metric = Self {
id: id.into(),
name: name.into(),
value: 0.0,
units: None,
threshold,
state: AlertState::Ok,
history: Vec::new(),
max_history: 20,
};
metric.state = metric.compute_state();
metric
}
pub fn with_units(mut self, units: impl Into<String>) -> Self {
self.units = Some(units.into());
self
}
pub fn with_value(mut self, value: f64) -> Self {
self.value = value;
self.state = self.compute_state();
self
}
pub fn with_max_history(mut self, max: usize) -> Self {
self.max_history = max;
self
}
pub fn update_value(&mut self, value: f64) {
self.value = value;
self.history.push(value);
if self.history.len() > self.max_history {
self.history.remove(0);
}
self.state = self.compute_state();
}
pub fn compute_state(&self) -> AlertState {
if self.value >= self.threshold.critical {
AlertState::Critical
} else if self.value >= self.threshold.warning {
AlertState::Warning
} else {
AlertState::Ok
}
}
pub fn display_value(&self) -> String {
match &self.units {
Some(units) => format!("{:.1}{}", self.value, units),
None => format!("{:.1}", self.value),
}
}
pub fn id(&self) -> &str {
&self.id
}
pub fn name(&self) -> &str {
&self.name
}
pub fn value(&self) -> f64 {
self.value
}
pub fn units(&self) -> Option<&str> {
self.units.as_deref()
}
pub fn threshold(&self) -> &AlertThreshold {
&self.threshold
}
pub fn state(&self) -> &AlertState {
&self.state
}
pub fn history(&self) -> &[f64] {
&self.history
}
pub fn max_history(&self) -> usize {
self.max_history
}
}