NAC_Blockchain/ops/nac-monitor/src/config.rs

215 lines
5.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
# 配置管理模块
管理NAC监控系统的配置。
*/
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;
use crate::error::{MonitorError, Result};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
/// 服务器配置
pub server: ServerConfig,
/// 指标收集配置
pub metrics: MetricsConfig,
/// 日志配置
pub logging: LoggingConfig,
/// 告警配置
pub alerting: AlertingConfig,
/// 存储配置
pub storage: StorageConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerConfig {
/// 监听地址
pub bind: String,
/// 监听端口
pub port: u16,
/// 工作线程数
pub workers: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricsConfig {
/// 指标收集间隔(秒)
pub collection_interval: u64,
/// Prometheus端点
pub prometheus_endpoint: String,
/// 自定义指标
pub custom_metrics: Vec<String>,
/// 启用的监控项
pub enabled_monitors: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoggingConfig {
/// 日志级别
pub level: String,
/// 日志输出路径
pub output_path: String,
/// 日志保留天数
pub retention_days: u32,
/// 日志格式
pub format: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AlertingConfig {
/// 告警规则文件
pub rules_file: String,
/// 通知渠道
pub notification_channels: Vec<NotificationChannel>,
/// 告警抑制时间(秒)
pub suppression_duration: u64,
/// 告警升级阈值
pub escalation_threshold: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NotificationChannel {
/// 渠道类型email, webhook, slack等
pub channel_type: String,
/// 渠道配置
pub config: serde_json::Value,
/// 是否启用
pub enabled: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StorageConfig {
/// 存储类型memory, file, database
pub storage_type: String,
/// 存储路径
pub path: String,
/// 数据保留时间(小时)
pub retention_hours: u64,
}
impl Config {
/// 从文件加载配置
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
let content = fs::read_to_string(path)
.map_err(|e| MonitorError::ConfigError(format!("读取配置文件失败: {}", e)))?;
let config: Config = serde_json::from_str(&content)
.map_err(|e| MonitorError::ConfigError(format!("解析配置文件失败: {}", e)))?;
Ok(config)
}
/// 保存配置到文件
pub fn save_to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
let content = serde_json::to_string_pretty(self)?;
fs::write(path, content)
.map_err(|e| MonitorError::ConfigError(format!("保存配置文件失败: {}", e)))?;
Ok(())
}
/// 创建默认配置
pub fn default() -> Self {
Config {
server: ServerConfig {
bind: "0.0.0.0".to_string(),
port: 8080,
workers: 4,
},
metrics: MetricsConfig {
collection_interval: 10,
prometheus_endpoint: "/metrics".to_string(),
custom_metrics: vec![],
enabled_monitors: vec![
"node".to_string(),
"network".to_string(),
"consensus".to_string(),
"transaction".to_string(),
],
},
logging: LoggingConfig {
level: "info".to_string(),
output_path: "./logs".to_string(),
retention_days: 30,
format: "json".to_string(),
},
alerting: AlertingConfig {
rules_file: "./alert_rules.json".to_string(),
notification_channels: vec![],
suppression_duration: 300,
escalation_threshold: 3,
},
storage: StorageConfig {
storage_type: "file".to_string(),
path: "./data".to_string(),
retention_hours: 168, // 7天
},
}
}
/// 验证配置
pub fn validate(&self) -> Result<()> {
if self.server.port == 0 {
return Err(MonitorError::ConfigError("端口号不能为0".to_string()));
}
if self.metrics.collection_interval == 0 {
return Err(MonitorError::ConfigError("指标收集间隔不能为0".to_string()));
}
if self.logging.retention_days == 0 {
return Err(MonitorError::ConfigError("日志保留天数不能为0".to_string()));
}
Ok(())
}
}
/// 监控系统配置(类型别名)
pub type MonitorConfig = Config;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = Config::default();
assert_eq!(config.server.port, 8080);
assert_eq!(config.metrics.collection_interval, 10);
}
#[test]
fn test_config_validation() {
let config = Config::default();
assert!(config.validate().is_ok());
}
#[test]
fn test_invalid_config() {
let mut config = Config::default();
config.server.port = 0;
assert!(config.validate().is_err());
}
}