Clean up warnings and add Status::Pending support to dashboard UI
This commit is contained in:
parent
41208aa2a0
commit
98e3ecb0ea
@ -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<StatusChange> {
|
||||
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<String, Status>, HashMap<String, String>) {
|
||||
|
||||
@ -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<Instant>,
|
||||
config: HostStatusConfig,
|
||||
notification_manager: Option<NotificationManager>,
|
||||
// Notification batching
|
||||
pending_changes: HashMap<String, (Status, Status, usize)>, // service -> (initial_status, current_status, change_count)
|
||||
batch_start_time: Option<Instant>,
|
||||
@ -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<String, Status> {
|
||||
&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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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(),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user