add process memory for processes using >1% memory

This commit is contained in:
Robin Appelman 2024-04-08 20:21:57 +02:00
commit 41f594cc41
6 changed files with 160 additions and 1 deletions

View file

@ -229,3 +229,28 @@ impl SensorData for GpuPowerUsage {
}
}
}
pub struct ProcData {
pub pid: i32,
pub name: String,
pub rss_memory: u64,
}
impl SensorData for ProcData {
fn write<W: Write>(&self, mut w: W, hostname: &str) {
writeln!(
&mut w,
r#"process_memory_rss{{host="{}", process="{}", pid="{}"}} {}"#,
hostname, self.name, self.pid, self.rss_memory
)
.ok();
}
}
impl SensorData for Vec<ProcData> {
fn write<W: Write>(&self, mut w: W, hostname: &str) {
for data in self {
data.write(&mut w, hostname)
}
}
}

View file

@ -1,3 +1,4 @@
use procfs::ProcError;
use std::ffi::NulError;
use std::fmt::Write;
use std::num::{ParseFloatError, ParseIntError};
@ -35,6 +36,8 @@ pub enum Error {
InvalidStringData(#[from] Utf8Error),
#[error(transparent)]
InvalidCStringData(#[from] NulError),
#[error(transparent)]
Proc(#[from] ProcError),
#[error("Failed to query vfs stats")]
StatVfs,
#[cfg(target_os = "windows")]

View file

@ -2,6 +2,7 @@ pub mod disk;
pub mod gpu;
pub mod hwmon;
pub mod power;
mod proc;
pub mod sensors;
use self::disk::zfs::pools;
@ -10,6 +11,7 @@ use self::sensors::*;
use crate::linux::disk::zfs::arcstats;
use crate::linux::gpu::{update_gpu_power, utilization};
use crate::linux::power::{CpuPowerSource, GpuPowerSource};
use crate::linux::proc::ProcSource;
use crate::{hostname, Error, MultiSensorSource, Result, SensorData, SensorSource};
use std::fmt::Write;
use std::sync::Mutex;
@ -31,6 +33,7 @@ pub struct Sensors {
disk_usage: Mutex<DiskUsageSource>,
cpu_power: Mutex<CpuPowerSource>,
gpu_power: Mutex<GpuPowerSource>,
proc: Mutex<ProcSource>,
}
impl Sensors {
@ -47,6 +50,7 @@ impl Sensors {
disk_usage: Mutex::new(DiskUsageSource::new()?),
cpu_power: Mutex::new(CpuPowerSource::new().unwrap_or_default()),
gpu_power: Mutex::new(GpuPowerSource),
proc: Mutex::new(ProcSource::new()?),
})
}
}
@ -63,6 +67,7 @@ pub fn get_metrics(sensors: &Sensors) -> Result<String> {
let cpu_power = sensors.cpu_power.lock().unwrap().read()?;
let gpu_power = sensors.gpu_power.lock().unwrap().read()?;
let mut net = sensors.net.lock().unwrap();
let mut proc = sensors.proc.lock().unwrap();
let networks = net.read()?;
let pools = pools();
let mut result = String::with_capacity(256);
@ -118,5 +123,9 @@ pub fn get_metrics(sensors: &Sensors) -> Result<String> {
usage.write(&mut result, &sensors.hostname);
}
for process in proc.read()? {
process?.write(&mut result, &sensors.hostname);
}
Ok(result)
}

46
src/linux/proc.rs Normal file
View file

@ -0,0 +1,46 @@
use crate::data::ProcData;
use crate::linux::sensors::MemorySource;
use crate::{MultiSensorSource, Result, SensorSource};
use procfs::page_size;
use procfs::process::all_processes;
use std::vec::IntoIter;
#[derive(Default)]
pub struct ProcSource {
page_size: u64,
page_cutoff: u64,
}
impl ProcSource {
pub fn new() -> Result<Self> {
let total_memory = MemorySource::new()?.read()?.total;
let page_size = page_size();
Ok(ProcSource {
page_size,
// output processes that use >1% of memory
page_cutoff: (total_memory / 100) / page_size,
})
}
}
impl MultiSensorSource for ProcSource {
type Data = ProcData;
type Iter<'a> = IntoIter<Result<ProcData>>;
fn read(&mut self) -> Result<Self::Iter<'_>> {
Ok(all_processes()?
.flatten()
.flat_map(|proc| proc.stat())
.filter(|stat| stat.rss > self.page_cutoff)
.map(|stat| {
Ok(ProcData {
pid: stat.pid,
name: stat.comm,
rss_memory: stat.rss * self.page_size,
})
})
.collect::<Vec<_>>()
.into_iter())
}
}