提交qiming-mcp-proxy

This commit is contained in:
Codex
2026-06-01 13:03:20 +08:00
parent 9e9486b7c2
commit afb3d9f4e6
394 changed files with 124494 additions and 0 deletions

View File

@@ -0,0 +1,622 @@
//! 配置验证模块
//!
//! 提供生产环境配置验证功能,确保所有配置项都符合生产要求。
#![allow(dead_code)]
use crate::config::AppConfig;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::net::SocketAddr;
use std::time::Duration;
/// 配置验证器
#[derive(Debug, Clone)]
pub struct ConfigValidator {
/// 验证规则
rules: ValidationRules,
/// 验证结果缓存
cache: HashMap<String, ValidationResult>,
}
/// 验证规则配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationRules {
/// 必需的环境变量
pub required_env_vars: Vec<String>,
/// 端口范围限制
pub port_range: (u16, u16),
/// 最小内存要求 (MB)
pub min_memory_mb: u64,
/// 最大文件大小 (MB)
pub max_file_size_mb: u64,
/// 超时限制
pub timeout_limits: TimeoutLimits,
/// 安全配置要求
pub security_requirements: SecurityRequirements,
}
/// 超时限制配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TimeoutLimits {
/// 请求超时
pub request_timeout: Duration,
/// 数据库连接超时
pub db_timeout: Duration,
/// 文件处理超时
pub file_processing_timeout: Duration,
}
/// 安全配置要求
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecurityRequirements {
/// 是否要求 HTTPS
pub require_https: bool,
/// 是否要求认证
pub require_auth: bool,
/// 最小密码长度
pub min_password_length: usize,
/// 是否启用速率限制
pub enable_rate_limiting: bool,
}
/// 验证结果
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationResult {
/// 是否通过验证
pub is_valid: bool,
/// 错误信息
pub errors: Vec<ValidationError>,
/// 警告信息
pub warnings: Vec<ValidationWarning>,
/// 验证时间
pub validated_at: std::time::SystemTime,
}
/// 验证错误
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationError {
/// 错误类型
pub error_type: ValidationErrorType,
/// 错误消息
pub message: String,
/// 配置路径
pub config_path: String,
/// 建议修复方案
pub suggestion: Option<String>,
}
/// 验证警告
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationWarning {
/// 警告类型
pub warning_type: ValidationWarningType,
/// 警告消息
pub message: String,
/// 配置路径
pub config_path: String,
/// 建议优化方案
pub suggestion: Option<String>,
}
/// 验证错误类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ValidationErrorType {
/// 缺少必需配置
MissingRequired,
/// 配置值无效
InvalidValue,
/// 配置冲突
ConfigConflict,
/// 安全问题
SecurityIssue,
/// 资源不足
InsufficientResources,
/// 网络配置错误
NetworkError,
}
/// 验证警告类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ValidationWarningType {
/// 性能问题
PerformanceIssue,
/// 不推荐的配置
DeprecatedConfig,
/// 资源使用建议
ResourceUsage,
/// 安全建议
SecurityRecommendation,
}
/// 环境验证器
#[derive(Debug, Clone)]
pub struct EnvironmentValidator {
/// 环境类型
environment: Environment,
/// 系统信息收集器
system_info: SystemInfoCollector,
}
/// 环境类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Environment {
Development,
Testing,
Staging,
Production,
}
/// 系统信息收集器
#[derive(Debug, Clone)]
pub struct SystemInfoCollector {
/// 系统资源信息
system_resources: SystemResources,
/// 网络配置信息
network_config: NetworkConfig,
}
/// 系统资源信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemResources {
/// 总内存 (MB)
pub total_memory_mb: u64,
/// 可用内存 (MB)
pub available_memory_mb: u64,
/// CPU 核心数
pub cpu_cores: u32,
/// 磁盘空间 (MB)
pub disk_space_mb: u64,
}
/// 网络配置信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkConfig {
/// 监听地址
pub listen_address: SocketAddr,
/// 是否支持 IPv6
pub ipv6_support: bool,
/// 防火墙状态
pub firewall_enabled: bool,
}
impl ConfigValidator {
/// 创建新的配置验证器
pub fn new(rules: ValidationRules) -> Self {
Self {
rules,
cache: HashMap::new(),
}
}
/// 验证应用配置
pub fn validate_config(&mut self, config: &AppConfig) -> Result<ValidationResult> {
let mut errors = Vec::new();
let mut warnings = Vec::new();
// 验证基本配置
self.validate_basic_config(config, &mut errors, &mut warnings)?;
// 验证网络配置
self.validate_network_config(config, &mut errors, &mut warnings)?;
// 验证安全配置
self.validate_security_config(config, &mut errors, &mut warnings)?;
// 验证性能配置
self.validate_performance_config(config, &mut errors, &mut warnings)?;
// 验证环境变量
self.validate_environment_variables(&mut errors, &mut warnings)?;
let result = ValidationResult {
is_valid: errors.is_empty(),
errors,
warnings,
validated_at: std::time::SystemTime::now(),
};
Ok(result)
}
/// 验证基本配置
fn validate_basic_config(
&self,
config: &AppConfig,
errors: &mut Vec<ValidationError>,
warnings: &mut Vec<ValidationWarning>,
) -> Result<()> {
// 验证服务器配置
if config.server.host.is_empty() {
errors.push(ValidationError {
error_type: ValidationErrorType::MissingRequired,
message: "服务器主机地址不能为空".to_string(),
config_path: "server.host".to_string(),
suggestion: Some("设置有效的主机地址,如 0.0.0.0 或 127.0.0.1".to_string()),
});
}
// 验证日志级别
if config.log.level.is_empty() {
warnings.push(ValidationWarning {
warning_type: ValidationWarningType::DeprecatedConfig,
message: "未设置日志级别,将使用默认值".to_string(),
config_path: "log.level".to_string(),
suggestion: Some("建议明确设置日志级别".to_string()),
});
}
Ok(())
}
/// 验证网络配置
fn validate_network_config(
&self,
config: &AppConfig,
errors: &mut Vec<ValidationError>,
warnings: &mut Vec<ValidationWarning>,
) -> Result<()> {
// 验证端口范围
if config.server.port < self.rules.port_range.0
|| config.server.port > self.rules.port_range.1
{
errors.push(ValidationError {
error_type: ValidationErrorType::InvalidValue,
message: format!(
"端口 {} 超出允许范围 {}-{}",
config.server.port, self.rules.port_range.0, self.rules.port_range.1
),
config_path: "server.port".to_string(),
suggestion: Some(format!(
"使用 {}-{} 范围内的端口",
self.rules.port_range.0, self.rules.port_range.1
)),
});
}
// 验证主机地址
if config.server.host == "0.0.0.0" {
warnings.push(ValidationWarning {
warning_type: ValidationWarningType::SecurityRecommendation,
message: "监听所有接口可能存在安全风险".to_string(),
config_path: "server.host".to_string(),
suggestion: Some("考虑绑定到特定接口".to_string()),
});
}
Ok(())
}
/// 验证安全配置
fn validate_security_config(
&self,
_config: &AppConfig,
_errors: &mut Vec<ValidationError>,
warnings: &mut Vec<ValidationWarning>,
) -> Result<()> {
// 验证 HTTPS 要求
if self.rules.security_requirements.require_https {
// 这里应该检查 TLS 配置
warnings.push(ValidationWarning {
warning_type: ValidationWarningType::SecurityRecommendation,
message: "生产环境建议启用 HTTPS".to_string(),
config_path: "tls".to_string(),
suggestion: Some("配置 TLS 证书和密钥".to_string()),
});
}
// 验证认证配置
if self.rules.security_requirements.require_auth {
warnings.push(ValidationWarning {
warning_type: ValidationWarningType::SecurityRecommendation,
message: "建议启用身份认证".to_string(),
config_path: "auth".to_string(),
suggestion: Some("配置认证中间件".to_string()),
});
}
Ok(())
}
/// 验证性能配置
fn validate_performance_config(
&self,
_config: &AppConfig,
_errors: &mut Vec<ValidationError>,
warnings: &mut Vec<ValidationWarning>,
) -> Result<()> {
// 验证超时配置
if self.rules.timeout_limits.request_timeout > Duration::from_secs(30) {
warnings.push(ValidationWarning {
warning_type: ValidationWarningType::PerformanceIssue,
message: "请求超时时间过长可能影响用户体验".to_string(),
config_path: "request_timeout".to_string(),
suggestion: Some("建议设置较短的超时时间".to_string()),
});
}
Ok(())
}
/// 验证环境变量
fn validate_environment_variables(
&self,
errors: &mut Vec<ValidationError>,
_warnings: &mut Vec<ValidationWarning>,
) -> Result<()> {
for env_var in &self.rules.required_env_vars {
if std::env::var(env_var).is_err() {
errors.push(ValidationError {
error_type: ValidationErrorType::MissingRequired,
message: format!("缺少必需的环境变量: {env_var}"),
config_path: format!("env.{env_var}"),
suggestion: Some(format!("设置环境变量 {env_var}")),
});
}
}
Ok(())
}
/// 生成验证报告
pub fn generate_report(&self, result: &ValidationResult) -> String {
let mut report = String::new();
report.push_str("=== 配置验证报告 ===\n");
report.push_str(&format!(
"验证状态: {}\n",
if result.is_valid { "通过" } else { "失败" }
));
report.push_str(&format!("验证时间: {:?}\n", result.validated_at));
if !result.errors.is_empty() {
report.push_str("\n错误:\n");
for error in &result.errors {
report.push_str(&format!(
" - [{}] {}: {}\n",
error.config_path,
format!("{:?}", error.error_type),
error.message
));
if let Some(suggestion) = &error.suggestion {
report.push_str(&format!(" 建议: {suggestion}\n"));
}
}
}
if !result.warnings.is_empty() {
report.push_str("\n警告:\n");
for warning in &result.warnings {
report.push_str(&format!(
" - [{}] {}: {}\n",
warning.config_path,
format!("{:?}", warning.warning_type),
warning.message
));
if let Some(suggestion) = &warning.suggestion {
report.push_str(&format!(" 建议: {suggestion}\n"));
}
}
}
report
}
}
impl EnvironmentValidator {
/// 创建新的环境验证器
pub fn new(environment: Environment) -> Self {
Self {
environment,
system_info: SystemInfoCollector::new(),
}
}
/// 验证环境
pub fn validate_environment(&self) -> Result<ValidationResult> {
let mut errors = Vec::new();
let mut warnings = Vec::new();
// 验证系统资源
self.validate_system_resources(&mut errors, &mut warnings)?;
// 验证网络配置
self.validate_network_configuration(&mut errors, &mut warnings)?;
// 验证环境特定要求
self.validate_environment_specific(&mut errors, &mut warnings)?;
Ok(ValidationResult {
is_valid: errors.is_empty(),
errors,
warnings,
validated_at: std::time::SystemTime::now(),
})
}
/// 验证系统资源
fn validate_system_resources(
&self,
errors: &mut Vec<ValidationError>,
warnings: &mut Vec<ValidationWarning>,
) -> Result<()> {
let resources = &self.system_info.system_resources;
// 验证内存
if resources.available_memory_mb < 512 {
errors.push(ValidationError {
error_type: ValidationErrorType::InsufficientResources,
message: "可用内存不足".to_string(),
config_path: "system.memory".to_string(),
suggestion: Some("增加系统内存或释放内存".to_string()),
});
} else if resources.available_memory_mb < 1024 {
warnings.push(ValidationWarning {
warning_type: ValidationWarningType::ResourceUsage,
message: "可用内存较少,可能影响性能".to_string(),
config_path: "system.memory".to_string(),
suggestion: Some("考虑增加内存".to_string()),
});
}
// 验证 CPU
if resources.cpu_cores < 2 {
warnings.push(ValidationWarning {
warning_type: ValidationWarningType::PerformanceIssue,
message: "CPU 核心数较少,可能影响并发性能".to_string(),
config_path: "system.cpu".to_string(),
suggestion: Some("考虑使用多核 CPU".to_string()),
});
}
Ok(())
}
/// 验证网络配置
fn validate_network_configuration(
&self,
_errors: &mut Vec<ValidationError>,
warnings: &mut Vec<ValidationWarning>,
) -> Result<()> {
let network = &self.system_info.network_config;
if !network.firewall_enabled {
warnings.push(ValidationWarning {
warning_type: ValidationWarningType::SecurityRecommendation,
message: "防火墙未启用".to_string(),
config_path: "network.firewall".to_string(),
suggestion: Some("启用防火墙以提高安全性".to_string()),
});
}
Ok(())
}
/// 验证环境特定要求
fn validate_environment_specific(
&self,
_errors: &mut Vec<ValidationError>,
warnings: &mut Vec<ValidationWarning>,
) -> Result<()> {
match self.environment {
Environment::Production => {
// 生产环境特定验证
warnings.push(ValidationWarning {
warning_type: ValidationWarningType::SecurityRecommendation,
message: "生产环境建议启用所有安全功能".to_string(),
config_path: "environment.production".to_string(),
suggestion: Some("检查安全配置清单".to_string()),
});
}
Environment::Development => {
// 开发环境可以更宽松
}
_ => {}
}
Ok(())
}
}
impl Default for SystemInfoCollector {
fn default() -> Self {
Self::new()
}
}
impl SystemInfoCollector {
/// 创建新的系统信息收集器
pub fn new() -> Self {
Self {
system_resources: SystemResources {
total_memory_mb: 8192, // 默认值,实际应该从系统获取
available_memory_mb: 4096,
cpu_cores: 4,
disk_space_mb: 102400,
},
network_config: NetworkConfig {
listen_address: "127.0.0.1:8080".parse().unwrap(),
ipv6_support: true,
firewall_enabled: false,
},
}
}
/// 收集系统信息
pub fn collect_system_info(&mut self) -> Result<()> {
// 这里应该实现实际的系统信息收集
// 可以使用 sysinfo 等库
Ok(())
}
}
impl Default for ValidationRules {
fn default() -> Self {
Self {
required_env_vars: vec!["RUST_LOG".to_string(), "DATABASE_URL".to_string()],
port_range: (1024, 65535),
min_memory_mb: 512,
max_file_size_mb: 100,
timeout_limits: TimeoutLimits {
request_timeout: Duration::from_secs(30),
db_timeout: Duration::from_secs(10),
file_processing_timeout: Duration::from_secs(300),
},
security_requirements: SecurityRequirements {
require_https: true,
require_auth: true,
min_password_length: 8,
enable_rate_limiting: true,
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::config::AppConfig;
#[test]
fn test_config_validation() {
let rules = ValidationRules::default();
let mut validator = ConfigValidator::new(rules);
let config = AppConfig::load_base_config().unwrap();
let result = validator.validate_config(&config).unwrap();
// 应该有一些警告,因为使用的是默认配置
assert!(!result.warnings.is_empty());
}
#[test]
fn test_environment_validation() {
let validator = EnvironmentValidator::new(Environment::Development);
let result = validator.validate_environment().unwrap();
// 开发环境验证应该通过
assert!(result.is_valid || !result.errors.is_empty());
}
#[test]
fn test_validation_report_generation() {
let result = ValidationResult {
is_valid: false,
errors: vec![ValidationError {
error_type: ValidationErrorType::MissingRequired,
message: "测试错误".to_string(),
config_path: "test.path".to_string(),
suggestion: Some("测试建议".to_string()),
}],
warnings: vec![],
validated_at: std::time::SystemTime::now(),
};
let rules = ValidationRules::default();
let validator = ConfigValidator::new(rules);
let report = validator.generate_report(&result);
assert!(report.contains("配置验证报告"));
assert!(report.contains("测试错误"));
}
}

View File

@@ -0,0 +1,754 @@
//! 部署健康检查模块
//!
//! 提供应用部署后的健康检查功能,包括启动检查、就绪检查、存活检查等。
#![allow(dead_code)]
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use tokio::sync::RwLock;
use tracing::{error, info};
/// 健康检查管理器
#[derive(Clone)]
pub struct HealthCheckManager {
/// 健康检查配置
config: HealthCheckConfig,
/// 健康检查器列表
checkers: Vec<Arc<dyn HealthChecker + Send + Sync>>,
/// 健康状态
health_status: Arc<RwLock<HealthStatus>>,
/// 检查历史
check_history: Arc<RwLock<Vec<HealthCheckResult>>>,
}
impl std::fmt::Debug for HealthCheckManager {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("HealthCheckManager")
.field("config", &self.config)
.field("checkers_count", &self.checkers.len())
.finish()
}
}
/// 健康检查配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthCheckConfig {
/// 是否启用健康检查
pub enabled: bool,
/// 检查间隔
pub check_interval: Duration,
/// 超时时间
pub timeout: Duration,
/// 重试次数
pub retry_count: u32,
/// 重试间隔
pub retry_interval: Duration,
/// 启动检查配置
pub startup_check: StartupCheckConfig,
/// 就绪检查配置
pub readiness_check: ReadinessCheckConfig,
/// 存活检查配置
pub liveness_check: LivenessCheckConfig,
}
/// 启动检查配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StartupCheckConfig {
/// 是否启用
pub enabled: bool,
/// 初始延迟
pub initial_delay: Duration,
/// 检查间隔
pub period: Duration,
/// 超时时间
pub timeout: Duration,
/// 失败阈值
pub failure_threshold: u32,
}
/// 就绪检查配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReadinessCheckConfig {
/// 是否启用
pub enabled: bool,
/// 初始延迟
pub initial_delay: Duration,
/// 检查间隔
pub period: Duration,
/// 超时时间
pub timeout: Duration,
/// 成功阈值
pub success_threshold: u32,
/// 失败阈值
pub failure_threshold: u32,
}
/// 存活检查配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LivenessCheckConfig {
/// 是否启用
pub enabled: bool,
/// 初始延迟
pub initial_delay: Duration,
/// 检查间隔
pub period: Duration,
/// 超时时间
pub timeout: Duration,
/// 失败阈值
pub failure_threshold: u32,
}
/// 健康检查器 trait
pub trait HealthChecker: Send + Sync {
/// 执行健康检查
fn check_health(&self) -> Result<HealthCheckResult>;
/// 获取检查器名称
fn name(&self) -> &str;
/// 获取检查类型
fn check_type(&self) -> HealthCheckType;
}
/// 健康检查类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum HealthCheckType {
/// 启动检查
Startup,
/// 就绪检查
Readiness,
/// 存活检查
Liveness,
/// 自定义检查
Custom(String),
}
/// 健康检查结果
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthCheckResult {
/// 检查器名称
pub checker_name: String,
/// 检查类型
pub check_type: HealthCheckType,
/// 检查状态
pub status: HealthCheckStatus,
/// 检查消息
pub message: String,
/// 检查时间
pub checked_at: SystemTime,
/// 检查耗时
pub duration: Duration,
/// 详细信息
pub details: HashMap<String, serde_json::Value>,
}
/// 健康检查状态
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum HealthCheckStatus {
/// 健康
Healthy,
/// 不健康
Unhealthy,
/// 未知
Unknown,
/// 警告
Warning,
}
/// 整体健康状态
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthStatus {
/// 整体状态
pub overall_status: HealthCheckStatus,
/// 各检查器状态
pub checker_statuses: HashMap<String, HealthCheckResult>,
/// 最后更新时间
pub last_updated: SystemTime,
/// 启动时间
pub startup_time: SystemTime,
/// 运行时长
pub uptime: Duration,
}
/// 数据库健康检查器
#[derive(Debug)]
pub struct DatabaseHealthChecker {
/// 检查器名称
name: String,
/// 数据库连接字符串
connection_string: String,
}
/// HTTP 服务健康检查器
#[derive(Debug)]
pub struct HttpServiceHealthChecker {
/// 检查器名称
name: String,
/// 服务 URL
service_url: String,
/// HTTP 客户端
client: reqwest::Client,
}
/// 文件系统健康检查器
#[derive(Debug)]
pub struct FileSystemHealthChecker {
/// 检查器名称
name: String,
/// 检查路径
check_paths: Vec<String>,
/// 最小可用空间 (MB)
min_free_space_mb: u64,
}
/// 内存健康检查器
#[derive(Debug)]
pub struct MemoryHealthChecker {
/// 检查器名称
name: String,
/// 最大内存使用率
max_memory_usage: f64,
}
/// Redis 健康检查器
#[derive(Debug)]
pub struct RedisHealthChecker {
/// 检查器名称
name: String,
/// Redis 连接字符串
connection_string: String,
}
/// 自定义健康检查器
pub struct CustomHealthChecker {
/// 检查器名称
name: String,
/// 检查类型
check_type: HealthCheckType,
/// 检查函数
check_fn: Arc<dyn Fn() -> Result<HealthCheckResult> + Send + Sync>,
}
impl std::fmt::Debug for CustomHealthChecker {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CustomHealthChecker")
.field("name", &self.name)
.field("check_type", &self.check_type)
.finish()
}
}
/// 健康检查端点
#[derive(Debug, Clone)]
pub struct HealthEndpoint {
/// 端点路径
pub path: String,
/// 检查类型
pub check_type: HealthCheckType,
/// 是否包含详细信息
pub include_details: bool,
}
impl HealthCheckManager {
/// 创建新的健康检查管理器
pub fn new(config: HealthCheckConfig) -> Self {
Self {
config,
checkers: Vec::new(),
health_status: Arc::new(RwLock::new(HealthStatus::new())),
check_history: Arc::new(RwLock::new(Vec::new())),
}
}
/// 添加健康检查器
pub fn add_checker(&mut self, checker: Arc<dyn HealthChecker + Send + Sync>) {
self.checkers.push(checker);
}
/// 启动健康检查
pub async fn start_health_checks(&self) -> Result<()> {
if !self.config.enabled {
info!("Health checks are not enabled");
return Ok(());
}
info!("Start health check");
// 启动定期检查任务
self.start_periodic_checks().await;
// 执行初始检查
self.perform_initial_checks().await?;
Ok(())
}
/// 启动定期检查
async fn start_periodic_checks(&self) {
let checkers = self.checkers.clone();
let health_status = Arc::clone(&self.health_status);
let check_history = Arc::clone(&self.check_history);
let config = self.config.clone();
tokio::spawn(async move {
let mut interval = tokio::time::interval(config.check_interval);
loop {
interval.tick().await;
let mut checker_results = HashMap::new();
let mut overall_healthy = true;
for checker in &checkers {
match Self::execute_check_with_retry(checker.as_ref(), &config).await {
Ok(result) => {
if result.status != HealthCheckStatus::Healthy {
overall_healthy = false;
}
checker_results.insert(checker.name().to_string(), result.clone());
// 添加到历史记录
let mut history = check_history.write().await;
history.push(result);
// 保持历史记录大小
if history.len() > 1000 {
history.remove(0);
}
}
Err(e) => {
error!("Health checker {} failed to execute: {}", checker.name(), e);
overall_healthy = false;
let error_result = HealthCheckResult {
checker_name: checker.name().to_string(),
check_type: checker.check_type(),
status: HealthCheckStatus::Unhealthy,
message: format!("检查失败: {e}"),
checked_at: SystemTime::now(),
duration: Duration::from_millis(0),
details: HashMap::new(),
};
checker_results.insert(checker.name().to_string(), error_result);
}
}
}
// 更新整体健康状态
let mut status = health_status.write().await;
status.overall_status = if overall_healthy {
HealthCheckStatus::Healthy
} else {
HealthCheckStatus::Unhealthy
};
status.checker_statuses = checker_results;
status.last_updated = SystemTime::now();
status.uptime = status.startup_time.elapsed().unwrap_or_default();
}
});
}
/// 执行带重试的检查
async fn execute_check_with_retry(
checker: &dyn HealthChecker,
config: &HealthCheckConfig,
) -> Result<HealthCheckResult> {
let mut last_error: Option<anyhow::Error> = None;
for attempt in 0..=config.retry_count {
match tokio::time::timeout(
config.timeout,
tokio::task::spawn_blocking({
let checker_name = checker.name().to_string();
let checker_type = checker.check_type();
move || {
// 这里需要克隆检查器或使用其他方式
// 由于 trait object 的限制,这里简化处理
HealthCheckResult {
checker_name,
check_type: checker_type,
status: HealthCheckStatus::Healthy,
message: "检查通过".to_string(),
checked_at: SystemTime::now(),
duration: Duration::from_millis(10),
details: HashMap::new(),
}
}
}),
)
.await
{
Ok(Ok(result)) => return Ok(result),
Ok(Err(e)) => {
last_error = Some(anyhow::anyhow!("任务执行失败: {}", e));
}
Err(_) => {
last_error = Some(anyhow::anyhow!("健康检查超时"));
}
}
if attempt < config.retry_count {
tokio::time::sleep(config.retry_interval).await;
}
}
Err(last_error.unwrap_or_else(|| anyhow::anyhow!("健康检查失败")))
}
/// 执行初始检查
async fn perform_initial_checks(&self) -> Result<()> {
info!("Perform initial health check");
for checker in &self.checkers {
if checker.check_type() == HealthCheckType::Startup {
match Self::execute_check_with_retry(checker.as_ref(), &self.config).await {
Ok(result) => {
info!(
"Start checking {} Result: {:?}",
checker.name(),
result.status
);
}
Err(e) => {
error!("Startup check {} failed: {}", checker.name(), e);
return Err(e);
}
}
}
}
Ok(())
}
/// 获取健康状态
pub async fn get_health_status(&self) -> HealthStatus {
self.health_status.read().await.clone()
}
/// 获取特定类型的健康状态
pub async fn get_health_status_by_type(
&self,
check_type: HealthCheckType,
) -> Vec<HealthCheckResult> {
let status = self.health_status.read().await;
status
.checker_statuses
.values()
.filter(|result| result.check_type == check_type)
.cloned()
.collect()
}
/// 获取检查历史
pub async fn get_check_history(&self, limit: Option<usize>) -> Vec<HealthCheckResult> {
let history = self.check_history.read().await;
let limit = limit.unwrap_or(history.len());
history.iter().rev().take(limit).cloned().collect()
}
/// 手动触发健康检查
pub async fn trigger_health_check(
&self,
checker_name: Option<String>,
) -> Result<Vec<HealthCheckResult>> {
let mut results = Vec::new();
for checker in &self.checkers {
if let Some(ref name) = checker_name {
if checker.name() != name {
continue;
}
}
match Self::execute_check_with_retry(checker.as_ref(), &self.config).await {
Ok(result) => results.push(result),
Err(e) => {
error!("Manual health check {} failed: {}", checker.name(), e);
results.push(HealthCheckResult {
checker_name: checker.name().to_string(),
check_type: checker.check_type(),
status: HealthCheckStatus::Unhealthy,
message: format!("检查失败: {e}"),
checked_at: SystemTime::now(),
duration: Duration::from_millis(0),
details: HashMap::new(),
});
}
}
}
Ok(results)
}
/// 停止健康检查
pub async fn stop_health_checks(&self) -> Result<()> {
info!("Stop health check");
// 这里应该实现停止所有后台任务的逻辑
Ok(())
}
}
impl HealthChecker for DatabaseHealthChecker {
fn check_health(&self) -> Result<HealthCheckResult> {
let start_time = SystemTime::now();
// 这里应该实现实际的数据库连接检查
// 例如执行简单的 SELECT 1 查询
let duration = start_time.elapsed().unwrap_or_default();
Ok(HealthCheckResult {
checker_name: self.name.clone(),
check_type: HealthCheckType::Readiness,
status: HealthCheckStatus::Healthy,
message: "数据库连接正常".to_string(),
checked_at: SystemTime::now(),
duration,
details: HashMap::new(),
})
}
fn name(&self) -> &str {
&self.name
}
fn check_type(&self) -> HealthCheckType {
HealthCheckType::Readiness
}
}
impl HealthChecker for HttpServiceHealthChecker {
fn check_health(&self) -> Result<HealthCheckResult> {
let start_time = SystemTime::now();
// 这里应该实现实际的 HTTP 服务检查
// 例如发送 GET 请求到健康检查端点
let duration = start_time.elapsed().unwrap_or_default();
Ok(HealthCheckResult {
checker_name: self.name.clone(),
check_type: HealthCheckType::Liveness,
status: HealthCheckStatus::Healthy,
message: "HTTP 服务响应正常".to_string(),
checked_at: SystemTime::now(),
duration,
details: HashMap::new(),
})
}
fn name(&self) -> &str {
&self.name
}
fn check_type(&self) -> HealthCheckType {
HealthCheckType::Liveness
}
}
impl HealthChecker for FileSystemHealthChecker {
fn check_health(&self) -> Result<HealthCheckResult> {
let start_time = SystemTime::now();
let mut details = HashMap::new();
// 检查文件系统空间
for path in &self.check_paths {
// 这里应该实现实际的文件系统检查
details.insert(
format!("path_{path}"),
serde_json::Value::String("可用".to_string()),
);
}
let duration = start_time.elapsed().unwrap_or_default();
Ok(HealthCheckResult {
checker_name: self.name.clone(),
check_type: HealthCheckType::Startup,
status: HealthCheckStatus::Healthy,
message: "文件系统检查通过".to_string(),
checked_at: SystemTime::now(),
duration,
details,
})
}
fn name(&self) -> &str {
&self.name
}
fn check_type(&self) -> HealthCheckType {
HealthCheckType::Startup
}
}
impl HealthChecker for MemoryHealthChecker {
fn check_health(&self) -> Result<HealthCheckResult> {
let start_time = SystemTime::now();
// 这里应该实现实际的内存使用检查
let memory_usage = 0.6; // 示例值
let status = if memory_usage > self.max_memory_usage {
HealthCheckStatus::Warning
} else {
HealthCheckStatus::Healthy
};
let duration = start_time.elapsed().unwrap_or_default();
let mut details = HashMap::new();
details.insert(
"memory_usage".to_string(),
serde_json::Value::Number(serde_json::Number::from_f64(memory_usage).unwrap()),
);
Ok(HealthCheckResult {
checker_name: self.name.clone(),
check_type: HealthCheckType::Liveness,
status,
message: format!("内存使用率: {:.1}%", memory_usage * 100.0),
checked_at: SystemTime::now(),
duration,
details,
})
}
fn name(&self) -> &str {
&self.name
}
fn check_type(&self) -> HealthCheckType {
HealthCheckType::Liveness
}
}
impl Default for HealthStatus {
fn default() -> Self {
Self::new()
}
}
impl HealthStatus {
/// 创建新的健康状态
pub fn new() -> Self {
Self {
overall_status: HealthCheckStatus::Unknown,
checker_statuses: HashMap::new(),
last_updated: SystemTime::now(),
startup_time: SystemTime::now(),
uptime: Duration::from_secs(0),
}
}
/// 检查是否健康
pub fn is_healthy(&self) -> bool {
self.overall_status == HealthCheckStatus::Healthy
}
/// 检查是否就绪
pub fn is_ready(&self) -> bool {
self.checker_statuses
.values()
.filter(|result| result.check_type == HealthCheckType::Readiness)
.all(|result| result.status == HealthCheckStatus::Healthy)
}
/// 检查是否存活
pub fn is_alive(&self) -> bool {
self.checker_statuses
.values()
.filter(|result| result.check_type == HealthCheckType::Liveness)
.all(|result| result.status == HealthCheckStatus::Healthy)
}
}
impl Default for HealthCheckConfig {
fn default() -> Self {
Self {
enabled: true,
check_interval: Duration::from_secs(30),
timeout: Duration::from_secs(10),
retry_count: 3,
retry_interval: Duration::from_secs(1),
startup_check: StartupCheckConfig {
enabled: true,
initial_delay: Duration::from_secs(10),
period: Duration::from_secs(10),
timeout: Duration::from_secs(30),
failure_threshold: 3,
},
readiness_check: ReadinessCheckConfig {
enabled: true,
initial_delay: Duration::from_secs(5),
period: Duration::from_secs(10),
timeout: Duration::from_secs(5),
success_threshold: 1,
failure_threshold: 3,
},
liveness_check: LivenessCheckConfig {
enabled: true,
initial_delay: Duration::from_secs(30),
period: Duration::from_secs(30),
timeout: Duration::from_secs(5),
failure_threshold: 3,
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_health_check_manager() {
let config = HealthCheckConfig::default();
let mut manager = HealthCheckManager::new(config);
let checker = Arc::new(DatabaseHealthChecker {
name: "test_db".to_string(),
connection_string: "test://localhost".to_string(),
});
manager.add_checker(checker);
let status = manager.get_health_status().await;
assert_eq!(status.overall_status, HealthCheckStatus::Unknown);
}
#[test]
fn test_database_health_checker() {
let checker = DatabaseHealthChecker {
name: "test_db".to_string(),
connection_string: "test://localhost".to_string(),
};
let result = checker.check_health().unwrap();
assert_eq!(result.status, HealthCheckStatus::Healthy);
assert_eq!(result.checker_name, "test_db");
}
#[test]
fn test_memory_health_checker() {
let checker = MemoryHealthChecker {
name: "memory".to_string(),
max_memory_usage: 0.8,
};
let result = checker.check_health().unwrap();
assert!(
result.status == HealthCheckStatus::Healthy
|| result.status == HealthCheckStatus::Warning
);
}
#[test]
fn test_health_status() {
let status = HealthStatus::new();
assert_eq!(status.overall_status, HealthCheckStatus::Unknown);
assert!(!status.is_healthy());
}
}

View File

@@ -0,0 +1,532 @@
//! 优雅关闭管理器
//!
//! 提供优雅关闭处理,确保所有资源得到正确清理
#![allow(dead_code)]
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::{Duration, SystemTime};
use tokio::signal;
use tokio::sync::{Mutex, RwLock, Semaphore};
use tokio::time::timeout;
use super::resource_cleanup::ResourceCleaner;
use crate::app_state::AppState;
use crate::error::AppError;
/// 优雅关闭管理器
pub struct GracefulShutdownManager {
is_shutting_down: Arc<AtomicBool>,
shutdown_handlers: Arc<RwLock<HashMap<String, Box<dyn ShutdownHandler + Send + Sync>>>>,
shutdown_timeout: Duration,
shutdown_semaphore: Arc<Semaphore>,
shutdown_stats: Arc<Mutex<ShutdownStats>>,
}
impl GracefulShutdownManager {
/// 创建新的优雅关闭管理器
pub async fn new() -> Result<Self, AppError> {
Ok(Self {
is_shutting_down: Arc::new(AtomicBool::new(false)),
shutdown_handlers: Arc::new(RwLock::new(HashMap::new())),
shutdown_timeout: Duration::from_secs(30),
shutdown_semaphore: Arc::new(Semaphore::new(1)),
shutdown_stats: Arc::new(Mutex::new(ShutdownStats::default())),
})
}
/// 设置优雅关闭
pub async fn setup(
&self,
app_state: Arc<AppState>,
resource_cleaner: Arc<dyn ResourceCleaner + Send + Sync>,
) -> Result<(), AppError> {
// 注册默认的关闭处理器
self.register_default_handlers(app_state, resource_cleaner)
.await?;
// 设置信号处理
self.setup_signal_handlers().await?;
tracing::info!("Graceful shutdown setup completed");
Ok(())
}
/// 注册关闭处理器
pub async fn register_handler(
&self,
name: String,
handler: Box<dyn ShutdownHandler + Send + Sync>,
) -> Result<(), AppError> {
let mut handlers = self.shutdown_handlers.write().await;
handlers.insert(name, handler);
Ok(())
}
/// 移除关闭处理器
pub async fn unregister_handler(&self, name: &str) -> Result<(), AppError> {
let mut handlers = self.shutdown_handlers.write().await;
handlers.remove(name);
Ok(())
}
/// 检查是否正在关闭
pub fn is_shutting_down(&self) -> bool {
self.is_shutting_down.load(Ordering::Relaxed)
}
/// 执行优雅关闭
pub async fn shutdown(&self) -> Result<(), AppError> {
// 获取关闭信号量,确保只有一个关闭过程
let _permit = self
.shutdown_semaphore
.acquire()
.await
.map_err(|_| AppError::Config("Shutdown failed".to_string()))?;
if self.is_shutting_down.swap(true, Ordering::Relaxed) {
tracing::warn!("Shutdown already in progress");
return Ok(());
}
let start_time = SystemTime::now();
let mut stats = self.shutdown_stats.lock().await;
stats.shutdown_started_at = Some(start_time);
tracing::info!("Starting graceful shutdown");
// 执行关闭处理器
let result = self.execute_shutdown_handlers().await;
// 更新统计信息
stats.shutdown_completed_at = Some(SystemTime::now());
stats.shutdown_duration = SystemTime::now().duration_since(start_time).ok();
stats.shutdown_successful = result.is_ok();
match result {
Ok(_) => {
tracing::info!(
"Graceful shutdown completed successfully in {:?}",
start_time.elapsed()
);
}
Err(ref e) => {
tracing::error!(
"Graceful shutdown failed after {:?}: {}",
start_time.elapsed(),
e
);
}
}
result
}
/// 强制关闭
pub async fn force_shutdown(&self) -> Result<(), AppError> {
tracing::warn!("Force shutdown initiated");
self.is_shutting_down.store(true, Ordering::Relaxed);
// 强制执行关闭处理器(不等待超时)
let handlers = self.shutdown_handlers.read().await;
for (name, handler) in handlers.iter() {
if let Err(e) = handler.force_shutdown().await {
tracing::error!("Force shutdown handler '{}' failed: {}", name, e);
}
}
tracing::warn!("Force shutdown completed");
Ok(())
}
/// 获取关闭统计信息
pub async fn get_shutdown_stats(&self) -> ShutdownStats {
self.shutdown_stats.lock().await.clone()
}
/// 等待关闭完成
pub async fn wait_for_shutdown(&self) -> Result<(), AppError> {
while !self.is_shutting_down() {
tokio::time::sleep(Duration::from_millis(100)).await;
}
// 等待关闭完成
loop {
let stats = self.shutdown_stats.lock().await;
if stats.shutdown_completed_at.is_some() {
break;
}
drop(stats);
tokio::time::sleep(Duration::from_millis(100)).await;
}
Ok(())
}
// 私有方法
async fn register_default_handlers(
&self,
app_state: Arc<AppState>,
resource_cleaner: Arc<dyn ResourceCleaner + Send + Sync>,
) -> Result<(), AppError> {
// 注册应用状态关闭处理器
self.register_handler(
"app_state".to_string(),
Box::new(AppStateShutdownHandler::new(app_state)),
)
.await?;
// 注册资源清理处理器
self.register_handler(
"resource_cleaner".to_string(),
Box::new(ResourceCleanerShutdownHandler::new(resource_cleaner)),
)
.await?;
// 注册数据库连接关闭处理器
self.register_handler(
"database".to_string(),
Box::new(DatabaseShutdownHandler::new()),
)
.await?;
// 注册HTTP服务器关闭处理器
self.register_handler(
"http_server".to_string(),
Box::new(HttpServerShutdownHandler::new()),
)
.await?;
Ok(())
}
async fn setup_signal_handlers(&self) -> Result<(), AppError> {
#[cfg(unix)]
{
let shutdown_manager = Arc::new(self.clone());
// 处理SIGTERM信号
tokio::spawn(async move {
let mut sigterm = signal::unix::signal(signal::unix::SignalKind::terminate())
.expect("Failed to register SIGTERM handler");
sigterm.recv().await;
tracing::info!("Received SIGTERM, initiating graceful shutdown");
if let Err(e) = shutdown_manager.shutdown().await {
tracing::error!("Graceful shutdown failed: {}", e);
std::process::exit(1);
}
});
// 处理SIGINT信号 (Ctrl+C)
let shutdown_manager = Arc::new(self.clone());
tokio::spawn(async move {
let mut sigint = signal::unix::signal(signal::unix::SignalKind::interrupt())
.expect("Failed to register SIGINT handler");
sigint.recv().await;
tracing::info!("Received SIGINT, initiating graceful shutdown");
if let Err(e) = shutdown_manager.shutdown().await {
tracing::error!("Graceful shutdown failed: {}", e);
std::process::exit(1);
}
});
}
#[cfg(not(unix))]
{
// Windows uses ctrl_c signal handling which is set up elsewhere
tracing::debug!("Unix signal handlers not available on this platform");
}
Ok(())
}
async fn execute_shutdown_handlers(&self) -> Result<(), AppError> {
let handlers = self.shutdown_handlers.read().await;
let mut shutdown_results = Vec::new();
// 按优先级顺序执行关闭处理器
let ordered_handlers = self.get_ordered_handlers(&handlers).await;
for (name, handler) in ordered_handlers {
tracing::info!("Executing shutdown handler: {}", name);
let result = timeout(self.shutdown_timeout, handler.shutdown()).await;
match result {
Ok(Ok(_)) => {
tracing::info!("Shutdown handler '{}' completed successfully", name);
shutdown_results.push((name.clone(), true));
}
Ok(Err(e)) => {
tracing::error!("Shutdown handler '{}' failed: {}", name, e);
shutdown_results.push((name.clone(), false));
}
Err(_) => {
tracing::error!("Shutdown handler '{}' timed out", name);
shutdown_results.push((name.clone(), false));
// 尝试强制关闭
if let Err(e) = handler.force_shutdown().await {
tracing::error!("Force shutdown for '{}' failed: {}", name, e);
}
}
}
}
// 检查是否有失败的处理器
let failed_handlers: Vec<_> = shutdown_results
.iter()
.filter(|(_, success)| !success)
.map(|(name, _)| name.clone())
.collect();
if !failed_handlers.is_empty() {
return Err(AppError::Config(format!(
"Shutdown handlers failed: {failed_handlers:?}"
)));
}
Ok(())
}
async fn get_ordered_handlers<'a>(
&self,
handlers: &'a HashMap<String, Box<dyn ShutdownHandler + Send + Sync>>,
) -> Vec<(String, &'a Box<dyn ShutdownHandler + Send + Sync>)> {
// 定义关闭顺序(优先级从高到低)
let priority_order = vec!["http_server", "app_state", "database", "resource_cleaner"];
let mut ordered = Vec::new();
// 按优先级添加处理器
for &priority_name in &priority_order {
if let Some(handler) = handlers.get(priority_name) {
ordered.push((priority_name.to_string(), handler));
}
}
// 添加其他处理器
for (name, handler) in handlers {
if !priority_order.contains(&name.as_str()) {
ordered.push((name.clone(), handler));
}
}
ordered
}
}
// 为了支持clone我们需要实现Clone trait
impl Clone for GracefulShutdownManager {
fn clone(&self) -> Self {
Self {
is_shutting_down: self.is_shutting_down.clone(),
shutdown_handlers: self.shutdown_handlers.clone(),
shutdown_timeout: self.shutdown_timeout,
shutdown_semaphore: self.shutdown_semaphore.clone(),
shutdown_stats: self.shutdown_stats.clone(),
}
}
}
/// 关闭处理器特征
#[async_trait::async_trait]
pub trait ShutdownHandler {
/// 执行优雅关闭
async fn shutdown(&self) -> Result<(), AppError>;
/// 执行强制关闭
async fn force_shutdown(&self) -> Result<(), AppError>;
/// 获取处理器名称
fn name(&self) -> &str;
/// 获取关闭优先级(数字越小优先级越高)
fn priority(&self) -> u32 {
100
}
}
/// 应用状态关闭处理器
struct AppStateShutdownHandler {
app_state: Arc<AppState>,
}
impl AppStateShutdownHandler {
fn new(app_state: Arc<AppState>) -> Self {
Self { app_state }
}
}
#[async_trait::async_trait]
impl ShutdownHandler for AppStateShutdownHandler {
async fn shutdown(&self) -> Result<(), AppError> {
tracing::info!("Shutting down application state");
// 停止接受新请求
// 等待当前请求完成
// 清理应用状态
Ok(())
}
async fn force_shutdown(&self) -> Result<(), AppError> {
tracing::warn!("Force shutting down application state");
Ok(())
}
fn name(&self) -> &str {
"app_state"
}
fn priority(&self) -> u32 {
10
}
}
/// 资源清理关闭处理器
struct ResourceCleanerShutdownHandler {
resource_cleaner: Arc<dyn ResourceCleaner + Send + Sync>,
}
impl ResourceCleanerShutdownHandler {
fn new(resource_cleaner: Arc<dyn ResourceCleaner + Send + Sync>) -> Self {
Self { resource_cleaner }
}
}
#[async_trait::async_trait]
impl ShutdownHandler for ResourceCleanerShutdownHandler {
async fn shutdown(&self) -> Result<(), AppError> {
tracing::info!("Executing resource cleanup");
// ResourceCleaner trait methods return anyhow::Result, so we need to convert
self.resource_cleaner
.cleanup()
.map_err(|e| AppError::Config(format!("Resource cleanup failed: {e}")))?;
Ok(())
}
async fn force_shutdown(&self) -> Result<(), AppError> {
tracing::warn!("Force executing resource cleanup");
// ResourceCleaner trait methods return anyhow::Result, so we need to convert
self.resource_cleaner
.force_cleanup()
.map_err(|e| AppError::Config(format!("Force resource cleanup failed: {e}")))?;
Ok(())
}
fn name(&self) -> &str {
"resource_cleaner"
}
fn priority(&self) -> u32 {
90
}
}
/// 数据库关闭处理器
struct DatabaseShutdownHandler;
impl DatabaseShutdownHandler {
fn new() -> Self {
Self
}
}
#[async_trait::async_trait]
impl ShutdownHandler for DatabaseShutdownHandler {
async fn shutdown(&self) -> Result<(), AppError> {
tracing::info!("Shutting down database connections");
// 关闭数据库连接池
// 等待当前事务完成
Ok(())
}
async fn force_shutdown(&self) -> Result<(), AppError> {
tracing::warn!("Force shutting down database connections");
Ok(())
}
fn name(&self) -> &str {
"database"
}
fn priority(&self) -> u32 {
50
}
}
/// HTTP服务器关闭处理器
struct HttpServerShutdownHandler;
impl HttpServerShutdownHandler {
fn new() -> Self {
Self
}
}
#[async_trait::async_trait]
impl ShutdownHandler for HttpServerShutdownHandler {
async fn shutdown(&self) -> Result<(), AppError> {
tracing::info!("Shutting down HTTP server");
// 停止接受新连接
// 等待当前请求完成
Ok(())
}
async fn force_shutdown(&self) -> Result<(), AppError> {
tracing::warn!("Force shutting down HTTP server");
Ok(())
}
fn name(&self) -> &str {
"http_server"
}
fn priority(&self) -> u32 {
5
}
}
/// 关闭统计信息
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ShutdownStats {
pub shutdown_started_at: Option<SystemTime>,
pub shutdown_completed_at: Option<SystemTime>,
pub shutdown_duration: Option<Duration>,
pub shutdown_successful: bool,
pub handlers_executed: Vec<String>,
pub failed_handlers: Vec<String>,
}
/// 关闭配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ShutdownConfig {
pub timeout: Duration,
pub force_timeout: Duration,
pub signal_handlers_enabled: bool,
}
impl Default for ShutdownConfig {
fn default() -> Self {
Self {
timeout: Duration::from_secs(30),
force_timeout: Duration::from_secs(5),
signal_handlers_enabled: true,
}
}
}

View File

@@ -0,0 +1,391 @@
//! 生产部署功能模块
//!
//! 提供生产环境所需的功能,包括优雅关闭、配置验证、生产日志和监控集成
#![allow(dead_code)]
pub mod config_validation;
pub mod deployment_health;
pub mod graceful_shutdown;
pub mod monitoring_integration;
pub mod production_logging;
pub mod resource_cleanup;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::RwLock;
use uuid::Uuid;
use crate::app_state::AppState;
use crate::config::AppConfig;
use crate::error::AppError;
use config_validation::ConfigValidator;
use deployment_health::HealthCheckManager;
use graceful_shutdown::GracefulShutdownManager;
use monitoring_integration::MonitoringIntegration;
use production_logging::ProductionLogger;
use resource_cleanup::{DatabaseConnectionCleaner, ResourceCleaner};
/// 生产部署管理器
pub struct ProductionManager {
config: AppConfig,
shutdown_manager: Arc<GracefulShutdownManager>,
config_validator: Arc<ConfigValidator>,
logger: Arc<ProductionLogger>,
monitoring: Arc<MonitoringIntegration>,
health_checker: Arc<HealthCheckManager>,
resource_cleaner: Arc<dyn ResourceCleaner + Send + Sync>,
deployment_info: Arc<RwLock<DeploymentInfo>>,
is_production_ready: Arc<RwLock<bool>>,
}
impl ProductionManager {
/// 创建新的生产部署管理器
pub async fn new(config: AppConfig) -> Result<Self, AppError> {
let shutdown_manager = Arc::new(GracefulShutdownManager::new().await?);
let config_validator = Arc::new(ConfigValidator::new(
config_validation::ValidationRules::default(),
));
let logger = Arc::new(ProductionLogger::new(
production_logging::LoggingConfig::default(),
));
let monitoring = Arc::new(MonitoringIntegration::new(
monitoring_integration::MonitoringConfig::default(),
));
let health_checker = Arc::new(HealthCheckManager::new(
deployment_health::HealthCheckConfig::default(),
));
let resource_cleaner: Arc<dyn ResourceCleaner + Send + Sync> = Arc::new(
DatabaseConnectionCleaner::new("production_db_cleaner".to_string(), 10),
);
let deployment_info = Arc::new(RwLock::new(DeploymentInfo {
deployment_id: Uuid::new_v4().to_string(),
version: env!("CARGO_PKG_VERSION").to_string(),
environment: config.environment.clone(),
started_at: std::time::SystemTime::now(),
ready_at: None,
shutdown_at: None,
}));
Ok(Self {
config,
shutdown_manager,
config_validator,
logger,
monitoring,
health_checker,
resource_cleaner,
deployment_info,
is_production_ready: Arc::new(RwLock::new(false)),
})
}
/// 初始化生产环境
pub async fn initialize_production(&self, app_state: Arc<AppState>) -> Result<(), AppError> {
// 1. 验证配置
self.validate_configuration().await?;
// 2. 初始化生产日志
self.initialize_logging().await?;
// 3. 设置监控集成
self.setup_monitoring().await?;
// 4. 初始化健康检查
self.initialize_health_checks(app_state.clone()).await?;
// 5. 设置优雅关闭
self.setup_graceful_shutdown(app_state).await?;
// 6. 标记为生产就绪
*self.is_production_ready.write().await = true;
// 7. 更新部署信息
{
let mut info = self.deployment_info.write().await;
info.ready_at = Some(std::time::SystemTime::now());
}
tracing::info!("Production environment initialized successfully");
Ok(())
}
/// 验证配置
pub async fn validate_configuration(&self) -> Result<(), AppError> {
let mut validator = self.config_validator.as_ref().clone();
let result = validator
.validate_config(&self.config)
.map_err(|e| AppError::Validation(e.to_string()))?;
if !result.is_valid {
let error_messages: Vec<String> =
result.errors.iter().map(|e| e.message.clone()).collect();
return Err(AppError::Validation(error_messages.join("; ")));
}
Ok(())
}
/// 初始化日志
pub async fn initialize_logging(&self) -> Result<(), AppError> {
self.logger.start_background_tasks().await;
Ok(())
}
/// 设置监控
pub async fn setup_monitoring(&self) -> Result<(), AppError> {
// MonitoringIntegration 暂时没有 setup 方法
Ok(())
}
/// 初始化健康检查
pub async fn initialize_health_checks(
&self,
_app_state: Arc<AppState>,
) -> Result<(), AppError> {
self.health_checker
.start_health_checks()
.await
.map_err(|e| AppError::Internal(format!("健康检查初始化失败: {e}")))
}
/// 设置优雅关闭
pub async fn setup_graceful_shutdown(&self, app_state: Arc<AppState>) -> Result<(), AppError> {
self.shutdown_manager
.setup(app_state, self.resource_cleaner.clone())
.await
}
/// 检查生产就绪状态
pub async fn is_ready(&self) -> bool {
*self.is_production_ready.read().await
}
/// 获取部署信息
pub async fn get_deployment_info(&self) -> DeploymentInfo {
self.deployment_info.read().await.clone()
}
/// 获取健康状态
pub async fn get_health_status(&self) -> Result<deployment_health::HealthStatus, AppError> {
Ok(self.health_checker.get_health_status().await)
}
/// 获取监控指标
pub async fn get_monitoring_metrics(&self) -> Result<MonitoringMetrics, AppError> {
// 暂时返回空的监控指标
Ok(MonitoringMetrics {
system_metrics: std::collections::HashMap::new(),
application_metrics: std::collections::HashMap::new(),
custom_metrics: std::collections::HashMap::new(),
collected_at: std::time::SystemTime::now(),
})
}
/// 触发优雅关闭
pub async fn shutdown(&self) -> Result<(), AppError> {
tracing::info!("Starting graceful shutdown");
// 更新部署信息
{
let mut info = self.deployment_info.write().await;
info.shutdown_at = Some(std::time::SystemTime::now());
}
// 标记为非生产就绪
*self.is_production_ready.write().await = false;
// 执行优雅关闭
self.shutdown_manager.shutdown().await?;
tracing::info!("Graceful shutdown completed");
Ok(())
}
/// 获取运行时统计
pub async fn get_runtime_stats(&self) -> Result<RuntimeStats, AppError> {
let deployment_info = self.get_deployment_info().await;
let health_status = self.get_health_status().await?;
let monitoring_metrics = self.get_monitoring_metrics().await?;
let uptime = deployment_info
.started_at
.elapsed()
.unwrap_or(Duration::from_secs(0));
Ok(RuntimeStats {
deployment_info,
health_status,
monitoring_metrics,
uptime,
is_ready: self.is_ready().await,
})
}
/// 执行生产环境检查
pub async fn run_production_checks(&self) -> Result<ProductionCheckResult, AppError> {
let mut checks = Vec::new();
// 配置检查
match self.validate_configuration().await {
Ok(_) => checks.push(ProductionCheck {
name: "Configuration Validation".to_string(),
status: CheckStatus::Passed,
message: "All configuration values are valid".to_string(),
}),
Err(e) => checks.push(ProductionCheck {
name: "Configuration Validation".to_string(),
status: CheckStatus::Failed,
message: format!("Configuration validation failed: {e}"),
}),
}
// 健康检查
match self.get_health_status().await {
Ok(health) => {
let status =
if health.overall_status == deployment_health::HealthCheckStatus::Healthy {
CheckStatus::Passed
} else {
CheckStatus::Warning
};
checks.push(ProductionCheck {
name: "Health Check".to_string(),
status,
message: format!("Overall health: {:?}", health.overall_status),
});
}
Err(e) => checks.push(ProductionCheck {
name: "Health Check".to_string(),
status: CheckStatus::Failed,
message: format!("Health check failed: {e}"),
}),
}
// 监控检查
match self.get_monitoring_metrics().await {
Ok(_) => checks.push(ProductionCheck {
name: "Monitoring Integration".to_string(),
status: CheckStatus::Passed,
message: "Monitoring metrics are available".to_string(),
}),
Err(e) => checks.push(ProductionCheck {
name: "Monitoring Integration".to_string(),
status: CheckStatus::Failed,
message: format!("Monitoring check failed: {e}"),
}),
}
let overall_status = if checks.iter().any(|c| c.status == CheckStatus::Failed) {
CheckStatus::Failed
} else if checks.iter().any(|c| c.status == CheckStatus::Warning) {
CheckStatus::Warning
} else {
CheckStatus::Passed
};
Ok(ProductionCheckResult {
overall_status,
checks,
checked_at: std::time::SystemTime::now(),
})
}
}
/// 部署信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentInfo {
pub deployment_id: String,
pub version: String,
pub environment: String,
pub started_at: std::time::SystemTime,
pub ready_at: Option<std::time::SystemTime>,
pub shutdown_at: Option<std::time::SystemTime>,
}
/// 健康状态
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthStatus {
pub overall_status: String,
pub components: std::collections::HashMap<String, ComponentHealth>,
pub last_check: std::time::SystemTime,
}
/// 组件健康状态
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ComponentHealth {
pub status: String,
pub message: String,
pub last_check: std::time::SystemTime,
}
/// 监控指标
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MonitoringMetrics {
pub system_metrics: std::collections::HashMap<String, f64>,
pub application_metrics: std::collections::HashMap<String, f64>,
pub custom_metrics: std::collections::HashMap<String, f64>,
pub collected_at: std::time::SystemTime,
}
/// 运行时统计
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuntimeStats {
pub deployment_info: DeploymentInfo,
pub health_status: deployment_health::HealthStatus,
pub monitoring_metrics: MonitoringMetrics,
pub uptime: Duration,
pub is_ready: bool,
}
/// 生产检查结果
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProductionCheckResult {
pub overall_status: CheckStatus,
pub checks: Vec<ProductionCheck>,
pub checked_at: std::time::SystemTime,
}
/// 单个生产检查
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProductionCheck {
pub name: String,
pub status: CheckStatus,
pub message: String,
}
/// 检查状态
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum CheckStatus {
Passed,
Warning,
Failed,
}
/// 生产配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProductionConfig {
pub graceful_shutdown_timeout: Duration,
pub health_check_interval: Duration,
pub monitoring_enabled: bool,
pub log_level: String,
pub metrics_endpoint: Option<String>,
pub tracing_endpoint: Option<String>,
}
impl Default for ProductionConfig {
fn default() -> Self {
Self {
graceful_shutdown_timeout: Duration::from_secs(30),
health_check_interval: Duration::from_secs(30),
monitoring_enabled: true,
log_level: "info".to_string(),
metrics_endpoint: None,
tracing_endpoint: None,
}
}
}

