diff options
author | Clement Tsang <34804052+ClementTsang@users.noreply.github.com> | 2021-01-01 18:09:28 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-01 18:09:28 -0500 |
commit | 90be9730a62e2a935ccf01cdd6e320c65624722a (patch) | |
tree | b22a66210a2af97f0ced92dc27d89a6ad2137f63 /src/app | |
parent | d8d72d060d4bd4473bfe769673a2227bda948c97 (diff) |
feature: Add network interface filtering (#381)
Adds a new option in the config file to filter out network interfaces. Also add the option to filter by whole words.
Interface follows that of the existing ones:
```toml
[net_filter]
is_list_ignored = false
list = ["virbr0.*"]
regex = true
case_sensitive = false
whole_word = false
```
Diffstat (limited to 'src/app')
-rw-r--r-- | src/app/data_harvester.rs | 23 | ||||
-rw-r--r-- | src/app/data_harvester/disks.rs | 113 | ||||
-rw-r--r-- | src/app/data_harvester/network.rs | 44 | ||||
-rw-r--r-- | src/app/data_harvester/temperature.rs | 116 |
4 files changed, 189 insertions, 107 deletions
diff --git a/src/app/data_harvester.rs b/src/app/data_harvester.rs index 63d9a07c..0fc8c6a5 100644 --- a/src/app/data_harvester.rs +++ b/src/app/data_harvester.rs @@ -14,6 +14,8 @@ use crate::app::layout_manager::UsedWidgets; use futures::join; +use super::DataFilters; + pub mod batteries; pub mod cpu; pub mod disks; @@ -96,15 +98,15 @@ pub struct DataCollector { battery_list: Option<Vec<Battery>>, #[cfg(target_os = "linux")] page_file_size_kb: u64, + filters: DataFilters, } -impl Default for DataCollector { - fn default() -> Self { - // trace!("Creating default data collector..."); +impl DataCollector { + pub fn new(filters: DataFilters) -> Self { DataCollector { data: Data::default(), #[cfg(not(target_os = "linux"))] - sys: System::new_with_specifics(sysinfo::RefreshKind::new()), // FIXME: Make this run on only macOS and Windows. + sys: System::new_with_specifics(sysinfo::RefreshKind::new()), #[cfg(target_os = "linux")] previous_cpu_times: vec![], #[cfg(target_os = "linux")] @@ -132,11 +134,10 @@ impl Default for DataCollector { // page_file_size_kb libc::sysconf(libc::_SC_PAGESIZE) as u64 / 1024 }, + filters, } } -} -impl DataCollector { pub fn init(&mut self) { #[cfg(target_os = "linux")] { @@ -147,6 +148,7 @@ impl DataCollector { self.sys.refresh_memory(); self.mem_total_kb = self.sys.get_total_memory(); + // 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(); @@ -295,6 +297,7 @@ impl DataCollector { &mut self.total_tx, current_instant, self.widgets_to_harvest.use_net, + &self.filters.net_filter, ) } #[cfg(not(target_os = "windows"))] @@ -305,12 +308,14 @@ impl DataCollector { &mut self.total_tx, current_instant, self.widgets_to_harvest.use_net, + &self.filters.net_filter, ) } }; let mem_data_fut = mem::get_mem_data(self.widgets_to_harvest.use_mem); - let disk_data_fut = disks::get_disk_usage(self.widgets_to_harvest.use_disk); - let disk_io_usage_fut = disks::get_io_usage(false, self.widgets_to_harvest.use_disk); + let disk_data_fut = + disks::get_disk_usage(self.widgets_to_harvest.use_disk, &self.filters.disk_filter); + let disk_io_usage_fut = disks::get_io_usage(self.widgets_to_harvest.use_disk); let temp_data_fut = { #[cfg(not(target_os = "linux"))] { @@ -318,6 +323,7 @@ impl DataCollector { &self.sys, &self.temperature_type, self.widgets_to_harvest.use_temp, + &self.filters.temp_filter, ) } @@ -326,6 +332,7 @@ impl DataCollector { temperature::get_temperature_data( &self.temperature_type, self.widgets_to_harvest.use_temp, + &self.filters.temp_filter, ) } }; diff --git a/src/app/data_harvester/disks.rs b/src/app/data_harvester/disks.rs index 8c447a46..5a67a909 100644 --- a/src/app/data_harvester/disks.rs +++ b/src/app/data_harvester/disks.rs @@ -1,3 +1,5 @@ +use crate::app::Filter; + #[derive(Debug, Clone, Default)] pub struct DiskHarvest { pub name: String, @@ -15,9 +17,7 @@ pub struct IOData { pub type IOHarvest = std::collections::HashMap<String, Option<IOData>>; -pub async fn get_io_usage( - get_physical: bool, 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); } @@ -26,37 +26,23 @@ pub async fn get_io_usage( let mut io_hash: std::collections::HashMap<String, Option<IOData>> = std::collections::HashMap::new(); - if get_physical { - let physical_counter_stream = heim::disk::io_counters_physical().await?; - futures::pin_mut!(physical_counter_stream); - - while let Some(io) = physical_counter_stream.next().await { - if let Ok(io) = io { - let mount_point = io.device_name().to_str().unwrap_or("Name Unavailable"); - io_hash.insert( - mount_point.to_string(), - Some(IOData { - read_bytes: io.read_bytes().get::<heim::units::information::megabyte>(), - write_bytes: io.write_bytes().get::<heim::units::information::megabyte>(), - }), - ); - } - } - } else { - let counter_stream = heim::disk::io_counters().await?; - futures::pin_mut!(counter_stream); - - while let Some(io) = counter_stream.next().await { - if let Ok(io) = io { - let mount_point = io.device_name().to_str().unwrap_or("Name Unavailable"); - io_hash.insert( - mount_point.to_string(), - Some(IOData { - read_bytes: io.read_bytes().get::<heim::units::information::byte>(), - write_bytes: io.write_bytes().get::<heim::units::information::byte>(), - }), - ); - } + + let counter_stream = heim::disk::io_counters().await?; + futures::pin_mut!(counter_stream); + + while let Some(io) = counter_stream.next().await { + if let Ok(io) = io { + let mount_point = io.device_name().to_str().unwrap_or("Name Unavailable"); + + // FIXME: [MOUNT POINT] Add the filter here I guess? + + io_hash.insert( + mount_point.to_string(), + Some(IOData { + read_bytes: io.read_bytes().get::<heim::units::information::byte>(), + write_bytes: io.write_bytes().get::<heim::units::information::byte>(), + }), + ); } } @@ -64,7 +50,7 @@ pub async fn get_io_usage( } pub async fn get_disk_usage( - actually_get: bool, + actually_get: bool, name_filter: &Option<Filter>, ) -> crate::utils::error::Result<Option<Vec<DiskHarvest>>> { if !actually_get { return Ok(None); @@ -77,26 +63,43 @@ pub async fn get_disk_usage( futures::pin_mut!(partitions_stream); while let Some(part) = partitions_stream.next().await { - if let Ok(part) = part { - let partition = part; - let usage = heim::disk::usage(partition.mount_point().to_path_buf()).await?; - - vec_disks.push(DiskHarvest { - free_space: usage.free().get::<heim::units::information::byte>(), - used_space: usage.used().get::<heim::units::information::byte>(), - total_space: usage.total().get::<heim::units::information::byte>(), - mount_point: (partition - .mount_point() - .to_str() - .unwrap_or("Name Unavailable")) - .to_string(), - name: (partition - .device() - .unwrap_or_else(|| std::ffi::OsStr::new("Name Unavailable")) - .to_str() - .unwrap_or("Name Unavailable")) - .to_string(), - }); + if let Ok(partition) = part { + let name = (partition + .device() + .unwrap_or_else(|| std::ffi::OsStr::new("Name Unavailable")) + .to_str() + .unwrap_or("Name Unavailable")) + .to_string(); + + let mount_point = (partition + .mount_point() + .to_str() + .unwrap_or("Name Unavailable")) + .to_string(); + + let to_keep = if let Some(filter) = name_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 + } else { + true + }; + + if to_keep { + let usage = heim::disk::usage(partition.mount_point().to_path_buf()).await?; + vec_disks.push(DiskHarvest { + free_space: usage.free().get::<heim::units::information::byte>(), + used_space: usage.used().get::<heim::units::information::byte>(), + total_space: usage.total().get::<heim::units::information::byte>(), + mount_point, + name, + }); + } } } diff --git a/src/app/data_harvester/network.rs b/src/app/data_harvester/network.rs index dcb496cd..55d757f6 100644 --- a/src/app/data_harvester/network.rs +++ b/src/app/data_harvester/network.rs @@ -20,6 +20,7 @@ impl NetworkHarvest { pub async 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>> { use sysinfo::{NetworkExt, SystemExt}; @@ -31,9 +32,24 @@ pub async fn get_network_data( let mut total_tx: u64 = 0; let networks = sys.get_networks(); - for (_, network) in networks { - total_rx += network.get_total_received(); - total_tx += network.get_total_transmitted(); + 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 + } else { + true + }; + + if to_keep { + total_rx += network.get_total_received(); + total_tx += network.get_total_transmitted(); + } } let elapsed_time = curr_time.duration_since(prev_net_access_time).as_secs_f64(); @@ -57,10 +73,11 @@ pub async fn get_network_data( })) } +// FIXME: Eventually make it so that this thing also takes individual usage into account, so we can allow for showing per-interface! #[cfg(not(target_os = "windows"))] 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, + curr_time: Instant, actually_get: bool, filter: &Option<crate::app::Filter>, ) -> crate::utils::error::Result<Option<NetworkHarvest>> { use futures::StreamExt; @@ -75,8 +92,23 @@ pub async fn get_network_data( while let Some(io) = io_data.next().await { if let Ok(io) = io { - total_rx += io.bytes_recv().get::<heim::units::information::byte>(); - total_tx += io.bytes_sent().get::<heim::units::information::byte>(); + 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 { + total_rx += io.bytes_recv().get::<heim::units::information::byte>(); + total_tx += io.bytes_sent().get::<heim::units::information::byte>(); + } } } diff --git a/src/app/data_harvester/temperature.rs b/src/app/data_harvester/temperature.rs index 512850c9..1c818e31 100644 --- a/src/app/data_harvester/temperature.rs +++ b/src/app/data_harvester/temperature.rs @@ -1,9 +1,10 @@ use std::cmp::Ordering; +use crate::app::Filter; + #[derive(Default, Debug, Clone)] pub struct TempHarvest { - pub component_name: Option<String>, - pub component_label: Option<String>, + pub name: String, pub temperature: f32, } @@ -22,7 +23,7 @@ impl Default for TemperatureType { #[cfg(not(target_os = "linux"))] pub async fn get_temperature_data( - sys: &sysinfo::System, temp_type: &TemperatureType, actually_get: bool, + sys: &sysinfo::System, temp_type: &TemperatureType, actually_get: bool, filter: &Option<Filter>, ) -> crate::utils::error::Result<Option<Vec<TempHarvest>>> { use sysinfo::{ComponentExt, SystemExt}; @@ -42,17 +43,35 @@ pub async fn get_temperature_data( let sensor_data = sys.get_components(); for component in sensor_data { - temperature_vec.push(TempHarvest { - component_name: None, - component_label: Some(component.get_label().to_string()), - temperature: match temp_type { - TemperatureType::Celsius => component.get_temperature(), - TemperatureType::Kelvin => convert_celsius_to_kelvin(component.get_temperature()), - TemperatureType::Fahrenheit => { - convert_celsius_to_fahrenheit(component.get_temperature()) + let name = component.get_label().to_string(); + + 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 + } else { + true + }; + + if to_keep { + temperature_vec.push(TempHarvest { + name, + temperature: match temp_type { + TemperatureType::Celsius => component.get_temperature(), + TemperatureType::Kelvin => { + convert_celsius_to_kelvin(component.get_temperature()) + } + TemperatureType::Fahrenheit => { + convert_celsius_to_fahrenheit(component.get_temperature()) + } + }, + }); + } } temp_vec_sort(&mut temperature_vec); @@ -61,7 +80,7 @@ pub async fn get_temperature_data( #[cfg(target_os = "linux")] pub async fn get_temperature_data( - temp_type: &TemperatureType, actually_get: bool, + temp_type: &TemperatureType, actually_get: bool, filter: &Option<Filter>, ) -> crate::utils::error::Result<Option<Vec<TempHarvest>>> { use futures::StreamExt; use heim::units::thermodynamic_temperature; @@ -75,26 +94,51 @@ pub async fn get_temperature_data( let mut sensor_data = heim::sensors::temperatures().boxed_local(); while let Some(sensor) = sensor_data.next().await { if let Ok(sensor) = sensor { - temperature_vec.push(TempHarvest { - component_name: Some(sensor.unit().to_string()), - component_label: if let Some(label) = sensor.label() { - Some(label.to_string()) - } else { - None - }, - temperature: match temp_type { - TemperatureType::Celsius => sensor - .current() - .get::<thermodynamic_temperature::degree_celsius>(), - TemperatureType::Kelvin => { - sensor.current().get::<thermodynamic_temperature::kelvin>() + let component_name = Some(sensor.unit().to_string()); + let component_label = if let Some(label) = sensor.label() { + Some(label.to_string()) + } else { + None + }; + + let name = match (component_name, component_label) { + (Some(name), Some(label)) => format!("{}: {}", name, label), + (None, Some(label)) => label.to_string(), + (Some(name), None) => name.to_string(), + (None, None) => String::default(), + }; + + 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; } - TemperatureType::Fahrenheit => sensor - .current() - .get::<thermodynamic_temperature::degree_fahrenheit>( - ), - }, - }); + } + ret + } else { + true + }; + + if to_keep { + temperature_vec.push(TempHarvest { + name, + temperature: match temp_type { + TemperatureType::Celsius => sensor + .current() + .get::<thermodynamic_temperature::degree_celsius>( + ), + TemperatureType::Kelvin => { + sensor.current().get::<thermodynamic_temperature::kelvin>() + } + TemperatureType::Fahrenheit => sensor + .current() + .get::<thermodynamic_temperature::degree_fahrenheit>( + ), + }, + }); + } } } @@ -116,9 +160,5 @@ fn temp_vec_sort(temperature_vec: &mut Vec<TempHarvest>) { None => Ordering::Equal, }); - temperature_vec.sort_by(|a, b| { - a.component_name - .partial_cmp(&b.component_name) - .unwrap_or(Ordering::Equal) - }); + temperature_vec.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap_or(Ordering::Equal)); } |