mirror of
				https://github.com/csehviktor/status-monitor.git
				synced 2025-08-08 18:06:14 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			98 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			98 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| 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),
 | |
|         }
 | |
|     }
 | |
| }
 |