From 98e3ecb0ea49b6f7dc3674b23ad5ace6e08d1afa Mon Sep 17 00:00:00 2001 From: Christoffer Martinsson Date: Tue, 21 Oct 2025 18:27:11 +0200 Subject: [PATCH] Clean up warnings and add Status::Pending support to dashboard UI --- agent/src/notifications/mod.rs | 45 --------------- agent/src/status/mod.rs | 85 ++-------------------------- dashboard/src/ui/theme.rs | 3 + dashboard/src/ui/widgets/backup.rs | 1 + dashboard/src/ui/widgets/services.rs | 3 + 5 files changed, 11 insertions(+), 126 deletions(-) diff --git a/agent/src/notifications/mod.rs b/agent/src/notifications/mod.rs index 93c3a4e..63bdfe8 100644 --- a/agent/src/notifications/mod.rs +++ b/agent/src/notifications/mod.rs @@ -61,46 +61,6 @@ impl NotificationManager { }) } - /// Update metric status and return status change if any - pub fn update_metric_status( - &mut self, - metric_name: &str, - new_status: Status, - ) -> Option { - let old_status = self - .metric_statuses - .get(metric_name) - .copied() - .unwrap_or(Status::Unknown); - - - // Check if status actually changed - if old_status != new_status { - // Update stored status only on change - self.metric_statuses - .insert(metric_name.to_string(), new_status); - - // Save status to disk only when status changes - self.save_status(); - debug!( - "Status change detected for {}: {:?} -> {:?}", - metric_name, old_status, new_status - ); - - Some(StatusChange { - metric_name: metric_name.to_string(), - old_status, - new_status, - timestamp: Utc::now(), - details: None, // Will be populated when needed - }) - } else { - // No status change - update stored status but don't save to disk - self.metric_statuses - .insert(metric_name.to_string(), new_status); - None - } - } /// Send notification for status change pub async fn send_status_change_notification( @@ -249,11 +209,6 @@ impl NotificationManager { Ok(()) } - /// Process any pending notifications (placeholder) - pub async fn process_pending(&mut self) { - // Placeholder for batch notification processing - // Could be used for email queue processing, etc. - } /// Load status from disk fn load_status(file_path: &str) -> (HashMap, HashMap) { diff --git a/agent/src/status/mod.rs b/agent/src/status/mod.rs index 33011d7..332732f 100644 --- a/agent/src/status/mod.rs +++ b/agent/src/status/mod.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use std::time::Instant; use tracing::{debug, info, error}; use serde::{Deserialize, Serialize}; -use crate::notifications::{NotificationManager, StatusChange}; +use crate::notifications::StatusChange; use chrono::Utc; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -25,14 +25,6 @@ impl Default for HostStatusConfig { } } -pub struct StatusChangeEvent { - pub service_name: String, - pub old_status: Status, - pub new_status: Status, - pub host_status_changed: bool, - pub old_host_status: Status, - pub new_host_status: Status, -} #[derive(Debug, Clone)] pub struct StatusChangeSummary { @@ -59,7 +51,6 @@ pub struct HostStatusManager { previous_host_status: Status, last_status_change: Option, config: HostStatusConfig, - notification_manager: Option, // Notification batching pending_changes: HashMap, // service -> (initial_status, current_status, change_count) batch_start_time: Option, @@ -75,7 +66,6 @@ impl HostStatusManager { previous_host_status: Status::Unknown, last_status_change: None, config, - notification_manager: None, pending_changes: HashMap::new(), batch_start_time: None, batch_start_host_status: Status::Unknown, @@ -157,74 +147,7 @@ impl HostStatusManager { } } - /// Determine whether a notification should be sent for this status change - /// This implements the core logic: suppress individual recoveries, only notify on full host recovery - pub fn should_send_notification(&self, event: &StatusChangeEvent) -> bool { - if !self.config.enabled { - return false; - } - match (event.old_status, event.new_status) { - // Always notify on service problems (transitions TO warning/critical) - (_, Status::Warning) | (_, Status::Critical) => { - debug!("Notification approved: service '{}' transitioned to {:?}", event.service_name, event.new_status); - true - }, - // Only notify on recovery if ALL services are OK (host status is OK) - (Status::Warning | Status::Critical | Status::Unknown, Status::Ok) => { - let should_notify = self.current_host_status == Status::Ok; - if should_notify { - info!("Recovery notification approved: service '{}' recovered and all services are OK", event.service_name); - } else { - debug!("Recovery notification suppressed: service '{}' recovered but other services still have issues (host status: {:?})", - event.service_name, self.current_host_status); - } - should_notify - }, - // No notification for other transitions - _ => { - debug!("No notification needed for status transition: {:?} -> {:?}", event.old_status, event.new_status); - false - } - } - } - - /// Get the current overall host status - pub fn get_host_status(&self) -> Status { - self.current_host_status - } - - /// Check if all services are in OK status - pub fn all_services_ok(&self) -> bool { - !self.service_statuses.is_empty() && - self.service_statuses.values().all(|s| *s == Status::Ok) - } - - /// Get the current service statuses (for debugging/monitoring) - pub fn get_service_statuses(&self) -> &HashMap { - &self.service_statuses - } - - /// Get the number of services in each status - pub fn get_status_summary(&self) -> (usize, usize, usize, usize, usize) { - let mut ok_count = 0; - let mut pending_count = 0; - let mut warning_count = 0; - let mut critical_count = 0; - let mut unknown_count = 0; - - for status in self.service_statuses.values() { - match status { - Status::Ok => ok_count += 1, - Status::Pending => pending_count += 1, - Status::Warning => warning_count += 1, - Status::Critical => critical_count += 1, - Status::Unknown => unknown_count += 1, - } - } - - (ok_count, pending_count, warning_count, critical_count, unknown_count) - } /// 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) { @@ -345,10 +268,10 @@ impl HostStatusManager { fn format_aggregated_details(&self, aggregated: &AggregatedStatusChanges) -> String { let mut details = String::new(); + let duration = aggregated.end_time.duration_since(aggregated.start_time).as_secs(); details.push_str(&format!( - "Status Summary ({} to {})\n", - aggregated.start_time.elapsed().as_secs(), - 0 + "Status Summary ({}s duration)\n", + duration )); if aggregated.host_status_initial != aggregated.host_status_final { diff --git a/dashboard/src/ui/theme.rs b/dashboard/src/ui/theme.rs index db5aec1..3658943 100644 --- a/dashboard/src/ui/theme.rs +++ b/dashboard/src/ui/theme.rs @@ -143,6 +143,7 @@ impl Theme { pub fn status_color(status: Status) -> Color { match status { Status::Ok => Self::success(), + Status::Pending => Self::info(), // Blue for pending Status::Warning => Self::warning(), Status::Critical => Self::error(), Status::Unknown => Self::muted_text(), @@ -245,6 +246,7 @@ impl StatusIcons { pub fn get_icon(status: Status) -> &'static str { match status { Status::Ok => "●", + Status::Pending => "◉", // Hollow circle for pending Status::Warning => "◐", Status::Critical => "◯", Status::Unknown => "?", @@ -256,6 +258,7 @@ impl StatusIcons { let icon = Self::get_icon(status); let status_color = match status { Status::Ok => Theme::success(), // Green + Status::Pending => Theme::info(), // Blue Status::Warning => Theme::warning(), // Yellow Status::Critical => Theme::error(), // Red Status::Unknown => Theme::muted_text(), // Gray diff --git a/dashboard/src/ui/widgets/backup.rs b/dashboard/src/ui/widgets/backup.rs index 2984b0b..82ba22f 100644 --- a/dashboard/src/ui/widgets/backup.rs +++ b/dashboard/src/ui/widgets/backup.rs @@ -382,6 +382,7 @@ impl BackupWidget { "Status: {}", match self.overall_status { Status::Ok => "OK", + Status::Pending => "Pending", Status::Warning => "Warning", Status::Critical => "Failed", Status::Unknown => "Unknown", diff --git a/dashboard/src/ui/widgets/services.rs b/dashboard/src/ui/widgets/services.rs index e3b1333..a1c6c74 100644 --- a/dashboard/src/ui/widgets/services.rs +++ b/dashboard/src/ui/widgets/services.rs @@ -112,6 +112,7 @@ impl ServicesWidget { // Parent services always show active/inactive status let status_str = match info.widget_status { Status::Ok => "active".to_string(), + Status::Pending => "pending".to_string(), Status::Warning => "inactive".to_string(), Status::Critical => "failed".to_string(), Status::Unknown => "unknown".to_string(), @@ -146,6 +147,7 @@ impl ServicesWidget { } else { match info.widget_status { Status::Ok => "active".to_string(), + Status::Pending => "pending".to_string(), Status::Warning => "inactive".to_string(), Status::Critical => "failed".to_string(), Status::Unknown => "unknown".to_string(), @@ -154,6 +156,7 @@ impl ServicesWidget { let status_color = match info.widget_status { Status::Ok => Theme::success(), + Status::Pending => Theme::info(), Status::Warning => Theme::warning(), Status::Critical => Theme::error(), Status::Unknown => Theme::muted_text(),