use crate::error::{RusTorchError, RusTorchResult};
use std::collections::HashMap;
use std::time::Instant;
#[derive(Debug, Clone)]
pub struct SystemMetrics {
pub cpu_usage_percent: f64,
pub available_memory_bytes: u64,
pub total_memory_bytes: u64,
pub load_average_1min: f64,
pub disk_read_bytes_per_sec: u64,
pub disk_write_bytes_per_sec: u64,
pub network_rx_bytes_per_sec: u64,
pub network_tx_bytes_per_sec: u64,
pub process_count: usize,
pub thread_count: usize,
pub timestamp: Instant,
}
impl Default for SystemMetrics {
fn default() -> Self {
Self {
cpu_usage_percent: 0.0,
available_memory_bytes: 0,
total_memory_bytes: 0,
load_average_1min: 0.0,
disk_read_bytes_per_sec: 0,
disk_write_bytes_per_sec: 0,
network_rx_bytes_per_sec: 0,
network_tx_bytes_per_sec: 0,
process_count: 0,
thread_count: 0,
timestamp: Instant::now(),
}
}
}
#[derive(Debug)]
pub struct SystemProfiler {
history: Vec<SystemMetrics>,
max_history_size: usize,
}
impl SystemProfiler {
pub fn new() -> Self {
Self {
history: Vec::new(),
max_history_size: 1000,
}
}
pub fn collect_metrics(&mut self) -> RusTorchResult<SystemMetrics> {
let metrics = SystemMetrics {
cpu_usage_percent: self.get_cpu_usage()?,
available_memory_bytes: self.get_available_memory()?,
total_memory_bytes: self.get_total_memory()?,
load_average_1min: self.get_load_average()?,
disk_read_bytes_per_sec: 0, disk_write_bytes_per_sec: 0, network_rx_bytes_per_sec: 0, network_tx_bytes_per_sec: 0, process_count: self.get_process_count()?,
thread_count: self.get_thread_count()?,
timestamp: Instant::now(),
};
self.history.push(metrics.clone());
if self.history.len() > self.max_history_size {
self.history.remove(0);
}
Ok(metrics)
}
pub fn get_history(&self) -> &[SystemMetrics] {
&self.history
}
pub fn clear_history(&mut self) {
self.history.clear();
}
pub fn get_system_summary(&self) -> SystemSummary {
if self.history.is_empty() {
return SystemSummary::default();
}
let cpu_values: Vec<f64> = self.history.iter().map(|m| m.cpu_usage_percent).collect();
let memory_usage_values: Vec<f64> = self
.history
.iter()
.map(|m| {
if m.total_memory_bytes > 0 {
((m.total_memory_bytes - m.available_memory_bytes) as f64
/ m.total_memory_bytes as f64)
* 100.0
} else {
0.0
}
})
.collect();
SystemSummary {
avg_cpu_usage: cpu_values.iter().sum::<f64>() / cpu_values.len() as f64,
max_cpu_usage: cpu_values.iter().fold(0.0, |a, &b| a.max(b)),
avg_memory_usage_percent: memory_usage_values.iter().sum::<f64>()
/ memory_usage_values.len() as f64,
max_memory_usage_percent: memory_usage_values.iter().fold(0.0, |a, &b| a.max(b)),
sample_count: self.history.len(),
}
}
fn get_cpu_usage(&self) -> RusTorchResult<f64> {
Ok(0.0)
}
fn get_available_memory(&self) -> RusTorchResult<u64> {
Ok(8 * 1024 * 1024 * 1024) }
fn get_total_memory(&self) -> RusTorchResult<u64> {
Ok(16 * 1024 * 1024 * 1024) }
fn get_load_average(&self) -> RusTorchResult<f64> {
Ok(1.0)
}
fn get_process_count(&self) -> RusTorchResult<usize> {
Ok(100)
}
fn get_thread_count(&self) -> RusTorchResult<usize> {
Ok(num_cpus::get() * 2)
}
}
impl Default for SystemProfiler {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct SystemSummary {
pub avg_cpu_usage: f64,
pub max_cpu_usage: f64,
pub avg_memory_usage_percent: f64,
pub max_memory_usage_percent: f64,
pub sample_count: usize,
}
impl Default for SystemSummary {
fn default() -> Self {
Self {
avg_cpu_usage: 0.0,
max_cpu_usage: 0.0,
avg_memory_usage_percent: 0.0,
max_memory_usage_percent: 0.0,
sample_count: 0,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_system_profiler_creation() {
let profiler = SystemProfiler::new();
assert_eq!(profiler.history.len(), 0);
}
#[test]
fn test_metrics_collection() {
let mut profiler = SystemProfiler::new();
let result = profiler.collect_metrics();
assert!(result.is_ok());
assert_eq!(profiler.history.len(), 1);
}
#[test]
fn test_system_summary() {
let mut profiler = SystemProfiler::new();
for _ in 0..3 {
let _ = profiler.collect_metrics();
}
let summary = profiler.get_system_summary();
assert_eq!(summary.sample_count, 3);
}
#[test]
fn test_history_limit() {
let mut profiler = SystemProfiler::new();
profiler.max_history_size = 5;
for _ in 0..10 {
let _ = profiler.collect_metrics();
}
assert_eq!(profiler.history.len(), 5);
}
}