From c84e9698d7576427a693edcdfdacddc0e5df5819 Mon Sep 17 00:00:00 2001 From: Mahesh Asolkar Date: Fri, 6 Jun 2025 17:50:16 -0700 Subject: [PATCH] Added CPU usage module --- src/bar_modules/bar_module_cpu.rs | 183 ++++++++++++++++++++++++++++++ src/bar_modules/mod.rs | 1 + src/main.rs | 2 + 3 files changed, 186 insertions(+) create mode 100644 src/bar_modules/bar_module_cpu.rs diff --git a/src/bar_modules/bar_module_cpu.rs b/src/bar_modules/bar_module_cpu.rs new file mode 100644 index 0000000..4580c5d --- /dev/null +++ b/src/bar_modules/bar_module_cpu.rs @@ -0,0 +1,183 @@ +use std::fs::File; +// use std::path::Path; +// use std::io::prelude::*; +// use regex::Regex; +use std::io::{self, BufRead, BufReader}; +use std::thread; +use std::time::Duration; + +use crate::common; +use crate::bar_modules; + +#[derive(Debug, Default, Clone)] +struct CpuTimes { + user: u64, + nice: u64, + system: u64, + idle: u64, + iowait: u64, + irq: u64, + softirq: u64, + steal: u64, + guest: u64, + guest_nice: u64, +} + +impl CpuTimes { + pub fn new() -> Self { + CpuTimes { + user: 0, + nice: 0, + system: 0, + idle: 0, + iowait: 0, + irq: 0, + softirq: 0, + steal: 0, + guest: 0, + guest_nice: 0 + } + } + + 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 + } + + fn idle(&self) -> u64 { + self.idle + self.iowait + } +} + +#[derive(Clone)] +pub struct UnibarModuleCpu { + opts: common::AppOptions, + cpu_times_sample_1: CpuTimes, + cpu_times_sample_2: CpuTimes, +} + +impl UnibarModuleCpu { + + // -------------------- + pub fn new(o :common::AppOptions) -> Self { + UnibarModuleCpu { + opts: o, + cpu_times_sample_1: CpuTimes::new(), + cpu_times_sample_2: CpuTimes::new(), + } + } + + // -------------------- + // cpu 242109 7 60985 6538626 8344 39138 9647 0 0 0 + // * user – time spent in user mode + // * nice – time spent processing nice processes in user mode + // * system – time spent executing kernel code + // * idle – time spent idle + // * iowait – time spent waiting for I/O + // * irq – time spent servicing interrupts + // * softirq – time spent servicing software interrupts + // * steal – time stolen from a virtual machine + // * guest – time spent running a virtual CPU for a guest operating system + // * guest_nice – time spent running a virtual CPU for a “niced” guest operating system + fn read_cpu_times(&self) -> io::Result { + let file = File::open("/proc/stat")?; + let reader = BufReader::new(file); + + for line in reader.lines() { + let line = line?; + if line.starts_with("cpu ") { + let fields: Vec = line.split_whitespace().skip(1).map(|s| s.parse().unwrap_or(0)).collect(); + + if fields.len() >= 8 { + return Ok(CpuTimes { + user: fields[0], + nice: fields[1], + system: fields[2], + idle: fields[3], + iowait: fields[4], + irq: fields[5], + softirq: fields[6], + steal: fields[7], + guest: if fields.len() > 8 { fields[8] } else { 0 }, + guest_nice: if fields.len() > 9 { fields[9] } else { 0 }, + }); + } + } + } + + Err(io::Error::new(io::ErrorKind::InvalidData, "Could not find cpu line in /proc/stat")) + } +} + +impl bar_modules::BarModuleActions for UnibarModuleCpu { + + // -------------------- + fn generate_data(&mut self) { + self.cpu_times_sample_1 = self.read_cpu_times().expect("REASON"); + thread::sleep(Duration::from_millis(1000)); + self.cpu_times_sample_2 = self.read_cpu_times().expect("REASON"); + + if self.opts.debug_json { + println!("-----> CPU times sample 1 - {:#?}", self.cpu_times_sample_1); + println!("-----> CPU times sample 2 - {:#?}", self.cpu_times_sample_2); + } + } + + // -------------------- + fn get_content(&self) -> String { + let sample_1_total = self.cpu_times_sample_1.total(); + let sample_2_total = self.cpu_times_sample_2.total(); + + let sample_1_idle = self.cpu_times_sample_1.idle(); + let sample_2_idle = self.cpu_times_sample_2.idle(); + + let total_diff = sample_2_total - sample_1_total; + let idle_diff = sample_2_idle - sample_1_idle; + + if total_diff > 0 { + let cpu_usage = (1.0 - (idle_diff as f64 / total_diff as f64)) * 100.0; + return format!("{}%", cpu_usage.ceil() as i32); + } else { + return format!("CPU?"); + } + // let re = Regex::new(r"cpu\s+.*").unwrap(); + // let caps = re.captures(self.procstat_str.as_str()).unwrap(); + + // let cpu_line = caps.get(0).unwrap().as_str(); + // if self.opts.debug_json { + // println!("-----> CPU line - {:#?}", cpu_line); + // } + + // let binding = Regex::new(r"\s+").unwrap(); + // let mut parts :Vec<&str> = binding.split(cpu_line).collect(); + + // parts.remove(0); // Remove the 'cpu' part + + // let cpu_idle :f32 = parts[3].parse::().unwrap(); + // let mut cpu_total :f32 = 0.0; + // for usg in parts { + // cpu_total += usg.parse::().unwrap(); + // } + // return format!("{}%", (((cpu_total - cpu_idle)/cpu_total) * 100.0).ceil() as i32); + } + + // -------------------- + fn get_icon(&self) -> String { + return "💻".to_string(); + } +} + +impl bar_modules::BarModuleDebug for UnibarModuleCpu { + + // -------------------- + fn post_debug(&self) { + } +} diff --git a/src/bar_modules/mod.rs b/src/bar_modules/mod.rs index 9c364a4..96a0160 100644 --- a/src/bar_modules/mod.rs +++ b/src/bar_modules/mod.rs @@ -21,3 +21,4 @@ pub mod bar_module_weather; pub mod bar_module_music; pub mod bar_module_network; pub mod bar_module_memory; +pub mod bar_module_cpu; diff --git a/src/main.rs b/src/main.rs index 215dd94..bd71e48 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,6 +55,7 @@ impl Unibar { let bar_modules_enabled: Vec> = vec! [ Box::new(bar_modules::bar_module_music::UnibarModuleMusic::new(self.opts.clone())), Box::new(bar_modules::bar_module_memory::UnibarModuleMemory::new(self.opts.clone())), + Box::new(bar_modules::bar_module_cpu::UnibarModuleCpu::new(self.opts.clone())), Box::new(bar_modules::bar_module_network::UnibarModuleNetwork::new(self.opts.clone())), Box::new(bar_modules::bar_module_weather::UnibarModuleWeather::new(self.opts.clone())), ]; @@ -85,6 +86,7 @@ impl Unibar { Box::new(bar_modules::bar_module_music::UnibarModuleMusic::new(self.opts.clone())), Box::new(bar_modules::bar_module_memory::UnibarModuleMemory::new(self.opts.clone())), Box::new(bar_modules::bar_module_network::UnibarModuleNetwork::new(self.opts.clone())), + Box::new(bar_modules::bar_module_cpu::UnibarModuleCpu::new(self.opts.clone())), ]; for md in bar_modules_debugged { md.post_debug();