Implement comprehensive backup monitoring and fix timestamp issues

- Add BackupCollector for reading TOML status files with disk space metrics
- Implement BackupWidget with disk usage display and service status details
- Fix backup script disk space parsing by adding missing capture_output=True
- Update backup widget to show actual disk usage instead of repository size
- Fix timestamp parsing to use backup completion time instead of start time
- Resolve timezone issues by using UTC timestamps in backup script
- Add disk identification metrics (product name, serial number) to backup status
- Enhance UI layout with proper backup monitoring integration
This commit is contained in:
2025-10-18 18:33:41 +02:00
parent 8a36472a3d
commit 125111ee99
19 changed files with 2788 additions and 1020 deletions

View File

@@ -5,7 +5,7 @@ use std::time::Instant;
use tracing::{info, error, debug};
use crate::config::{CollectorConfig, AgentConfig};
use crate::collectors::{Collector, cpu::CpuCollector, memory::MemoryCollector, disk::DiskCollector, systemd::SystemdCollector, cached_collector::CachedCollector};
use crate::collectors::{Collector, cpu::CpuCollector, memory::MemoryCollector, disk::DiskCollector, systemd::SystemdCollector, backup::BackupCollector, cached_collector::CachedCollector};
use crate::cache::MetricCacheManager;
/// Manages all metric collectors with intelligent caching
@@ -51,6 +51,17 @@ impl MetricCollectionManager {
collectors.push(Box::new(systemd_collector));
info!("BENCHMARK: Systemd collector only");
},
Some("backup") => {
// Backup collector only
if config.backup.enabled {
let backup_collector = BackupCollector::new(
config.backup.backup_paths.first().cloned(),
config.backup.max_age_hours
);
collectors.push(Box::new(backup_collector));
info!("BENCHMARK: Backup collector only");
}
},
Some("none") => {
// No collectors - test agent loop only
info!("BENCHMARK: No collectors enabled");
@@ -76,6 +87,15 @@ impl MetricCollectionManager {
let systemd_collector = SystemdCollector::new();
collectors.push(Box::new(systemd_collector));
info!("Systemd collector initialized");
if config.backup.enabled {
let backup_collector = BackupCollector::new(
config.backup.backup_paths.first().cloned(),
config.backup.max_age_hours
);
collectors.push(Box::new(backup_collector));
info!("Backup collector initialized");
}
}
}
@@ -94,6 +114,40 @@ impl MetricCollectionManager {
})
}
/// Force collection from ALL collectors immediately (used at startup)
pub async fn collect_all_metrics_force(&mut self) -> Result<Vec<Metric>> {
let mut all_metrics = Vec::new();
let now = Instant::now();
info!("Force collecting from ALL {} collectors for startup", self.collectors.len());
// Force collection from every collector regardless of intervals
for collector in &self.collectors {
let collector_name = collector.name();
match collector.collect().await {
Ok(metrics) => {
info!("Force collected {} metrics from {} collector", metrics.len(), collector_name);
// Cache all new metrics
for metric in &metrics {
self.cache_manager.cache_metric(metric.clone()).await;
}
all_metrics.extend(metrics);
self.last_collection_times.insert(collector_name.to_string(), now);
}
Err(e) => {
error!("Collector '{}' failed during force collection: {}", collector_name, e);
// Continue with other collectors even if one fails
}
}
}
info!("Force collection completed: {} total metrics cached", all_metrics.len());
Ok(all_metrics)
}
/// Collect metrics from all collectors with intelligent caching
pub async fn collect_all_metrics(&mut self) -> Result<Vec<Metric>> {
let mut all_metrics = Vec::new();
@@ -111,6 +165,7 @@ impl MetricCollectionManager {
// Determine cache interval for this collector type - ALL REALTIME FOR FAST UPDATES
let cache_interval_secs = match collector_name {
"cpu" | "memory" | "disk" | "systemd" => 2, // All realtime for fast updates
"backup" => 10, // Backup metrics every 10 seconds for testing
_ => 2, // All realtime for fast updates
};
@@ -168,6 +223,13 @@ impl MetricCollectionManager {
.collect()
}
/// Get all cached metrics from the cache manager
pub async fn get_all_cached_metrics(&self) -> Result<Vec<Metric>> {
let cached_metrics = self.cache_manager.get_all_cached_metrics().await;
debug!("Retrieved {} cached metrics for broadcast", cached_metrics.len());
Ok(cached_metrics)
}
/// Determine which collector handles a specific metric
fn get_collector_for_metric(&self, metric_name: &str) -> String {
if metric_name.starts_with("cpu_") {
@@ -178,6 +240,8 @@ impl MetricCollectionManager {
"disk".to_string()
} else if metric_name.starts_with("service_") {
"systemd".to_string()
} else if metric_name.starts_with("backup_") {
"backup".to_string()
} else {
"unknown".to_string()
}