summaryrefslogtreecommitdiffstats
path: root/src/app
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2023-12-28 04:00:58 +0000
committerGitHub <noreply@github.com>2023-12-27 23:00:58 -0500
commit22b40780ade874bed8682f0ffc31450458bd5659 (patch)
treec3c67626498aea1e14be0b47b9ef1fc637450cdd /src/app
parent28d2950d92f44f3b664fcaeede07e5ed4b30fd49 (diff)
refactor: pull data collection out of nested folder structure (#1364)
* refactor: pull data collection out of nested folder structure * fix sysinfo * comment
Diffstat (limited to 'src/app')
-rw-r--r--src/app/data_farmer.rs5
-rw-r--r--src/app/data_harvester.rs493
-rw-r--r--src/app/data_harvester/batteries.rs10
-rw-r--r--src/app/data_harvester/batteries/battery.rs51
-rw-r--r--src/app/data_harvester/cpu.rs23
-rw-r--r--src/app/data_harvester/cpu/sysinfo.rs39
-rw-r--r--src/app/data_harvester/disks.rs193
-rw-r--r--src/app/data_harvester/disks/freebsd.rs94
-rw-r--r--src/app/data_harvester/disks/io_counters.rs30
-rw-r--r--src/app/data_harvester/disks/other.rs53
-rw-r--r--src/app/data_harvester/disks/unix.rs73
-rw-r--r--src/app/data_harvester/disks/unix/file_systems.rs185
-rw-r--r--src/app/data_harvester/disks/unix/linux/counters.rs95
-rw-r--r--src/app/data_harvester/disks/unix/linux/mod.rs5
-rw-r--r--src/app/data_harvester/disks/unix/linux/partition.rs190
-rw-r--r--src/app/data_harvester/disks/unix/macos/counters.rs49
-rw-r--r--src/app/data_harvester/disks/unix/macos/io_kit.rs10
-rw-r--r--src/app/data_harvester/disks/unix/macos/io_kit/bindings.rs58
-rw-r--r--src/app/data_harvester/disks/unix/macos/io_kit/io_disks.rs23
-rw-r--r--src/app/data_harvester/disks/unix/macos/io_kit/io_iterator.rs54
-rw-r--r--src/app/data_harvester/disks/unix/macos/io_kit/io_object.rs140
-rw-r--r--src/app/data_harvester/disks/unix/macos/mod.rs4
-rw-r--r--src/app/data_harvester/disks/unix/other/bindings.rs46
-rw-r--r--src/app/data_harvester/disks/unix/other/mod.rs4
-rw-r--r--src/app/data_harvester/disks/unix/other/partition.rs99
-rw-r--r--src/app/data_harvester/disks/unix/usage.rs32
-rw-r--r--src/app/data_harvester/disks/windows.rs77
-rw-r--r--src/app/data_harvester/disks/windows/bindings.rs176
-rw-r--r--src/app/data_harvester/disks/zfs_io_counters.rs152
-rw-r--r--src/app/data_harvester/memory.rs26
-rw-r--r--src/app/data_harvester/memory/arc.rs75
-rw-r--r--src/app/data_harvester/memory/sysinfo.rs60
-rw-r--r--src/app/data_harvester/memory/windows.rs30
-rw-r--r--src/app/data_harvester/network.rs20
-rw-r--r--src/app/data_harvester/network/sysinfo.rs51
-rw-r--r--src/app/data_harvester/nvidia.rs148
-rw-r--r--src/app/data_harvester/processes.rs141
-rw-r--r--src/app/data_harvester/processes/freebsd.rs71
-rw-r--r--src/app/data_harvester/processes/linux.rs430
-rw-r--r--src/app/data_harvester/processes/linux/process.rs291
-rw-r--r--src/app/data_harvester/processes/macos.rs63
-rw-r--r--src/app/data_harvester/processes/macos/sysctl_bindings.rs328
-rw-r--r--src/app/data_harvester/processes/unix.rs36
-rw-r--r--src/app/data_harvester/processes/unix/process_ext.rs153
-rw-r--r--src/app/data_harvester/processes/unix/user_table.rs31
-rw-r--r--src/app/data_harvester/processes/windows.rs128
-rw-r--r--src/app/data_harvester/temperature.rs84
-rw-r--r--src/app/data_harvester/temperature/linux.rs480
-rw-r--r--src/app/data_harvester/temperature/sysinfo.rs53
-rw-r--r--src/app/query.rs2
50 files changed, 4 insertions, 5160 deletions
diff --git a/src/app/data_farmer.rs b/src/app/data_farmer.rs
index 669e4630..4a2e09fe 100644
--- a/src/app/data_farmer.rs
+++ b/src/app/data_farmer.rs
@@ -13,14 +13,15 @@
//! memory usage and higher CPU usage - you will be trying to process more and
//! more points as this is used!
+use crate::data_collection::processes::ProcessHarvest;
use std::{collections::BTreeMap, time::Instant, vec::Vec};
use hashbrown::HashMap;
#[cfg(feature = "battery")]
-use crate::data_harvester::batteries;
+use crate::data_collection::batteries;
use crate::{
- data_harvester::{cpu, disks, memory, network, processes::ProcessHarvest, temperature, Data},
+ data_collection::{cpu, disks, memory, network, temperature, Data},
utils::data_prefixes::*,
utils::gen_util::get_decimal_bytes,
Pid,
diff --git a/src/app/data_harvester.rs b/src/app/data_harvester.rs
deleted file mode 100644
index d140e29e..00000000
--- a/src/app/data_harvester.rs
+++ /dev/null
@@ -1,493 +0,0 @@
-//! This is the main file to house data collection functions.
-
-use std::time::{Duration, Instant};
-
-#[cfg(any(target_os = "linux", feature = "gpu"))]
-use hashbrown::HashMap;
-#[cfg(feature = "battery")]
-use starship_battery::{Battery, Manager};
-use sysinfo::{System, SystemExt};
-
-use self::temperature::TemperatureType;
-use super::DataFilters;
-use crate::app::layout_manager::UsedWidgets;
-
-#[cfg(feature = "nvidia")]
-pub mod nvidia;
-
-#[cfg(feature = "battery")]
-pub mod batteries;
-
-pub mod cpu;
-pub mod disks;
-pub mod memory;
-pub mod network;
-pub mod processes;
-pub mod temperature;
-
-#[derive(Clone, Debug)]
-pub struct Data {
- pub collection_time: Instant,
- pub cpu: Option<cpu::CpuHarvest>,
- pub load_avg: Option<cpu::LoadAvgHarvest>,
- pub memory: Option<memory::MemHarvest>,
- #[cfg(not(target_os = "windows"))]
- pub cache: 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>>,
- pub disks: Option<Vec<disks::DiskHarvest>>,
- pub io: Option<disks::IoHarvest>,
- #[cfg(feature = "battery")]
- pub list_of_batteries: Option<Vec<batteries::BatteryHarvest>>,
- #[cfg(feature = "zfs")]
- pub arc: Option<memory::MemHarvest>,
- #[cfg(feature = "gpu")]
- pub gpu: Option<Vec<(String, memory::MemHarvest)>>,
-}
-
-impl Default for Data {
- fn default() -> Self {
- Data {
- collection_time: Instant::now(),
- cpu: None,
- load_avg: None,
- memory: None,
- #[cfg(not(target_os = "windows"))]
- cache: None,
- swap: None,
- temperature_sensors: None,
- list_of_processes: None,
- disks: None,
- io: None,
- network: None,
- #[cfg(feature = "battery")]
- list_of_batteries: None,
- #[cfg(feature = "zfs")]
- arc: None,
- #[cfg(feature = "gpu")]
- gpu: None,
- }
- }
-}
-
-impl Data {
- pub fn cleanup(&mut self) {
- self.io = None;
- self.temperature_sensors = None;
- self.list_of_processes = None;
- self.disks = None;
- self.memory = None;
- self.swap = None;
- self.cpu = None;
- self.load_avg = None;
-
- if let Some(network) = &mut self.network {
- network.first_run_cleanup();
- }
- #[cfg(feature = "zfs")]
- {
- self.arc = None;
- }
- #[cfg(feature = "gpu")]
- {
- self.gpu = None;
- }
- }
-}
-
-#[derive(Debug)]
-pub struct DataCollector {
- pub data: Data,
- sys: System,
- temperature_type: TemperatureType,
- use_current_cpu_total: bool,
- unnormalized_cpu: bool,
- last_collection_time: Instant,
- total_rx: u64,
- total_tx: u64,
- show_average_cpu: bool,
- widgets_to_harvest: UsedWidgets,
- filters: DataFilters,
-
- #[cfg(target_os = "linux")]
- pid_mapping: HashMap<crate::Pid, processes::PrevProcDetails>,
- #[cfg(target_os = "linux")]
- prev_idle: f64,
- #[cfg(target_os = "linux")]
- prev_non_idle: f64,
-
- #[cfg(feature = "battery")]
- battery_manager: Option<Manager>,
- #[cfg(feature = "battery")]
- battery_list: Option<Vec<Battery>>,
-
- #[cfg(target_family = "unix")]
- user_table: processes::UserTable,
-
- #[cfg(feature = "gpu")]
- gpu_pids: Option<Vec<HashMap<u32, (u64, u32)>>>,
- #[cfg(feature = "gpu")]
- gpus_total_mem: Option<u64>,
-}
-
-impl DataCollector {
- pub fn new(filters: DataFilters) -> Self {
- DataCollector {
- data: Data::default(),
- sys: System::new_with_specifics(sysinfo::RefreshKind::new()),
- #[cfg(target_os = "linux")]
- pid_mapping: HashMap::default(),
- #[cfg(target_os = "linux")]
- prev_idle: 0_f64,
- #[cfg(target_os = "linux")]
- prev_non_idle: 0_f64,
- temperature_type: TemperatureType::Celsius,
- use_current_cpu_total: false,
- unnormalized_cpu: false,
- last_collection_time: Instant::now(),
- total_rx: 0,
- total_tx: 0,
- show_average_cpu: false,
- widgets_to_harvest: UsedWidgets::default(),
- #[cfg(feature = "battery")]
- battery_manager: None,
- #[cfg(feature = "battery")]
- battery_list: None,
- filters,
- #[cfg(target_family = "unix")]
- user_table: Default::default(),
- #[cfg(feature = "gpu")]
- gpu_pids: None,
- #[cfg(feature = "gpu")]
- gpus_total_mem: None,
- }
- }
-
- pub fn init(&mut self) {
- #[cfg(feature = "battery")]
- {
- if self.widgets_to_harvest.use_battery {
- if let Ok(battery_manager) = Manager::new() {
- if let Ok(batteries) = battery_manager.batteries() {
- let battery_list: Vec<Battery> = batteries.filter_map(Result::ok).collect();
- if !battery_list.is_empty() {
- self.battery_list = Some(battery_list);
- self.battery_manager = Some(battery_manager);
- }
- }
- }
- }
- }
-
- // Sysinfo-related list refreshing.
- if self.widgets_to_harvest.use_net {
- self.sys.refresh_networks_list();
- }
-
- if self.widgets_to_harvest.use_temp {
- self.sys.refresh_components_list();
- }
-
- #[cfg(target_os = "windows")]
- {
- if self.widgets_to_harvest.use_proc {
- self.sys.refresh_users_list();
- }
-
- if self.widgets_to_harvest.use_disk {
- self.sys.refresh_disks_list();
- }
- }
-
- self.update_data();
-
- // Sleep a few seconds to avoid potentially weird data.
- const SLEEP: Duration = get_sleep_duration();
-
- std::thread::sleep(SLEEP);
- self.data.cleanup();
- }
-
- pub fn set_data_collection(&mut self, used_widgets: UsedWidgets) {
- self.widgets_to_harvest = used_widgets;
- }
-
- pub fn set_temperature_type(&mut self, temperature_type: TemperatureType) {
- self.temperature_type = temperature_type;
- }
-
- pub fn set_use_current_cpu_total(&mut self, use_current_cpu_total: bool) {
- self.use_current_cpu_total = use_current_cpu_total;
- }
-
- pub fn set_unnormalized_cpu(&mut self, unnormalized_cpu: bool) {
- self.unnormalized_cpu = unnormalized_cpu;
- }
-
- pub fn set_show_average_cpu(&mut self, show_average_cpu: bool) {
- self.show_average_cpu = show_average_cpu;
- }
-
- /// Refresh sysinfo data. We use sysinfo for the following data:
- /// - CPU usage
- /// - Memory usage
- /// - Network usage
- /// - Processes (non-Linux)
- /// - Disk (Windows)
- /// - Temperatures (non-Linux)
- fn refresh_sysinfo_data(&mut self) {
- // Refresh once every minute. If it's too frequent it can cause segfaults.
- const LIST_REFRESH_TIME: Duration = Duration::from_secs(60);
- let refresh_start = Instant::now();
-
- if self.widgets_to_harvest.use_cpu || self.widgets_to_harvest.use_proc {
- self.sys.refresh_cpu();
- }
-
- if self.widgets_to_harvest.use_mem || self.widgets_to_harvest.use_proc {
- self.sys.refresh_memory();
- }
-
- if self.widgets_to_harvest.use_net {
- if refresh_start.duration_since(self.last_collection_time) > LIST_REFRESH_TIME {
- self.sys.refresh_networks_list();
- }
- self.sys.refresh_networks();
- }
-
- // sysinfo is used on non-Linux systems for the following:
- // - Processes (users list as well for Windows)
- // - Disks (Windows only)
- // - Temperatures and temperature components list.
- #[cfg(not(target_os = "linux"))]
- {
- if self.widgets_to_harvest.use_proc {
- // For Windows, sysinfo also handles the users list.
- #[cfg(target_os = "windows")]
- if refresh_start.duration_since(self.last_collection_time) > LIST_REFRESH_TIME {
- self.sys.refresh_users_list();
- }
-
- self.sys.refresh_processes();
- }
-
- if self.widgets_to_harvest.use_temp {
- if refresh_start.duration_since(self.last_collection_time) > LIST_REFRESH_TIME {
- self.sys.refresh_components_list();
- }
- self.sys.refresh_components();
- }
- }
-
- #[cfg(target_os = "windows")]
- if self.widgets_to_harvest.use_disk {
- if refresh_start.duration_since(self.last_collection_time) > LIST_REFRESH_TIME {
- self.sys.refresh_disks_list();
- }
- self.sys.refresh_disks();
- }
- }
-
- pub fn update_data(&mut self) {
- self.refresh_sysinfo_data();
-
- self.data.collection_time = Instant::now();
-
- self.update_cpu_usage();
- self.update_memory_usage();
- self.update_temps();
- #[cfg(feature = "battery")]
- self.update_batteries();
- #[cfg(feature = "gpu")]
- self.update_gpus(); // update_gpus before procs for gpu_pids but after temps for appending
- self.update_processes();
- self.update_network_usage();
- self.update_disks();
-
- // Update times for future reference.
- self.last_collection_time = self.data.collection_time;
- }
-
- #[cfg(feature = "gpu")]
- #[inline]
- fn update_gpus(&mut self) {
- if self.widgets_to_harvest.use_gpu {
- #[cfg(feature = "nvidia")]
- if let Some(data) = nvidia::get_nvidia_vecs(
- &self.temperature_type,
- &self.filters.temp_filter,
- &self.widgets_to_harvest,
- ) {
- if let Some(mut temp) = data.temperature {
- if let Some(sensors) = &mut self.data.temperature_sensors {
- sensors.append(&mut temp);
- } else {
- self.data.temperature_sensors = Some(temp);
- }
- }
- if let Some(mem) = data.memory {
- self.data.gpu = Some(mem);
- }
- if let Some(proc) = data.procs {
- self.gpu_pids = Some(proc.1);
- self.gpus_total_mem = Some(proc.0);
- }
- }
- }
- }
-
- #[inline]
- fn update_cpu_usage(&mut self) {
- if self.widgets_to_harvest.use_cpu {
- self.data.cpu = cpu::get_cpu_data_list(&self.sys, self.show_average_cpu).ok();
-
- #[cfg(target_family = "unix")]
- {
- self.data.load_avg = cpu::get_load_avg().ok();
- }
- }
- }
-
- #[inline]
- fn update_processes(&mut self) {
- if self.widgets_to_harvest.use_proc {
- if let Ok(mut process_list) = self.get_processes() {
- // NB: To avoid duplicate sorts on rerenders/events, we sort the processes by PID here.
- // We also want to avoid re-sorting *again* later on if we're sorting by PID, since we already
- // did it here!
- process_list.sort_unstable_by_key(|p| p.pid);
- self.data.list_of_processes = Some(process_list);
- }
- }
- }
-
- #[inline]
- fn update_temps(&mut self) {
- if self.widgets_to_harvest.use_temp {
- #[cfg(not(target_os = "linux"))]
- if let Ok(data) = temperature::get_temperature_data(
- &self.sys,
- &self.temperature_type,
- &self.filters.temp_filter,
- ) {
- self.data.temperature_sensors = data;
- }
-
- #[cfg(target_os = "linux")]
- if let Ok(data) =
- temperature::get_temperature_data(&self.temperature_type, &self.filters.temp_filter)
- {
- self.data.temperature_sensors = data;
- }
- }
- }
-
- #[inline]
- fn update_memory_usage(&mut self) {
- if self.widgets_to_harvest.use_mem {
- self.data.memory = memory::get_ram_usage(&self.sys);
-
- #[cfg(not(target_os = "windows"))]
- if self.widgets_to_harvest.use_cache {
- self.data.cache = memory::get_cache_usage(&self.sys);
- }
-
- self.data.swap = memory::get_swap_usage(
- #[cfg(not(target_os = "windows"))]
- &self.sys,
- );
-
- #[cfg(feature = "zfs")]
- {
- self.data.arc = memory::arc::get_arc_usage();
- }
- }
- }
-
- #[inline]
- fn update_network_usage(&mut self) {
- let current_instant = self.data.collection_time;
-
- 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);
- }
- }
-
- #[inline]
- #[cfg(feature = "battery")]
- fn update_batteries(&mut self) {
- if let Some(battery_manager) = &self.battery_manager {
- if let Some(battery_list) = &mut self.battery_list {
- self.data.list_of_batteries =
- Some(batteries::refresh_batteries(battery_manager, battery_list));
- }
- }
- }
-
- #[inline]
- fn update_disks(&mut self) {
- if self.widgets_to_harvest.use_disk {
- self.data.disks = disks::get_disk_usage(self).ok();
- self.data.io = disks::get_io_usage().ok();
- }
- }
-
- /// Returns the total memory of the system.
- #[inline]
- fn total_memory(&self) -> u64 {
- if let Some(memory) = &self.data.memory {
- memory.total_bytes
- } else {
- self.sys.total_memory()
- }
- }
-}
-
-/// We set a sleep duration between 10ms and 250ms, ideally sysinfo's [`System::MINIMUM_CPU_UPDATE_INTERVAL`] + 1.
-///
-/// We bound the upper end to avoid waiting too long (e.g. FreeBSD is 1s, which I'm fine with losing
-/// accuracy on for the first refresh), and we bound the lower end just to avoid the off-chance that
-/// refreshing too quickly causes problems. This second case should only happen on unsupported
-/// systems via sysinfo, in which case [`System::MINIMUM_CPU_UPDATE_INTERVAL`] is defined as 0.
-///
-/// We also do `INTERVAL + 1` for some wiggle room, just in case.
-const fn get_sleep_duration() -> Duration {
- const MIN_SLEEP: u64 = 10;
- const MAX_SLEEP: u64 = 250;
- const INTERVAL: u64 = System::MINIMUM_CPU_UPDATE_INTERVAL.as_millis() as u64;
-
- if INTERVAL < MIN_SLEEP {
- Duration::from_millis(MIN_SLEEP)
- } else if INTERVAL > MAX_SLEEP {
- Duration::from_millis(MAX_SLEEP)
- } else {
- Duration::from_millis(INTERVAL + 1)
- }
-}
-
-#[cfg(target_os = "freebsd")]
-/// Deserialize [libxo](https://www.freebsd.org/cgi/man.cgi?query=libxo&apropos=0&sektion=0&manpath=FreeBSD+13.1-RELEASE+and+Ports&arch=default&format=html) JSON data
-fn deserialize_xo<T>(key: &str, data: &[u8]) -> Result<T, std::io::Error>
-where
- T: serde::de::DeserializeOwned,
-{
- let mut value: serde_json::Value = serde_json::from_slice(data)?;
- value
- .as_object_mut()
- .and_then(|map| map.remove(key))
- .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "key not found"))
- .and_then(|val| serde_json::from_value(val).map_err(|err| err.into()))
-}
diff --git a/src/app/data_harvester/batteries.rs b/src/app/data_harvester/batteries.rs
deleted file mode 100644
index 8c0e4a92..00000000
--- a/src/app/data_harvester/batteries.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//! 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/batteries/battery.rs b/src/app/data_harvester/batteries/battery.rs
deleted file mode 100644
index ec95ada2..00000000
--- a/src/app/data_harvester/batteries/battery.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-//! 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, refer to the [starship_battery](https://github.com/starship/rust-battery) repo/docs.
-
-use starship_battery::{
- units::{power::watt, ratio::percent, time::second},
- Battery, Manager, State,
-};
-
-#[derive(Debug, Clone)]
-pub struct BatteryHarvest {
- pub charge_percent: f64,
- pub secs_until_full: Option<i64>,
- pub secs_until_empty: Option<i64>,
- pub power_consumption_rate_watts: f64,
- pub health_percent: f64,
- pub state: State,
-}
-
-pub fn refresh_batteries(manager: &Manager, batteries: &mut [Battery]) -> Vec<BatteryHarvest> {
- batteries
- .iter_mut()
- .filter_map(|battery| {
- if manager.refresh(battery).is_ok() {
- Some(BatteryHarvest {
- secs_until_full: {
- let optional_time = battery.time_to_full();
- optional_time.map(|time| f64::from(time.get::<second>()) as i64)
- },
- secs_until_empty: {
- let optional_time = battery.time_to_empty();
- 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>()),
- health_percent: f64::from(battery.state_of_health().get::<percent>()),
- state: battery.state(),
- })
- } else {
- None
- }
- })
- .collect::<Vec<_>>()
-}
diff --git a/src/app/data_harvester/cpu.rs b/src/app/data_harvester/cpu.rs
deleted file mode 100644
index 843df161..00000000
--- a/src/app/data_harvester/cpu.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-//! Data collection for CPU usage and load average.
-
-pub mod sysinfo;
-pub use self::sysinfo::*;
-
-pub type LoadAvgHarvest = [f32; 3];
-
-#[derive(Debug, Clone, Copy)]
-pub enum CpuDataType {
- Avg,
- Cpu(usize),
-}
-
-#[derive(Debug, Clone)]
-pub struct CpuData {
- pub data_type: CpuDataType,
- pub cpu_usage: f64,
-}