Skip to main content

Mountain/IPC/Common/HealthStatus/
HealthMonitor.rs

1
2//! Aggregate health monitor: a 0-100 score, the list of currently
3//! tracked issues (each paired with its severity for fast filtering),
4//! a recovery-attempt counter, and the timestamp of the last update.
5//! `Recalculate` derives the score deterministically from the issue
6//! list using the severity → penalty table:
7//! Low=5, Medium=15, High=25, Critical=40.
8
9use std::time::Instant;
10
11use serde::Serialize;
12
13use crate::IPC::Common::HealthStatus::{HealthIssue, SeverityLevel};
14
15#[derive(Debug, Clone, Serialize)]
16pub struct Struct {
17	pub HealthScore:u8,
18
19	pub Issues:Vec<(HealthIssue::Enum, SeverityLevel::Enum)>,
20
21	pub RecoveryAttempts:u32,
22
23	#[serde(skip)]
24	pub LastCheck:Instant,
25}
26
27impl Default for Struct {
28	fn default() -> Self { Self { HealthScore:100, Issues:Vec::new(), RecoveryAttempts:0, LastCheck:Instant::now() } }
29}
30
31impl Struct {
32	pub fn new() -> Self { Self::default() }
33
34	pub fn AddIssue(&mut self, Issue:HealthIssue::Enum) {
35		let Severity = Issue.Severity();
36
37		self.Issues.push((Issue, Severity));
38
39		self.Recalculate();
40	}
41
42	pub fn RemoveIssue(&mut self, Issue:&HealthIssue::Enum) {
43		self.Issues.retain(|(I, _)| I != Issue);
44
45		self.Recalculate();
46	}
47
48	pub fn ClearIssues(&mut self) {
49		self.Issues.clear();
50
51		self.HealthScore = 100;
52
53		self.LastCheck = Instant::now();
54	}
55
56	fn Recalculate(&mut self) {
57		let mut Score:i32 = 100;
58
59		for (_, Severity) in &self.Issues {
60			Score -= match Severity {
61				SeverityLevel::Enum::Low => 5,
62
63				SeverityLevel::Enum::Medium => 15,
64
65				SeverityLevel::Enum::High => 25,
66
67				SeverityLevel::Enum::Critical => 40,
68			};
69		}
70
71		self.HealthScore = Score.max(0).min(100) as u8;
72
73		self.LastCheck = Instant::now();
74	}
75
76	pub fn IsHealthy(&self) -> bool { self.HealthScore >= 70 }
77
78	pub fn IsCritical(&self) -> bool { self.HealthScore < 50 }
79
80	pub fn IssuesBySeverity(&self, Severity:SeverityLevel::Enum) -> Vec<&HealthIssue::Enum> {
81		self.Issues.iter().filter(|(_, S)| *S == Severity).map(|(I, _)| I).collect()
82	}
83
84	pub fn IncrementRecoveryAttempts(&mut self) { self.RecoveryAttempts += 1; }
85}