feature: Add support for displaying load average (#392)

This commit is contained in:
pvanheus 2021-03-13 03:03:25 +02:00 committed by GitHub
parent fd41c1367c
commit d8f8a92b55
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 79 additions and 3 deletions

View file

@ -16,8 +16,9 @@ use once_cell::sync::Lazy;
use std::{time::Instant, vec::Vec}; use std::{time::Instant, vec::Vec};
use crate::app::data_harvester::load_avg::LoadAvgHarvest;
use crate::{ use crate::{
data_harvester::{batteries, cpu, disks, mem, network, processes, temperature, Data}, data_harvester::{batteries, cpu, disks, load_avg, mem, network, processes, temperature, Data},
utils::gen_util::get_simple_byte_values, utils::gen_util::get_simple_byte_values,
}; };
use regex::Regex; use regex::Regex;
@ -30,6 +31,7 @@ pub struct TimedData {
pub rx_data: Value, pub rx_data: Value,
pub tx_data: Value, pub tx_data: Value,
pub cpu_data: Vec<Value>, pub cpu_data: Vec<Value>,
pub load_avg_data: [f32; 3],
pub mem_data: Option<Value>, pub mem_data: Option<Value>,
pub swap_data: Option<Value>, pub swap_data: Option<Value>,
} }
@ -52,6 +54,7 @@ pub struct DataCollection {
pub memory_harvest: mem::MemHarvest, pub memory_harvest: mem::MemHarvest,
pub swap_harvest: mem::MemHarvest, pub swap_harvest: mem::MemHarvest,
pub cpu_harvest: cpu::CpuHarvest, pub cpu_harvest: cpu::CpuHarvest,
pub load_avg_harvest: load_avg::LoadAvgHarvest,
pub process_harvest: Vec<processes::ProcessHarvest>, pub process_harvest: Vec<processes::ProcessHarvest>,
pub disk_harvest: Vec<disks::DiskHarvest>, pub disk_harvest: Vec<disks::DiskHarvest>,
pub io_harvest: disks::IOHarvest, pub io_harvest: disks::IOHarvest,
@ -71,6 +74,7 @@ impl Default for DataCollection {
memory_harvest: mem::MemHarvest::default(), memory_harvest: mem::MemHarvest::default(),
swap_harvest: mem::MemHarvest::default(), swap_harvest: mem::MemHarvest::default(),
cpu_harvest: cpu::CpuHarvest::default(), cpu_harvest: cpu::CpuHarvest::default(),
load_avg_harvest: load_avg::LoadAvgHarvest::default(),
process_harvest: Vec::default(), process_harvest: Vec::default(),
disk_harvest: Vec::default(), disk_harvest: Vec::default(),
io_harvest: disks::IOHarvest::default(), io_harvest: disks::IOHarvest::default(),
@ -143,6 +147,11 @@ impl DataCollection {
self.eat_cpu(cpu, &mut new_entry); self.eat_cpu(cpu, &mut new_entry);
} }
// Load Average
if let Some(load_avg) = harvested_data.load_avg {
self.eat_load_avg(load_avg, &mut new_entry);
}
// Temp // Temp
if let Some(temperature_sensors) = harvested_data.temperature_sensors { if let Some(temperature_sensors) = harvested_data.temperature_sensors {
self.eat_temp(temperature_sensors); self.eat_temp(temperature_sensors);
@ -228,6 +237,12 @@ impl DataCollection {
self.cpu_harvest = cpu.to_vec(); self.cpu_harvest = cpu.to_vec();
} }
fn eat_load_avg(&mut self, load_avg: LoadAvgHarvest, new_entry: &mut TimedData) {
new_entry.load_avg_data = load_avg;
self.load_avg_harvest = load_avg;
}
fn eat_temp(&mut self, temperature_sensors: Vec<temperature::TempHarvest>) { fn eat_temp(&mut self, temperature_sensors: Vec<temperature::TempHarvest>) {
// trace!("Eating temps."); // trace!("Eating temps.");
// TODO: [PO] To implement // TODO: [PO] To implement

View file

@ -19,6 +19,7 @@ use super::DataFilters;
pub mod batteries; pub mod batteries;
pub mod cpu; pub mod cpu;
pub mod disks; pub mod disks;
pub mod load_avg;
pub mod mem; pub mod mem;
pub mod network; pub mod network;
pub mod processes; pub mod processes;
@ -28,6 +29,7 @@ pub mod temperature;
pub struct Data { pub struct Data {
pub last_collection_time: Instant, pub last_collection_time: Instant,
pub cpu: Option<cpu::CpuHarvest>, pub cpu: Option<cpu::CpuHarvest>,
pub load_avg: Option<load_avg::LoadAvgHarvest>,
pub memory: Option<mem::MemHarvest>, pub memory: Option<mem::MemHarvest>,
pub swap: Option<mem::MemHarvest>, pub swap: Option<mem::MemHarvest>,
pub temperature_sensors: Option<Vec<temperature::TempHarvest>>, pub temperature_sensors: Option<Vec<temperature::TempHarvest>>,
@ -43,6 +45,7 @@ impl Default for Data {
Data { Data {
last_collection_time: Instant::now(), last_collection_time: Instant::now(),
cpu: None, cpu: None,
load_avg: None,
memory: None, memory: None,
swap: None, swap: None,
temperature_sensors: None, temperature_sensors: None,
@ -64,6 +67,7 @@ impl Data {
self.memory = None; self.memory = None;
self.swap = None; self.swap = None;
self.cpu = None; self.cpu = None;
self.load_avg = None;
if let Some(network) = &mut self.network { if let Some(network) = &mut self.network {
network.first_run_cleanup(); network.first_run_cleanup();
@ -248,6 +252,14 @@ impl DataCollector {
self.data.cpu = Some(cpu_data); self.data.cpu = Some(cpu_data);
} }
} }
#[cfg(target_family = "unix")]
{
// Load Average
if let Ok(load_avg_data) = load_avg::get_load_avg().await {
self.data.load_avg = Some(load_avg_data);
}
}
} }
// Batteries // Batteries

View file

@ -0,0 +1,12 @@
pub type LoadAvgHarvest = [f32; 3];
#[cfg(target_family = "unix")]
pub async fn get_load_avg() -> crate::error::Result<LoadAvgHarvest> {
let (one, five, fifteen) = heim::cpu::os::unix::loadavg().await?;
Ok([
one.get::<heim::units::ratio::ratio>(),
five.get::<heim::units::ratio::ratio>(),
fifteen.get::<heim::units::ratio::ratio>(),
])
}

View file

@ -222,6 +222,7 @@ fn main() -> Result<()> {
&mut app.canvas_data.cpu_data, &mut app.canvas_data.cpu_data,
false, false,
); );
app.canvas_data.load_avg_data = app.data_collection.load_avg_harvest;
} }
// Processes // Processes

View file

@ -56,6 +56,7 @@ pub struct DisplayableData {
pub mem_data: Vec<Point>, pub mem_data: Vec<Point>,
pub swap_data: Vec<Point>, pub swap_data: Vec<Point>,
pub load_avg_data: [f32; 3],
pub cpu_data: Vec<ConvertedCpuData>, pub cpu_data: Vec<ConvertedCpuData>,
pub battery_data: Vec<ConvertedBatteryData>, pub battery_data: Vec<ConvertedBatteryData>,
} }

View file

@ -247,8 +247,42 @@ impl CpuGraphWidget for Painter {
self.colours.border_style self.colours.border_style
}; };
let title = if app_state.is_expanded { let title = if cfg!(target_family = "unix") {
let load_avg = app_state.canvas_data.load_avg_data;
let load_avg_str = format!(
"─ {:.2} {:.2} {:.2} ",
load_avg[0], load_avg[1], load_avg[2]
);
let load_avg_str_size =
UnicodeSegmentation::graphemes(load_avg_str.as_str(), true).count();
if app_state.is_expanded {
const TITLE_BASE: &str = " CPU ── Esc to go back "; const TITLE_BASE: &str = " CPU ── Esc to go back ";
Spans::from(vec![
Span::styled(" CPU ", self.colours.widget_title_style),
Span::styled(load_avg_str, self.colours.widget_title_style),
Span::styled(
format!(
"─{}─ Esc to go back ",
"".repeat(usize::from(draw_loc.width).saturating_sub(
load_avg_str_size
+ UnicodeSegmentation::graphemes(TITLE_BASE, true).count()
+ 2
))
),
border_style,
),
])
} else {
Spans::from(vec![
Span::styled(" CPU ", self.colours.widget_title_style),
Span::styled(load_avg_str, self.colours.widget_title_style),
])
}
} else if app_state.is_expanded {
const TITLE_BASE: &str = " CPU ── Esc to go back ";
Spans::from(vec![ Spans::from(vec![
Span::styled(" CPU ", self.colours.widget_title_style), Span::styled(" CPU ", self.colours.widget_title_style),
Span::styled( Span::styled(
@ -262,7 +296,7 @@ impl CpuGraphWidget for Painter {
), ),
]) ])
} else { } else {
Spans::from(Span::styled(" CPU ", self.colours.widget_title_style)) Spans::from(vec![Span::styled(" CPU ", self.colours.widget_title_style)])
}; };
f.render_widget( f.render_widget(

View file

@ -315,6 +315,7 @@ pub fn handle_force_redraws(app: &mut App) {
&mut app.canvas_data.cpu_data, &mut app.canvas_data.cpu_data,
app.is_frozen, app.is_frozen,
); );
app.canvas_data.load_avg_data = app.data_collection.load_avg_harvest;
app.cpu_state.force_update = None; app.cpu_state.force_update = None;
} }