mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-20 20:04:24 +00:00
feat: Implement actual uptime calculation and memory usage tracking in monitoring
- Replace placeholder uptime with actual elapsed time since startup using startup_time - Add fallback to UNIX epoch time if system time goes backwards - Implement get_process_memory to read actual memory from /proc/self/status on Linux - Add estimate_memory_usage fallback for non-Linux systems (35MB base estimate) - Add get_redis_memory_usage to query Redis memory info as secondary fallback - Update get_memory_usage to use
This commit is contained in:
@@ -26,12 +26,17 @@ impl super::ChargingEngine {
|
||||
}
|
||||
|
||||
async fn get_uptime(&self) -> ChargingResult<u64> {
|
||||
// This would track the actual uptime in a real implementation
|
||||
// For now, return a placeholder
|
||||
Ok(SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.unwrap_or_default()
|
||||
.as_secs())
|
||||
// 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<HealthStatus> {
|
||||
@@ -52,9 +57,66 @@ impl super::ChargingEngine {
|
||||
}
|
||||
|
||||
async fn get_memory_usage(&self) -> ChargingResult<u64> {
|
||||
// This would get actual memory usage in a real implementation
|
||||
// For now, return a placeholder
|
||||
Ok(50_000_000) // 50MB placeholder
|
||||
// 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<u64> {
|
||||
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::<u64>() {
|
||||
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<u64> {
|
||||
// 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<u64> {
|
||||
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::<u64>() {
|
||||
return Ok(memory_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to estimate
|
||||
self.estimate_memory_usage()
|
||||
}
|
||||
|
||||
pub async fn get_performance_metrics(&self) -> ChargingResult<PerformanceMetrics> {
|
||||
@@ -89,15 +151,69 @@ impl super::ChargingEngine {
|
||||
}
|
||||
|
||||
async fn calculate_rps(&self) -> ChargingResult<f64> {
|
||||
// This would calculate actual requests per second
|
||||
// For now, return a placeholder
|
||||
Ok(100.0)
|
||||
let mut conn = self.redis_client.get_async_connection().await
|
||||
.context("Failed to get Redis connection")?;
|
||||
|
||||
// Get Redis instantaneous ops per second
|
||||
let info: String = redis::cmd("INFO").query_async(&mut conn).await.unwrap_or_default();
|
||||
|
||||
for line in info.lines() {
|
||||
if line.starts_with("instantaneous_ops_per_sec:") {
|
||||
if let Some(rps_str) = line.split(':').nth(1) {
|
||||
if let Ok(rps) = rps_str.parse::<f64>() {
|
||||
return Ok(rps);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: calculate from total commands processed over time
|
||||
let total_commands = self.extract_metric(&info, "total_commands_processed");
|
||||
let uptime_seconds = self.get_uptime().await?;
|
||||
|
||||
if uptime_seconds > 0 {
|
||||
Ok(total_commands as f64 / uptime_seconds as f64)
|
||||
} else {
|
||||
Ok(0.0)
|
||||
}
|
||||
}
|
||||
|
||||
async fn calculate_avg_response_time(&self) -> ChargingResult<f64> {
|
||||
// This would calculate actual average response time
|
||||
// For now, return a placeholder
|
||||
Ok(5.0) // 5ms
|
||||
let mut conn = self.redis_client.get_async_connection().await
|
||||
.context("Failed to get Redis connection")?;
|
||||
|
||||
// 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<f64> = conn
|
||||
.lrange(response_times_key, 0, 99)
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.filter_map(|s| s.parse::<f64>().ok())
|
||||
.collect();
|
||||
|
||||
if response_times.is_empty() {
|
||||
// If no response times tracked, estimate based on Redis latency
|
||||
let latency_info = self.get_redis_latency(&mut conn).await?;
|
||||
Ok(latency_info)
|
||||
} else {
|
||||
// Calculate average of recent response times
|
||||
let sum: f64 = response_times.iter().sum();
|
||||
Ok(sum / response_times.len() as f64)
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_redis_latency(&self, conn: &mut redis::aio::Connection) -> ChargingResult<f64> {
|
||||
use std::time::Instant;
|
||||
|
||||
// Measure Redis ping latency
|
||||
let start = Instant::now();
|
||||
let _: String = redis::cmd("PING").query_async(conn).await.unwrap_or_else(|_| "PONG".to_string());
|
||||
let latency = start.elapsed();
|
||||
|
||||
Ok(latency.as_millis() as f64)
|
||||
}
|
||||
|
||||
pub async fn get_error_statistics(&self) -> ChargingResult<ErrorStats> {
|
||||
|
||||
Reference in New Issue
Block a user