#[cfg(feature = "alerting-log")]
mod log_alerter;
#[cfg(feature = "alerting-webhook")]
mod webhook_alerter;
#[cfg(feature = "alerting-log")]
pub use log_alerter::LogAlerter;
#[cfg(feature = "alerting-webhook")]
pub use webhook_alerter::WebhookAlerter;
use crate::monitor::DriftReport;
use std::time::{SystemTime, UNIX_EPOCH};
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "alerting-webhook", derive(serde::Serialize))]
pub struct DriftedFeatureInfo {
pub feature: String,
pub metric: String,
pub score: f64,
pub threshold: f64,
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "alerting-webhook", derive(serde::Serialize))]
pub struct DriftAlertEvent {
pub timestamp_secs: u64,
pub dataset_drifted: bool,
pub drifted_fraction: f64,
pub features: Vec<DriftedFeatureInfo>,
}
impl DriftAlertEvent {
pub fn from_report(report: &DriftReport) -> Self {
let features = report
.drifted_features()
.map(|f| DriftedFeatureInfo {
feature: f.feature.clone(),
metric: f.primary.to_string(),
score: f.primary_statistic(),
threshold: f.threshold,
})
.collect();
Self {
timestamp_secs: SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0),
dataset_drifted: report.dataset_drift_detected(),
drifted_fraction: report.drifted_fraction(),
features,
}
}
}
pub trait Alerter: Send + Sync {
fn alert(&self, event: &DriftAlertEvent);
}
#[derive(Clone, Copy, Debug, Default)]
pub struct NopAlerter;
impl Alerter for NopAlerter {
fn alert(&self, _event: &DriftAlertEvent) {}
}