Skip to main content

max / makenotwork

2.3 KB · 81 lines History Blame Raw
1 //! health alert/recovery messages. Domain half of the Alerter split;
2 //! shared dispatch/cooldown plumbing lives in the parent module.
3
4 use std::fmt::Write as _;
5
6 use tracing::instrument;
7
8 use super::{AlertCategory, AlertMeta, Alerter, health_status_priority};
9
10 impl Alerter {
11 #[instrument(skip_all)]
12 pub async fn send_health_alert(
13 &self,
14 target: &str,
15 label: &str,
16 from_status: &str,
17 to_status: &str,
18 error: Option<&str>,
19 ) {
20 let alert_key = format!("health:{target}");
21 let subject = format!("[PoM] {target}: {from_status} -> {to_status}");
22 let mut body = format!(
23 "Target: {label} ({target})\n\
24 Status: {from_status} -> {to_status}\n\
25 Instance: {}\n\
26 Time: {}\n",
27 self.instance_name,
28 chrono::Utc::now().to_rfc3339(),
29 );
30 if let Some(err) = error {
31 let _ = writeln!(body, "Error: {err}");
32 }
33 body.push_str("\n- PoM");
34
35 let priority = health_status_priority(to_status);
36 self.fire_failure(
37 &subject,
38 &body,
39 priority,
40 "pom-health",
41 Some(target),
42 AlertMeta {
43 key: &alert_key,
44 category: AlertCategory::Health,
45 from: Some(from_status),
46 to: Some(to_status),
47 error,
48 },
49 )
50 .await;
51 }
52
53 #[instrument(skip_all)]
54 pub async fn send_health_recovery(&self, target: &str, label: &str, from_status: &str) {
55 let alert_key = format!("health:{target}");
56 let subject = format!("[PoM] {target}: recovered");
57 let body = format!(
58 "Target: {label} ({target})\n\
59 Status: {from_status} -> operational\n\
60 Instance: {}\n\
61 Time: {}\n\n\
62 - PoM",
63 self.instance_name,
64 chrono::Utc::now().to_rfc3339(),
65 );
66
67 self.fire_recovery(
68 &subject,
69 &body,
70 AlertMeta {
71 key: &alert_key,
72 category: AlertCategory::Recovery,
73 from: Some(from_status),
74 to: Some("operational"),
75 error: None,
76 },
77 )
78 .await;
79 }
80 }
81