212 lines
5.4 KiB
Rust
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()
|
|
}
|
|
}
|