diff options
author | gennyble <gen@nyble.dev> | 2025-02-25 19:21:59 -0600 |
---|---|---|
committer | gennyble <gen@nyble.dev> | 2025-02-25 19:21:59 -0600 |
commit | 337b1faeeb414c5dad9a1b2cf80460a5e74eacbe (patch) | |
tree | 39c5d8e630672c4ffc51488556184c4fc3f189a4 | |
parent | f9df72033b29ed08811ac87d1ef22002eac4b992 (diff) | |
download | awake-337b1faeeb414c5dad9a1b2cf80460a5e74eacbe.tar.gz awake-337b1faeeb414c5dad9a1b2cf80460a5e74eacbe.zip |
Make CPU graph better
-rw-r--r-- | src/db.rs | 5 | ||||
-rw-r--r-- | src/gatherer.rs | 43 | ||||
-rw-r--r-- | src/griph/mod.rs | 25 | ||||
-rwxr-xr-x | src/main.rs | 9 |
4 files changed, 71 insertions, 11 deletions
diff --git a/src/db.rs b/src/db.rs index 9a0256a..0abf722 100644 --- a/src/db.rs +++ b/src/db.rs @@ -238,4 +238,9 @@ impl DbCpuinfo { let avg = used_sum as f32 / self.span_sec as f32; avg } + + /// The sum of the user, nice, and system deltas + pub fn usage_sum(&self) -> usize { + self.user_delta + self.nice_delta + self.system_delta + } } diff --git a/src/gatherer.rs b/src/gatherer.rs index 7289f60..53e46f1 100644 --- a/src/gatherer.rs +++ b/src/gatherer.rs @@ -10,7 +10,11 @@ use std::{ use regex_lite::Regex; use time::OffsetDateTime; -use crate::{db::DbMeminfo, griph, AwakeState}; +use crate::{ + db::DbMeminfo, + griph::{self, Style}, + AwakeState, +}; pub struct Gatherer { state: AwakeState, @@ -124,7 +128,7 @@ pub fn make_mem_graph(state: &AwakeState) { // right side, so last in the array usages.reverse(); - let gif = griph::make_1line(0, max, &usages); + let gif = griph::make_1line(0, max, &usages, Style::Line); let path = state.cache_path.join("current_hostmeminfo.gif"); gif.save(path).unwrap(); @@ -162,7 +166,7 @@ pub fn make_net_graph(state: &AwakeState) { mixed.sort(); let kinda_highest = mixed[511 - 32]; - let high_bound = (kinda_highest as f32 / 256.0).ceil().min(1.0) as usize * 256; + let high_bound = (kinda_highest as f32 / 256.0).ceil().max(1.0) as usize * 256; state .netinfo_upper_bound .store(high_bound, Ordering::Release); @@ -180,14 +184,39 @@ pub fn make_cpu_graph(state: &AwakeState) { let now = OffsetDateTime::now_utc(); let cleaned = clean_series(&infos, |cpu| cpu.stamp, now); - // Scalling by 10 because the graph system does not like to have a max of only 100 due to some bad programming - let mut usages = extract(&cleaned, |cpu| (cpu.average_usage() * 10.0) as usize); + + // Usages are of the unit of hundreths of a second of CPU usage averaged over a minute. + // A value of 1 means the cpu saw 1% CPU usage + let usages = extract(&cleaned, |cpu| cpu.average_usage()); + + let mut zeroed: Vec<f32> = usages.iter().map(|m| m.unwrap_or(0.0)).collect(); + zeroed.sort_by(|a, b| a.partial_cmp(&b).unwrap()); + let kinda_highest = zeroed[255 - 8]; + + tracing::debug!( + "kinda_highest = {kinda_highest} // highest = {}", + zeroed[255] + ); + + // high_vound unit: hundreths of a second (1% / 1) + let high_bound = kinda_highest.max(1.0); + state + .cpuinfo_upper_bound + .store(high_bound as usize, Ordering::Release); + + // can't scale the range, so we have to scale the inputs. + // Finally, we multiply by ten to put it in a 0-1000 range + let scale_factor = 100.0 / high_bound; + let mut scaled: Vec<Option<usize>> = usages + .iter() + .map(|m| m.map(|v| (v * scale_factor) as usize * 10)) + .collect(); // Reversing here because we want latest valeus on on the // right side, so last in the array - usages.reverse(); + scaled.reverse(); - let gif = griph::make_1line(0, 1000, &usages); + let gif = griph::make_1line(0, 1000, &scaled, Style::UnderfilledLine); let path = state.cache_path.join("current_hostcpuinfo.gif"); gif.save(path).unwrap(); diff --git a/src/griph/mod.rs b/src/griph/mod.rs index b1449f5..636ffd9 100644 --- a/src/griph/mod.rs +++ b/src/griph/mod.rs @@ -10,6 +10,7 @@ pub const DARK_PALETTE: &[u8] = &[ 48, 192, 48, // Secondary 2 Colour - Green 96, 96, 224, // Primary Underfill - Light Blue 48, 128, 48, // Secondary Underfill - Lesser Green + 144, 144, 144 // Graphline Underfill - 16 * 9 gray ]; const BACKGROUND: u8 = 0; @@ -20,22 +21,40 @@ const LINE1: u8 = 4; const LINE2: u8 = 5; const LINE1_FILL: u8 = 6; const LINE2_FILL: u8 = 7; +const LINE_FILL: u8 = 8; const WIDTH: usize = 256; const HEIGHT: usize = 160; const SIZE: usize = WIDTH * HEIGHT; -pub fn make_1line(min: usize, max: usize, values: &[Option<usize>]) -> Gif { +pub enum Style { + Line, + UnderfilledLine, +} + +pub fn make_1line(min: usize, max: usize, values: &[Option<usize>], style: Style) -> Gif { let range = max - min; // this assumes a range of values that is >1 per pixel let vpp = range / HEIGHT; let mut raster = vec![0; SIZE]; + let mut standard = Gif::new(WIDTH as u16, HEIGHT as u16); + draw_grid(&mut raster); draw_line(&mut raster, values, vpp, LINE); - let mut standard = Gif::new(WIDTH as u16, HEIGHT as u16); - standard.set_palette(Some(DARK_PALETTE[0..12].try_into().unwrap())); + let plt = match style { + Style::Line => { + draw_line(&mut raster, values, vpp, LINE); + &DARK_PALETTE[0..12] + } + Style::UnderfilledLine => { + draw_line_underfill(&mut raster, values, vpp, LINE_FILL, LINE); + &DARK_PALETTE + } + }; + + standard.set_palette(Some(plt.try_into().unwrap())); standard.push( ImageBuilder::new(WIDTH as u16, HEIGHT as u16) .build(raster) diff --git a/src/main.rs b/src/main.rs index 5ba279f..d4faf9f 100755 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,7 @@ use std::{ os::unix::fs::MetadataExt, str::FromStr, sync::{ - atomic::{AtomicUsize, Ordering}, + atomic::{AtomicU8, AtomicUsize, Ordering}, Arc, }, time::Duration, @@ -55,7 +55,10 @@ pub struct AwakeState { pub do_statistics: bool, pub database: Arc<Database>, pub cache_path: Utf8PathBuf, + /// kbps pub netinfo_upper_bound: Arc<AtomicUsize>, + /// whole digit % cpu usage + pub cpuinfo_upper_bound: Arc<AtomicUsize>, } #[tokio::main] @@ -97,6 +100,7 @@ async fn main() { database: Arc::new(database), cache_path: cache.into(), netinfo_upper_bound: Arc::new(AtomicUsize::new(256)), + cpuinfo_upper_bound: Arc::new(AtomicUsize::new(100)), }; match std::env::args().nth(1).as_deref() { @@ -437,6 +441,9 @@ fn template_content(state: AwakeState, frontmatter: &Frontmatter, marked: String let netinfo_upper = state.netinfo_upper_bound.load(Ordering::Relaxed); doc.set("stats.net.max_bound", netinfo_upper); + + let cpuinfo_upper = state.cpuinfo_upper_bound.load(Ordering::Relaxed); + doc.set("stats.cpu.max_bound", cpuinfo_upper); } doc.compile() |