summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2021-05-15 18:57:02 -0700
committerGitHub <noreply@github.com>2021-05-15 21:57:02 -0400
commit6847f2ff0ce5827c0779a1dfcb9e6a8a657652b1 (patch)
tree2b957d6701f06720baf2cab836303400f340e6f2 /src
parent39c5ee991e8a02a72da398433c62f4a1b8c7acbb (diff)
refactor: split up data collection by OS (#482)
Refactor to split up data collection by OS and/or the backing library. The goal is to make it easier to work with and add new OS support, as opposed to how it was prior where we stored OS-independent implementations all in the same file.
Diffstat (limited to 'src')
-rw-r--r--src/app/data_farmer.rs23
-rw-r--r--src/app/data_harvester.rs13
-rw-r--r--src/app/data_harvester/batteries/battery.rs (renamed from src/app/data_harvester/batteries.rs)11
-rw-r--r--src/app/data_harvester/batteries/mod.rs10
-rw-r--r--src/app/data_harvester/cpu/heim/linux.rs16
-rw-r--r--src/app/data_harvester/cpu/heim/mod.rs (renamed from src/app/data_harvester/cpu.rs)55
-rw-r--r--src/app/data_harvester/cpu/heim/unix.rs (renamed from src/app/data_harvester/load_avg.rs)5
-rw-r--r--src/app/data_harvester/cpu/heim/windows_macos.rs10
-rw-r--r--src/app/data_harvester/cpu/mod.rs14
-rw-r--r--src/app/data_harvester/disks/heim/linux.rs34
-rw-r--r--src/app/data_harvester/disks/heim/mod.rs (renamed from src/app/data_harvester/disks.rs)49
-rw-r--r--src/app/data_harvester/disks/heim/windows_macos.rs14
-rw-r--r--src/app/data_harvester/disks/mod.rs10
-rw-r--r--src/app/data_harvester/memory/heim.rs (renamed from src/app/data_harvester/mem.rs)2
-rw-r--r--src/app/data_harvester/memory/mod.rs10
-rw-r--r--src/app/data_harvester/network/heim.rs (renamed from src/app/data_harvester/network.rs)78
-rw-r--r--src/app/data_harvester/network/mod.rs30
-rw-r--r--src/app/data_harvester/network/sysinfo.rs60
-rw-r--r--src/app/data_harvester/processes/linux.rs (renamed from src/app/data_harvester/processes.rs)294
-rw-r--r--src/app/data_harvester/processes/macos.rs139
-rw-r--r--src/app/data_harvester/processes/mod.rs97
-rw-r--r--src/app/data_harvester/processes/unix.rs30
-rw-r--r--src/app/data_harvester/processes/windows.rs72
-rw-r--r--src/app/data_harvester/temperature.rs153
-rw-r--r--src/app/data_harvester/temperature/heim.rs54
-rw-r--r--src/app/data_harvester/temperature/mod.rs73
-rw-r--r--src/app/data_harvester/temperature/sysinfo.rs47
27 files changed, 795 insertions, 608 deletions
diff --git a/src/app/data_farmer.rs b/src/app/data_farmer.rs
index c58e4f1b..73830842 100644
--- a/src/app/data_farmer.rs
+++ b/src/app/data_farmer.rs
@@ -16,9 +16,8 @@ use once_cell::sync::Lazy;
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},
+ data_harvester::{batteries, cpu, disks, memory, network, processes, temperature, Data},
utils::gen_util::{get_decimal_bytes, GIGA_LIMIT},
};
use regex::Regex;
@@ -51,10 +50,10 @@ pub struct DataCollection {
pub frozen_instant: Option<Instant>,
pub timed_data_vec: Vec<(Instant, TimedData)>,
pub network_harvest: network::NetworkHarvest,
- pub memory_harvest: mem::MemHarvest,
- pub swap_harvest: mem::MemHarvest,
+ pub memory_harvest: memory::MemHarvest,
+ pub swap_harvest: memory::MemHarvest,
pub cpu_harvest: cpu::CpuHarvest,
- pub load_avg_harvest: load_avg::LoadAvgHarvest,
+ pub load_avg_harvest: cpu::LoadAvgHarvest,
pub process_harvest: Vec<processes::ProcessHarvest>,
pub disk_harvest: Vec<disks::DiskHarvest>,
pub io_harvest: disks::IoHarvest,
@@ -71,10 +70,10 @@ impl Default for DataCollection {
frozen_instant: None,
timed_data_vec: Vec::default(),
network_harvest: network::NetworkHarvest::default(),
- memory_harvest: mem::MemHarvest::default(),
- swap_harvest: mem::MemHarvest::default(),
+ memory_harvest: memory::MemHarvest::default(),
+ swap_harvest: memory::MemHarvest::default(),
cpu_harvest: cpu::CpuHarvest::default(),
- load_avg_harvest: load_avg::LoadAvgHarvest::default(),
+ load_avg_harvest: cpu::LoadAvgHarvest::default(),
process_harvest: Vec::default(),
disk_harvest: Vec::default(),
io_harvest: disks::IoHarvest::default(),
@@ -90,8 +89,8 @@ impl DataCollection {
pub fn reset(&mut self) {
self.timed_data_vec = Vec::default();
self.network_harvest = network::NetworkHarvest::default();
- self.memory_harvest = mem::MemHarvest::default();
- self.swap_harvest = mem::MemHarvest::default();
+ self.memory_harvest = memory::MemHarvest::default();
+ self.swap_harvest = memory::MemHarvest::default();
self.cpu_harvest = cpu::CpuHarvest::default();
self.process_harvest = Vec::default();
self.disk_harvest = Vec::default();
@@ -180,7 +179,7 @@ impl DataCollection {
}
fn eat_memory_and_swap(
- &mut self, memory: mem::MemHarvest, swap: mem::MemHarvest, new_entry: &mut TimedData,
+ &mut self, memory: memory::MemHarvest, swap: memory::MemHarvest, new_entry: &mut TimedData,
) {
// trace!("Eating mem and swap.");
// Memory
@@ -230,7 +229,7 @@ impl DataCollection {
self.cpu_harvest = cpu.to_vec();
}
- fn eat_load_avg(&mut self, load_avg: LoadAvgHarvest, new_entry: &mut TimedData) {
+ fn eat_load_avg(&mut self, load_avg: cpu::LoadAvgHarvest, new_entry: &mut TimedData) {
new_entry.load_avg_data = load_avg;
self.load_avg_harvest = load_avg;
diff --git a/src/app/data_harvester.rs b/src/app/data_harvester.rs
index 60ff5a2a..feab6005 100644
--- a/src/app/data_harvester.rs
+++ b/src/app/data_harvester.rs
@@ -19,8 +19,7 @@ use super::DataFilters;
pub mod batteries;
pub mod cpu;
pub mod disks;
-pub mod load_avg;
-pub mod mem;
+pub mod memory;
pub mod network;
pub mod processes;
pub mod temperature;
@@ -29,9 +28,9 @@ pub mod temperature;
pub struct Data {
pub last_collection_time: Instant,
pub cpu: Option<cpu::CpuHarvest>,
- pub load_avg: Option<load_avg::LoadAvgHarvest>,
- pub memory: Option<mem::MemHarvest>,
- pub swap: Option<mem::MemHarvest>,
+ pub load_avg: Option<cpu::LoadAvgHarvest>,
+ pub memory: Option<memory::MemHarvest>,
+ pub swap: Option<memory::MemHarvest>,
pub temperature_sensors: Option<Vec<temperature::TempHarvest>>,
pub network: Option<network::NetworkHarvest>,
pub list_of_processes: Option<Vec<processes::ProcessHarvest>>,
@@ -232,7 +231,7 @@ impl DataCollector {
#[cfg(target_family = "unix")]
{
// Load Average
- if let Ok(load_avg_data) = load_avg::get_load_avg().await {
+ if let Ok(load_avg_data) = cpu::get_load_avg().await {
self.data.load_avg = Some(load_avg_data);
}
}
@@ -299,7 +298,7 @@ impl DataCollector {
)
}
};
- let mem_data_fut = mem::get_mem_data(self.widgets_to_harvest.use_mem);
+ let mem_data_fut = memory::get_mem_data(self.widgets_to_harvest.use_mem);
let disk_data_fut = disks::get_disk_usage(
self.widgets_to_harvest.use_disk,
&self.filters.disk_filter,
diff --git a/src/app/data_harvester/batteries.rs b/src/app/data_harvester/batteries/battery.rs
index 98cf6ae6..7e4644e9 100644
--- a/src/app/data_harvester/batteries.rs
+++ b/src/app/data_harvester/batteries/battery.rs
@@ -1,3 +1,14 @@
+//! Uses the battery crate from svartalf.
+//! Covers battery usage for:
+//! - Linux 2.6.39+
+//! - MacOS 10.10+
+//! - iOS
+//! - Windows 7+
+//! - FreeBSD
+//! - DragonFlyBSD
+//!
+//! For more information, see https://github.com/svartalf/rust-battery
+
use battery::{
units::{power::watt, ratio::percent, time::second},
Battery, Manager,
diff --git a/src/app/data_harvester/batteries/mod.rs b/src/app/data_harvester/batteries/mod.rs
new file mode 100644
index 00000000..8c0e4a92
--- /dev/null
+++ b/src/app/data_harvester/batteries/mod.rs
@@ -0,0 +1,10 @@
+//! Data collection for batteries.
+//!
+//! For Linux, macOS, Windows, FreeBSD, Dragonfly, and iOS, this is handled by the battery crate.
+
+cfg_if::cfg_if! {
+ if #[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "ios"))] {
+ pub mod battery;
+ pub use self::battery::*;
+ }
+}
diff --git a/src/app/data_harvester/cpu/heim/linux.rs b/src/app/data_harvester/cpu/heim/linux.rs
new file mode 100644
index 00000000..542685d4
--- /dev/null
+++ b/src/app/data_harvester/cpu/heim/linux.rs
@@ -0,0 +1,16 @@
+//! Linux-specific functions regarding CPU usage.
+
+use heim::cpu::os::linux::CpuTimeExt;
+pub fn convert_cpu_times(cpu_time: &heim::cpu::CpuTime) -> (f64, f64) {
+ let working_time: f64 = (cpu_time.user()
+ + cpu_time.nice()
+ + cpu_time.system()
+ + cpu_time.irq()
+ + cpu_time.soft_irq()
+ + cpu_time.steal())
+ .get::<heim::units::time::second>();
+ (
+ working_time,
+ working_time + (cpu_time.idle() + cpu_time.io_wait()).get::<heim::units::time::second>(),
+ )
+}
diff --git a/src/app/data_harvester/cpu.rs b/src/app/data_harvester/cpu/heim/mod.rs
index 61e79e28..73a97b5b 100644
--- a/src/app/data_harvester/cpu.rs
+++ b/src/app/data_harvester/cpu/heim/mod.rs
@@ -1,3 +1,23 @@
+//! CPU stats through heim.
+//! Supports macOS, Linux, and Windows.
+
+cfg_if::cfg_if! {
+ if #[cfg(target_os = "linux")] {
+ pub mod linux;
+ pub use linux::*;
+ } else if #[cfg(any(target_os = "macos", target_os = "windows"))] {
+ pub mod windows_macos;
+ pub use windows_macos::*;
+ }
+}
+
+cfg_if::cfg_if! {
+ if #[cfg(target_family = "unix")] {
+ pub mod unix;
+ pub use unix::*;
+ }
+}
+
#[derive(Default, Debug, Clone)]
pub struct CpuData {
pub cpu_prefix: String,
@@ -10,42 +30,13 @@ pub type CpuHarvest = Vec<CpuData>;
pub type PastCpuWork = f64;
pub type PastCpuTotal = f64;
+use futures::StreamExt;
+use std::collections::VecDeque;
+
pub async fn get_cpu_data_list(
show_average_cpu: bool, previous_cpu_times: &mut Vec<(PastCpuWork, PastCpuTotal)>,
previous_average_cpu_time: &mut Option<(PastCpuWork, PastCpuTotal)>,
) -> crate::error::Result<CpuHarvest> {
- use futures::StreamExt;
- #[cfg(target_os = "linux")]
- use heim::cpu::os::linux::CpuTimeExt;
- use std::collections::VecDeque;
-
- fn convert_cpu_times(cpu_time: &heim::cpu::CpuTime) -> (f64, f64) {
- #[cfg(not(target_os = "linux"))]
- {
- let working_time: f64 =
- (cpu_time.user() + cpu_time.system()).get::<heim::units::time::second>();
- (
- working_time,
- working_time + cpu_time.idle().get::<heim::units::time::second>(),
- )
- }
- #[cfg(target_os = "linux")]
- {
- let working_time: f64 = (cpu_time.user()
- + cpu_time.nice()
- + cpu_time.system()
- + cpu_time.irq()
- + cpu_time.soft_irq()
- + cpu_time.steal())
- .get::<heim::units::time::second>();
- (
- working_time,
- working_time
- + (cpu_time.idle() + cpu_time.io_wait()).get::<heim::units::time::second>(),
- )
- }
- }
-
fn calculate_cpu_usage_percentage(
(previous_working_time, previous_total_time): (f64, f64),
(current_working_time, current_total_time): (f64, f64),
diff --git a/src/app/data_harvester/load_avg.rs b/src/app/data_harvester/cpu/heim/unix.rs
index 0f58ea8b..74340951 100644
--- a/src/app/data_harvester/load_avg.rs
+++ b/src/app/data_harvester/cpu/heim/unix.rs
@@ -1,6 +1,7 @@
-pub type LoadAvgHarvest = [f32; 3];
+//! Unix-specific functions regarding CPU usage.
+
+use crate::app::data_harvester::cpu::LoadAvgHarvest;
-#[cfg(target_family = "unix")]
pub async fn get_load_avg() -> crate::error::Result<LoadAvgHarvest> {
let (one, five, fifteen) = heim::cpu::os::unix::loadavg().await?;
diff --git a/src/app/data_harvester/cpu/heim/windows_macos.rs b/src/app/data_harvester/cpu/heim/windows_macos.rs
new file mode 100644
index 00000000..34abc818
--- /dev/null
+++ b/src/app/data_harvester/cpu/heim/windows_macos.rs
@@ -0,0 +1,10 @@
+//! Windows and macOS-specific functions regarding CPU usage.
+
+pub fn convert_cpu_times(cpu_time: &heim::cpu::CpuTime) -> (f64, f64) {
+ let working_time: f64 =
+ (cpu_time.user() + cpu_time.system()).get::<heim::units::time::second>();
+ (
+ working_time,
+ working_time + cpu_time.idle().get::<heim::units::time::second>(),
+ )
+}
diff --git a/src/app/data_harvester/cpu/mod.rs b/src/app/data_harvester/cpu/mod.rs
new file mode 100644
index 00000000..81a0db4c
--- /dev/null
+++ b/src/app/data_harvester/cpu/mod.rs
@@ -0,0 +1,14 @@
+//! Data collection for CPU usage and load average.
+//!
+//! For CPU usage, Linux, macOS, and Windows are handled by Heim.
+//!
+//! For load average, macOS and Linux are supported through Heim.
+
+cfg_if::cfg_if! {
+ if #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] {
+ pub mod heim;
+ pub use self::heim::*;
+ }
+}
+
+pub type LoadAvgHarvest = [f32; 3];
diff --git a/src/app/data_harvester/disks/heim/linux.rs b/src/app/data_harvester/disks/heim/linux.rs
new file mode 100644
index 00000000..cbc99d9f
--- /dev/null
+++ b/src/app/data_harvester/disks/heim/linux.rs
@@ -0,0 +1,34 @@
+//! Linux-specific things for Heim disk data collection.
+
+use heim::disk::Partition;
+
+pub fn get_device_name(partition: &Partition) -> String {
+ if let Some(device) = partition.device() {
+ // See if this disk is actually mounted elsewhere on Linux...
+ // This is a workaround to properly map I/O in some cases (i.e. disk encryption), see
+ // https://github.com/ClementTsang/bottom/issues/419
+ if let Ok(path) = std::fs::read_link(device) {
+ if path.is_absolute() {
+ path.into_os_string()
+ } else {
+ let mut combined_path = std::path::PathBuf::new();
+ combined_path.push(device);
+ combined_path.pop(); // Pop the current file...
+ combined_path.push(path);
+
+ if let Ok(canon_path) = std::fs::canonicalize(combined_path) {
+ // Resolve the local path into an absolute one...
+ canon_path.into_os_string()
+ } else {
+ device.to_os_string()
+ }
+ }
+ } else {
+ device.to_os_string()
+ }
+ .into_string()
+ .unwrap_or_else(|_| "Name Unavailable".to_string())
+ } else {
+ "Name Unavailable".to_string()
+ }
+}
diff --git a/src/app/data_harvester/disks.rs b/src/app/data_harvester/disks/heim/mod.rs
index 103bb701..a79d00db 100644
--- a/src/app/data_harvester/disks.rs
+++ b/src/app/data_harvester/disks/heim/mod.rs
@@ -1,5 +1,15 @@
use crate::app::Filter;
+cfg_if::cfg_if! {
+ if #[cfg(target_os = "linux")] {
+ pub mod linux;
+ pub use linux::*;
+ } else if #[cfg(any(target_os = "macos", target_os = "windows"))] {
+ pub mod windows_macos;
+ pub use windows_macos::*;
+ }
+}
+
#[derive(Debug, Clone, Default)]
pub struct DiskHarvest {
pub name: String,
@@ -62,44 +72,7 @@ pub async fn get_disk_usage(
while let Some(part) = partitions_stream.next().await {
if let Ok(partition) = part {
- let symlink: std::ffi::OsString;
-
- let name = (if let Some(device) = partition.device() {
- // See if this disk is actually mounted elsewhere on Linux...
- // This is a workaround to properly map I/O in some cases (i.e. disk encryption), see
- // https://github.com/ClementTsang/bottom/issues/419
- if cfg!(target_os = "linux") {
- if let Ok(path) = std::fs::read_link(device) {
- if path.is_absolute() {
- symlink = path.into_os_string();
- symlink.as_os_str()
- } else {
- let mut combined_path = std::path::PathBuf::new();
- combined_path.push(device);
- combined_path.pop(); // Pop the current file...
- combined_path.push(path.clone());
-
- if let Ok(path) = std::fs::canonicalize(combined_path) {
- // Resolve the local path into an absolute one...
- symlink = path.into_os_string();
- symlink.as_os_str()
- } else {
- symlink = path.into_os_string();
- symlink.as_os_str()
- }
- }
- } else {
- device
- }
- } else {
- device
- }
- } else {
- std::ffi::OsStr::new("Name Unavailable")
- }
- .to_str()
- .unwrap_or("Name Unavailable"))
- .to_string();
+ let name = get_device_name(&partition);
let mount_point = (partition
.mount_point()
diff --git a/src/app/data_harvester/disks/heim/windows_macos.rs b/src/app/data_harvester/disks/heim/windows_macos.rs
new file mode 100644
index 00000000..428733bf
--- /dev/null
+++ b/src/app/data_harvester/disks/heim/windows_macos.rs
@@ -0,0 +1,14 @@
+//! macOS and Windows-specific things for Heim disk data collection.
+
+use heim::disk::Partition;
+
+pub fn get_device_name(partition: &Partition) -> String {
+ if let Some(device) = partition.device() {
+ device
+ .to_os_string()
+ .into_string()
+ .unwrap_or_else(|_| "Name Unavailable".to_string())
+ } else {
+ "Name Unavailable".to_string()
+ }
+}
diff --git a/src/app/data_harvester/disks/mod.rs b/src/app/data_harvester/disks/mod.rs
new file mode 100644
index 00000000..e5a52336
--- /dev/null
+++ b/src/app/data_harvester/disks/mod.rs
@@ -0,0 +1,10 @@
+//! Data collection for disks (IO, usage, space, etc.).
+//!
+//! For Linux, macOS, and Windows, this is handled by heim.
+
+cfg_if::cfg_if! {
+ if #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] {
+ pub mod heim;
+ pub use self::heim::*;
+ }
+}
diff --git a/src/app/data_harvester/mem.rs b/src/app/data_harvester/memory/heim.rs
index 014cbcdc..5319b1b3 100644
--- a/src/app/data_harvester/mem.rs
+++ b/src/app/data_harvester/memory/heim.rs
@@ -1,3 +1,5 @@
+//! Data collection for memory via heim.
+
#[derive(Debug, Clone)]
pub struct MemHarvest {
pub mem_total_in_kib: u64,
diff --git a/src/app/data_harvester/memory/mod.rs b/src/app/data_harvester/memory/mod.rs
new file mode 100644
index 00000000..588a3c3b
--- /dev/null
+++ b/src/app/data_harvester/memory/mod.rs
@@ -0,0 +1,10 @@
+//! Data collection for memory.
+//!
+//! For Linux, macOS, and Windows, this is handled by Heim.
+
+cfg_if::cfg_if! {
+ if #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] {
+ pub mod heim;
+ pub use self::heim::*;
+ }
+}
diff --git a/src/app/data_harvester/network.rs b/src/app/data_harvester/network/heim.rs
index 650a68e3..d18287c8 100644
--- a/src/app/data_harvester/network.rs
+++ b/src/app/data_harvester/network/heim.rs
@@ -1,81 +1,9 @@
-use std::time::Instant;
-
-#[derive(Default, Clone, Debug)]
-/// All units in bits.
-pub struct NetworkHarvest {
- pub rx: u64,
- pub tx: u64,
- pub total_rx: u64,
- pub total_tx: u64,
-}
-
-impl NetworkHarvest {
- pub fn first_run_cleanup(&mut self) {
- self.rx = 0;
- self.tx = 0;
- }
-}
-
-/// Separate Windows implementation required due to https://github.com/heim-rs/heim/issues/26.
-#[cfg(target_os = "windows")]
-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};
-
- if !actually_get {
- return Ok(None);
- }
-
- let mut total_rx: u64 = 0;
- let mut total_tx: u64 = 0;
-
- let networks = sys.get_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
- } else {
- true
- };
-
- if to_keep {
- total_rx += network.get_total_received() * 8;
- total_tx += network.get_total_transmitted() * 8;
- }
- }
+//! Gets network data via heim.
- 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,
- }))
-}
+use super::NetworkHarvest;
+use std::time::Instant;
// 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, filter: &Option<crate::app::Filter>,
diff --git a/src/app/data_harvester/network/mod.rs b/src/app/data_harvester/network/mod.rs
new file mode 100644
index 00000000..c717e6ac
--- /dev/null
+++ b/src/app/data_harvester/network/mod.rs
@@ -0,0 +1,30 @@
+//! 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(target_os = "windows")] {
+ pub mod sysinfo;
+ pub use self::sysinfo::*;
+ }
+}
+
+#[derive(Default, Clone, Debug)]
+/// All units in bits.
+pub struct NetworkHarvest {
+ pub rx: u64,
+ pub tx: u64,
+ pub total_rx: u64,
+ pub total_tx: u64,
+}
+
+impl NetworkHarvest {
+ pub fn first_run_cleanup(&mut self) {
+ self.rx = 0;
+ self.tx = 0;
+ }
+}
diff --git a/src/app/data_harvester/network/sysinfo.rs b/src/app/data_harvester/network/sysinfo.rs
new file mode 100644
index 00000000..c7a7db00
--- /dev/null
+++ b/src/app/data_harvester/network/sysinfo.rs
@@ -0,0 +1,60 @@
+//! Gets network data via sysinfo.
+
+use super::NetworkHarvest;
+use std::time::Instant;
+
+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};
+
+ if !actually_get {
+ return Ok(None);
+ }
+
+ let mut total_rx: u64 = 0;
+ let mut total_tx: u64 = 0;
+
+ let networks = sys.get_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
+ } else {
+ true
+ };
+
+ if to_keep {
+ total_rx += network.get_total_received() * 8;
+ total_tx += network.get_total_transmitted() * 8;
+ }
+ }
+
+ 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/processes.rs b/src/app/data_harvester/processes/linux.rs
index 94f6fb62..d6778ba3 100644
--- a/src/app/data_harvester/processes.rs
+++ b/src/app/data_harvester/processes/linux.rs
@@ -1,99 +1,20 @@
+//! Process data collection for Linux.
+
+use crate::utils::error::{self, BottomError};
use crate::Pid;
-use sysinfo::ProcessStatus;
+use super::ProcessHarvest;
-#[cfg(target_family = "unix")]
-use crate::utils::error;
+use sysinfo::ProcessStatus;
-#[cfg(target_os = "linux")]
use procfs::process::{Process, Stat};
-#[cfg(target_os = "linux")]
-use crate::utils::error::BottomError;
-
-#[cfg(target_os = "linux")]
use fxhash::{FxHashMap, FxHashSet};
-#[cfg(not(target_os = "linux"))]
-use sysinfo::{ProcessExt, ProcessorExt, System, SystemExt};
-
/// Maximum character length of a /proc/<PID>/stat process name.
/// If it's equal or greater, then we instead refer to the command for the name.
-#[cfg(target_os = "linux")]
const MAX_STAT_NAME_LEN: usize = 15;
-// TODO: Add value so we know if it's sorted ascending or descending by default?
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub enum ProcessSorting {
- CpuPercent,
- Mem,
- MemPercent,
- Pid,
- ProcessName,
- Command,
- ReadPerSecond,
- WritePerSecond,
- TotalRead,
- TotalWrite,
- State,
- User,
- Count,
-}
-
-impl std::fmt::Display for ProcessSorting {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(
- f,
- "{}",
- match &self {
- ProcessSorting::CpuPercent => "CPU%",
- ProcessSorting::MemPercent => "Mem%",
- ProcessSorting::Mem => "Mem",
- ProcessSorting::ReadPerSecond => "R/s",
- ProcessSorting::WritePerSecond => "W/s",
- ProcessSorting::TotalRead => "T.Read",
- ProcessSorting::TotalWrite => "T.Write",
- ProcessSorting::State => "State",
- ProcessSorting::ProcessName => "Name",
- ProcessSorting::Command => "Command",
- ProcessSorting::Pid => "PID",
- ProcessSorting::Count => "Count",
- ProcessSorting::User => "User",
- }
- )
- }
-}
-
-impl Default for ProcessSorting {
- fn default() -> Self {
- ProcessSorting::CpuPercent
- }
-}
-
-#[derive(Debug, Clone, Default)]
-pub struct ProcessHarvest {
- pub pid: Pid,
- pub parent_pid: Option<Pid>, // Remember, parent_pid 0 is root...
- pub cpu_usage_percent: f64,
- pub mem_usage_percent: f64,
- pub mem_usage_bytes: u64,
- // pub rss_kb: u64,
- // pub virt_kb: u64,
- pub name: String,
- pub command: String,
- pub read_bytes_per_sec: u64,
- pub write_bytes_per_sec: u64,
- pub total_read_bytes: u64,
- pub total_write_bytes: u64,
- pub process_state: String,
- pub process_state_char: char,
-
- /// This is the *effective* user ID.
- #[cfg(target_family = "unix")]
- pub uid: Option<libc::uid_t>,
-}
-
-#[cfg(target_os = "linux")]
#[derive(Debug, Clone)]
pub struct PrevProcDetails {
pub total_read_bytes: u64,
@@ -102,7 +23,6 @@ pub struct PrevProcDetails {
pub process: Process,
}