All checks were successful
Build and Release / build-and-release (push) Successful in 1m43s
Agent changes: - Parse /proc/net/vlan/config to extract VLAN IDs for interfaces - Detect primary physical interface via default route - Auto-assign primary interface as parent for virtual interfaces without explicit parent - Added vlan_id field to NetworkInterfaceData Dashboard changes: - Display VLAN ID in format "interface (vlan X): IP" - Show VLAN IDs for both nested and standalone virtual interfaces This ensures virtual interfaces (docker0, tailscale0, etc.) are properly nested under the primary physical NIC, and VLAN interfaces show their IDs. Updated to version 0.1.170
231 lines
6.3 KiB
Rust
231 lines
6.3 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 network: NetworkData,
|
|
pub cpu: CpuData,
|
|
pub memory: MemoryData,
|
|
pub storage: StorageData,
|
|
}
|
|
|
|
/// Network interface monitoring data
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct NetworkData {
|
|
pub interfaces: Vec<NetworkInterfaceData>,
|
|
}
|
|
|
|
/// Individual network interface data
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct NetworkInterfaceData {
|
|
pub name: String,
|
|
pub ipv4_addresses: Vec<String>,
|
|
pub ipv6_addresses: Vec<String>,
|
|
pub is_physical: bool,
|
|
pub link_status: Status,
|
|
pub parent_interface: Option<String>,
|
|
pub vlan_id: Option<u16>,
|
|
}
|
|
|
|
/// 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 serial_number: Option<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 {
|
|
network: NetworkData {
|
|
interfaces: Vec::new(),
|
|
},
|
|
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,
|
|
},
|
|
}
|
|
}
|
|
} |