Improve notification email format with detailed service groupings

This commit is contained in:
Christoffer Martinsson 2025-10-21 19:25:43 +02:00
parent 34822bd835
commit 7ead8ee98a

View File

@ -251,10 +251,32 @@ impl HostStatusManager {
details: Some(self.format_aggregated_details(aggregated)), details: Some(self.format_aggregated_details(aggregated)),
}; };
// Create a descriptive summary based on change types
let mut summary_parts = Vec::new();
let critical_count = aggregated.service_summaries.iter().filter(|s| s.final_status == Status::Critical).count();
let warning_count = aggregated.service_summaries.iter().filter(|s| s.final_status == Status::Warning).count();
let recovery_count = aggregated.service_summaries.iter().filter(|s|
matches!((s.initial_status, s.final_status), (Status::Warning | Status::Critical, Status::Ok))
).count();
let startup_count = aggregated.service_summaries.iter().filter(|s|
matches!((s.initial_status, s.final_status), (Status::Unknown, Status::Ok | Status::Pending))
).count();
if critical_count > 0 { summary_parts.push(format!("{} critical", critical_count)); }
if warning_count > 0 { summary_parts.push(format!("{} warning", warning_count)); }
if recovery_count > 0 { summary_parts.push(format!("{} recovered", recovery_count)); }
if startup_count > 0 { summary_parts.push(format!("{} started", startup_count)); }
let summary_text = if summary_parts.is_empty() {
format!("{} service changes", aggregated.service_summaries.len())
} else {
summary_parts.join(", ")
};
// Create a dummy metric for the notification // Create a dummy metric for the notification
let summary_metric = Metric { let summary_metric = Metric {
name: "host_status_summary".to_string(), name: "host_status_summary".to_string(),
value: cm_dashboard_shared::MetricValue::String(format!("{} services changed", aggregated.service_summaries.len())), value: cm_dashboard_shared::MetricValue::String(summary_text),
status: aggregated.host_status_final, status: aggregated.host_status_final,
timestamp: Utc::now().timestamp() as u64, timestamp: Utc::now().timestamp() as u64,
description: Some("Aggregated status summary".to_string()), description: Some("Aggregated status summary".to_string()),
@ -282,32 +304,72 @@ impl HostStatusManager {
)); ));
} }
details.push_str("Service Changes:\n"); // Group services by change type
let mut critical_changes = Vec::new();
let mut warning_changes = Vec::new();
let mut recovery_changes = Vec::new();
let mut startup_changes = Vec::new();
let mut other_changes = Vec::new();
for summary in &aggregated.service_summaries { for summary in &aggregated.service_summaries {
if summary.significant_change { let change_info = format!(
let status_indicator = if summary.final_status == Status::Ok && "{}: {:?} → {:?}{}",
(summary.initial_status == Status::Warning || summary.initial_status == Status::Critical) { summary.service_name,
"" summary.initial_status,
} else if summary.final_status == Status::Warning { summary.final_status,
"🟡" if summary.change_count > 1 { format!(" ({} changes)", summary.change_count) } else { String::new() }
} else if summary.final_status == Status::Critical { );
"🔴"
} else {
""
};
details.push_str(&format!( match (summary.initial_status, summary.final_status) {
" {} {}: {:?} → {:?}", (_, Status::Critical) => critical_changes.push(change_info),
status_indicator, (_, Status::Warning) => warning_changes.push(change_info),
summary.service_name, (Status::Warning | Status::Critical, Status::Ok) => recovery_changes.push(change_info),
summary.initial_status, (Status::Unknown, Status::Ok | Status::Pending) => startup_changes.push(change_info),
summary.final_status _ => other_changes.push(change_info),
)); }
}
if summary.change_count > 1 { // Show critical problems first
details.push_str(&format!(" ({} changes)", summary.change_count)); if !critical_changes.is_empty() {
} details.push_str(&format!("🔴 CRITICAL ISSUES ({}):\n", critical_changes.len()));
details.push('\n'); for change in critical_changes {
details.push_str(&format!(" {}\n", change));
}
details.push('\n');
}
// Show warnings
if !warning_changes.is_empty() {
details.push_str(&format!("🟡 WARNINGS ({}):\n", warning_changes.len()));
for change in warning_changes {
details.push_str(&format!(" {}\n", change));
}
details.push('\n');
}
// Show recoveries
if !recovery_changes.is_empty() {
details.push_str(&format!("✅ RECOVERIES ({}):\n", recovery_changes.len()));
for change in recovery_changes {
details.push_str(&format!(" {}\n", change));
}
details.push('\n');
}
// Show startups (usually not important but good to know)
if !startup_changes.is_empty() {
details.push_str(&format!("🟢 SERVICE STARTUPS ({}):\n", startup_changes.len()));
for change in startup_changes {
details.push_str(&format!(" {}\n", change));
}
details.push('\n');
}
// Show other changes
if !other_changes.is_empty() {
details.push_str(&format!(" OTHER CHANGES ({}):\n", other_changes.len()));
for change in other_changes {
details.push_str(&format!(" {}\n", change));
} }
} }