Skip to main content

obs_core/
watcher.rs

1use core_types::Timestamp;
2
3use crate::{
4    alert::{Alert, AlertSeverity},
5    aggregator::MetricsAggregator,
6    bus::AlertBus,
7};
8
9/// Bridges a [`crate::aggregator::MetricsAggregator`] health report to the alert bus.
10///
11/// On each call to [`HealthWatcher::poll`] the watcher queries the aggregator's
12/// health report and fires an alert for any component that is `Degraded` or
13/// `Unhealthy`.
14pub 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    /// Poll the aggregator and fire alerts for degraded / unhealthy components.
24    /// Returns the number of alerts fired.
25    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}