use sysinfo::{MemoryRefreshKind, Pid, ProcessRefreshKind, RefreshKind, System};
#[derive(Debug, Clone, Default)]
pub struct MemoryStats {
pub total: u64,
pub free: u64,
pub available: u64,
pub usage: u64,
pub used_percent: f64,
}
#[derive(Debug, Clone, Default)]
pub struct ProcessMemoryStats {
pub used_percent: f64,
}
#[derive(Debug, Clone, Default)]
pub struct CgroupMemoryStats {
pub limit: i64,
pub usage: u64,
pub used_percent: f64,
}
#[derive(Debug, Clone, Default)]
pub struct Memory {}
impl Memory {
pub fn get_stats(&self) -> MemoryStats {
let sys =
System::new_with_specifics(RefreshKind::new().with_memory(MemoryRefreshKind::new()));
let used_percent = (sys.used_memory() as f64 / sys.total_memory() as f64) * 100.0;
MemoryStats {
total: sys.total_memory(),
free: sys.free_memory(),
available: sys.available_memory(),
usage: sys.used_memory(),
used_percent: used_percent.clamp(0.0, 100.0),
}
}
pub fn get_process_stats(&self, pid: u32) -> ProcessMemoryStats {
let sys = System::new_with_specifics(
RefreshKind::new().with_processes(ProcessRefreshKind::new().with_memory()),
);
let used_percent = (sys.process(Pid::from_u32(pid)).unwrap().memory() as f64
/ sys.total_memory() as f64)
* 100.0;
ProcessMemoryStats {
used_percent: used_percent.clamp(0.0, 100.0),
}
}
#[allow(unused_variables)]
pub fn get_cgroup_stats(&self, pid: u32) -> Option<CgroupMemoryStats> {
#[cfg(target_os = "linux")]
{
use crate::cgroups::get_cgroup_by_pid;
use cgroups_rs::fs::memory::MemController;
use tracing::error;
match get_cgroup_by_pid(pid) {
Ok(cgroup) => {
if let Some(memory_controller) = cgroup.controller_of::<MemController>() {
let memory_stats = memory_controller.memory_stat();
let used_percent = if memory_stats.limit_in_bytes > 0 {
(memory_stats.usage_in_bytes as f64
/ memory_stats.limit_in_bytes as f64)
* 100.0
} else {
(memory_stats.usage_in_bytes as f64 / self.get_stats().total as f64)
* 100.0
};
return Some(CgroupMemoryStats {
limit: memory_stats.limit_in_bytes,
usage: memory_stats.usage_in_bytes,
used_percent: used_percent.clamp(0.0, 100.0),
});
}
}
Err(err) => {
error!("failed to get cgroup for pid {}: {}", pid, err);
return None;
}
}
}
None
}
}