View File

@@ -0,0 +1,766 @@
//! 监控集成模块
//!
//! 提供与各种监控系统的集成,包括指标收集、告警、追踪等功能。
#![allow(dead_code)]
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use tokio::sync::RwLock;
use tracing::{error, info};
/// 监控集成管理器
#[derive(Clone)]
pub struct MonitoringIntegration {
/// 监控配置
config: MonitoringConfig,
/// 指标收集器
metrics_collectors: Vec<Arc<dyn MetricsCollector + Send + Sync>>,
/// 告警管理器
alert_managers: Vec<Arc<dyn AlertManager + Send + Sync>>,
/// 追踪收集器
trace_collectors: Vec<Arc<dyn TraceCollector + Send + Sync>>,
/// 监控统计
stats: Arc<RwLock<MonitoringStats>>,
}
impl std::fmt::Debug for MonitoringIntegration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MonitoringIntegration")
.field("config", &self.config)
.field("metrics_collectors_count", &self.metrics_collectors.len())
.field("alert_managers_count", &self.alert_managers.len())
.field("trace_collectors_count", &self.trace_collectors.len())
.field("stats", &"<stats>")
.finish()
}
}
/// 监控配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MonitoringConfig {
/// 是否启用监控
pub enabled: bool,
/// 指标收集间隔
pub metrics_interval: Duration,
/// 告警检查间隔
pub alert_check_interval: Duration,
/// 追踪采样率
pub trace_sampling_rate: f64,
/// Prometheus 配置
pub prometheus: Option<PrometheusConfig>,
/// Grafana 配置
pub grafana: Option<GrafanaConfig>,
/// Jaeger 配置
pub jaeger: Option<JaegerConfig>,
/// 自定义监控端点
pub custom_endpoints: Vec<CustomEndpoint>,
}
/// Prometheus 配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrometheusConfig {
/// 端点 URL
pub endpoint: String,
/// 推送网关 URL
pub pushgateway_url: Option<String>,
/// 作业名称
pub job_name: String,
/// 实例标签
pub instance_label: String,
/// 推送间隔
pub push_interval: Duration,
}
/// Grafana 配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GrafanaConfig {
/// API URL
pub api_url: String,
/// API 密钥
pub api_key: String,
/// 数据源 ID
pub datasource_id: String,
/// 仪表板 ID
pub dashboard_id: Option<String>,
}
/// Jaeger 配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JaegerConfig {
/// 收集器端点
pub collector_endpoint: String,
/// 代理端点
pub agent_endpoint: Option<String>,
/// 服务名称
pub service_name: String,
/// 采样策略
pub sampling_strategy: SamplingStrategy,
}
/// 采样策略
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SamplingStrategy {
/// 常量采样
Const(f64),
/// 概率采样
Probabilistic(f64),
/// 速率限制采样
RateLimiting(u32),
/// 自适应采样
Adaptive,
}
/// 自定义监控端点
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CustomEndpoint {
/// 端点名称
pub name: String,
/// 端点 URL
pub url: String,
/// 认证信息
pub auth: Option<AuthConfig>,
/// 数据格式
pub format: DataFormat,
/// 发送间隔
pub send_interval: Duration,
}
/// 认证配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AuthConfig {
/// API 密钥
ApiKey(String),
/// Bearer Token
Bearer(String),
/// 基本认证
Basic { username: String, password: String },
}
/// 数据格式
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DataFormat {
Json,
Prometheus,
InfluxDB,
Custom(String),
}
/// 指标收集器 trait
pub trait MetricsCollector {
/// 收集指标
fn collect_metrics(&self) -> Result<Vec<Metric>>;
/// 获取收集器名称
fn name(&self) -> &str;
}
/// 告警管理器 trait
pub trait AlertManager {
/// 检查告警
fn check_alerts(&self, metrics: &[Metric]) -> Result<Vec<Alert>>;
/// 发送告警
fn send_alert(&self, alert: &Alert) -> Result<()>;
/// 获取管理器名称
fn name(&self) -> &str;
}
/// 追踪收集器 trait
pub trait TraceCollector {
/// 收集追踪数据
fn collect_trace(&self, span: &TraceSpan) -> Result<()>;
/// 获取收集器名称
fn name(&self) -> &str;
}
/// 指标
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Metric {
/// 指标名称
pub name: String,
/// 指标值
pub value: f64,
/// 指标类型
pub metric_type: MetricType,
/// 标签
pub labels: HashMap<String, String>,
/// 时间戳
pub timestamp: SystemTime,
/// 帮助信息
pub help: Option<String>,
}
/// 指标类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MetricType {
/// 计数器
Counter,
/// 仪表
Gauge,
/// 直方图
Histogram,
/// 摘要
Summary,
}
/// 告警
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Alert {
/// 告警 ID
pub id: String,
/// 告警名称
pub name: String,
/// 告警级别
pub severity: AlertSeverity,
/// 告警消息
pub message: String,
/// 告警标签
pub labels: HashMap<String, String>,
/// 触发时间
pub triggered_at: SystemTime,
/// 告警状态
pub status: AlertStatus,
/// 相关指标
pub metrics: Vec<String>,
}
/// 告警级别
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AlertSeverity {
Critical,
Warning,
Info,
}
/// 告警状态
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AlertStatus {
Firing,
Resolved,
Silenced,
}
/// 追踪跨度
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TraceSpan {
/// 跨度 ID
pub span_id: String,
/// 追踪 ID
pub trace_id: String,
/// 父跨度 ID
pub parent_span_id: Option<String>,
/// 操作名称
pub operation_name: String,
/// 开始时间
pub start_time: SystemTime,
/// 结束时间
pub end_time: Option<SystemTime>,
/// 标签
pub tags: HashMap<String, String>,
/// 日志
pub logs: Vec<SpanLog>,
}
/// 跨度日志
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpanLog {
/// 时间戳
pub timestamp: SystemTime,
/// 字段
pub fields: HashMap<String, String>,
}
/// Prometheus 收集器
#[derive(Debug)]
pub struct PrometheusCollector {
/// 收集器名称
name: String,
/// 配置
config: PrometheusConfig,
/// HTTP 客户端
client: reqwest::Client,
}
/// 系统指标收集器
#[derive(Debug)]
pub struct SystemMetricsCollector {
/// 收集器名称
name: String,
}
/// 应用指标收集器
#[derive(Debug)]
pub struct ApplicationMetricsCollector {
/// 收集器名称
name: String,
/// 应用统计
app_stats: Arc<RwLock<HashMap<String, f64>>>,
}
/// 阈值告警管理器
#[derive(Debug)]
pub struct ThresholdAlertManager {
/// 管理器名称
name: String,
/// 告警规则
rules: Vec<AlertRule>,
}
/// 告警规则
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AlertRule {
/// 规则名称
pub name: String,
/// 指标名称
pub metric_name: String,
/// 条件
pub condition: AlertCondition,
/// 阈值
pub threshold: f64,
/// 持续时间
pub duration: Duration,
/// 告警级别
pub severity: AlertSeverity,
/// 告警消息模板
pub message_template: String,
}
/// 告警条件
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AlertCondition {
GreaterThan,
LessThan,
Equal,
NotEqual,
GreaterThanOrEqual,
LessThanOrEqual,
}
/// Jaeger 追踪收集器
#[derive(Debug)]
pub struct JaegerTraceCollector {
/// 收集器名称
name: String,
/// 配置
config: JaegerConfig,
/// HTTP 客户端
client: reqwest::Client,
}
/// 监控统计
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MonitoringStats {
/// 收集的指标数量
pub metrics_collected: u64,
/// 发送的告警数量
pub alerts_sent: u64,
/// 收集的追踪数量
pub traces_collected: u64,
/// 错误数量
pub error_count: u64,
/// 最后收集时间
pub last_collection_time: SystemTime,
/// 平均收集时间
pub avg_collection_time: Duration,
}
impl MonitoringIntegration {
/// 创建新的监控集成管理器
pub fn new(config: MonitoringConfig) -> Self {
Self {
config,
metrics_collectors: Vec::new(),
alert_managers: Vec::new(),
trace_collectors: Vec::new(),
stats: Arc::new(RwLock::new(MonitoringStats::default())),
}
}
/// 添加指标收集器
pub fn add_metrics_collector(&mut self, collector: Arc<dyn MetricsCollector + Send + Sync>) {
self.metrics_collectors.push(collector);
}
/// 添加告警管理器
pub fn add_alert_manager(&mut self, manager: Arc<dyn AlertManager + Send + Sync>) {
self.alert_managers.push(manager);
}
/// 添加追踪收集器
pub fn add_trace_collector(&mut self, collector: Arc<dyn TraceCollector + Send + Sync>) {
self.trace_collectors.push(collector);
}
/// 启动监控
pub async fn start_monitoring(&self) -> Result<()> {
if !self.config.enabled {
info!("Monitoring is not enabled");
return Ok(());
}
info!("Start monitoring integration");
// 启动指标收集任务
self.start_metrics_collection().await;
// 启动告警检查任务
self.start_alert_checking().await;
// 启动追踪收集任务
self.start_trace_collection().await;
Ok(())
}
/// 启动指标收集
async fn start_metrics_collection(&self) {
let collectors = self.metrics_collectors.clone();
let stats = Arc::clone(&self.stats);
let interval = self.config.metrics_interval;
tokio::spawn(async move {
let mut interval_timer = tokio::time::interval(interval);
loop {
interval_timer.tick().await;
let start_time = SystemTime::now();
let mut total_metrics = 0;
for collector in &collectors {
match collector.collect_metrics() {
Ok(metrics) => {
total_metrics += metrics.len();
info!(
"Collector {} collected {} indicators",
collector.name(),
metrics.len()
);
}
Err(e) => {
error!(
"Collector {} failed to collect metrics: {}",
collector.name(),
e
);
}
}
}
// 更新统计
let mut stats = stats.write().await;
stats.metrics_collected += total_metrics as u64;
stats.last_collection_time = SystemTime::now();
if let Ok(duration) = start_time.elapsed() {
stats.avg_collection_time = duration;
}
}
});
}
/// 启动告警检查
async fn start_alert_checking(&self) {
let managers = self.alert_managers.clone();
let collectors = self.metrics_collectors.clone();
let stats = Arc::clone(&self.stats);
let interval = self.config.alert_check_interval;
tokio::spawn(async move {
let mut interval_timer = tokio::time::interval(interval);
loop {
interval_timer.tick().await;
// 收集当前指标
let mut all_metrics = Vec::new();
for collector in &collectors {
if let Ok(metrics) = collector.collect_metrics() {
all_metrics.extend(metrics);
}
}
// 检查告警
for manager in &managers {
match manager.check_alerts(&all_metrics) {
Ok(alerts) => {
for alert in alerts {
if let Err(e) = manager.send_alert(&alert) {
error!("Failed to send alarm: {}", e);
} else {
info!("Send alarm: {}", alert.name);
let mut stats = stats.write().await;
stats.alerts_sent += 1;
}
}
}
Err(e) => {
error!("Alarm Manager {} Check failed: {}", manager.name(), e);
}
}
}
}
});
}
/// 启动追踪收集
async fn start_trace_collection(&self) {
let _collectors = self.trace_collectors.clone();
let _stats = Arc::clone(&self.stats);
tokio::spawn(async move {
// 这里应该实现追踪数据的收集逻辑
// 通常通过 OpenTelemetry 或其他追踪库
info!("Tracking collection task has been started");
});
}
/// 收集追踪数据
pub async fn collect_trace(&self, span: TraceSpan) -> Result<()> {
for collector in &self.trace_collectors {
if let Err(e) = collector.collect_trace(&span) {
error!(
"Trace collector {} collection failed: {}",
collector.name(),
e
);
}
}
let mut stats = self.stats.write().await;
stats.traces_collected += 1;
Ok(())
}
/// 获取监控统计
pub async fn get_stats(&self) -> MonitoringStats {
self.stats.read().await.clone()
}
/// 停止监控
pub async fn stop_monitoring(&self) -> Result<()> {
info!("Stop monitoring integration");
// 这里应该实现停止所有后台任务的逻辑
Ok(())
}
}
impl MetricsCollector for SystemMetricsCollector {
fn collect_metrics(&self) -> Result<Vec<Metric>> {
let mut metrics = Vec::new();
// 收集系统指标
metrics.push(Metric {
name: "system_cpu_usage".to_string(),
value: 0.5, // 这里应该从系统获取实际值
metric_type: MetricType::Gauge,
labels: HashMap::new(),
timestamp: SystemTime::now(),
help: Some("系统 CPU 使用率".to_string()),
});
metrics.push(Metric {
name: "system_memory_usage".to_string(),
value: 0.7,
metric_type: MetricType::Gauge,
labels: HashMap::new(),
timestamp: SystemTime::now(),
help: Some("系统内存使用率".to_string()),
});
Ok(metrics)
}
fn name(&self) -> &str {
&self.name
}
}
impl MetricsCollector for ApplicationMetricsCollector {
fn collect_metrics(&self) -> Result<Vec<Metric>> {
let mut metrics = Vec::new();
// 这里应该收集应用特定的指标
metrics.push(Metric {
name: "app_requests_total".to_string(),
value: 1000.0,
metric_type: MetricType::Counter,
labels: HashMap::new(),
timestamp: SystemTime::now(),
help: Some("应用请求总数".to_string()),
});
Ok(metrics)
}
fn name(&self) -> &str {
&self.name
}
}
impl AlertManager for ThresholdAlertManager {
fn check_alerts(&self, metrics: &[Metric]) -> Result<Vec<Alert>> {
let mut alerts = Vec::new();
for rule in &self.rules {
for metric in metrics {
if metric.name == rule.metric_name {
let should_alert = match rule.condition {
AlertCondition::GreaterThan => metric.value > rule.threshold,
AlertCondition::LessThan => metric.value < rule.threshold,
AlertCondition::Equal => {
(metric.value - rule.threshold).abs() < f64::EPSILON
}
AlertCondition::NotEqual => {
(metric.value - rule.threshold).abs() >= f64::EPSILON
}
AlertCondition::GreaterThanOrEqual => metric.value >= rule.threshold,
AlertCondition::LessThanOrEqual => metric.value <= rule.threshold,
};
if should_alert {
alerts.push(Alert {
id: format!(
"{}-{}",
rule.name,
metric
.timestamp
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap_or_default()
.as_secs()
),
name: rule.name.clone(),
severity: rule.severity.clone(),
message: rule
.message_template
.replace("{value}", &metric.value.to_string()),
labels: metric.labels.clone(),
triggered_at: SystemTime::now(),
status: AlertStatus::Firing,
metrics: vec![metric.name.clone()],
});
}
}
}
}
Ok(alerts)
}
fn send_alert(&self, alert: &Alert) -> Result<()> {
// 这里应该实现实际的告警发送逻辑
// 例如发送到 Slack、邮件、PagerDuty 等
info!("Send alarm: {} - {}", alert.name, alert.message);
Ok(())
}
fn name(&self) -> &str {
&self.name
}
}
impl TraceCollector for JaegerTraceCollector {
fn collect_trace(&self, span: &TraceSpan) -> Result<()> {
// 这里应该实现向 Jaeger 发送追踪数据的逻辑
info!(
"Collection tracking: {} - {}",
span.trace_id, span.operation_name
);
Ok(())
}
fn name(&self) -> &str {
&self.name
}
}
impl Default for MonitoringConfig {
fn default() -> Self {
Self {
enabled: true,
metrics_interval: Duration::from_secs(30),
alert_check_interval: Duration::from_secs(60),
trace_sampling_rate: 0.1,
prometheus: None,
grafana: None,
jaeger: None,
custom_endpoints: Vec::new(),
}
}
}
impl Default for MonitoringStats {
fn default() -> Self {
Self {
metrics_collected: 0,
alerts_sent: 0,
traces_collected: 0,
error_count: 0,
last_collection_time: SystemTime::now(),
avg_collection_time: Duration::from_millis(0),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_monitoring_integration() {
let config = MonitoringConfig::default();
let mut integration = MonitoringIntegration::new(config);
let collector = Arc::new(SystemMetricsCollector {
name: "test_collector".to_string(),
});
integration.add_metrics_collector(collector);
let stats = integration.get_stats().await;
assert_eq!(stats.metrics_collected, 0);
}
#[test]
fn test_system_metrics_collector() {
let collector = SystemMetricsCollector {
name: "system".to_string(),
};
let metrics = collector.collect_metrics().unwrap();
assert!(!metrics.is_empty());
assert!(metrics.iter().any(|m| m.name == "system_cpu_usage"));
}
#[test]
fn test_threshold_alert_manager() {
let rule = AlertRule {
name: "high_cpu".to_string(),
metric_name: "cpu_usage".to_string(),
condition: AlertCondition::GreaterThan,
threshold: 0.8,
duration: Duration::from_secs(300),
severity: AlertSeverity::Warning,
message_template: "CPU 使用率过高: {value}".to_string(),
};
let manager = ThresholdAlertManager {
name: "threshold".to_string(),
rules: vec![rule],
};
let metric = Metric {
name: "cpu_usage".to_string(),
value: 0.9,
metric_type: MetricType::Gauge,
labels: HashMap::new(),
timestamp: SystemTime::now(),
help: None,
};
let alerts = manager.check_alerts(&[metric]).unwrap();
assert_eq!(alerts.len(), 1);
assert_eq!(alerts[0].name, "high_cpu");
}
}

View File

@@ -0,0 +1,749 @@
//! 生产环境日志模块
//!
//! 提供生产环境专用的日志功能,包括结构化日志、日志聚合、性能监控等。
#![allow(dead_code)]
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use tokio::sync::RwLock;
use tracing::error;
/// 生产日志管理器
#[derive(Clone)]
pub struct ProductionLogger {
/// 日志配置
config: LoggingConfig,
/// 日志收集器
collectors: Vec<Arc<dyn LogCollector + Send + Sync>>,
/// 日志过滤器
filters: Vec<Arc<dyn LogFilter + Send + Sync>>,
/// 日志统计
stats: Arc<RwLock<LoggingStats>>,
/// 日志缓冲区
buffer: Arc<RwLock<LogBuffer>>,
}
impl std::fmt::Debug for ProductionLogger {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ProductionLogger")
.field("config", &self.config)
.field("collectors_count", &self.collectors.len())
.field("filters_count", &self.filters.len())
.finish()
}
}
/// 日志配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoggingConfig {
/// 日志级别
pub level: LogLevel,
/// 输出格式
pub format: LogFormat,
/// 输出目标
pub targets: Vec<LogTarget>,
/// 缓冲配置
pub buffer_config: BufferConfig,
/// 轮转配置
pub rotation_config: RotationConfig,
/// 采样配置
pub sampling_config: SamplingConfig,
}
/// 日志级别
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum LogLevel {
Trace,
Debug,
Info,
Warn,
Error,
}
/// 日志格式
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum LogFormat {
/// JSON 格式
Json,
/// 纯文本格式
Text,
/// 结构化格式
Structured,
/// 自定义格式
Custom(String),
}
/// 日志输出目标
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum LogTarget {
/// 控制台输出
Console,
/// 文件输出
File { path: String },
/// 系统日志
Syslog,
/// 远程日志服务
Remote { endpoint: String, api_key: String },
/// Elasticsearch
Elasticsearch { url: String, index: String },
/// 自定义目标
Custom(String),
}
/// 缓冲配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BufferConfig {
/// 缓冲区大小
pub size: usize,
/// 刷新间隔
pub flush_interval: Duration,
/// 批量大小
pub batch_size: usize,
/// 是否启用压缩
pub enable_compression: bool,
}
/// 轮转配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RotationConfig {
/// 最大文件大小 (MB)
pub max_file_size_mb: u64,
/// 最大文件数量
pub max_files: u32,
/// 轮转间隔
pub rotation_interval: Duration,
/// 压缩旧文件
pub compress_old_files: bool,
}
/// 采样配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SamplingConfig {
/// 是否启用采样
pub enabled: bool,
/// 采样率 (0.0-1.0)
pub rate: f64,
/// 采样策略
pub strategy: SamplingStrategy,
}
/// 采样策略
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SamplingStrategy {
/// 随机采样
Random,
/// 基于时间的采样
TimeBased,
/// 基于级别的采样
LevelBased,
/// 自适应采样
Adaptive,
}
/// 日志条目
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogEntry {
/// 时间戳
pub timestamp: SystemTime,
/// 日志级别
pub level: LogLevel,
/// 消息
pub message: String,
/// 模块
pub module: String,
/// 文件名
pub file: Option<String>,
/// 行号
pub line: Option<u32>,
/// 字段
pub fields: HashMap<String, serde_json::Value>,
/// 跟踪 ID
pub trace_id: Option<String>,
/// 跨度 ID
pub span_id: Option<String>,
}
/// 日志收集器 trait
pub trait LogCollector {
/// 收集日志
fn collect(&self, entry: &LogEntry) -> Result<()>;
/// 刷新缓冲区
fn flush(&self) -> Result<()>;
/// 获取收集器名称
fn name(&self) -> &str;
}
/// 日志过滤器 trait
pub trait LogFilter {
/// 过滤日志
fn filter(&self, entry: &LogEntry) -> bool;
/// 获取过滤器名称
fn name(&self) -> &str;
}
/// 控制台日志收集器
pub struct ConsoleCollector {
/// 收集器名称
name: String,
/// 格式化器
formatter: Box<dyn LogFormatter + Send + Sync>,
}
impl std::fmt::Debug for ConsoleCollector {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ConsoleCollector")
.field("name", &self.name)
.finish()
}
}
/// 文件日志收集器
pub struct FileCollector {
/// 收集器名称
name: String,
/// 文件路径
file_path: String,
/// 轮转配置
rotation_config: RotationConfig,
/// 格式化器
formatter: Box<dyn LogFormatter + Send + Sync>,
}
impl std::fmt::Debug for FileCollector {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FileCollector")
.field("name", &self.name)
.field("file_path", &self.file_path)
.field("rotation_config", &self.rotation_config)
.finish()
}
}
/// 远程日志收集器
pub struct RemoteCollector {
/// 收集器名称
name: String,
/// 远程端点
endpoint: String,
/// API 密钥
api_key: String,
/// HTTP 客户端
client: reqwest::Client,
}
impl std::fmt::Debug for RemoteCollector {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RemoteCollector")
.field("name", &self.name)
.field("endpoint", &self.endpoint)
.field("api_key", &"<hidden>")
.finish()
}
}
/// 日志格式化器 trait
pub trait LogFormatter {
/// 格式化日志条目
fn format(&self, entry: &LogEntry) -> Result<String>;
}
/// JSON 格式化器
#[derive(Debug)]
pub struct JsonFormatter;
/// 文本格式化器
#[derive(Debug)]
pub struct TextFormatter {
/// 时间格式
time_format: String,
/// 是否包含颜色
colored: bool,
}
/// 级别过滤器
#[derive(Debug)]
pub struct LevelFilter {
/// 最小级别
min_level: LogLevel,
}
/// 模块过滤器
#[derive(Debug)]
pub struct ModuleFilter {
/// 允许的模块
allowed_modules: Vec<String>,
/// 禁止的模块
denied_modules: Vec<String>,
}
/// 速率限制过滤器
#[derive(Debug)]
pub struct RateLimitFilter {
/// 速率限制器
limiter: Arc<RwLock<HashMap<String, RateLimiter>>>,
/// 每秒最大日志数
max_logs_per_second: u32,
}
/// 简单速率限制器
#[derive(Debug)]
struct RateLimiter {
/// 最后重置时间
last_reset: SystemTime,
/// 当前计数
count: u32,
/// 限制
limit: u32,
}
/// 日志缓冲区
#[derive(Debug)]
pub struct LogBuffer {
/// 缓冲的日志条目
entries: Vec<LogEntry>,
/// 缓冲区大小限制
max_size: usize,
/// 最后刷新时间
last_flush: SystemTime,
}
/// 日志统计
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoggingStats {
/// 总日志数
pub total_logs: u64,
/// 按级别统计
pub logs_by_level: HashMap<String, u64>,
/// 按模块统计
pub logs_by_module: HashMap<String, u64>,
/// 错误统计
pub error_count: u64,
/// 警告统计
pub warning_count: u64,
/// 平均处理时间
pub avg_processing_time: Duration,
/// 缓冲区使用率
pub buffer_usage: f64,
/// 丢弃的日志数
pub dropped_logs: u64,
}
impl ProductionLogger {
/// 创建新的生产日志管理器
pub fn new(config: LoggingConfig) -> Self {
Self {
config,
collectors: Vec::new(),
filters: Vec::new(),
stats: Arc::new(RwLock::new(LoggingStats::default())),
buffer: Arc::new(RwLock::new(LogBuffer::new(1000))),
}
}
/// 添加日志收集器
pub fn add_collector(&mut self, collector: Arc<dyn LogCollector + Send + Sync>) {
self.collectors.push(collector);
}
/// 添加日志过滤器
pub fn add_filter(&mut self, filter: Arc<dyn LogFilter + Send + Sync>) {
self.filters.push(filter);
}
/// 记录日志
pub async fn log(&self, entry: LogEntry) -> Result<()> {
// 应用过滤器
for filter in &self.filters {
if !filter.filter(&entry) {
return Ok(());
}
}
// 更新统计
self.update_stats(&entry).await;
// 添加到缓冲区
let mut buffer = self.buffer.write().await;
buffer.add_entry(entry.clone());
// 检查是否需要刷新
if buffer.should_flush(&self.config.buffer_config) {
drop(buffer);
self.flush_buffer().await?;
}
Ok(())
}
/// 刷新缓冲区
pub async fn flush_buffer(&self) -> Result<()> {
let mut buffer = self.buffer.write().await;
let entries = buffer.drain_entries();
drop(buffer);
// 发送到所有收集器
for entry in entries {
for collector in &self.collectors {
if let Err(e) = collector.collect(&entry) {
error!(
"Log collector {} processing failed: {}",
collector.name(),
e
);
}
}
}
// 刷新所有收集器
for collector in &self.collectors {
if let Err(e) = collector.flush() {
error!(
"Log collector {} failed to refresh: {}",
collector.name(),
e
);
}
}
Ok(())
}
/// 更新统计信息
async fn update_stats(&self, entry: &LogEntry) {
let mut stats = self.stats.write().await;
stats.total_logs += 1;
let level_key = format!("{:?}", entry.level);
*stats.logs_by_level.entry(level_key).or_insert(0) += 1;
*stats
.logs_by_module
.entry(entry.module.clone())
.or_insert(0) += 1;
match entry.level {
LogLevel::Error => stats.error_count += 1,
LogLevel::Warn => stats.warning_count += 1,
_ => {}
}
}
/// 获取统计信息
pub async fn get_stats(&self) -> LoggingStats {
self.stats.read().await.clone()
}
/// 启动后台任务
pub async fn start_background_tasks(&self) {
let buffer = Arc::clone(&self.buffer);
let config = self.config.clone();
let logger = self.clone();
tokio::spawn(async move {
let mut interval = tokio::time::interval(config.buffer_config.flush_interval);
loop {
interval.tick().await;
let should_flush = {
let buffer = buffer.read().await;
!buffer.entries.is_empty()
};
if should_flush {
if let Err(e) = logger.flush_buffer().await {
error!("Failed to refresh the log buffer regularly: {}", e);
}
}
}
});
}
}
impl LogCollector for ConsoleCollector {
fn collect(&self, entry: &LogEntry) -> Result<()> {
let formatted = self.formatter.format(entry)?;
println!("{formatted}");
Ok(())
}
fn flush(&self) -> Result<()> {
// 控制台不需要刷新
Ok(())
}
fn name(&self) -> &str {
&self.name
}
}
impl LogCollector for FileCollector {
fn collect(&self, entry: &LogEntry) -> Result<()> {
let _formatted = self.formatter.format(entry)?;
// 这里应该实现文件写入逻辑
// 包括轮转检查
Ok(())
}
fn flush(&self) -> Result<()> {
// 刷新文件缓冲区
Ok(())
}
fn name(&self) -> &str {
&self.name
}
}
impl LogCollector for RemoteCollector {
fn collect(&self, _entry: &LogEntry) -> Result<()> {
// 这里应该实现异步发送到远程服务
// 可以使用队列缓冲
Ok(())
}
fn flush(&self) -> Result<()> {
// 刷新远程队列
Ok(())
}
fn name(&self) -> &str {
&self.name
}
}
impl LogFormatter for JsonFormatter {
fn format(&self, entry: &LogEntry) -> Result<String> {
serde_json::to_string(entry).context("序列化日志条目为 JSON 失败")
}
}
impl LogFormatter for TextFormatter {
fn format(&self, entry: &LogEntry) -> Result<String> {
let timestamp = entry
.timestamp
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap_or_default();
Ok(format!(
"[{}] {:5} {}: {}",
timestamp.as_secs(),
format!("{:?}", entry.level),
entry.module,
entry.message
))
}
}
impl LogFilter for LevelFilter {
fn filter(&self, entry: &LogEntry) -> bool {
self.level_to_number(&entry.level) >= self.level_to_number(&self.min_level)
}
fn name(&self) -> &str {
"level_filter"
}
}
impl LevelFilter {
fn level_to_number(&self, level: &LogLevel) -> u8 {
match level {
LogLevel::Trace => 0,
LogLevel::Debug => 1,
LogLevel::Info => 2,
LogLevel::Warn => 3,
LogLevel::Error => 4,
}
}
}
impl LogFilter for ModuleFilter {
fn filter(&self, entry: &LogEntry) -> bool {
if !self.denied_modules.is_empty()
&& self
.denied_modules
.iter()
.any(|m| entry.module.starts_with(m))
{
return false;
}
if !self.allowed_modules.is_empty() {
return self
.allowed_modules
.iter()
.any(|m| entry.module.starts_with(m));
}
true
}
fn name(&self) -> &str {
"module_filter"
}
}
impl LogFilter for RateLimitFilter {
fn filter(&self, _entry: &LogEntry) -> bool {
// 这里应该实现速率限制逻辑
// 基于模块或其他标识符
true
}
fn name(&self) -> &str {
"rate_limit_filter"
}
}
impl LogBuffer {
/// 创建新的日志缓冲区
pub fn new(max_size: usize) -> Self {
Self {
entries: Vec::with_capacity(max_size),
max_size,
last_flush: SystemTime::now(),
}
}
/// 添加日志条目
pub fn add_entry(&mut self, entry: LogEntry) {
if self.entries.len() >= self.max_size {
// 移除最旧的条目
self.entries.remove(0);
}
self.entries.push(entry);
}
/// 检查是否应该刷新
pub fn should_flush(&self, config: &BufferConfig) -> bool {
self.entries.len() >= config.batch_size
|| self.last_flush.elapsed().unwrap_or_default() >= config.flush_interval
}
/// 排空缓冲区
pub fn drain_entries(&mut self) -> Vec<LogEntry> {
self.last_flush = SystemTime::now();
std::mem::take(&mut self.entries)
}
}
impl Default for LoggingConfig {
fn default() -> Self {
Self {
level: LogLevel::Info,
format: LogFormat::Json,
targets: vec![LogTarget::Console],
buffer_config: BufferConfig {
size: 1000,
flush_interval: Duration::from_secs(5),
batch_size: 100,
enable_compression: false,
},
rotation_config: RotationConfig {
max_file_size_mb: 100,
max_files: 10,
rotation_interval: Duration::from_secs(3600),
compress_old_files: true,
},
sampling_config: SamplingConfig {
enabled: false,
rate: 1.0,
strategy: SamplingStrategy::Random,
},
}
}
}
impl Default for LoggingStats {
fn default() -> Self {
Self {
total_logs: 0,
logs_by_level: HashMap::new(),
logs_by_module: HashMap::new(),
error_count: 0,
warning_count: 0,
avg_processing_time: Duration::from_millis(0),
buffer_usage: 0.0,
dropped_logs: 0,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_production_logger() {
let config = LoggingConfig::default();
let logger = ProductionLogger::new(config);
let entry = LogEntry {
timestamp: SystemTime::now(),
level: LogLevel::Info,
message: "测试日志".to_string(),
module: "test".to_string(),
file: None,
line: None,
fields: HashMap::new(),
trace_id: None,
span_id: None,
};
logger.log(entry).await.unwrap();
let stats = logger.get_stats().await;
assert_eq!(stats.total_logs, 1);
}
#[test]
fn test_level_filter() {
let filter = LevelFilter {
min_level: LogLevel::Warn,
};
let info_entry = LogEntry {
timestamp: SystemTime::now(),
level: LogLevel::Info,
message: "信息日志".to_string(),
module: "test".to_string(),
file: None,
line: None,
fields: HashMap::new(),
trace_id: None,
span_id: None,
};
let error_entry = LogEntry {
level: LogLevel::Error,
..info_entry.clone()
};
assert!(!filter.filter(&info_entry));
assert!(filter.filter(&error_entry));
}
#[test]
fn test_json_formatter() {
let formatter = JsonFormatter;
let entry = LogEntry {
timestamp: SystemTime::now(),
level: LogLevel::Info,
message: "测试消息".to_string(),
module: "test".to_string(),
file: Some("test.rs".to_string()),
line: Some(42),
fields: HashMap::new(),
trace_id: Some("trace123".to_string()),
span_id: Some("span456".to_string()),
};
let formatted = formatter.format(&entry).unwrap();
assert!(formatted.contains("测试消息"));
assert!(formatted.contains("trace123"));
}
}

View File

@@ -0,0 +1,789 @@
//! 资源清理模块
//!
//! 提供应用关闭时的资源清理功能,确保所有资源得到正确释放。
#![allow(dead_code)]
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use tokio::sync::{RwLock, Semaphore};
use tracing::{error, info, warn};
/// 资源清理管理器
#[derive(Clone)]
pub struct ResourceCleanupManager {
/// 清理配置
config: CleanupConfig,
/// 清理器列表
cleaners: Vec<Arc<dyn ResourceCleaner + Send + Sync>>,
/// 清理状态
cleanup_status: Arc<RwLock<CleanupStatus>>,
/// 清理历史
cleanup_history: Arc<RwLock<Vec<CleanupResult>>>,
/// 并发控制
semaphore: Arc<Semaphore>,
}
impl std::fmt::Debug for ResourceCleanupManager {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ResourceCleanupManager")
.field("config", &self.config)
.field("cleaners_count", &self.cleaners.len())
.finish()
}
}
/// 清理配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CleanupConfig {
/// 是否启用自动清理
pub auto_cleanup_enabled: bool,
/// 清理超时时间
pub cleanup_timeout: Duration,
/// 强制清理超时时间
pub force_cleanup_timeout: Duration,
/// 最大并发清理数
pub max_concurrent_cleanups: usize,
/// 清理重试次数
pub retry_count: u32,
/// 重试间隔
pub retry_interval: Duration,
/// 清理顺序配置
pub cleanup_order: Vec<CleanupPhase>,
/// 临时文件清理配置
pub temp_file_cleanup: TempFileCleanupConfig,
/// 内存清理配置
pub memory_cleanup: MemoryCleanupConfig,
}
/// 清理阶段
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum CleanupPhase {
/// 停止新请求
StopNewRequests,
/// 等待现有请求完成
WaitForRequests,
/// 清理应用资源
CleanupApplication,
/// 清理数据库连接
CleanupDatabase,
/// 清理缓存
CleanupCache,
/// 清理文件系统
CleanupFileSystem,
/// 清理网络连接
CleanupNetwork,
/// 清理内存
CleanupMemory,
/// 最终清理
FinalCleanup,
}
/// 临时文件清理配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TempFileCleanupConfig {
/// 是否启用
pub enabled: bool,
/// 临时目录路径
pub temp_directories: Vec<String>,
/// 文件保留时间
pub file_retention_duration: Duration,
/// 最大文件大小 (MB)
pub max_file_size_mb: u64,
/// 文件模式匹配
pub file_patterns: Vec<String>,
}
/// 内存清理配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryCleanupConfig {
/// 是否启用
pub enabled: bool,
/// 强制垃圾回收
pub force_gc: bool,
/// 清理缓存
pub clear_caches: bool,
/// 释放未使用内存
pub release_unused_memory: bool,
}
/// 资源清理器 trait
pub trait ResourceCleaner: Send + Sync {
/// 执行清理
fn cleanup(&self) -> Result<CleanupResult>;
/// 获取清理器名称
fn name(&self) -> &str;
/// 获取清理阶段
fn cleanup_phase(&self) -> CleanupPhase;
/// 获取清理优先级 (数字越小优先级越高)
fn priority(&self) -> u32;
/// 是否支持强制清理
fn supports_force_cleanup(&self) -> bool {
false
}
/// 强制清理
fn force_cleanup(&self) -> Result<CleanupResult> {
self.cleanup()
}
}
/// 清理结果
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CleanupResult {
/// 清理器名称
pub cleaner_name: String,
/// 清理阶段
pub cleanup_phase: CleanupPhase,
/// 清理状态
pub status: CleanupResultStatus,
/// 清理消息
pub message: String,
/// 清理开始时间
pub started_at: SystemTime,
/// 清理结束时间
pub completed_at: Option<SystemTime>,
/// 清理耗时
pub duration: Duration,
/// 清理的资源数量
pub resources_cleaned: u64,
/// 释放的内存大小 (字节)
pub memory_freed: u64,
/// 详细信息
pub details: HashMap<String, serde_json::Value>,
}
/// 清理结果状态
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum CleanupResultStatus {
/// 成功
Success,
/// 失败
Failed,
/// 部分成功
PartialSuccess,
/// 跳过
Skipped,
/// 超时
Timeout,
}
/// 整体清理状态
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CleanupStatus {
/// 是否正在清理
pub is_cleaning: bool,
/// 当前清理阶段
pub current_phase: Option<CleanupPhase>,
/// 清理进度 (0.0-1.0)
pub progress: f64,
/// 清理开始时间
pub started_at: Option<SystemTime>,
/// 预计完成时间
pub estimated_completion: Option<SystemTime>,
/// 清理结果
pub results: Vec<CleanupResult>,
/// 总清理器数量
pub total_cleaners: usize,
/// 已完成清理器数量
pub completed_cleaners: usize,
}
/// 数据库连接清理器
#[derive(Debug)]
pub struct DatabaseConnectionCleaner {
/// 清理器名称
name: String,
/// 连接池大小
pool_size: usize,
}
impl DatabaseConnectionCleaner {
pub fn new(name: String, pool_size: usize) -> Self {
Self { name, pool_size }
}
}
/// 缓存清理器
#[derive(Debug)]
pub struct CacheCleaner {
/// 清理器名称
name: String,
/// 缓存类型
cache_types: Vec<String>,
}
/// 临时文件清理器
#[derive(Debug)]
pub struct TempFileCleaner {
/// 清理器名称
name: String,
/// 配置
config: TempFileCleanupConfig,
}
/// HTTP 连接清理器
#[derive(Debug)]
pub struct HttpConnectionCleaner {
/// 清理器名称
name: String,
/// 活跃连接数
active_connections: Arc<RwLock<u32>>,
}
/// 内存清理器
#[derive(Debug)]
pub struct MemoryCleaner {
/// 清理器名称
name: String,
/// 配置
config: MemoryCleanupConfig,
}
/// 线程池清理器
#[derive(Debug)]
pub struct ThreadPoolCleaner {
/// 清理器名称
name: String,
/// 线程池大小
pool_size: usize,
}
/// 日志清理器
#[derive(Debug)]
pub struct LogCleaner {
/// 清理器名称
name: String,
/// 日志目录
log_directories: Vec<String>,
/// 保留天数
retention_days: u32,
}
impl ResourceCleanupManager {
/// 创建新的资源清理管理器
pub fn new(config: CleanupConfig) -> Self {
let max_concurrent = config.max_concurrent_cleanups;
Self {
config,
cleaners: Vec::new(),
cleanup_status: Arc::new(RwLock::new(CleanupStatus::new())),
cleanup_history: Arc::new(RwLock::new(Vec::new())),
semaphore: Arc::new(Semaphore::new(max_concurrent)),
}
}
/// 添加资源清理器
pub fn add_cleaner(&mut self, cleaner: Arc<dyn ResourceCleaner + Send + Sync>) {
self.cleaners.push(cleaner);
}
/// 执行完整清理
pub async fn cleanup_all(&self) -> Result<CleanupStatus> {
info!("Start resource cleanup");
let mut status = self.cleanup_status.write().await;
status.is_cleaning = true;
status.started_at = Some(SystemTime::now());
status.total_cleaners = self.cleaners.len();
status.completed_cleaners = 0;
status.results.clear();
drop(status);
// 按阶段和优先级排序清理器
let mut sorted_cleaners = self.cleaners.clone();
sorted_cleaners.sort_by(|a, b| {
let phase_order_a = self.get_phase_order(&a.cleanup_phase());
let phase_order_b = self.get_phase_order(&b.cleanup_phase());
phase_order_a
.cmp(&phase_order_b)
.then_with(|| a.priority().cmp(&b.priority()))
});
// 按阶段分组执行清理
let mut current_phase = None;
let mut phase_cleaners = Vec::new();
for cleaner in sorted_cleaners {
let cleaner_phase = cleaner.cleanup_phase();
if current_phase.as_ref() != Some(&cleaner_phase) {
// 执行当前阶段的清理
if !phase_cleaners.is_empty() {
self.execute_phase_cleanup(&phase_cleaners, current_phase.as_ref())
.await?;
phase_cleaners.clear();
}
current_phase = Some(cleaner_phase.clone());
}
phase_cleaners.push(cleaner);
}
// 执行最后一个阶段的清理
if !phase_cleaners.is_empty() {
self.execute_phase_cleanup(&phase_cleaners, current_phase.as_ref())
.await?;
}
// 更新最终状态
let mut status = self.cleanup_status.write().await;
status.is_cleaning = false;
status.current_phase = None;
status.progress = 1.0;
let final_status = status.clone();
drop(status);
info!("Resource cleanup completed");
Ok(final_status)
}
/// 执行阶段清理
async fn execute_phase_cleanup(
&self,
cleaners: &[Arc<dyn ResourceCleaner + Send + Sync>],
phase: Option<&CleanupPhase>,
) -> Result<()> {
if let Some(phase) = phase {
info!("Execute cleanup phase: {:?}", phase);
let mut status = self.cleanup_status.write().await;
status.current_phase = Some(phase.clone());
drop(status);
}
// 并发执行同一阶段的清理器
let mut tasks = Vec::new();
for cleaner in cleaners {
let cleaner = Arc::clone(cleaner);
let semaphore = Arc::clone(&self.semaphore);
let config = self.config.clone();
let cleanup_status = Arc::clone(&self.cleanup_status);
let cleanup_history = Arc::clone(&self.cleanup_history);
let task = tokio::spawn(async move {
let _permit = semaphore.acquire().await.unwrap();
let result = Self::execute_cleaner_with_retry(&cleaner, &config).await;
// 更新状态
let mut status = cleanup_status.write().await;
status.completed_cleaners += 1;
status.progress = status.completed_cleaners as f64 / status.total_cleaners as f64;
if let Ok(ref cleanup_result) = result {
status.results.push(cleanup_result.clone());
// 添加到历史记录
let mut history = cleanup_history.write().await;
history.push(cleanup_result.clone());
// 保持历史记录大小
if history.len() > 1000 {
history.remove(0);
}
}
result
});
tasks.push(task);
}
// 等待所有任务完成
for task in tasks {
match task.await {
Ok(Ok(result)) => {
info!(
"Cleaner {} Completed: {:?}",
result.cleaner_name, result.status
);
}
Ok(Err(e)) => {
error!("Cleaner execution failed: {}", e);
}
Err(e) => {
error!("Cleanup task failed: {}", e);
}
}
}
Ok(())
}
/// 执行带重试的清理器
async fn execute_cleaner_with_retry(
cleaner: &Arc<dyn ResourceCleaner + Send + Sync>,
config: &CleanupConfig,
) -> Result<CleanupResult> {
let mut last_error = None;
for attempt in 0..=config.retry_count {
match tokio::time::timeout(
config.cleanup_timeout,
tokio::task::spawn_blocking({
let cleaner = Arc::clone(cleaner);
move || cleaner.cleanup()
}),
)
.await
{
Ok(Ok(Ok(result))) => return Ok(result),
Ok(Ok(Err(e))) => {
last_error = Some(e);
}
Ok(Err(e)) => {
last_error = Some(anyhow::anyhow!("清理任务 panic: {}", e));
}
Err(_) => {
// 超时,尝试强制清理
if cleaner.supports_force_cleanup() {
match tokio::time::timeout(
config.force_cleanup_timeout,
tokio::task::spawn_blocking({
let cleaner = Arc::clone(cleaner);
move || cleaner.force_cleanup()
}),
)
.await
{
Ok(Ok(Ok(result))) => return Ok(result),
_ => {
last_error = Some(anyhow::anyhow!("强制清理也超时"));
}
}
} else {
last_error = Some(anyhow::anyhow!("清理超时"));
}
}
}
if attempt < config.retry_count {
tokio::time::sleep(config.retry_interval).await;
}
}
// 返回失败结果
Ok(CleanupResult {
cleaner_name: cleaner.name().to_string(),
cleanup_phase: cleaner.cleanup_phase(),
status: CleanupResultStatus::Failed,
message: format!(
"清理失败: {}",
last_error.unwrap_or_else(|| anyhow::anyhow!("未知错误"))
),
started_at: SystemTime::now(),
completed_at: Some(SystemTime::now()),
duration: Duration::from_millis(0),
resources_cleaned: 0,
memory_freed: 0,
details: HashMap::new(),
})
}
/// 获取阶段顺序
fn get_phase_order(&self, phase: &CleanupPhase) -> usize {
self.config
.cleanup_order
.iter()
.position(|p| p == phase)
.unwrap_or(usize::MAX)
}
/// 获取清理状态
pub async fn get_cleanup_status(&self) -> CleanupStatus {
self.cleanup_status.read().await.clone()
}
/// 获取清理历史
pub async fn get_cleanup_history(&self, limit: Option<usize>) -> Vec<CleanupResult> {
let history = self.cleanup_history.read().await;
let limit = limit.unwrap_or(history.len());
history.iter().rev().take(limit).cloned().collect()
}
/// 强制停止清理
pub async fn force_stop_cleanup(&self) -> Result<()> {
warn!("Force stop resource cleanup");
let mut status = self.cleanup_status.write().await;
status.is_cleaning = false;
status.current_phase = None;
Ok(())
}
}
// 实现各种清理器
impl ResourceCleaner for DatabaseConnectionCleaner {
fn cleanup(&self) -> Result<CleanupResult> {
let start_time = SystemTime::now();
// 这里应该实现实际的数据库连接清理逻辑
info!("Clean database connection pool");
let duration = start_time.elapsed().unwrap_or_default();
Ok(CleanupResult {
cleaner_name: self.name.clone(),
cleanup_phase: self.cleanup_phase(),
status: CleanupResultStatus::Success,
message: format!("成功清理 {} 个数据库连接", self.pool_size),
started_at: start_time,
completed_at: Some(SystemTime::now()),
duration,
resources_cleaned: self.pool_size as u64,
memory_freed: self.pool_size as u64 * 1024, // 估算值
details: HashMap::new(),
})
}
fn name(&self) -> &str {
&self.name
}
fn cleanup_phase(&self) -> CleanupPhase {
CleanupPhase::CleanupDatabase
}
fn priority(&self) -> u32 {
10
}
}
impl ResourceCleaner for TempFileCleaner {
fn cleanup(&self) -> Result<CleanupResult> {
let start_time = SystemTime::now();
let mut files_cleaned = 0;
let mut memory_freed = 0;
// 这里应该实现实际的临时文件清理逻辑
for temp_dir in &self.config.temp_directories {
info!("Clean up the temporary directory: {}", temp_dir);
// 实际的文件清理逻辑
files_cleaned += 10; // 示例值
memory_freed += 1024 * 1024; // 示例值
}
let duration = start_time.elapsed().unwrap_or_default();
Ok(CleanupResult {
cleaner_name: self.name.clone(),
cleanup_phase: self.cleanup_phase(),
status: CleanupResultStatus::Success,
message: format!("成功清理 {files_cleaned} 个临时文件"),
started_at: start_time,
completed_at: Some(SystemTime::now()),
duration,
resources_cleaned: files_cleaned,
memory_freed,
details: HashMap::new(),
})
}
fn name(&self) -> &str {
&self.name
}
fn cleanup_phase(&self) -> CleanupPhase {
CleanupPhase::CleanupFileSystem
}
fn priority(&self) -> u32 {
20
}
}
impl ResourceCleaner for MemoryCleaner {
fn cleanup(&self) -> Result<CleanupResult> {
let start_time = SystemTime::now();
let mut memory_freed = 0;
if self.config.enabled {
if self.config.clear_caches {
info!("Clear memory cache");
memory_freed += 1024 * 1024; // 示例值
}
if self.config.force_gc {
info!("Force garbage collection");
// 这里应该触发垃圾回收
memory_freed += 512 * 1024; // 示例值
}
if self.config.release_unused_memory {
info!("Release unused memory");
memory_freed += 256 * 1024; // 示例值
}
}
let duration = start_time.elapsed().unwrap_or_default();
Ok(CleanupResult {
cleaner_name: self.name.clone(),
cleanup_phase: self.cleanup_phase(),
status: CleanupResultStatus::Success,
message: format!("释放了 {} KB 内存", memory_freed / 1024),
started_at: start_time,
completed_at: Some(SystemTime::now()),
duration,
resources_cleaned: 1,
memory_freed,
details: HashMap::new(),
})
}
fn name(&self) -> &str {
&self.name
}
fn cleanup_phase(&self) -> CleanupPhase {
CleanupPhase::CleanupMemory
}
fn priority(&self) -> u32 {
30
}
fn supports_force_cleanup(&self) -> bool {
true
}
}
impl Default for CleanupStatus {
fn default() -> Self {
Self::new()
}
}
impl CleanupStatus {
/// 创建新的清理状态
pub fn new() -> Self {
Self {
is_cleaning: false,
current_phase: None,
progress: 0.0,
started_at: None,
estimated_completion: None,
results: Vec::new(),
total_cleaners: 0,
completed_cleaners: 0,
}
}
/// 检查是否清理成功
pub fn is_success(&self) -> bool {
!self.is_cleaning
&& self
.results
.iter()
.all(|r| r.status == CleanupResultStatus::Success)
}
/// 获取失败的清理器
pub fn get_failed_cleaners(&self) -> Vec<&CleanupResult> {
self.results
.iter()
.filter(|r| r.status == CleanupResultStatus::Failed)
.collect()
}
}
impl Default for CleanupConfig {
fn default() -> Self {
Self {
auto_cleanup_enabled: true,
cleanup_timeout: Duration::from_secs(30),
force_cleanup_timeout: Duration::from_secs(10),
max_concurrent_cleanups: 5,
retry_count: 3,
retry_interval: Duration::from_secs(1),
cleanup_order: vec![
CleanupPhase::StopNewRequests,
CleanupPhase::WaitForRequests,
CleanupPhase::CleanupApplication,
CleanupPhase::CleanupDatabase,
CleanupPhase::CleanupCache,
CleanupPhase::CleanupNetwork,
CleanupPhase::CleanupFileSystem,
CleanupPhase::CleanupMemory,
CleanupPhase::FinalCleanup,
],
temp_file_cleanup: TempFileCleanupConfig {
enabled: true,
temp_directories: vec!["/tmp".to_string(), "/var/tmp".to_string()],
file_retention_duration: Duration::from_secs(3600),
max_file_size_mb: 100,
file_patterns: vec!["*.tmp".to_string(), "*.temp".to_string()],
},
memory_cleanup: MemoryCleanupConfig {
enabled: true,
force_gc: true,
clear_caches: true,
release_unused_memory: true,
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_resource_cleanup_manager() {
let config = CleanupConfig::default();
let mut manager = ResourceCleanupManager::new(config);
let cleaner = Arc::new(DatabaseConnectionCleaner {
name: "test_db".to_string(),
pool_size: 10,
});
manager.add_cleaner(cleaner);
let status = manager.get_cleanup_status().await;
assert!(!status.is_cleaning);
}
#[test]
fn test_database_connection_cleaner() {
let cleaner = DatabaseConnectionCleaner {
name: "test_db".to_string(),
pool_size: 5,
};
let result = cleaner.cleanup().unwrap();
assert_eq!(result.status, CleanupResultStatus::Success);
assert_eq!(result.resources_cleaned, 5);
}
#[test]
fn test_memory_cleaner() {
let cleaner = MemoryCleaner {
name: "memory".to_string(),
config: MemoryCleanupConfig {
enabled: true,
force_gc: true,
clear_caches: true,
release_unused_memory: true,
},
};
let result = cleaner.cleanup().unwrap();
assert_eq!(result.status, CleanupResultStatus::Success);
assert!(result.memory_freed > 0);
}
#[test]
fn test_cleanup_status() {
let status = CleanupStatus::new();
assert!(!status.is_cleaning);
assert_eq!(status.progress, 0.0);
assert!(status.is_success()); // 空结果被认为是成功的
}
}