create cpu breakdown

This commit is contained in:
csehviktor
2025-07-03 06:12:03 +02:00
parent 52ef3dcb6b
commit 18f56ad5cc
3 changed files with 108 additions and 9 deletions

97
agent/src/cpu.rs Normal file
View File

@@ -0,0 +1,97 @@
use std::collections::HashMap;
use common::metrics::CpuBreakdown;
#[derive(Debug, Clone, Copy)]
struct CpuValues {
pub user: u64,
pub nice: u64,
pub system: u64,
pub idle: u64,
pub iowait: u64,
pub irq: u64,
pub softirq: u64,
pub steal: u64,
pub guest: u64,
pub guest_nice: u64,
}
impl CpuValues {
pub fn total(&self) -> u64 {
self.user + self.nice + self.system + self.idle + self.iowait +
self.irq + self.softirq + self.steal + self.guest + self.guest_nice
}
}
pub struct CpuStatReader {
previous_stats: HashMap<String, CpuValues>,
}
impl CpuStatReader {
pub fn new() -> Self {
Self { previous_stats: HashMap::new() }
}
pub fn read_global_cpu_stats(&mut self) -> anyhow::Result<CpuBreakdown> {
let content = std::fs::read_to_string("/proc/stat").unwrap();
let cpu_line = content
.lines()
.find(|line| line.starts_with("cpu "))
.unwrap();
self.parse_cpu_line(cpu_line)
}
fn parse_cpu_line(&mut self, line: &str) -> anyhow::Result<CpuBreakdown> {
let parts: Vec<&str> = line.split_whitespace().collect();
let cpu_name = parts[0].to_string();
let parse = |num: usize| -> u64 {
parts[num].parse().ok().unwrap()
};
let values = CpuValues {
user: parse(1),
nice: parse(2),
system: parse(3),
idle: parse(4),
iowait: parse(5),
irq: parse(6),
softirq: parse(7),
steal: parse(8),
guest: parse(9),
guest_nice: parse(10),
};
let previous = self.previous_stats.get(&cpu_name).copied();
let percentages = self.calculate_percentages(&values, previous);
self.previous_stats.insert(cpu_name, values);
Ok(percentages)
}
fn calculate_percentages(&self, current: &CpuValues, previous: Option<CpuValues>) -> CpuBreakdown {
let Some(prev) = previous else {
return CpuBreakdown::default();
};
let total_delta = current.total().saturating_sub(prev.total()) as f32;
if total_delta <= 0.0 {
return CpuBreakdown::default();
}
let calculate_pct = |current: u64, prev: u64| {
(current.saturating_sub(prev) as f32 / total_delta) * 100.0
};
CpuBreakdown {
system: calculate_pct(current.system, prev.system),
user: calculate_pct(current.user, prev.user),
idle: calculate_pct(current.idle, prev.idle),
steal: calculate_pct(current.steal, prev.steal),
iowait: calculate_pct(current.iowait, prev.iowait),
}
}
}