Skip to main content

confium_coordinator/coordinator/
alerts.rs

1//! Prometheus alerting rules for the coordinator metrics.
2//!
3//! Generates a YAML file of Prometheus alerting rules covering the
4//! most critical operational conditions. Import directly into
5//! Prometheus via the rule_files configuration.
6
7/// Generate the alerting rules as a YAML string.
8pub fn generate_alerts_yaml() -> String {
9    r#"# Confium coordinator alerting rules.
10# Generated by confium-tc::coordinator::alerts.
11groups:
12  - name: confium-coordinator
13    interval: 30s
14    rules:
15      - alert: ConfiumHighErrorRate
16        expr: |
17          rate(confium_aggregations_failed_total[5m])
18          / clamp_min(rate(confium_aggregations_attempted_total[5m]), 0.001)
19          > 0.1
20        for: 5m
21        labels:
22          severity: critical
23        annotations:
24          summary: "Aggregation error rate > 10%"
25          description: "More than 10% of aggregation attempts are failing."
26
27      - alert: ConfiumSessionsExpiredRate
28        expr: rate(confium_sessions_expired_total[5m]) > 1
29        for: 10m
30        labels:
31          severity: warning
32        annotations:
33          summary: "High session expiry rate"
34          description: "More than 1 session/second expiring for 10 minutes."
35
36      - alert: ConfiumNoActiveSigners
37        expr: confium_registered_signers == 0
38        for: 2m
39        labels:
40          severity: critical
41        annotations:
42          summary: "No registered signers"
43          description: "Coordinator has no registered signers — cannot sign."
44
45      - alert: ConfiumTooManyActiveSessions
46        expr: confium_active_sessions > 50
47        for: 5m
48        labels:
49          severity: warning
50        annotations:
51          summary: "Many active sessions"
52          description: "More than 50 active sessions for 5 minutes."
53
54      - alert: ConfiumSessionsAborted
55        expr: rate(confium_sessions_aborted_total[5m]) > 0.5
56        for: 5m
57        labels:
58          severity: warning
59        annotations:
60          summary: "Sessions being aborted"
61          description: "More than 0.5 sessions/second being aborted."
62
63      - alert: ConfiumCoordinatorDown
64        expr: up{job="confium-coordinator"} == 0
65        for: 1m
66        labels:
67          severity: critical
68        annotations:
69          summary: "Coordinator is down"
70          description: "Prometheus cannot scrape the coordinator."
71"#
72    .to_string()
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn generates_non_empty_yaml() {
81        let yaml = generate_alerts_yaml();
82        assert!(!yaml.is_empty());
83    }
84
85    #[test]
86    fn contains_alert_groups() {
87        let yaml = generate_alerts_yaml();
88        assert!(yaml.contains("groups:"));
89        assert!(yaml.contains("confium-coordinator"));
90    }
91
92    #[test]
93    fn has_high_error_rate_alert() {
94        let yaml = generate_alerts_yaml();
95        assert!(yaml.contains("ConfiumHighErrorRate"));
96        assert!(yaml.contains("severity: critical"));
97    }
98
99    #[test]
100    fn has_no_signers_alert() {
101        let yaml = generate_alerts_yaml();
102        assert!(yaml.contains("ConfiumNoActiveSigners"));
103    }
104
105    #[test]
106    fn has_capacity_alert() {
107        let yaml = generate_alerts_yaml();
108        assert!(yaml.contains("ConfiumTooManyActiveSessions"));
109    }
110
111    #[test]
112    fn has_coordinator_down_alert() {
113        let yaml = generate_alerts_yaml();
114        assert!(yaml.contains("ConfiumCoordinatorDown"));
115    }
116
117    #[test]
118    fn all_alerts_have_summary() {
119        let yaml = generate_alerts_yaml();
120        let alert_count = yaml.matches("- alert:").count();
121        let summary_count = yaml.matches("summary:").count();
122        assert_eq!(
123            alert_count, summary_count,
124            "each alert should have a summary"
125        );
126    }
127
128    #[test]
129    fn all_alerts_have_for_clause() {
130        let yaml = generate_alerts_yaml();
131        let alert_count = yaml.matches("- alert:").count();
132        let for_count = yaml.matches("for:").count();
133        assert_eq!(
134            alert_count, for_count,
135            "each alert should have a 'for' clause"
136        );
137    }
138}