use super::ContainerCpuInfo; use bollard::query_parameters::{ListContainersOptions, StatsOptions}; use bollard::Docker; use futures_util::stream::TryStreamExt; use std::error::Error; /// Get CPU statistics for all containers pub async fn get_all_containers_cpu_stats( docker: &Docker, ) -> Result, Box> { let containers = docker .list_containers(Some(ListContainersOptions { all: true, ..Default::default() })) .await?; let mut cpu_infos = Vec::new(); for container in containers { let id = container.id.unwrap_or_default(); // Skip if no ID if id.is_empty() { continue; } if let Some(cpu_info) = get_single_container_cpu_stats(docker, &id).await? { cpu_infos.push(cpu_info); } } Ok(cpu_infos) } /// Get CPU statistics for a specific container pub async fn get_single_container_cpu_stats( docker: &Docker, container_id: &str, ) -> Result, Box> { let mut stats_stream = docker.stats( container_id, Some(StatsOptions { stream: false, one_shot: true, }), ); if let Some(stats) = stats_stream.try_next().await? { if let (Some(cpu_stats), Some(precpu_stats)) = (&stats.cpu_stats, &stats.precpu_stats) { if let (Some(cpu_usage), Some(pre_cpu_usage)) = (&cpu_stats.cpu_usage, &precpu_stats.cpu_usage) { let cpu_delta = cpu_usage .total_usage .unwrap_or(0) .saturating_sub(pre_cpu_usage.total_usage.unwrap_or(0)); let system_delta = cpu_stats .system_cpu_usage .unwrap_or(0) .saturating_sub(precpu_stats.system_cpu_usage.unwrap_or(0)); let online_cpus = cpu_stats.online_cpus.unwrap_or(1); let cpu_percent = if system_delta > 0 && online_cpus > 0 { (cpu_delta as f64 / system_delta as f64) * online_cpus as f64 * 100.0 } else { 0.0 }; return Ok(Some(ContainerCpuInfo { container_id: Some(container_id.to_string()), cpu_usage_percent: Some(cpu_percent), system_cpu_usage: Some(cpu_stats.system_cpu_usage.unwrap_or(0)), container_cpu_usage: Some(cpu_usage.total_usage.unwrap_or(0)), online_cpus: Some(online_cpus), })); } } } Ok(None) } /// Get average CPU usage across all containers pub async fn get_average_cpu_usage(docker: &Docker) -> Result> { let cpu_infos = get_all_containers_cpu_stats(docker).await?; if cpu_infos.is_empty() { return Ok(0.0); } let total_cpu: f64 = cpu_infos .iter() .map(|cpu| cpu.cpu_usage_percent.unwrap()) .sum(); Ok(total_cpu / cpu_infos.len() as f64) }