Mercurial > lbo > hg > myi3stat
changeset 28:e5c831894653
Add CPU load metric
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Tue, 16 Feb 2016 21:37:02 +0100 |
parents | 2e623c2fb4f1 |
children | 974108b35b11 |
files | src/main.rs src/metrics/cpu_load.rs src/metrics/mod.rs |
diffstat | 3 files changed, 130 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/main.rs Tue Feb 16 21:36:46 2016 +0100 +++ b/src/main.rs Tue Feb 16 21:37:02 2016 +0100 @@ -74,7 +74,7 @@ /// Returns a map of metric -> position in ordering list fn make_ordering_map(ord_list: String) -> BTreeMap<String, i32> { let parts = ord_list.split(","); - let mut i = 0; + let mut i = 1; let mut ordmap = BTreeMap::new(); for metric in parts { @@ -120,6 +120,7 @@ } fn register_metrics(registry: &mut AvailableMetrics) { + use metrics::cpu_load; use metrics::load; use metrics::net; use metrics::time; @@ -138,6 +139,12 @@ minutes.", "", load::make_load_metric()); + registry.register_metric("cpu_load", + "Shows the cpu load in percent over the last measure interval. abs \ + means: 4 core seconds = 400%; rel means (on a quadcore): 4 core \ + seconds = 100%", + "abs|rel", + cpu_load::make_cpu_load_metric()); } fn main() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/metrics/cpu_load.rs Tue Feb 16 21:37:02 2016 +0100 @@ -0,0 +1,121 @@ +use framework::*; +use helper::get_procfs_file_lines; + +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")); + + match lines { + None => return 0, + Some(lns) => { + for line in lns { + match self.total_cpu_regex.captures(&line) { + None => return 0, + Some(cpts) => { + return self.calc_total_cpu_millis(cpts.at(1).unwrap_or("0"), + cpts.at(2).unwrap_or("0"), + cpts.at(3).unwrap_or("0")) + } + } + } + } + } + return 0; + } + + fn calc_total_cpu_millis(&self, user: &str, nice: &str, sys: &str) -> u64 { + use std::str::FromStr; + return (1000 / self.user_hz) * + (u64::from_str(user).unwrap_or(0) + u64::from_str(nice).unwrap_or(0) + + u64::from_str(sys).unwrap_or(0)); + } +} + +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()) +}