use crate::alert_storage::{AlertStorage, StoredAlert};
use crate::alert_system::{AlertSeverity, AlertNotification};
use async_trait::async_trait;
use serde::Serialize;
use std::collections::HashMap;
use tokio::sync::RwLock;
use std::sync::Arc;
#[derive(Debug, Serialize)]
pub struct RemediationAction {
pub action_type: RemediationType,
pub target: String,
pub parameters: HashMap<String, String>,
pub priority: u8,
pub requires_approval: bool,
}
#[derive(Debug, Serialize, PartialEq)]
pub enum RemediationType {
ScaleResource,
RestartService,
AdjustThreshold,
ClearCache,
RollbackDeploy,
}
#[derive(Debug, Serialize)]
pub struct RemediationResult {
pub success: bool,
pub action: RemediationAction,
pub execution_time: std::time::Duration,
pub error_message: Option<String>,
}
#[async_trait]
pub trait RemediationExecutor: Send + Sync {
async fn execute(&self, action: &RemediationAction) -> Result<RemediationResult, RemediationError>;
}
#[derive(Debug, thiserror::Error)]
pub enum RemediationError {
#[error("Failed to execute remediation: {0}")]
ExecutionError(String),
#[error("Invalid remediation parameters: {0}")]
InvalidParameters(String),
#[error("Remediation timeout")]
Timeout,
}
pub struct AutoRemediator {
storage: AlertStorage,
executors: HashMap<RemediationType, Box<dyn RemediationExecutor>>,
action_history: Arc<RwLock<Vec<RemediationResult>>>,
}
impl AutoRemediator {
pub fn new(storage: AlertStorage) -> Self {
Self {
storage,
executors: HashMap::new(),
action_history: Arc::new(RwLock::new(Vec::new())),
}
}
pub fn register_executor<E: RemediationExecutor + 'static>(
&mut self,
remediation_type: RemediationType,
executor: E,
) {
self.executors.insert(remediation_type, Box::new(executor));
}
pub async fn handle_alert(&self, alert: &AlertNotification) -> Result<Option<RemediationResult>, RemediationError> {
if let Some(action) = self.determine_remediation_action(alert) {
if let Some(executor) = self.executors.get(&action.action_type) {
let result = executor.execute(&action).await?;
self.action_history.write().await.push(result.clone());
Ok(Some(result))
} else {
Ok(None)
}
} else {
Ok(None)
}
}
fn determine_remediation_action(&self, alert: &AlertNotification) -> Option<RemediationAction> {
match alert.alert.severity {
AlertSeverity::Critical => None, AlertSeverity::Warning => self.create_warning_remediation(alert),
AlertSeverity::Info => self.create_info_remediation(alert),
}
}
fn create_warning_remediation(&self, alert: &AlertNotification) -> Option<RemediationAction> {
let mut parameters = HashMap::new();
parameters.insert("metric".to_string(), alert.alert.metric_name.clone());
parameters.insert("threshold".to_string(), alert.alert.threshold.to_string());
Some(RemediationAction {
action_type: RemediationType::AdjustThreshold,
target: alert.alert.metric_name.clone(),
parameters,
priority: 7,
requires_approval: true,
})
}
fn create_info_remediation(&self, alert: &AlertNotification) -> Option<RemediationAction> {
let mut parameters = HashMap::new();
parameters.insert("service".to_string(), alert.alert.metric_name.clone());
Some(RemediationAction {
action_type: RemediationType::ClearCache,
target: alert.alert.metric_name.clone(),
parameters,
priority: 5,
requires_approval: false,
})
}
}
pub struct ThresholdAdjustmentExecutor;
#[async_trait]
impl RemediationExecutor for ThresholdAdjustmentExecutor {
async fn execute(&self, action: &RemediationAction) -> Result<RemediationResult, RemediationError> {
let start_time = std::time::Instant::now();
Ok(RemediationResult {
success: true,
action: action.clone(),
execution_time: start_time.elapsed(),
error_message: None,
})
}
}