use async_trait::async_trait; use cm_dashboard_shared::{Metric, SharedError}; use std::time::Duration; pub mod cached_collector; pub mod cpu; pub mod memory; pub mod disk; pub mod systemd; pub mod error; pub use error::CollectorError; /// Performance metrics for a collector #[derive(Debug, Clone)] pub struct PerformanceMetrics { pub last_collection_time: Duration, pub collection_efficiency_percent: f32, } /// Base trait for all collectors with extreme efficiency requirements #[async_trait] pub trait Collector: Send + Sync { /// Name of this collector fn name(&self) -> &str; /// Collect all metrics this collector provides async fn collect(&self) -> Result, CollectorError>; /// Get performance metrics for monitoring collector efficiency fn get_performance_metrics(&self) -> Option { None } } /// CPU efficiency rules for all collectors pub mod efficiency { /// CRITICAL: All collectors must follow these efficiency rules to minimize system impact /// 1. FILE READING RULES /// - Read entire files in single syscall when possible /// - Use BufReader only for very large files (>4KB) /// - Never read files character by character /// - Cache file descriptors when safe (immutable paths) /// 2. PARSING RULES /// - Use split() instead of regex for simple patterns /// - Parse numbers with from_str() not complex parsing /// - Avoid string allocations in hot paths /// - Use str::trim() before parsing numbers /// 3. MEMORY ALLOCATION RULES /// - Reuse Vec buffers when possible /// - Pre-allocate collections with known sizes /// - Use str slices instead of String when possible /// - Avoid clone() in hot paths /// 4. SYSTEM CALL RULES /// - Minimize syscalls - prefer single reads over multiple /// - Use /proc filesystem efficiently /// - Avoid spawning processes when /proc data available /// - Cache static data (like CPU count) /// 5. ERROR HANDLING RULES /// - Use Result<> but minimize allocation in error paths /// - Log errors at debug level only to avoid I/O overhead /// - Graceful degradation - missing metrics better than failing /// - Never panic in collectors /// 6. CONCURRENCY RULES /// - Collectors must be thread-safe but avoid locks /// - Use atomic operations for simple counters /// - Avoid shared mutable state between collections /// - Each collection should be independent pub const PERFORMANCE_TARGET_OVERHEAD_PERCENT: f32 = 0.1; } /// Utility functions for efficient system data collection pub mod utils { use std::fs; use super::CollectorError; /// Read entire file content efficiently pub fn read_proc_file(path: &str) -> Result { fs::read_to_string(path).map_err(|e| CollectorError::SystemRead { path: path.to_string(), error: e.to_string(), }) } /// Parse float from string slice efficiently pub fn parse_f32(s: &str) -> Result { s.trim().parse().map_err(|e: std::num::ParseFloatError| CollectorError::Parse { value: s.to_string(), error: e.to_string(), }) } /// Parse integer from string slice efficiently pub fn parse_u64(s: &str) -> Result { s.trim().parse().map_err(|e: std::num::ParseIntError| CollectorError::Parse { value: s.to_string(), error: e.to_string(), }) } /// Split string and get nth element safely pub fn split_nth<'a>(s: &'a str, delimiter: char, n: usize) -> Option<&'a str> { s.split(delimiter).nth(n) } }