added Option to data structs

This commit is contained in:
2025-10-06 12:43:15 +02:00
parent a7cae5e93f
commit 06cec6ff9f
6 changed files with 87 additions and 65 deletions

View File

@@ -4,7 +4,7 @@
//! //!
use crate::docker::stats; use crate::docker::stats;
use crate::docker::stats::{ContainerCpuInfo, ContainerNetworkInfo}; use crate::docker::stats::{ContainerCpuInfo, ContainerNetworkInfo};
use crate::models::{DockerRegistrationDto, DockerMetricDto, DockerContainer}; use crate::models::DockerContainer;
use bollard::query_parameters::{ use bollard::query_parameters::{
CreateImageOptions, ListContainersOptions, RestartContainerOptions, CreateImageOptions, ListContainersOptions, RestartContainerOptions,
@@ -178,14 +178,15 @@ pub async fn get_network_stats(
Ok(net_info) Ok(net_info)
} else { } else {
// Return default network info if not found // Return default network info if not found
println!("No network info found for container {}", container_id);
Ok(ContainerNetworkInfo { Ok(ContainerNetworkInfo {
container_id: container_id.to_string(), container_id: Some(container_id.to_string()),
rx_bytes: 0, rx_bytes: None,
tx_bytes: 0, tx_bytes: None,
rx_packets: 0, rx_packets: None,
tx_packets: 0, tx_packets: None,
rx_errors: 0, rx_errors: None,
tx_errors: 0, tx_errors: None,
}) })
} }
} }
@@ -201,12 +202,13 @@ pub async fn get_cpu_stats(
Ok(cpu_info) Ok(cpu_info)
} else { } else {
// Return default CPU info if not found // Return default CPU info if not found
println!("No CPU info found for container {}", container_id);
Ok(ContainerCpuInfo { Ok(ContainerCpuInfo {
container_id: container_id.to_string(), container_id: Some(container_id.to_string()),
cpu_usage_percent: 0.0, cpu_usage_percent: None,
system_cpu_usage: 0, system_cpu_usage: None,
container_cpu_usage: 0, container_cpu_usage: None,
online_cpus: 1, online_cpus: None,
}) })
} }
} }

View File

