All checks were successful
Build and Release / build-and-release (push) Successful in 1m19s
Updates disk collector and dashboard to show drive serial numbers instead of device names (sdX) for MergerFS data/parity drives. Agent extracts serial numbers from SMART data and dashboard displays them when available, falling back to device names.
208 lines
5.7 KiB
Rust
208 lines
5.7 KiB
Rust
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<String>,
|
|
pub timestamp: u64,
|
|
pub system: SystemData,
|
|
pub services: Vec<ServiceData>,
|
|
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<f32>,
|
|
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<TmpfsData>,
|
|
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<DriveData>,
|
|
pub pools: Vec<PoolData>,
|
|
}
|
|
|
|
/// Individual drive data
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct DriveData {
|
|
pub name: String,
|
|
pub health: String,
|
|
pub temperature_celsius: Option<f32>,
|
|
pub wear_percent: Option<f32>,
|
|
pub filesystems: Vec<FilesystemData>,
|
|
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<PoolDriveData>,
|
|
pub parity_drives: Vec<PoolDriveData>,
|
|
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<String>,
|
|
pub temperature_celsius: Option<f32>,
|
|
pub wear_percent: Option<f32>,
|
|
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<SubServiceData>,
|
|
}
|
|
|
|
/// 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<SubServiceMetric>,
|
|
}
|
|
|
|
/// Individual metric for a sub-service
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct SubServiceMetric {
|
|
pub label: String,
|
|
pub value: f32,
|
|
pub unit: Option<String>,
|
|
}
|
|
|
|
/// Backup system data
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct BackupData {
|
|
pub status: String,
|
|
pub total_size_gb: Option<f32>,
|
|
pub repository_health: Option<String>,
|
|
pub repository_disk: Option<BackupDiskData>,
|
|
pub last_backup_size_gb: Option<f32>,
|
|
pub start_time_raw: Option<String>,
|
|
}
|
|
|
|
/// 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<f32>,
|
|
pub temperature_celsius: Option<f32>,
|
|
}
|
|
|
|
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,
|
|
},
|
|
}
|
|
}
|
|
} |