Mountain/IPC/Common/
HealthStatus.rs1use std::{collections::HashSet, time::Instant};
7
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
12pub enum SeverityLevel {
13 Low,
15 Medium,
17 High,
19 Critical,
21}
22
23#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
25pub enum HealthIssue {
26 HighLatency(String),
28 MemoryPressure(String),
30 ConnectionLoss(String),
32 QueueOverflow(String),
34 SecurityViolation(String),
36 PerformanceDegradation(String),
38 Custom(String),
40}
41
42impl HealthIssue {
43 pub fn severity(&self) -> SeverityLevel {
45 match self {
46 HealthIssue::HighLatency(_) => SeverityLevel::Medium,
47 HealthIssue::MemoryPressure(_) => SeverityLevel::Medium,
48 HealthIssue::ConnectionLoss(_) => SeverityLevel::High,
49 HealthIssue::QueueOverflow(_) => SeverityLevel::High,
50 HealthIssue::SecurityViolation(_) => SeverityLevel::Critical,
51 HealthIssue::PerformanceDegradation(_) => SeverityLevel::Medium,
52 HealthIssue::Custom(_) => SeverityLevel::Low,
53 }
54 }
55
56 pub fn description(&self) -> &str {
58 match self {
59 HealthIssue::HighLatency(desc) => desc,
60 HealthIssue::MemoryPressure(desc) => desc,
61 HealthIssue::ConnectionLoss(desc) => desc,
62 HealthIssue::QueueOverflow(desc) => desc,
63 HealthIssue::SecurityViolation(desc) => desc,
64 HealthIssue::PerformanceDegradation(desc) => desc,
65 HealthIssue::Custom(desc) => desc,
66 }
67 }
68}
69
70#[derive(Debug, Clone, Serialize)]
72pub struct HealthMonitor {
73 pub health_score:u8,
75 pub issues:Vec<(HealthIssue, SeverityLevel)>,
77 pub recovery_attempts:u32,
79 #[serde(skip)]
81 pub last_check:Instant,
82}
83
84impl Default for HealthMonitor {
85 fn default() -> Self {
86 Self {
87 health_score:100,
88 issues:Vec::new(),
89 recovery_attempts:0,
90 last_check:Instant::now(),
91 }
92 }
93}
94
95impl HealthMonitor {
96 pub fn new() -> Self {
98 Self {
99 health_score:100,
100 issues:Vec::new(),
101 recovery_attempts:0,
102 last_check:Instant::now(),
103 }
104 }
105
106 pub fn add_issue(&mut self, issue:HealthIssue) {
108 let severity = issue.severity();
109 self.issues.push((issue.clone(), severity));
110 self.recalculate_score();
111 }
112
113 pub fn remove_issue(&mut self, issue:&HealthIssue) {
115 self.issues.retain(|(i, _)| i != issue);
116 self.recalculate_score();
117 }
118
119 pub fn clear_issues(&mut self) {
121 self.issues.clear();
122 self.health_score = 100;
123 self.last_check = Instant::now();
124 }
125
126 fn recalculate_score(&mut self) {
128 let mut score:i32 = 100;
129
130 for (_issue, severity) in &self.issues {
131 let penalty = match severity {
132 SeverityLevel::Low => 5,
133 SeverityLevel::Medium => 15,
134 SeverityLevel::High => 25,
135 SeverityLevel::Critical => 40,
136 };
137 score -= penalty;
138 }
139
140 self.health_score = score.max(0).min(100) as u8;
141 self.last_check = Instant::now();
142 }
143
144 pub fn is_healthy(&self) -> bool { self.health_score >= 70 }
146
147 pub fn is_critical(&self) -> bool { self.health_score < 50 }
149
150 pub fn issues_by_severity(&self, severity:SeverityLevel) -> Vec<&HealthIssue> {
152 self.issues.iter().filter(|(_, s)| *s == severity).map(|(i, _)| i).collect()
153 }
154
155 pub fn increment_recovery_attempts(&mut self) { self.recovery_attempts += 1; }
157}
158