Update to v0.1.19 with event-driven status aggregation
All checks were successful
Build and Release / build-and-release (push) Successful in 2m4s
All checks were successful
Build and Release / build-and-release (push) Successful in 2m4s
Major architectural improvements: CORE CHANGES: - Remove notification_interval_seconds - status aggregation now immediate - Status calculation moved to collection phase instead of transmission - Event-driven transmission triggers immediately on status changes - Dual transmission strategy: immediate on change + periodic backup - Real-time notifications without batching delays TECHNICAL IMPROVEMENTS: - process_metric() now returns bool indicating status change - Immediate ZMQ broadcast when status changes detected - Status aggregation happens during metric collection, not later - Legacy get_nixos_build_info() method removed (unused) - All compilation warnings fixed BEHAVIOR CHANGES: - Critical alerts sent instantly instead of waiting for intervals - Dashboard receives real-time status updates - Notifications triggered immediately on status transitions - Backup periodic transmission every 1s ensures heartbeat This provides much more responsive monitoring with instant alerting while maintaining the reliability of periodic transmission as backup.
This commit is contained in:
@@ -9,7 +9,6 @@ use chrono::Utc;
|
||||
pub struct HostStatusConfig {
|
||||
pub enabled: bool,
|
||||
pub aggregation_method: String, // "worst_case"
|
||||
pub notification_interval_seconds: u64,
|
||||
}
|
||||
|
||||
impl Default for HostStatusConfig {
|
||||
@@ -17,7 +16,6 @@ impl Default for HostStatusConfig {
|
||||
Self {
|
||||
enabled: true,
|
||||
aggregation_method: "worst_case".to_string(),
|
||||
notification_interval_seconds: 30,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,25 +158,69 @@ impl HostStatusManager {
|
||||
|
||||
|
||||
|
||||
/// Process a metric - updates status (notifications handled separately via batching)
|
||||
pub async fn process_metric(&mut self, metric: &Metric, _notification_manager: &mut crate::notifications::NotificationManager) {
|
||||
// Just update status - notifications are handled by process_pending_notifications
|
||||
self.update_service_status(metric.name.clone(), metric.status);
|
||||
/// Process a metric - updates status and triggers immediate notifications if status changed
|
||||
pub async fn process_metric(&mut self, metric: &Metric, notification_manager: &mut crate::notifications::NotificationManager) -> bool {
|
||||
let old_status = self.service_statuses.get(&metric.name).copied().unwrap_or(Status::Unknown);
|
||||
let new_status = metric.status;
|
||||
|
||||
// Update status
|
||||
self.update_service_status(metric.name.clone(), new_status);
|
||||
|
||||
// Check if status actually changed
|
||||
if old_status != new_status {
|
||||
debug!("Status change detected for {}: {:?} -> {:?}", metric.name, old_status, new_status);
|
||||
|
||||
// Process notification immediately on status change
|
||||
if let Err(e) = self.process_status_change(&metric.name, old_status, new_status, notification_manager).await {
|
||||
error!("Failed to process status change notification: {}", e);
|
||||
}
|
||||
|
||||
return true; // Status changed - caller should trigger immediate transmission
|
||||
}
|
||||
|
||||
false // No status change
|
||||
}
|
||||
|
||||
/// Process pending notifications - call this at notification intervals
|
||||
/// Process immediate status change notification
|
||||
async fn process_status_change(&mut self, metric_name: &str, old_status: Status, new_status: Status, notification_manager: &mut crate::notifications::NotificationManager) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
if !self.config.enabled {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Create immediate notification for this specific status change
|
||||
let status_summary = StatusChangeSummary {
|
||||
service_name: metric_name.to_string(),
|
||||
initial_status: old_status,
|
||||
final_status: new_status,
|
||||
change_count: 1,
|
||||
};
|
||||
|
||||
let aggregated = AggregatedStatusChanges {
|
||||
start_time: Instant::now(),
|
||||
end_time: Instant::now(),
|
||||
service_summaries: vec![status_summary],
|
||||
host_status_initial: old_status,
|
||||
host_status_final: new_status,
|
||||
requires_notification: true,
|
||||
};
|
||||
|
||||
// Send immediate notification using existing method
|
||||
if let Err(e) = self.send_aggregated_email(&aggregated, notification_manager).await {
|
||||
error!("Failed to send immediate notification: {}", e);
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
info!("Sent immediate notification for {} status change: {:?} -> {:?}", metric_name, old_status, new_status);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Process pending notifications - legacy method, now rarely used
|
||||
pub async fn process_pending_notifications(&mut self, notification_manager: &mut crate::notifications::NotificationManager) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
if !self.config.enabled || self.pending_changes.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let batch_start = self.batch_start_time.unwrap_or_else(Instant::now);
|
||||
let batch_duration = batch_start.elapsed();
|
||||
|
||||
// Only process if enough time has passed
|
||||
if batch_duration.as_secs() < self.config.notification_interval_seconds {
|
||||
return Ok(());
|
||||
}
|
||||
// Process notifications immediately without interval batching
|
||||
|
||||
// Create aggregated status changes
|
||||
let aggregated = self.create_aggregated_changes();
|
||||
|
||||
Reference in New Issue
Block a user