1use core_types::Timestamp;
2
3use crate::{
4 alert::{Alert, AlertSeverity},
5 aggregator::MetricsAggregator,
6 bus::AlertBus,
7};
8
9pub struct HealthWatcher {
15 pub name: String,
16}
17
18impl HealthWatcher {
19 pub fn new(name: impl Into<String>) -> Self {
20 Self { name: name.into() }
21 }
22
23 pub fn poll(&self, agg: &MetricsAggregator, bus: &mut AlertBus, now: Timestamp) -> usize {
26 use core_types::HealthStatus;
27
28 let report = agg.health_report();
29 let mut n = 0;
30 for comp in &report.components {
31 let (severity, reason) = match &comp.status {
32 HealthStatus::Healthy => continue,
33 HealthStatus::Degraded { reason } => (AlertSeverity::Warn, reason.clone()),
34 HealthStatus::Unhealthy { reason } => (AlertSeverity::Error, reason.clone()),
35 };
36 bus.fire(Alert::new(
37 comp.name.clone(),
38 format!("{}_HEALTH", comp.name.to_uppercase()),
39 reason,
40 severity,
41 now,
42 ));
43 n += 1;
44 }
45 n
46 }
47}