Skip to main content

Mountain/IPC/Common/HealthStatus/
HealthMonitor.rs

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