Added CPU usage module

This commit is contained in:
Mahesh Asolkar 2025-06-06 17:50:16 -07:00
parent e6719dc6f5
commit c84e9698d7
Signed by: asolkar
GPG Key ID: 371CA8164433BDCC
3 changed files with 186 additions and 0 deletions

View File

@ -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<CpuTimes> {
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<u64> = 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::<f32>().unwrap();
// let mut cpu_total :f32 = 0.0;
// for usg in parts {
// cpu_total += usg.parse::<f32>().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) {
}
}

View File

@ -21,3 +21,4 @@ pub mod bar_module_weather;
pub mod bar_module_music; pub mod bar_module_music;
pub mod bar_module_network; pub mod bar_module_network;
pub mod bar_module_memory; pub mod bar_module_memory;
pub mod bar_module_cpu;

View File

@ -55,6 +55,7 @@ impl Unibar {
let bar_modules_enabled: Vec<Box<dyn bar_modules::BarModuleActions>> = vec! [ let bar_modules_enabled: Vec<Box<dyn bar_modules::BarModuleActions>> = vec! [
Box::new(bar_modules::bar_module_music::UnibarModuleMusic::new(self.opts.clone())), 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_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_network::UnibarModuleNetwork::new(self.opts.clone())),
Box::new(bar_modules::bar_module_weather::UnibarModuleWeather::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_music::UnibarModuleMusic::new(self.opts.clone())),
Box::new(bar_modules::bar_module_memory::UnibarModuleMemory::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_network::UnibarModuleNetwork::new(self.opts.clone())),
Box::new(bar_modules::bar_module_cpu::UnibarModuleCpu::new(self.opts.clone())),
]; ];
for md in bar_modules_debugged { for md in bar_modules_debugged {
md.post_debug(); md.post_debug();