summaryrefslogtreecommitdiffstats
path: root/src/app
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2021-04-04 05:38:57 -0400
committerGitHub <noreply@github.com>2021-04-04 05:38:57 -0400
commiteb6a737d3430920061cd5e54bf4dc40da21f1fc5 (patch)
treeb329c4b729f31de80405b3a2d015c1525d80d618 /src/app
parent40f4c796f8d1832e7ef9db7c87db558a1ce12b62 (diff)
feature: Rework network y-axis, linear interpolation for off-screen data (#437)
Rewrite of the y-axis labeling and scaling for the network widget, along with more customization. This still has one step to be optimized (cache results so we don't have to recalculate the legend each time), but will be done in another PR for sake of this one being too large already. Furthermore, this change adds linear interpolation at the 0 point in the case a data point shoots too far back - this seems to have lead to ugly gaps to the left of graphs in some cases, because the left hand limit was not big enough for the data point. We address this by grabbing values just outside the time range and linearly interpolating at the leftmost limit. This affects all graph widgets (CPU, mem, network). This can be optimized, and will hopefully be prior to release in a separate change.
Diffstat (limited to 'src/app')
-rw-r--r--src/app/data_farmer.rs33
-rw-r--r--src/app/data_harvester.rs2
-rw-r--r--src/app/data_harvester/batteries.rs12
-rw-r--r--src/app/data_harvester/disks.rs10
-rw-r--r--src/app/data_harvester/network.rs13
-rw-r--r--src/app/data_harvester/processes.rs26
-rw-r--r--src/app/data_harvester/temperature.rs6
-rw-r--r--src/app/query.rs6
-rw-r--r--src/app/states.rs26
9 files changed, 67 insertions, 67 deletions
diff --git a/src/app/data_farmer.rs b/src/app/data_farmer.rs
index bfc7ae8d..4a2f470e 100644
--- a/src/app/data_farmer.rs
+++ b/src/app/data_farmer.rs
@@ -19,7 +19,7 @@ use std::{time::Instant, vec::Vec};
use crate::app::data_harvester::load_avg::LoadAvgHarvest;
use crate::{
data_harvester::{batteries, cpu, disks, load_avg, mem, network, processes, temperature, Data},
- utils::gen_util::get_simple_byte_values,
+ utils::gen_util::get_decimal_bytes,
};
use regex::Regex;
@@ -57,7 +57,7 @@ pub struct DataCollection {
pub load_avg_harvest: load_avg::LoadAvgHarvest,
pub process_harvest: Vec<processes::ProcessHarvest>,
pub disk_harvest: Vec<disks::DiskHarvest>,
- pub io_harvest: disks::IOHarvest,
+ pub io_harvest: disks::IoHarvest,
pub io_labels_and_prev: Vec<((u64, u64), (u64, u64))>,
pub io_labels: Vec<(String, String)>,
pub temp_harvest: Vec<temperature::TempHarvest>,
@@ -77,7 +77,7 @@ impl Default for DataCollection {
load_avg_harvest: load_avg::LoadAvgHarvest::default(),
process_harvest: Vec::default(),
disk_harvest: Vec::default(),
- io_harvest: disks::IOHarvest::default(),
+ io_harvest: disks::IoHarvest::default(),
io_labels_and_prev: Vec::default(),
io_labels: Vec::default(),
temp_harvest: Vec::default(),
@@ -95,7 +95,7 @@ impl DataCollection {
self.cpu_harvest = cpu::CpuHarvest::default();
self.process_harvest = Vec::default();
self.disk_harvest = Vec::default();
- self.io_harvest = disks::IOHarvest::default();
+ self.io_harvest = disks::IoHarvest::default();
self.io_labels_and_prev = Vec::default();
self.temp_harvest = Vec::default();
self.battery_harvest = Vec::default();
@@ -205,22 +205,15 @@ impl DataCollection {
}
fn eat_network(&mut self, network: network::NetworkHarvest, new_entry: &mut TimedData) {
- // trace!("Eating network.");
- // FIXME [NETWORKING; CONFIG]: The ability to config this?
- // FIXME [NETWORKING]: Support bits, support switching between decimal and binary units (move the log part to conversion and switch on the fly)
// RX
- new_entry.rx_data = if network.rx > 0 {
- (network.rx as f64).log2()
- } else {
- 0.0
- };
+ if network.rx > 0 {
+ new_entry.rx_data = network.rx as f64;
+ }
// TX
- new_entry.tx_data = if network.tx > 0 {
- (network.tx as f64).log2()
- } else {
- 0.0
- };
+ if network.tx > 0 {
+ new_entry.tx_data = network.tx as f64;
+ }
// In addition copy over latest data for easy reference
self.network_harvest = network;
@@ -250,7 +243,7 @@ impl DataCollection {
}
fn eat_disks(
- &mut self, disks: Vec<disks::DiskHarvest>, io: disks::IOHarvest, harvested_time: Instant,
+ &mut self, disks: Vec<disks::DiskHarvest>, io: disks::IoHarvest, harvested_time: Instant,
) {
// trace!("Eating disks.");
// TODO: [PO] To implement
@@ -300,8 +293,8 @@ impl DataCollection {
*io_prev = (io_r_pt, io_w_pt);
if let Some(io_labels) = self.io_labels.get_mut(itx) {
- let converted_read = get_simple_byte_values(r_rate, false);
- let converted_write = get_simple_byte_values(w_rate, false);
+ let converted_read = get_decimal_bytes(r_rate);
+ let converted_write = get_decimal_bytes(w_rate);
*io_labels = (
format!("{:.*}{}/s", 0, converted_read.0, converted_read.1),
format!("{:.*}{}/s", 0, converted_write.0, converted_write.1),
diff --git a/src/app/data_harvester.rs b/src/app/data_harvester.rs
index 3b7a0f63..207bb23a 100644
--- a/src/app/data_harvester.rs
+++ b/src/app/data_harvester.rs
@@ -36,7 +36,7 @@ pub struct Data {
pub network: Option<network::NetworkHarvest>,
pub list_of_processes: Option<Vec<processes::ProcessHarvest>>,
pub disks: Option<Vec<disks::DiskHarvest>>,
- pub io: Option<disks::IOHarvest>,
+ pub io: Option<disks::IoHarvest>,
pub list_of_batteries: Option<Vec<batteries::BatteryHarvest>>,
}
diff --git a/src/app/data_harvester/batteries.rs b/src/app/data_harvester/batteries.rs
index 66e3c76b..98cf6ae6 100644
--- a/src/app/data_harvester/batteries.rs
+++ b/src/app/data_harvester/batteries.rs
@@ -20,19 +20,11 @@ pub fn refresh_batteries(manager: &Manager, batteries: &mut [Battery]) -> Vec<Ba
Some(BatteryHarvest {
secs_until_full: {
let optional_time = battery.time_to_full();
- if let Some(time) = optional_time {
- Some(f64::from(time.get::<second>()) as i64)
- } else {
- None
- }
+ optional_time.map(|time| f64::from(time.get::<second>()) as i64)
},
secs_until_empty: {
let optional_time = battery.time_to_empty();
- if let Some(time) = optional_time {
- Some(f64::from(time.get::<second>()) as i64)
- } else {
- None
- }
+ optional_time.map(|time| f64::from(time.get::<second>()) as i64)
},
charge_percent: f64::from(battery.state_of_charge().get::<percent>()),
power_consumption_rate_watts: f64::from(battery.energy_rate().get::<watt>()),
diff --git a/src/app/data_harvester/disks.rs b/src/app/data_harvester/disks.rs
index 246f5b5d..ba1d2d49 100644
--- a/src/app/data_harvester/disks.rs
+++ b/src/app/data_harvester/disks.rs
@@ -10,21 +10,21 @@ pub struct DiskHarvest {
}
#[derive(Clone, Debug)]
-pub struct IOData {
+pub struct IoData {
pub read_bytes: u64,
pub write_bytes: u64,
}
-pub type IOHarvest = std::collections::HashMap<String, Option<IOData>>;
+pub type IoHarvest = std::collections::HashMap<String, Option<IoData>>;
-pub async fn get_io_usage(actually_get: bool) -> crate::utils::error::Result<Option<IOHarvest>> {
+pub async fn get_io_usage(actually_get: bool) -> crate::utils::error::Result<Option<IoHarvest>> {
if !actually_get {
return Ok(None);
}
use futures::StreamExt;
- let mut io_hash: std::collections::HashMap<String, Option<IOData>> =
+ let mut io_hash: std::collections::HashMap<String, Option<IoData>> =
std::collections::HashMap::new();
let counter_stream = heim::disk::io_counters().await?;
@@ -37,7 +37,7 @@ pub async fn get_io_usage(actually_get: bool) -> crate::utils::error::Result<Opt
// FIXME: [MOUNT POINT] Add the filter here I guess?
io_hash.insert(
mount_point.to_string(),
- Some(IOData {
+ Some(IoData {
read_bytes: io.read_bytes().get::<heim::units::information::byte>(),
write_bytes: io.write_bytes().get::<heim::units::information::byte>(),
}),
diff --git a/src/app/data_harvester/network.rs b/src/app/data_harvester/network.rs
index 55d757f6..52dc8468 100644
--- a/src/app/data_harvester/network.rs
+++ b/src/app/data_harvester/network.rs
@@ -1,6 +1,7 @@
use std::time::Instant;
#[derive(Default, Clone, Debug)]
+/// All units in bits.
pub struct NetworkHarvest {
pub rx: u64,
pub tx: u64,
@@ -47,8 +48,8 @@ pub async fn get_network_data(
};
if to_keep {
- total_rx += network.get_total_received();
- total_tx += network.get_total_transmitted();
+ total_rx += network.get_total_received() * 8;
+ total_tx += network.get_total_transmitted() * 8;
}
}
@@ -106,8 +107,12 @@ pub async fn get_network_data(
};
if to_keep {
- total_rx += io.bytes_recv().get::<heim::units::information::byte>();
- total_tx += io.bytes_sent().get::<heim::units::information::byte>();
+ // TODO: Use bytes as the default instead, perhaps?
+ // Since you might have to do a double conversion (bytes -> bits -> bytes) in some cases;
+ // but if you stick to bytes, then in the bytes, case, you do no conversion, and in the bits case,
+ // you only do one conversion...
+ total_rx += io.bytes_recv().get::<heim::units::information::bit>();
+ total_tx += io.bytes_sent().get::<heim::units::information::bit>();
}
}
}
diff --git a/src/app/data_harvester/processes.rs b/src/app/data_harvester/processes.rs
index 4d7beda0..52e80c27 100644
--- a/src/app/data_harvester/processes.rs
+++ b/src/app/data_harvester/processes.rs
@@ -2,6 +2,9 @@ use crate::Pid;
use std::path::PathBuf;
use sysinfo::ProcessStatus;
+#[cfg(target_os = "linux")]
+use std::path::Path;
+
#[cfg(target_family = "unix")]
use crate::utils::error;
@@ -168,7 +171,7 @@ fn cpu_usage_calculation(
// SC in case that the parsing will fail due to length:
if val.len() <= 10 {
- return Err(error::BottomError::InvalidIO(format!(
+ return Err(error::BottomError::InvalidIo(format!(
"CPU parsing will fail due to too short of a return value; saw {} values, expected 10 values.",
val.len()
)));
@@ -222,8 +225,8 @@ fn get_linux_process_vsize_rss(stat: &[&str]) -> (u64, u64) {
#[cfg(target_os = "linux")]
/// Preferably use this only on small files.
-fn read_path_contents(path: &PathBuf) -> std::io::Result<String> {
- Ok(std::fs::read_to_string(path)?)
+fn read_path_contents(path: &Path) -> std::io::Result<String> {
+ std::fs::read_to_string(path)
}
#[cfg(target_os = "linux")]
@@ -272,9 +275,8 @@ fn get_macos_cpu_usage(pids: &[i32]) -> std::io::Result<std::collections::HashMa
let output = std::process::Command::new("ps")
.args(&["-o", "pid=,pcpu=", "-p"])
.arg(
- pids.iter()
- .map(i32::to_string)
- .intersperse(",".to_string())
+ // Has to look like this since otherwise, it you hit a `unstable_name_collisions` warning.
+ Itertools::intersperse(pids.iter().map(i32::to_string), ",".to_string())
.collect::<String>(),
)
.output()?;
@@ -298,7 +300,7 @@ fn get_macos_cpu_usage(pids: &[i32]) -> std::io::Result<std::collections::HashMa
}
#[cfg(target_os = "linux")]
-fn get_uid_and_gid(path: &PathBuf) -> (Option<u32>, Option<u32>) {
+fn get_uid_and_gid(path: &Path) -> (Option<u32>, Option<u32>) {
// FIXME: [OPT] - can we merge our /stat and /status calls?
use std::io::prelude::*;
use std::io::BufReader;
@@ -470,15 +472,15 @@ fn read_proc(
Ok(ProcessHarvest {
pid,
parent_pid,
- name,
- command,
+ cpu_usage_percent,
mem_usage_percent,
mem_usage_bytes,
- cpu_usage_percent,
- total_read_bytes,
- total_write_bytes,
+ name,
+ command,
read_bytes_per_sec,
write_bytes_per_sec,
+ total_read_bytes,
+ total_write_bytes,
process_state,
process_state_char,
uid,
diff --git a/src/app/data_harvester/temperature.rs b/src/app/data_harvester/temperature.rs
index 1c818e31..3786adc7 100644
--- a/src/app/data_harvester/temperature.rs
+++ b/src/app/data_harvester/temperature.rs
@@ -95,11 +95,7 @@ pub async fn get_temperature_data(
while let Some(sensor) = sensor_data.next().await {
if let Ok(sensor) = sensor {
let component_name = Some(sensor.unit().to_string());
- let component_label = if let Some(label) = sensor.label() {
- Some(label.to_string())
- } else {
- None
- };
+ let component_label = sensor.label().map(|label| label.to_string());
let name = match (component_name, component_label) {
(Some(name), Some(label)) => format!("{}: {}", name, label),
diff --git a/src/app/query.rs b/src/app/query.rs
index 5a827aec..a783c658 100644
--- a/src/app/query.rs
+++ b/src/app/query.rs
@@ -188,11 +188,7 @@ impl ProcessQuery for ProcWidgetState {
let initial_or = Or {
lhs: And {
lhs: Prefix {
- or: if let Some(or) = list_of_ors.pop_front() {
- Some(Box::new(or))
- } else {
- None
- },
+ or: list_of_ors.pop_front().map(Box::new),
compare_prefix: None,
regex_prefix: None,
},
diff --git a/src/app/states.rs b/src/app/states.rs
index 39dd0222..c8af1737 100644
--- a/src/app/states.rs
+++ b/src/app/states.rs
@@ -42,18 +42,18 @@ pub struct AppScrollWidgetState {
#[derive(PartialEq)]
pub enum KillSignal {
- CANCEL,
- KILL(usize),
+ Cancel,
+ Kill(usize),
}
impl Default for KillSignal {
#[cfg(target_family = "unix")]
fn default() -> Self {
- KillSignal::KILL(15)
+ KillSignal::Kill(15)
}
#[cfg(target_os = "windows")]
fn default() -> Self {
- KillSignal::KILL(1)
+ KillSignal::Kill(1)
}
}
@@ -690,13 +690,29 @@ impl ProcState {
pub struct NetWidgetState {
pub current_display_time: u64,
pub autohide_timer: Option<Instant>,
+ // pub draw_max_range_cache: f64,
+ // pub draw_labels_cache: Vec<String>,
+ // pub draw_time_start_cache: f64,
+ // TODO: Re-enable these when we move net details state-side!
+ // pub unit_type: DataUnitTypes,
+ // pub scale_type: AxisScaling,
}
impl NetWidgetState {
- pub fn init(current_display_time: u64, autohide_timer: Option<Instant>) -> Self {
+ pub fn init(
+ current_display_time: u64,
+ autohide_timer: Option<Instant>,
+ // unit_type: DataUnitTypes,
+ // scale_type: AxisScaling,
+ ) -> Self {
NetWidgetState {
current_display_time,
autohide_timer,
+ // draw_max_range_cache: 0.0,
+ // draw_labels_cache: vec![],
+ // draw_time_start_cache: 0.0,
+ // unit_type,
+ // scale_type,
}
}
}