Files
node-notifier/system_monitor/src/lib.rs
2025-07-30 22:13:58 +02:00

212 lines
5.4 KiB
Rust

use sysinfo::{Disks, System};
#[derive(Debug, Clone)]
pub struct SystemMetrics {
pub cpu_usage: f32,
pub memory_usage: f32,
pub swap_usage: f32,
pub disk_usage: f32,
}
#[derive(Debug, Clone)]
pub struct ThresholdViolation {
pub metric_name: String,
pub current_value: f32,
pub threshold: f32,
pub severity: Severity,
}
#[derive(Debug, Clone)]
pub enum Severity {
Warning,
Critical,
}
pub struct ResourceThreshold {
pub name: String,
pub get_usage_fn: fn(&System, &Disks) -> f32,
pub threshold: f32,
pub critical_threshold: Option<f32>, // Nouveau: seuil critique
pub value: f32,
}
impl ResourceThreshold {
pub fn new(name: String, get_usage_fn: fn(&System, &Disks) -> f32, threshold: f32) -> Self {
Self {
name,
get_usage_fn,
threshold,
critical_threshold: None,
value: 0.0,
}
}
pub fn with_critical_threshold(mut self, critical_threshold: f32) -> Self {
self.critical_threshold = Some(critical_threshold);
self
}
pub fn check(&mut self, sys: &System, disks: &Disks) -> Option<ThresholdViolation> {
self.value = (self.get_usage_fn)(sys, disks);
if let Some(critical) = self.critical_threshold {
if self.value > critical {
return Some(ThresholdViolation {
metric_name: self.name.clone(),
current_value: self.value,
threshold: critical,
severity: Severity::Critical,
});
}
}
if self.value > self.threshold {
Some(ThresholdViolation {
metric_name: self.name.clone(),
current_value: self.value,
threshold: self.threshold,
severity: Severity::Warning,
})
} else {
None
}
}
}
pub fn get_cpu_usage(sys: &System, _: &Disks) -> f32 {
sys.global_cpu_usage()
}
pub fn get_memory_usage(sys: &System, _: &Disks) -> f32 {
let total_memory = sys.total_memory() as f32;
let used_memory = sys.used_memory() as f32;
if total_memory == 0.0 {
return 0.0;
}
used_memory / total_memory * 100.0
}
pub fn get_swap_usage(sys: &System, _: &Disks) -> f32 {
let total_swap = sys.total_swap() as f32;
let used_swap = sys.used_swap() as f32;
if total_swap == 0.0 {
return 0.0;
}
used_swap / total_swap * 100.0
}
pub fn get_disk_usage(_: &System, disks: &Disks) -> f32 {
let mut total_used_space = 0.0;
let mut total_space = 0.0;
for disk in disks {
if let Some(mount_point) = disk.mount_point().to_str() {
if mount_point == "/" || mount_point == "/home" {
total_used_space += disk.total_space() as f32 - disk.available_space() as f32;
total_space += disk.total_space() as f32;
}
}
}
if total_space == 0.0 {
return 0.0; // Avoid division by zero
}
(total_used_space / total_space) * 100.0
}
pub fn get_default_resource_thresholds() -> Vec<ResourceThreshold> {
vec![
ResourceThreshold::new(
"CPU".to_string(),
get_cpu_usage,
80.0,
).with_critical_threshold(95.0),
ResourceThreshold::new(
"Memory".to_string(),
get_memory_usage,
80.0,
).with_critical_threshold(95.0),
ResourceThreshold::new(
"Swap".to_string(),
get_swap_usage,
80.0,
).with_critical_threshold(95.0),
ResourceThreshold::new(
"Disk".to_string(),
get_disk_usage,
80.0,
).with_critical_threshold(90.0),
]
}
pub struct SystemMonitor {
pub system: System,
pub disks: Disks,
pub thresholds: Vec<ResourceThreshold>,
}
impl SystemMonitor {
pub fn new() -> Self {
let mut system = System::new_all();
let mut disks = Disks::new_with_refreshed_list();
system.refresh_all();
disks.refresh(true);
Self {
system,
disks,
thresholds: get_default_resource_thresholds(),
}
}
pub fn new_with_thresholds(thresholds: Vec<ResourceThreshold>) -> Self {
let mut system = System::new_all();
let mut disks = Disks::new_with_refreshed_list();
system.refresh_all();
disks.refresh(true);
Self {
system,
disks,
thresholds,
}
}
pub fn refresh(&mut self) {
self.system.refresh_all();
self.disks.refresh(true);
}
pub fn check_thresholds(&mut self) -> Vec<ThresholdViolation> {
let mut violations = Vec::new();
for threshold in &mut self.thresholds {
if let Some(violation) = threshold.check(&self.system, &self.disks) {
violations.push(violation);
}
}
violations
}
pub fn get_metrics(&self) -> SystemMetrics {
SystemMetrics {
cpu_usage: get_cpu_usage(&self.system, &self.disks),
memory_usage: get_memory_usage(&self.system, &self.disks),
swap_usage: get_swap_usage(&self.system, &self.disks),
disk_usage: get_disk_usage(&self.system, &self.disks),
}
}
}
impl Default for SystemMonitor {
fn default() -> Self {
Self::new()
}
}