#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub enum Severity {
#[default]
Normal,
Warning,
Critical,
}
#[derive(Clone, Debug)]
pub struct Thresholds {
pub io_pressure_warning: f64,
pub io_pressure_critical: f64,
pub cpu_usage_warning: f32,
pub memory_available_warning_mb: u64,
pub memory_available_critical_mb: u64,
pub cpu_temp_warning: f64,
pub cpu_temp_critical: f64,
pub dimm_temp_warning: f64,
pub dimm_temp_critical: f64,
pub disk_temp_warning: f64,
pub disk_temp_critical: f64,
pub mem_pressure_warning: f64,
pub mem_pressure_critical: f64,
pub iowait_warning: f64,
pub iowait_critical: f64,
}
impl Default for Thresholds {
fn default() -> Self {
Self {
io_pressure_warning: 10.0,
io_pressure_critical: 25.0,
cpu_usage_warning: 80.0,
memory_available_warning_mb: 1024,
memory_available_critical_mb: 256,
cpu_temp_warning: 75.0,
cpu_temp_critical: 85.0,
dimm_temp_warning: 70.0,
dimm_temp_critical: 80.0,
disk_temp_warning: 50.0,
disk_temp_critical: 60.0,
mem_pressure_warning: 10.0,
mem_pressure_critical: 25.0,
iowait_warning: 20.0,
iowait_critical: 40.0,
}
}
}
impl Thresholds {
pub fn io_pressure_severity(&self, value: f64) -> Severity {
if value >= self.io_pressure_critical {
Severity::Critical
} else if value >= self.io_pressure_warning {
Severity::Warning
} else {
Severity::Normal
}
}
pub fn cpu_usage_severity(&self, value: f32) -> Severity {
if value >= self.cpu_usage_warning {
Severity::Warning
} else {
Severity::Normal
}
}
pub fn memory_available_severity(&self, value_mb: u64) -> Severity {
if value_mb <= self.memory_available_critical_mb {
Severity::Critical
} else if value_mb <= self.memory_available_warning_mb {
Severity::Warning
} else {
Severity::Normal
}
}
pub fn cpu_temp_severity(&self, value: f64) -> Severity {
if value >= self.cpu_temp_critical {
Severity::Critical
} else if value >= self.cpu_temp_warning {
Severity::Warning
} else {
Severity::Normal
}
}
pub fn dimm_temp_severity(&self, value: f64) -> Severity {
if value >= self.dimm_temp_critical {
Severity::Critical
} else if value >= self.dimm_temp_warning {
Severity::Warning
} else {
Severity::Normal
}
}
pub fn disk_temp_severity(&self, value: f64) -> Severity {
if value >= self.disk_temp_critical {
Severity::Critical
} else if value >= self.disk_temp_warning {
Severity::Warning
} else {
Severity::Normal
}
}
pub fn mem_pressure_severity(&self, value: f64) -> Severity {
if value >= self.mem_pressure_critical {
Severity::Critical
} else if value >= self.mem_pressure_warning {
Severity::Warning
} else {
Severity::Normal
}
}
pub fn iowait_severity(&self, iowait_pct: f64) -> Severity {
if iowait_pct >= self.iowait_critical {
Severity::Critical
} else if iowait_pct >= self.iowait_warning {
Severity::Warning
} else {
Severity::Normal
}
}
}
#[cfg(test)]
mod tests {
use super::{Severity, Thresholds};
#[test]
fn high_is_bad_thresholds_use_warning_and_critical_bounds() {
let thresholds = Thresholds::default();
assert_eq!(thresholds.cpu_usage_severity(79.9), Severity::Normal);
assert_eq!(thresholds.io_pressure_severity(9.9), Severity::Normal);
assert_eq!(thresholds.io_pressure_severity(10.0), Severity::Warning);
assert_eq!(thresholds.io_pressure_severity(25.0), Severity::Critical);
assert_eq!(thresholds.mem_pressure_severity(9.9), Severity::Normal);
assert_eq!(thresholds.mem_pressure_severity(10.0), Severity::Warning);
assert_eq!(thresholds.mem_pressure_severity(25.0), Severity::Critical);
assert_eq!(thresholds.iowait_severity(19.9), Severity::Normal);
assert_eq!(thresholds.iowait_severity(20.0), Severity::Warning);
assert_eq!(thresholds.iowait_severity(40.0), Severity::Critical);
}
#[test]
fn cpu_usage_is_warning_only_even_when_saturated() {
let thresholds = Thresholds::default();
assert_eq!(thresholds.cpu_usage_severity(79.9), Severity::Normal);
assert_eq!(thresholds.cpu_usage_severity(80.0), Severity::Warning);
assert_eq!(thresholds.cpu_usage_severity(95.0), Severity::Warning);
assert_eq!(thresholds.cpu_usage_severity(100.0), Severity::Warning);
}
#[test]
fn low_memory_available_is_bad() {
let thresholds = Thresholds::default();
assert_eq!(thresholds.memory_available_severity(2048), Severity::Normal);
assert_eq!(
thresholds.memory_available_severity(1024),
Severity::Warning
);
assert_eq!(
thresholds.memory_available_severity(256),
Severity::Critical
);
}
#[test]
fn temperature_thresholds_share_boundary_behavior() {
let thresholds = Thresholds::default();
assert_eq!(thresholds.cpu_temp_severity(74.9), Severity::Normal);
assert_eq!(thresholds.cpu_temp_severity(75.0), Severity::Warning);
assert_eq!(thresholds.cpu_temp_severity(85.0), Severity::Critical);
assert_eq!(thresholds.dimm_temp_severity(69.9), Severity::Normal);
assert_eq!(thresholds.dimm_temp_severity(70.0), Severity::Warning);
assert_eq!(thresholds.dimm_temp_severity(80.0), Severity::Critical);
assert_eq!(thresholds.disk_temp_severity(49.9), Severity::Normal);
assert_eq!(thresholds.disk_temp_severity(50.0), Severity::Warning);
assert_eq!(thresholds.disk_temp_severity(60.0), Severity::Critical);
}
}