summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2023-03-04 01:34:52 -0500
committerGitHub <noreply@github.com>2023-03-04 01:34:52 -0500
commit994c11e3b35a9ca56c5f20796dd55fd7cc739cee (patch)
treec29cf469085efabba650b7bfd9518cb1d2a517f6 /src
parentea318e83c94fab0786ac42d4560d3baffd86ffb3 (diff)
refactor: migrate network collection to sysinfo (#1041)
* refactor: migrate network collection to sysinfo * remove net feature from heim * comments and changelog
Diffstat (limited to 'src')
-rw-r--r--src/app.rs8
-rw-r--r--src/app/data_harvester.rs81
-rw-r--r--src/app/data_harvester/network.rs14
-rw-r--r--src/app/data_harvester/network/heim.rs67
-rw-r--r--src/app/data_harvester/network/sysinfo.rs27
-rw-r--r--src/app/filter.rs62
-rw-r--r--src/options.rs2
7 files changed, 106 insertions, 155 deletions
diff --git a/src/app.rs b/src/app.rs
index 7ae3a2c8..b83cabfa 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -7,6 +7,7 @@ use std::{
use concat_string::concat_string;
use data_farmer::*;
use data_harvester::temperature;
+use filter::*;
use layout_manager::*;
pub use states::*;
use typed_builder::*;
@@ -23,6 +24,7 @@ use crate::{
pub mod data_farmer;
pub mod data_harvester;
+pub mod filter;
pub mod frozen_state;
pub mod layout_manager;
mod process_killer;
@@ -81,12 +83,6 @@ pub struct DataFilters {
pub net_filter: Option<Filter>,
}
-#[derive(Debug, Clone)]
-pub struct Filter {
- pub is_list_ignored: bool,
- pub list: Vec<regex::Regex>,
-}
-
#[derive(TypedBuilder)]
pub struct App {
#[builder(default = false, setter(skip))]
diff --git a/src/app/data_harvester.rs b/src/app/data_harvester.rs
index fc8e090d..72009b29 100644
--- a/src/app/data_harvester.rs
+++ b/src/app/data_harvester.rs
@@ -160,19 +160,25 @@ impl DataCollector {
self.sys.refresh_memory();
self.mem_total_kb = self.sys.total_memory();
+ // Refresh network list once at the start.
+ // TODO: may be worth refreshing every once in a while (maybe on a separate timer).
+ if self.widgets_to_harvest.use_net {
+ self.sys.refresh_networks_list();
+ }
+
+ if self.widgets_to_harvest.use_proc || self.widgets_to_harvest.use_cpu {
+ self.sys.refresh_cpu();
+ }
+
#[cfg(not(target_os = "linux"))]
{
// TODO: Would be good to get this and network list running on a timer instead...?
+
// Refresh components list once...
if self.widgets_to_harvest.use_temp {
self.sys.refresh_components_list();
}
- // Refresh network list once...
- if cfg!(target_os = "windows") && self.widgets_to_harvest.use_net {
- self.sys.refresh_networks_list();
- }
-
if cfg!(target_os = "windows") && self.widgets_to_harvest.use_proc {
self.sys.refresh_users_list();
}
@@ -183,10 +189,6 @@ impl DataCollector {
}
}
- if self.widgets_to_harvest.use_proc || self.widgets_to_harvest.use_cpu {
- self.sys.refresh_cpu();
- }
-
#[cfg(feature = "battery")]
{
if self.widgets_to_harvest.use_battery {
@@ -238,6 +240,10 @@ impl DataCollector {
self.sys.refresh_memory();
}
+ if self.widgets_to_harvest.use_net {
+ self.sys.refresh_networks();
+ }
+
#[cfg(not(target_os = "linux"))]
{
if self.widgets_to_harvest.use_proc {
@@ -247,13 +253,6 @@ impl DataCollector {
self.sys.refresh_components();
}
- #[cfg(target_os = "windows")]
- {
- if self.widgets_to_harvest.use_net {
- self.sys.refresh_networks();
- }
- }
-
#[cfg(target_os = "freebsd")]
{
if self.widgets_to_harvest.use_disk {
@@ -392,31 +391,20 @@ impl DataCollector {
}
}
- let network_data_fut = {
- #[cfg(any(target_os = "windows", target_os = "freebsd"))]
- {
- network::get_network_data(
- &self.sys,
- self.last_collection_time,
- &mut self.total_rx,
- &mut self.total_tx,
- current_instant,
- self.widgets_to_harvest.use_net,
- &self.filters.net_filter,
- )
- }
- #[cfg(not(any(target_os = "windows", target_os = "freebsd")))]
- {
- network::get_network_data(
- self.last_collection_time,
- &mut self.total_rx,
- &mut self.total_tx,
- current_instant,
- self.widgets_to_harvest.use_net,
- &self.filters.net_filter,
- )
- }
- };
+ if self.widgets_to_harvest.use_net {
+ let net_data = network::get_network_data(
+ &self.sys,
+ self.last_collection_time,
+ &mut self.total_rx,
+ &mut self.total_tx,
+ current_instant,
+ &self.filters.net_filter,
+ );
+
+ self.total_rx = net_data.total_rx;
+ self.total_tx = net_data.total_tx;
+ self.data.network = Some(net_data);
+ }
let disk_data_fut = disks::get_disk_usage(
self.widgets_to_harvest.use_disk,
@@ -425,16 +413,7 @@ impl DataCollector {
);
let disk_io_usage_fut = disks::get_io_usage(self.widgets_to_harvest.use_disk);
- let (net_data, disk_res, io_res) =
- join!(network_data_fut, disk_data_fut, disk_io_usage_fut,);
-
- if let Ok(net_data) = net_data {
- if let Some(net_data) = &net_data {
- self.total_rx = net_data.total_rx;
- self.total_tx = net_data.total_tx;
- }
- self.data.network = net_data;
- }
+ let (disk_res, io_res) = join!(disk_data_fut, disk_io_usage_fut,);
if let Ok(disks) = disk_res {
self.data.disks = disks;
diff --git a/src/app/data_harvester/network.rs b/src/app/data_harvester/network.rs
index 3497ceca..b2faebca 100644
--- a/src/app/data_harvester/network.rs
+++ b/src/app/data_harvester/network.rs
@@ -1,17 +1,7 @@
//! Data collection for network usage/IO.
-//!
-//! For Linux and macOS, this is handled by Heim.
-//! For Windows, this is handled by sysinfo.
-cfg_if::cfg_if! {
- if #[cfg(any(target_os = "linux", target_os = "macos"))] {
- pub mod heim;
- pub use self::heim::*;
- } else if #[cfg(any(target_os = "freebsd", target_os = "windows"))] {
- pub mod sysinfo;
- pub use self::sysinfo::*;
- }
-}
+pub mod sysinfo;
+pub use self::sysinfo::*;
#[derive(Default, Clone, Debug)]
/// All units in bits.
diff --git a/src/app/data_harvester/network/heim.rs b/src/app/data_harvester/network/heim.rs
deleted file mode 100644
index 646c8528..00000000
--- a/src/app/data_harvester/network/heim.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-//! Gets network data via heim.
-
-use std::time::Instant;
-
-use super::NetworkHarvest;
-
-// TODO: Eventually make it so that this thing also takes individual usage into account, so we can show per-interface!
-pub async fn get_network_data(
- prev_net_access_time: Instant, prev_net_rx: &mut u64, prev_net_tx: &mut u64,
- curr_time: Instant, actually_get: bool, filter: &Option<crate::app::Filter>,
-) -> crate::utils::error::Result<Option<NetworkHarvest>> {
- use futures::StreamExt;
-
- if !actually_get {
- return Ok(None);
- }
-
- let io_data = heim::net::io_counters().await?;
- futures::pin_mut!(io_data);
- let mut total_rx: u64 = 0;
- let mut total_tx: u64 = 0;
-
- while let Some(io) = io_data.next().await {
- if let Ok(io) = io {
- let to_keep = if let Some(filter) = filter {
- let mut ret = filter.is_list_ignored;
- for r in &filter.list {
- if r.is_match(io.interface()) {
- ret = !filter.is_list_ignored;
- break;
- }
- }
- ret
- } else {
- true
- };
- if to_keep {
- // 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>();
- }
- }
- }
-
- let elapsed_time = curr_time.duration_since(prev_net_access_time).as_secs_f64();
-
- let (rx, tx) = if elapsed_time == 0.0 {
- (0, 0)
- } else {
- (
- ((total_rx.saturating_sub(*prev_net_rx)) as f64 / elapsed_time) as u64,
- ((total_tx.saturating_sub(*prev_net_tx)) as f64 / elapsed_time) as u64,
- )
- };
-
- *prev_net_rx = total_rx;
- *prev_net_tx = total_tx;
- Ok(Some(NetworkHarvest {
- rx,
- tx,
- total_rx,
- total_tx,
- }))
-}
diff --git a/src/app/data_harvester/network/sysinfo.rs b/src/app/data_harvester/network/sysinfo.rs
index e3aea9e7..ec21bd42 100644
--- a/src/app/data_harvester/network/sysinfo.rs
+++ b/src/app/data_harvester/network/sysinfo.rs
@@ -2,33 +2,24 @@
use std::time::Instant;
+use crate::app::Filter;
+
use super::NetworkHarvest;
-pub async fn get_network_data(
+// TODO: Eventually make it so that this thing also takes individual usage into account, so we can show per-interface!
+pub fn get_network_data(
sys: &sysinfo::System, prev_net_access_time: Instant, prev_net_rx: &mut u64,
- prev_net_tx: &mut u64, curr_time: Instant, actually_get: bool,
- filter: &Option<crate::app::Filter>,
-) -> crate::utils::error::Result<Option<NetworkHarvest>> {
+ prev_net_tx: &mut u64, curr_time: Instant, filter: &Option<Filter>,
+) -> NetworkHarvest {
use sysinfo::{NetworkExt, SystemExt};
- if !actually_get {
- return Ok(None);
- }
-
let mut total_rx: u64 = 0;
let mut total_tx: u64 = 0;
let networks = sys.networks();
for (name, network) in networks {
let to_keep = if let Some(filter) = filter {
- let mut ret = filter.is_list_ignored;
- for r in &filter.list {
- if r.is_match(name) {
- ret = !filter.is_list_ignored;
- break;
- }
- }
- ret
+ filter.keep_entry(name)
} else {
true
};
@@ -52,10 +43,10 @@ pub async fn get_network_data(
*prev_net_rx = total_rx;
*prev_net_tx = total_tx;
- Ok(Some(NetworkHarvest {
+ NetworkHarvest {
rx,
tx,
total_rx,
total_tx,
- }))
+ }
}
diff --git a/src/app/filter.rs b/src/app/filter.rs
new file mode 100644
index 00000000..b9695268
--- /dev/null
+++ b/src/app/filter.rs
@@ -0,0 +1,62 @@
+#[derive(Debug, Clone)]
+pub struct Filter {
+ // TODO: Maybe change to "ignore_matches"?
+ pub is_list_ignored: bool,
+ pub list: Vec<regex::Regex>,
+}
+
+impl Filter {
+ /// Whether the filter should keep the entry or reject it.
+ #[inline]
+ pub(crate) fn keep_entry(&self, value: &str) -> bool {
+ self.list
+ .iter()
+ .find(|regex| regex.is_match(value))
+ .map(|_| !self.is_list_ignored)
+ .unwrap_or(self.is_list_ignored)
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use regex::Regex;
+
+ use super::*;
+
+ /// Test based on the issue in <https://github.com/ClementTsang/bottom/pull/1037>.
+ #[test]
+ fn filter_is_list_ignored() {
+ let results = [
+ "CPU socket temperature",
+ "wifi_0",
+ "motherboard temperature",
+ "amd gpu",
+ ];
+
+ let ignore_true = Filter {
+ is_list_ignored: true,
+ list: vec![Regex::new("temperature").unwrap()],
+ };
+
+ assert_eq!(
+ results
+ .into_iter()
+ .filter(|r| ignore_true.keep_entry(r))
+ .collect::<Vec<_>>(),
+ vec!["wifi_0", "amd gpu"]
+ );
+
+ let ignore_false = Filter {
+ is_list_ignored: false,
+ list: vec![Regex::new("temperature").unwrap()],
+ };
+
+ assert_eq!(
+ results
+ .into_iter()
+ .filter(|r| ignore_false.keep_entry(r))
+ .collect::<Vec<_>>(),
+ vec!["CPU socket temperature", "motherboard temperature"]
+ );
+ }
+}
diff --git a/src/options.rs b/src/options.rs
index 1c001e44..0a620129 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -17,7 +17,7 @@ use starship_battery::Manager;
use typed_builder::*;
use crate::{
- app::{layout_manager::*, *},
+ app::{filter::Filter, layout_manager::*, *},
canvas::{canvas_styling::CanvasColours, ColourScheme},
constants::*,
units::data_units::DataUnit,