use serde::{Deserialize, Serialize}; use crate::Status; /// Complete structured data from an agent #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AgentData { pub hostname: String, pub agent_version: String, pub build_version: Option, pub timestamp: u64, pub system: SystemData, pub services: Vec, pub backup: BackupData, } /// System-level monitoring data #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SystemData { pub cpu: CpuData, pub memory: MemoryData, pub storage: StorageData, } /// CPU monitoring data #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CpuData { pub load_1min: f32, pub load_5min: f32, pub load_15min: f32, pub frequency_mhz: f32, pub temperature_celsius: Option, pub load_status: Status, pub temperature_status: Status, } /// Memory monitoring data #[derive(Debug, Clone, Serialize, Deserialize)] pub struct MemoryData { pub usage_percent: f32, pub total_gb: f32, pub used_gb: f32, pub available_gb: f32, pub swap_total_gb: f32, pub swap_used_gb: f32, pub tmpfs: Vec, pub usage_status: Status, } /// Tmpfs filesystem data #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TmpfsData { pub mount: String, pub usage_percent: f32, pub used_gb: f32, pub total_gb: f32, } /// Storage monitoring data #[derive(Debug, Clone, Serialize, Deserialize)] pub struct StorageData { pub drives: Vec, pub pools: Vec, } /// Individual drive data #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DriveData { pub name: String, pub health: String, pub temperature_celsius: Option, pub wear_percent: Option, pub filesystems: Vec, pub temperature_status: Status, pub health_status: Status, } /// Filesystem on a drive #[derive(Debug, Clone, Serialize, Deserialize)] pub struct FilesystemData { pub mount: String, pub usage_percent: f32, pub used_gb: f32, pub total_gb: f32, pub usage_status: Status, } /// Storage pool (MergerFS, RAID, etc.) #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PoolData { pub name: String, pub mount: String, pub pool_type: String, // "mergerfs", "raid", etc. pub health: String, pub usage_percent: f32, pub used_gb: f32, pub total_gb: f32, pub data_drives: Vec, pub parity_drives: Vec, pub health_status: Status, pub usage_status: Status, } /// Drive in a storage pool #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PoolDriveData { pub name: String, pub serial_number: Option, pub temperature_celsius: Option, pub wear_percent: Option, pub health: String, pub health_status: Status, pub temperature_status: Status, } /// Service monitoring data #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ServiceData { pub name: String, pub memory_mb: f32, pub disk_gb: f32, pub user_stopped: bool, pub service_status: Status, pub sub_services: Vec, } /// Sub-service data (nginx sites, docker containers, etc.) #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SubServiceData { pub name: String, pub service_status: Status, pub metrics: Vec, } /// Individual metric for a sub-service #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SubServiceMetric { pub label: String, pub value: f32, pub unit: Option, } /// Backup system data #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BackupData { pub status: String, pub total_size_gb: Option, pub repository_health: Option, pub repository_disk: Option, pub last_backup_size_gb: Option, pub start_time_raw: Option, } /// Backup repository disk information #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BackupDiskData { pub serial: String, pub usage_percent: f32, pub used_gb: f32, pub total_gb: f32, pub wear_percent: Option, pub temperature_celsius: Option, } impl AgentData { /// Create new agent data with current timestamp pub fn new(hostname: String, agent_version: String) -> Self { Self { hostname, agent_version, build_version: None, timestamp: chrono::Utc::now().timestamp() as u64, system: SystemData { cpu: CpuData { load_1min: 0.0, load_5min: 0.0, load_15min: 0.0, frequency_mhz: 0.0, temperature_celsius: None, load_status: Status::Unknown, temperature_status: Status::Unknown, }, memory: MemoryData { usage_percent: 0.0, total_gb: 0.0, used_gb: 0.0, available_gb: 0.0, swap_total_gb: 0.0, swap_used_gb: 0.0, tmpfs: Vec::new(), usage_status: Status::Unknown, }, storage: StorageData { drives: Vec::new(), pools: Vec::new(), }, }, services: Vec::new(), backup: BackupData { status: "unknown".to_string(), total_size_gb: None, repository_health: None, repository_disk: None, last_backup_size_gb: None, start_time_raw: None, }, } } }