100 lines
3.1 KiB
Rust
100 lines
3.1 KiB
Rust
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<Vec<ContainerCpuInfo>, Box<dyn Error + Send + Sync>> {
|
|
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<Option<ContainerCpuInfo>, Box<dyn Error + Send + Sync>> {
|
|
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<f64, Box<dyn Error + Send + Sync>> {
|
|
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)
|
|
}
|