use cm_dashboard_shared::{Metric, Status}; use std::time::Instant; pub mod store; pub mod subscription; pub use store::MetricStore; /// Widget types that can subscribe to metrics #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] pub enum WidgetType { Cpu, Memory, Storage, Services, Backup, Hosts, Alerts, } /// Historical metric data point #[derive(Debug, Clone)] pub struct MetricDataPoint { pub metric: Metric, pub received_at: Instant, } /// Metric filtering and selection utilities pub mod filter { use super::*; /// Filter metrics by widget type subscription pub fn filter_metrics_for_widget<'a>( metrics: &'a [Metric], subscriptions: &[String], ) -> Vec<&'a Metric> { metrics .iter() .filter(|metric| subscriptions.contains(&metric.name)) .collect() } /// Get metrics by pattern matching pub fn filter_metrics_by_pattern<'a>( metrics: &'a [Metric], pattern: &str, ) -> Vec<&'a Metric> { if pattern.is_empty() { return metrics.iter().collect(); } metrics .iter() .filter(|metric| metric.name.contains(pattern)) .collect() } /// Aggregate status from multiple metrics pub fn aggregate_widget_status(metrics: &[&Metric]) -> Status { if metrics.is_empty() { return Status::Unknown; } let statuses: Vec = metrics.iter().map(|m| m.status).collect(); Status::aggregate(&statuses) } } /// Widget metric subscription definitions pub mod subscriptions { /// CPU widget metric subscriptions pub const CPU_WIDGET_METRICS: &[&str] = &[ "cpu_load_1min", "cpu_load_5min", "cpu_load_15min", "cpu_temperature_celsius", "cpu_frequency_mhz", ]; /// Memory widget metric subscriptions pub const MEMORY_WIDGET_METRICS: &[&str] = &[ "memory_usage_percent", "memory_total_gb", "memory_used_gb", "memory_available_gb", "memory_swap_total_gb", "memory_swap_used_gb", "disk_tmp_size_mb", "disk_tmp_total_mb", "disk_tmp_usage_percent", ]; /// Storage widget metric subscriptions pub const STORAGE_WIDGET_METRICS: &[&str] = &[ "disk_nvme0_temperature_celsius", "disk_nvme0_wear_percent", "disk_nvme0_spare_percent", "disk_nvme0_hours", "disk_nvme0_capacity_gb", "disk_nvme0_usage_gb", "disk_nvme0_usage_percent", ]; /// Services widget metric subscriptions /// Note: Individual service metrics are dynamically discovered /// Pattern: "service_{name}_status" and "service_{name}_memory_mb" pub const SERVICES_WIDGET_METRICS: &[&str] = &[ // Individual service metrics will be matched by pattern in the widget // e.g., "service_sshd_status", "service_nginx_status", etc. ]; /// Backup widget metric subscriptions pub const BACKUP_WIDGET_METRICS: &[&str] = &[ "backup_overall_status", "backup_duration_seconds", "backup_last_run_timestamp", "backup_total_services", "backup_total_repo_size_gb", "backup_services_completed_count", "backup_services_failed_count", "backup_services_disabled_count", ]; /// Get all metric subscriptions for a widget type pub fn get_widget_subscriptions(widget_type: super::WidgetType) -> &'static [&'static str] { match widget_type { super::WidgetType::Cpu => CPU_WIDGET_METRICS, super::WidgetType::Memory => MEMORY_WIDGET_METRICS, super::WidgetType::Storage => STORAGE_WIDGET_METRICS, super::WidgetType::Services => SERVICES_WIDGET_METRICS, super::WidgetType::Backup => BACKUP_WIDGET_METRICS, super::WidgetType::Hosts => &[], // Hosts widget doesn't subscribe to specific metrics super::WidgetType::Alerts => &[], // Alerts widget aggregates from all metrics } } }