Mercurial > lbo > hg > myi3stat
view src/metrics/cpu_load.rs @ 32:11e03e26ace0
Use better value extraction for load
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Thu, 18 Feb 2016 15:23:05 +0100 |
parents | 432a454037aa |
children |
line wrap: on
line source
use framework::*; use helper::{get_procfs_file_lines, extract_from_str}; extern crate regex; use self::regex::Regex; extern crate libc; #[derive(PartialEq)] enum DisplayMode { Absolute, Relative, } struct CPULoadMetric { mode: DisplayMode, ncpu: i32, user_hz: u64, last_cpu_millis: u64, individual_cpu_regex: Regex, total_cpu_regex: Regex, } impl CPULoadMetric { fn new() -> CPULoadMetric { use self::libc::{sysconf, _SC_CLK_TCK}; CPULoadMetric { mode: DisplayMode::Absolute, ncpu: 1, user_hz: unsafe { sysconf(_SC_CLK_TCK) } as u64, last_cpu_millis: 0, individual_cpu_regex: Regex::new(r"^cpu(\d+)\s+").unwrap(), // user nice system total_cpu_regex: Regex::new(r"^cpu\s+(\d+)\s+(\d+)\s+(\d+)").unwrap(), } } fn get_number_of_cores(&self) -> i32 { let lines = get_procfs_file_lines(String::from("/stat")); match lines { None => 1, Some(lns) => { let mut n = 0; for line in lns { if self.individual_cpu_regex.is_match(&line) { n += 1; } else if n > 0 { break; } } n } } } fn get_total_cpu_millis(&self) -> u64 { let lines = get_procfs_file_lines(String::from("/stat")).unwrap_or(Vec::new()); for line in lines { let nums: Vec<u64> = extract_from_str(&line, &self.total_cpu_regex, 0); if nums.len() < 3 { continue; } return self.calc_total_cpu_millis(nums[0], nums[1], nums[2]); } return 0; } fn calc_total_cpu_millis(&self, user: u64, nice: u64, sys: u64) -> u64 { return (1000 / self.user_hz) * (user + nice + sys); } } impl Metric for CPULoadMetric { // arg can be "abs" or "rel" (default is 'abs') // "abs" means that a fully loaded CPU has a load of #cores * 100% // "rel" means that a fully loaded CPU has a load of 100%. fn init(&mut self, _: &mut MetricState, arg: Option<String>) { match arg { None => (), Some(s) => { if s == "rel" { self.mode = DisplayMode::Relative; } } } self.ncpu = self.get_number_of_cores(); } fn render(&mut self, st: &mut MetricState) -> RenderResult { // evaluation interval in milliseconds let interval = MetricState::now() - st.last_called; let current_time = self.get_total_cpu_millis(); let diff = current_time - self.last_cpu_millis; self.last_cpu_millis = current_time; let mut percentage = 100f64 * (diff as f64 / interval as f64); if self.mode == DisplayMode::Relative { percentage /= self.ncpu as f64; } RenderResult::new(format!("{:4.0}%", percentage), Color::Default) } } pub fn make_cpu_load_metric() -> Box<Metric> { Box::new(CPULoadMetric::new()) }