From 5c03c48e224045c38ebedceea41fd361508b73f1 Mon Sep 17 00:00:00 2001 From: nutcas3 Date: Sat, 25 Apr 2026 00:47:45 +0300 Subject: [PATCH] feat: Remove system statistics and health check methods from monitoring module and update Redis connection handling - Remove get_system_statistics/get_uptime/health_check/get_memory_usage/get_process_memory/estimate_memory_usage/get_redis_memory_usage methods from ChargingEngine impl - Remove SystemStats/HealthStatus struct definitions - Update get_performance_metrics/calculate_rps/calculate_avg_response_time/get_error_statistics/get_last_error/get_redis_latency to use get_multiplexed_async_connection instead of get_async_connection - Replace context error handling with map --- .../src/monitoring/monitoring.rs | 168 ++---------------- 1 file changed, 19 insertions(+), 149 deletions(-) diff --git a/apps/charging-engine/src/monitoring/monitoring.rs b/apps/charging-engine/src/monitoring/monitoring.rs index 1efdd43..02f9b57 100644 --- a/apps/charging-engine/src/monitoring/monitoring.rs +++ b/apps/charging-engine/src/monitoring/monitoring.rs @@ -4,124 +4,10 @@ use std::time::SystemTime; use crate::errors::{ChargingError, ChargingResult, ErrorContext}; use super::types::{SystemStats, HealthStatus}; -impl super::ChargingEngine { - pub async fn get_system_statistics(&self) -> ChargingResult { - let mut conn = self.redis_client.get_async_connection().await - .context("Failed to get Redis connection")?; - - let active_sessions: u64 = conn.get("stats:active_sessions").await.unwrap_or(0); - let total_accounts: u64 = conn.keys("account:*").await.unwrap_or_default().len() as u64; - let blocked_users: u64 = conn.keys("block:*").await.unwrap_or_default().len() as u64; - let low_balance_alerts: u64 = conn.keys("alert:low_balance:*").await.unwrap_or_default().len() as u64; - - let stats = SystemStats { - active_sessions, - total_accounts, - blocked_users, - low_balance_alerts, - uptime: self.get_uptime().await?, - }; - - Ok(stats) - } - - async fn get_uptime(&self) -> ChargingResult { - // Calculate actual uptime since startup - match self.startup_time.elapsed() { - Ok(duration) => Ok(duration.as_secs()), - Err(_) => { - // If system time went backwards, fallback to current time - Ok(SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap_or_default() - .as_secs()) - } - } - } - - pub async fn health_check(&self) -> ChargingResult { - let mut conn = self.redis_client.get_async_connection().await - .context("Failed to get Redis connection")?; - - // Test Redis connection - let _: String = conn.get("health_check").await.unwrap_or_else(|_| "ok".to_string()); - - let status = HealthStatus { - redis_connected: true, - active_sync: true, - last_sync: chrono::Utc::now(), - memory_usage: self.get_memory_usage().await?, - }; - - Ok(status) - } - - async fn get_memory_usage(&self) -> ChargingResult { - // Get actual memory usage from system - match self.get_process_memory() { - Ok(memory_bytes) => Ok(memory_bytes), - Err(_) => { - // Fallback to Redis memory usage if system memory fails - self.get_redis_memory_usage().await - } - } - } - - fn get_process_memory(&self) -> ChargingResult { - use std::fs; - - // Try to read from /proc/self/status for Linux systems - if let Ok(status) = fs::read_to_string("/proc/self/status") { - for line in status.lines() { - if line.starts_with("VmRSS:") { - if let Some(memory_str) = line.split_whitespace().nth(1) { - if let Ok(memory_kb) = memory_str.parse::() { - return Ok(memory_kb * 1024); // Convert KB to bytes - } - } - } - } - } - - // Fallback for non-Linux systems or if reading fails - self.estimate_memory_usage() - } - - fn estimate_memory_usage(&self) -> ChargingResult { - // Estimate memory usage based on known structures - // This is a rough estimate for non-Linux systems - let base_memory = 20_000_000; // 20MB base - let redis_connections = 5_000_000; // 5MB per connection estimate - let session_data = 10_000_000; // 10MB for session data - - Ok(base_memory + redis_connections + session_data) - } - - async fn get_redis_memory_usage(&self) -> ChargingResult { - let mut conn = self.redis_client.get_async_connection().await - .context("Failed to get Redis connection")?; - - // Get Redis memory info - let info: String = redis::cmd("INFO").query_async(&mut conn).await.unwrap_or_default(); - - // Parse memory usage from Redis info - for line in info.lines() { - if line.starts_with("used_memory:") { - if let Some(memory_str) = line.split(':').nth(1) { - if let Ok(memory_bytes) = memory_str.parse::() { - return Ok(memory_bytes); - } - } - } - } - - // Fallback to estimate - self.estimate_memory_usage() - } - +impl crate::charging::ChargingEngine { pub async fn get_performance_metrics(&self) -> ChargingResult { - let mut conn = self.redis_client.get_async_connection().await - .context("Failed to get Redis connection")?; + let mut conn = self.redis_client.get_multiplexed_async_connection().await + .map_err(|e| crate::errors::ChargingError::RedisConnection(e.to_string()))?; // Get Redis info let info: String = redis::cmd("INFO").query_async(&mut conn).await.unwrap_or_default(); @@ -151,8 +37,8 @@ impl super::ChargingEngine { } async fn calculate_rps(&self) -> ChargingResult { - let mut conn = self.redis_client.get_async_connection().await - .context("Failed to get Redis connection")?; + let mut conn = self.redis_client.get_multiplexed_async_connection().await + .map_err(|e| crate::errors::ChargingError::RedisConnection(e.to_string()))?; // Get Redis instantaneous ops per second let info: String = redis::cmd("INFO").query_async(&mut conn).await.unwrap_or_default(); @@ -179,17 +65,17 @@ impl super::ChargingEngine { } async fn calculate_avg_response_time(&self) -> ChargingResult { - let mut conn = self.redis_client.get_async_connection().await - .context("Failed to get Redis connection")?; + let mut conn = self.redis_client.get_multiplexed_async_connection().await + .map_err(|e| crate::errors::ChargingError::RedisConnection(e.to_string()))?; // Track response times in Redis for calculation let response_times_key = "metrics:response_times"; // Get recent response times (last 100 operations) - let response_times: Vec = conn - .lrange(response_times_key, 0, 99) + let response_times_raw: Vec = redis::AsyncCommands::lrange(&mut conn, response_times_key, 0, 99) .await - .unwrap_or_default() + .unwrap_or_default(); + let response_times: Vec = response_times_raw .into_iter() .filter_map(|s| s.parse::().ok()) .collect(); @@ -205,7 +91,7 @@ impl super::ChargingEngine { } } - async fn get_redis_latency(&self, conn: &mut redis::aio::Connection) -> ChargingResult { + async fn get_redis_latency(&self, conn: &mut redis::aio::MultiplexedConnection) -> ChargingResult { use std::time::Instant; // Measure Redis ping latency @@ -217,18 +103,18 @@ impl super::ChargingEngine { } pub async fn get_error_statistics(&self) -> ChargingResult { - let mut conn = self.redis_client.get_async_connection().await - .context("Failed to get Redis connection")?; + let mut conn = self.redis_client.get_multiplexed_async_connection().await + .map_err(|e| crate::errors::ChargingError::RedisConnection(e.to_string()))?; let pattern = "error:*".to_string(); - let keys: Vec = conn.keys(&pattern).await - .context("Failed to get error keys")?; + let keys: Vec = redis::AsyncCommands::keys(&mut conn, &pattern).await + .map_err(|e| crate::errors::ChargingError::RedisOperation(e.to_string()))?; let mut total_errors = 0u64; let mut error_types = std::collections::HashMap::new(); for key in keys { - if let Ok(count) = conn.get::<_, u64>(&key).await { + if let Ok(count) = redis::AsyncCommands::get::<_, u64>(&mut conn, &key).await { total_errors += count; let error_type = key.split(':').nth(1).unwrap_or("unknown"); @@ -246,30 +132,14 @@ impl super::ChargingEngine { } async fn get_last_error(&self) -> ChargingResult> { - let mut conn = self.redis_client.get_async_connection().await - .context("Failed to get Redis connection")?; + let mut conn = self.redis_client.get_multiplexed_async_connection().await + .map_err(|e| crate::errors::ChargingError::RedisConnection(e.to_string()))?; - let last_error: Option = conn.get("last_error").await.unwrap_or(None); + let last_error: Option = redis::AsyncCommands::get(&mut conn, "last_error").await.unwrap_or(None); Ok(last_error) } } -#[derive(Debug, Clone)] -pub struct SystemStats { - pub active_sessions: u64, - pub total_accounts: u64, - pub blocked_users: u64, - pub low_balance_alerts: u64, - pub uptime: u64, -} - -#[derive(Debug, Clone)] -pub struct HealthStatus { - pub redis_connected: bool, - pub active_sync: bool, - pub last_sync: chrono::DateTime, - pub memory_usage: u64, -} #[derive(Debug, Clone)] pub struct PerformanceMetrics {