use serde::{Deserialize, Serialize};
use std::{
fmt::{Display, Formatter, Result},
time::Duration,
};
use crate::{
format::{format_bytes, format_duration},
health_status::HealthStatus,
};
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct ContainerMetrics {
pub uptime: Duration,
pub memory_usage: u64,
pub memory_limit: Option<u64>,
pub memory_percentage: Option<f64>,
pub cpu_percentage: f64,
pub process_count: u32,
pub network_rx_bytes: u64,
pub network_tx_bytes: u64,
pub block_read_bytes: u64,
pub block_write_bytes: u64,
pub restart_count: u32,
pub last_exit_code: Option<i64>,
pub health_status: Option<HealthStatus>,
}
impl ContainerMetrics {
#[must_use]
pub const fn new() -> Self {
Self {
uptime: Duration::from_secs(0),
memory_usage: 0,
memory_limit: None,
memory_percentage: None,
cpu_percentage: 0.0,
process_count: 0,
network_rx_bytes: 0,
network_tx_bytes: 0,
block_read_bytes: 0,
block_write_bytes: 0,
restart_count: 0,
last_exit_code: None,
health_status: Some(HealthStatus::None),
}
}
pub fn calculate_memory_percentage(&mut self) {
if let Some(limit) = self.memory_limit {
if limit > 0 {
self.memory_percentage = Some((self.memory_usage as f64 / limit as f64) * 100.0);
}
}
}
#[must_use]
pub fn memory_usage_display(&self) -> String {
match (self.memory_percentage, self.memory_limit) {
(Some(pct), Some(limit)) => {
format!("{} / {} ({:.1}%)", format_bytes(self.memory_usage), format_bytes(limit), pct)
}
_ => format_bytes(self.memory_usage),
}
}
#[must_use]
pub fn network_usage_display(&self) -> String {
format!(
"↓{} ↑{}",
format_bytes(self.network_rx_bytes),
format_bytes(self.network_tx_bytes)
)
}
#[must_use]
pub fn disk_io_display(&self) -> String {
format!(
"R:{} W:{}",
format_bytes(self.block_read_bytes),
format_bytes(self.block_write_bytes)
)
}
}
impl Default for ContainerMetrics {
fn default() -> Self {
Self::new()
}
}
impl Display for ContainerMetrics {
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
write!(
fmt,
"Uptime: {}\nMemory: {}\nCPU: {:.1}%\nProcesses: {}\nNetwork: {}\nDisk I/O: {}\nRestarts: {}\nLast Exit Code: {:?}\nHealth: {}",
format_duration(self.uptime),
self.memory_usage_display(),
self.cpu_percentage,
self.process_count,
self.network_usage_display(),
self.disk_io_display(),
self.restart_count,
self.last_exit_code,
self.health_status.unwrap_or(HealthStatus::None)
)
}
}