Skip to main content

cbtop/alerting/
mod.rs

1//! Real-Time Alert Integration System (PMAT-040)
2//!
3//! Vendor-agnostic alert routing for anomaly detection with webhook support.
4//!
5//! # Features
6//!
7//! - Multi-channel alert routing (Slack, PagerDuty, Email, Webhook)
8//! - Alert severity levels (INFO, WARNING, CRITICAL)
9//! - Rate limiting and deduplication
10//! - Message templating
11//! - Dry-run mode for testing
12//!
13//! # Falsification Criteria (F1321-F1330)
14//!
15//! See `tests/alerting_f1321.rs` for falsification tests.
16
17mod router;
18mod types;
19
20pub use router::{AlertRouter, AlertRouterConfig};
21pub use types::{Alert, AlertChannel, AlertSeverity, DeliveryResult};
22
23/// Message template for alerts
24#[derive(Debug, Clone)]
25pub struct MessageTemplate {
26    /// Template string with placeholders
27    pub template: String,
28}
29
30impl MessageTemplate {
31    /// Create new template
32    pub fn new(template: &str) -> Self {
33        Self {
34            template: template.to_string(),
35        }
36    }
37
38    /// Render template with alert data
39    pub fn render(&self, alert: &Alert) -> String {
40        self.template
41            .replace("{title}", &alert.title)
42            .replace("{message}", &alert.message)
43            .replace("{severity}", alert.severity.name())
44            .replace("{source}", &alert.source)
45            .replace(
46                "{value}",
47                &alert.value.map(|v| format!("{:.2}", v)).unwrap_or_default(),
48            )
49            .replace(
50                "{threshold}",
51                &alert
52                    .threshold
53                    .map(|t| format!("{:.2}", t))
54                    .unwrap_or_default(),
55            )
56    }
57}
58
59/// Create alert from anomaly detection result
60pub fn alert_from_anomaly(
61    metric: &str,
62    value: f64,
63    expected: f64,
64    severity: AlertSeverity,
65) -> Alert {
66    let deviation = ((value - expected) / expected * 100.0).abs();
67    Alert::new(
68        &format!("Anomaly detected: {}", metric),
69        &format!(
70            "{} deviated {:.1}% from expected value {:.2}",
71            metric, deviation, expected
72        ),
73        severity,
74    )
75    .with_source(metric)
76    .with_value(value)
77    .with_threshold(expected)
78}
79
80#[cfg(test)]
81mod tests;