Christoffer Martinsson 2b2cb2da3e
All checks were successful
Build and Release / build-and-release (push) Successful in 1m7s
Complete atomic migration to structured data architecture
Implements clean structured data collection eliminating all string metric
parsing bugs. Collectors now populate AgentData directly with type-safe
field access.

Key improvements:
- Mount points preserved correctly (/ and /boot instead of root/boot)
- Tmpfs discovery added to memory collector
- Temperature data flows as typed f32 fields
- Zero string parsing overhead
- Complete removal of MetricCollectionManager bridge
- Direct ZMQ transmission of structured JSON

All functionality maintained: service tracking, notifications, status
evaluation, and multi-host monitoring.
2025-11-24 18:53:31 +01:00

173 lines
5.0 KiB
Rust

use anyhow::Result;
use cm_dashboard_shared::CacheConfig;
use serde::{Deserialize, Serialize};
use std::path::Path;
pub mod loader;
pub mod validation;
/// Main agent configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentConfig {
pub zmq: ZmqConfig,
pub collectors: CollectorConfig,
pub cache: CacheConfig,
pub notifications: NotificationConfig,
pub collection_interval_seconds: u64,
}
/// ZMQ communication configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ZmqConfig {
pub publisher_port: u16,
pub command_port: u16,
pub bind_address: String,
pub transmission_interval_seconds: u64,
/// Heartbeat transmission interval in seconds for host connectivity detection
#[serde(default = "default_heartbeat_interval_seconds")]
pub heartbeat_interval_seconds: u64,
}
/// Collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CollectorConfig {
pub cpu: CpuConfig,
pub memory: MemoryConfig,
pub disk: DiskConfig,
pub systemd: SystemdConfig,
pub backup: BackupConfig,
pub network: NetworkConfig,
pub nixos: NixOSConfig,
}
/// CPU collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CpuConfig {
pub enabled: bool,
pub interval_seconds: u64,
pub load_warning_threshold: f32,
pub load_critical_threshold: f32,
pub temperature_warning_threshold: f32,
pub temperature_critical_threshold: f32,
}
/// Memory collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryConfig {
pub enabled: bool,
pub interval_seconds: u64,
/// Memory usage warning threshold (percentage)
pub usage_warning_percent: f32,
/// Memory usage critical threshold (percentage)
pub usage_critical_percent: f32,
}
/// Disk collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiskConfig {
pub enabled: bool,
pub interval_seconds: u64,
/// Disk usage warning threshold (percentage)
pub usage_warning_percent: f32,
/// Disk usage critical threshold (percentage)
pub usage_critical_percent: f32,
/// Filesystem configurations (optional - auto-discovery used if empty)
#[serde(default)]
pub filesystems: Vec<FilesystemConfig>,
/// SMART monitoring thresholds
pub temperature_warning_celsius: f32,
pub temperature_critical_celsius: f32,
pub wear_warning_percent: f32,
pub wear_critical_percent: f32,
}
/// Filesystem configuration entry
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FilesystemConfig {
pub name: String,
pub uuid: String,
pub mount_point: String,
pub fs_type: String, // "ext4", "zfs", "xfs", "mergerfs", "btrfs"
pub monitor: bool,
pub storage_type: String, // "single", "raid", "mirror", "mergerfs", "zfs"
}
/// Systemd services collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemdConfig {
pub enabled: bool,
pub interval_seconds: u64,
pub service_name_filters: Vec<String>,
pub excluded_services: Vec<String>,
pub memory_warning_mb: f32,
pub memory_critical_mb: f32,
pub service_directories: std::collections::HashMap<String, Vec<String>>,
pub host_user_mapping: String,
pub nginx_check_interval_seconds: u64,
pub http_timeout_seconds: u64,
pub http_connect_timeout_seconds: u64,
pub nginx_latency_critical_ms: f32,
}
/// NixOS collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NixOSConfig {
pub enabled: bool,
pub interval_seconds: u64,
}
/// Backup collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BackupConfig {
pub enabled: bool,
pub interval_seconds: u64,
pub backup_paths: Vec<String>,
pub max_age_hours: u64,
}
/// Network collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkConfig {
pub enabled: bool,
pub interval_seconds: u64,
}
/// Notification configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NotificationConfig {
pub enabled: bool,
pub smtp_host: String,
pub smtp_port: u16,
pub from_email: String,
pub to_email: String,
pub rate_limit_minutes: u64,
/// Email notification batching interval in seconds (default: 60)
pub aggregation_interval_seconds: u64,
/// List of metric names to exclude from email notifications
#[serde(default)]
pub exclude_email_metrics: Vec<String>,
/// Path to maintenance mode file that suppresses email notifications when present
#[serde(default = "default_maintenance_mode_file")]
pub maintenance_mode_file: String,
}
fn default_heartbeat_interval_seconds() -> u64 {
5
}
fn default_maintenance_mode_file() -> String {
"/tmp/cm-maintenance".to_string()
}
impl AgentConfig {
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
loader::load_config(path)
}
pub fn validate(&self) -> Result<()> {
validation::validate_config(self)
}
}