@@ -11,7 +11,7 @@ pub mod container;
pub mod serverclientcomm; pub mod serverclientcomm;
pub mod stats; pub mod stats;
use crate::models::{DockerRegistrationDto, DockerMetricDto, DockerContainer, DockerContainerInfo}; use crate::models::{DockerContainer, DockerContainerInfo, DockerMetricDto, DockerRegistrationDto};
use bollard::{query_parameters::InspectContainerOptions, Docker}; use bollard::{query_parameters::InspectContainerOptions, Docker};
use std::error::Error; use std::error::Error;
@@ -60,14 +60,20 @@ impl DockerManager {
id: container.id, id: container.id,
image: container.image, image: container.image,
name: container.name, name: container.name,
})) }))
} }
/// Gets the current client version (image name) if running in Docker /// Gets the current client version (image name) if running in Docker
pub async fn get_client_version(&self) -> String { pub async fn get_client_version(&self) -> String {
match self.get_client_container().await { match self.get_client_container().await {
Ok(Some(container)) => container.image.clone().unwrap().split(':').next().unwrap_or("unknown").to_string(), Ok(Some(container)) => container
.image
.clone()
.unwrap()
.split(':')
.next()
.unwrap_or("unknown")
.to_string(),
Ok(None) => { Ok(None) => {
println!("Warning: No WatcherAgent container found"); println!("Warning: No WatcherAgent container found");
"unknown".to_string() "unknown".to_string()
@@ -118,9 +124,7 @@ impl DockerManager {
} }
/// Collects Docker metrics for all containers /// Collects Docker metrics for all containers
pub async fn collect_metrics( pub async fn collect_metrics(&self) -> Result<DockerMetricDto, Box<dyn Error + Send + Sync>> {
&self,
) -> Result<DockerMetricDto, Box<dyn Error + Send + Sync>> {
let containers = self.get_containers().await?; let containers = self.get_containers().await?;
let (cpu_stats, net_stats, mem_stats) = stats::get_container_stats(&self.docker).await?; let (cpu_stats, net_stats, mem_stats) = stats::get_container_stats(&self.docker).await?;
@@ -129,15 +133,15 @@ impl DockerManager {
.map(|container| { .map(|container| {
let cpu = cpu_stats let cpu = cpu_stats
.iter() .iter()
.find(|c| c.container_id == container.id) .find(|c| c.container_id == Some(container.id.clone()))
.cloned(); .cloned();
let network = net_stats let network = net_stats
.iter() .iter()
.find(|n| n.container_id == container.id) .find(|n| n.container_id == Some(container.id.clone()))
.cloned(); .cloned();
let ram = mem_stats let ram = mem_stats
.iter() .iter()
.find(|m| m.container_id == container.id) .find(|m| m.container_id == Some(container.id.clone()))
.cloned(); .cloned();
DockerContainerInfo { DockerContainerInfo {

View File

@@ -70,11 +70,11 @@ pub async fn get_single_container_cpu_stats(
}; };
return Ok(Some(ContainerCpuInfo { return Ok(Some(ContainerCpuInfo {
container_id: container_id.to_string(), container_id: Some(container_id.to_string()),
cpu_usage_percent: cpu_percent, cpu_usage_percent: Some(cpu_percent),
system_cpu_usage: cpu_stats.system_cpu_usage.unwrap_or(0), system_cpu_usage: Some(cpu_stats.system_cpu_usage.unwrap_or(0)),
container_cpu_usage: cpu_usage.total_usage.unwrap_or(0), container_cpu_usage: Some(cpu_usage.total_usage.unwrap_or(0)),
online_cpus, online_cpus: Some(online_cpus),
})); }));
} }
} }
@@ -91,6 +91,9 @@ pub async fn get_average_cpu_usage(docker: &Docker) -> Result<f64, Box<dyn Error
return Ok(0.0); return Ok(0.0);
} }
let total_cpu: f64 = cpu_infos.iter().map(|cpu| cpu.cpu_usage_percent).sum(); let total_cpu: f64 = cpu_infos
.iter()
.map(|cpu| cpu.cpu_usage_percent.unwrap())
.sum();
Ok(total_cpu / cpu_infos.len() as f64) Ok(total_cpu / cpu_infos.len() as f64)
} }

View File

@@ -6,30 +6,30 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ContainerCpuInfo { pub struct ContainerCpuInfo {
pub container_id: String, pub container_id: Option<String>,
pub cpu_usage_percent: f64, pub cpu_usage_percent: Option<f64>,
pub system_cpu_usage: u64, pub system_cpu_usage: Option<u64>,
pub container_cpu_usage: u64, pub container_cpu_usage: Option<u64>,
pub online_cpus: u32, pub online_cpus: Option<u32>,
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ContainerNetworkInfo { pub struct ContainerNetworkInfo {
pub container_id: String, pub container_id: Option<String>,
pub rx_bytes: u64, pub rx_bytes: Option<u64>,
pub tx_bytes: u64, pub tx_bytes: Option<u64>,
pub rx_packets: u64, pub rx_packets: Option<u64>,
pub tx_packets: u64, pub tx_packets: Option<u64>,
pub rx_errors: u64, pub rx_errors: Option<u64>,
pub tx_errors: u64, pub tx_errors: Option<u64>,
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ContainerMemoryInfo { pub struct ContainerMemoryInfo {
pub container_id: String, pub container_id: Option<String>,
pub memory_usage: u64, pub memory_usage: Option<u64>,
pub memory_limit: u64, pub memory_limit: Option<u64>,
pub memory_usage_percent: f64, pub memory_usage_percent: Option<f64>,
} }
use bollard::Docker; use bollard::Docker;
@@ -38,7 +38,14 @@ use std::error::Error;
/// Get container statistics for all containers using an existing Docker client /// Get container statistics for all containers using an existing Docker client
pub async fn get_container_stats( pub async fn get_container_stats(
docker: &Docker, docker: &Docker,
) -> Result<(Vec<ContainerCpuInfo>, Vec<ContainerNetworkInfo>, Vec<ContainerMemoryInfo>), Box<dyn Error + Send + Sync>> { ) -> Result<
(
Vec<ContainerCpuInfo>,
Vec<ContainerNetworkInfo>,
Vec<ContainerMemoryInfo>,
),
Box<dyn Error + Send + Sync>,
> {
let cpu_infos = cpu::get_all_containers_cpu_stats(docker).await?; let cpu_infos = cpu::get_all_containers_cpu_stats(docker).await?;
let net_infos = network::get_all_containers_network_stats(docker).await?; let net_infos = network::get_all_containers_network_stats(docker).await?;
let mem_infos = ram::get_all_containers_memory_stats(docker).await?; let mem_infos = ram::get_all_containers_memory_stats(docker).await?;
@@ -50,8 +57,14 @@ pub async fn get_container_stats(
pub async fn get_single_container_stats( pub async fn get_single_container_stats(
docker: &Docker, docker: &Docker,
container_id: &str, container_id: &str,
) -> Result<(Option<ContainerCpuInfo>, Option<ContainerNetworkInfo>, Option<ContainerMemoryInfo>), Box<dyn Error + Send + Sync>> ) -> Result<
{ (
Option<ContainerCpuInfo>,
Option<ContainerNetworkInfo>,
Option<ContainerMemoryInfo>,
),
Box<dyn Error + Send + Sync>,
> {
let cpu_info = cpu::get_single_container_cpu_stats(docker, container_id).await?; let cpu_info = cpu::get_single_container_cpu_stats(docker, container_id).await?;
let net_info = network::get_single_container_network_stats(docker, container_id).await?; let net_info = network::get_single_container_network_stats(docker, container_id).await?;
let mem_info = ram::get_single_container_memory_stats(docker, container_id).await?; let mem_info = ram::get_single_container_memory_stats(docker, container_id).await?;

View File

@@ -51,13 +51,13 @@ pub async fn get_single_container_network_stats(
// Take the first network interface (usually eth0) // Take the first network interface (usually eth0)
if let Some((_name, net)) = networks.into_iter().next() { if let Some((_name, net)) = networks.into_iter().next() {
return Ok(Some(ContainerNetworkInfo { return Ok(Some(ContainerNetworkInfo {
container_id: container_id.to_string(), container_id: Some(container_id.to_string()),
rx_bytes: net.rx_bytes.unwrap(), rx_bytes: net.rx_bytes,
tx_bytes: net.tx_bytes.unwrap(), tx_bytes: net.tx_bytes,
rx_packets: net.rx_packets.unwrap(), rx_packets: net.rx_packets,
tx_packets: net.tx_packets.unwrap(), tx_packets: net.tx_packets,
rx_errors: net.rx_errors.unwrap(), rx_errors: net.rx_errors,
tx_errors: net.tx_errors.unwrap(), tx_errors: net.tx_errors,
})); }));
} }
} }
@@ -72,8 +72,8 @@ pub async fn get_total_network_stats(
) -> Result<(u64, u64), Box<dyn Error + Send + Sync>> { ) -> Result<(u64, u64), Box<dyn Error + Send + Sync>> {
let net_infos = get_all_containers_network_stats(docker).await?; let net_infos = get_all_containers_network_stats(docker).await?;
let total_rx: u64 = net_infos.iter().map(|net| net.rx_bytes).sum(); let total_rx: u64 = net_infos.iter().map(|net| net.rx_bytes.unwrap()).sum();
let total_tx: u64 = net_infos.iter().map(|net| net.tx_bytes).sum(); let total_tx: u64 = net_infos.iter().map(|net| net.tx_bytes.unwrap()).sum();
Ok((total_rx, total_tx)) Ok((total_rx, total_tx))
} }

View File

@@ -58,10 +58,10 @@ pub async fn get_single_container_memory_stats(
}; };
return Ok(Some(ContainerMemoryInfo { return Ok(Some(ContainerMemoryInfo {
container_id: container_id.to_string(), container_id: Some(container_id.to_string()),
memory_usage, memory_usage: Some(memory_usage),
memory_limit, memory_limit: Some(memory_limit),
memory_usage_percent, memory_usage_percent: Some(memory_usage_percent),
})); }));
} }
} }
@@ -72,6 +72,6 @@ pub async fn get_single_container_memory_stats(
/// Get total memory usage across all containers /// Get total memory usage across all containers
pub async fn get_total_memory_usage(docker: &Docker) -> Result<u64, Box<dyn Error + Send + Sync>> { pub async fn get_total_memory_usage(docker: &Docker) -> Result<u64, Box<dyn Error + Send + Sync>> {
let mem_infos = get_all_containers_memory_stats(docker).await?; let mem_infos = get_all_containers_memory_stats(docker).await?;
let total_memory: u64 = mem_infos.iter().map(|mem| mem.memory_usage).sum(); let total_memory: u64 = mem_infos.iter().map(|mem| mem.memory_usage.unwrap()).sum();
Ok(total_memory) Ok(total_memory)
} }