use std::path::{Path, PathBuf};
use serde::Serialize;
use super::linux_mm::{
BuddyInfo, CgroupMemoryStats, FromRead, HugePageStats, Iomem, Meminfo, MemoryPressure, MemorySysctls, PageTypeInfo, ProcessMemoryStats,
SharedMemorySegments, SlabInfo, Swaps, VmStat, ZoneInfo,
};
#[derive(Clone, Default, Debug, Serialize)]
pub struct LinuxMemoryStats {
pub diagnostics: Option<Box<super::LinuxMemoryDiagnostics>>,
pub ksm: Option<Box<super::linux_mm::KsmStats>>,
pub compressed: Option<Box<super::linux_mm::CompressedMemoryStats>>,
pub numa: Option<Box<super::linux_mm::NumaStats>>,
pub meminfo: Option<Box<Meminfo>>,
pub vmstat: Option<VmStat>,
pub pressure: Option<MemoryPressure>,
pub shared_memory: Option<SharedMemorySegments>,
pub iomem: Option<Iomem>,
pub buddyinfo: Option<BuddyInfo>,
pub zoneinfo: Option<ZoneInfo>,
pub swaps: Option<Swaps>,
pub slabinfo: Option<SlabInfo>,
pub pagetypeinfo: Option<PageTypeInfo>,
pub sysctls: MemorySysctls,
pub cgroup: Box<CgroupMemoryStats>,
pub hugepages: Option<Box<HugePageStats>>,
pub process: Box<ProcessMemoryStats>,
}
impl LinuxMemoryStats {
pub fn current() -> Self {
Self::from_roots("/proc", "/sys")
}
pub fn from_roots(proc_root: impl AsRef<Path>, sys_root: impl AsRef<Path>) -> Self {
Self {
ksm: Some(Box::new(super::linux_mm::KsmStats::from_roots(
&sys_root,
proc_root.as_ref().join("self"),
std::process::id(),
))),
hugepages: Some(Box::new(HugePageStats::from_sys_root(&sys_root))),
numa: Some(Box::new(super::linux_mm::NumaStats::from_sys_root(&sys_root))),
compressed: Some(Box::new(super::linux_mm::CompressedMemoryStats::from_sys_root(&sys_root))),
..Self::from_proc_root(proc_root)
}
}
pub fn from_proc_root(root: impl AsRef<Path>) -> Self {
let root = root.as_ref();
Self {
meminfo: read(root.join("meminfo")).map(Box::new),
vmstat: read(root.join("vmstat")),
pressure: read(root.join("pressure/memory")),
shared_memory: read(root.join("sysvipc/shm")),
iomem: read(root.join("iomem")),
buddyinfo: read(root.join("buddyinfo")),
zoneinfo: read(root.join("zoneinfo")),
swaps: read(root.join("swaps")),
slabinfo: read(root.join("slabinfo")),
pagetypeinfo: read(root.join("pagetypeinfo")),
sysctls: MemorySysctls::from_proc_root(root),
cgroup: Box::new(CgroupMemoryStats::from_proc_root(root)),
hugepages: None,
numa: None,
compressed: None,
ksm: None,
diagnostics: None,
process: Box::new(ProcessMemoryStats::from_process_root(std::process::id(), root.join("self"))),
}
}
}
fn read<T: FromRead>(path: PathBuf) -> Option<T> {
match T::from_file(&path) {
Ok(snapshot) => Some(snapshot),
Err(error) => {
tracing::debug!(path = %path.display(), %error, "Linux memory statistics source unavailable");
None
}
}
}