mirror of
https://github.com/ClementTsang/bottom
synced 2024-11-22 20:23:12 +00:00
Redid some of the networking portion, changed cargo a bit, some refactoring
This commit is contained in:
parent
395a3083c6
commit
baf588be8a
11 changed files with 90 additions and 42 deletions
|
@ -26,7 +26,7 @@ heim = "0.0.9"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
rayon = "1.3"
|
rayon = "1.3"
|
||||||
regex = "1.3.1"
|
regex = "1.3.1"
|
||||||
sysinfo = "0.10"
|
sysinfo = "0.9" #0.9 seems to be the last working version for my Ryzen PC...
|
||||||
tokio = "0.2.6"
|
tokio = "0.2.6"
|
||||||
winapi = "0.3"
|
winapi = "0.3"
|
||||||
tui = {version = "0.8", features = ["crossterm"], default-features = false }
|
tui = {version = "0.8", features = ["crossterm"], default-features = false }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! This is the main file to house data collection functions.
|
//! This is the main file to house data collection functions.
|
||||||
|
|
||||||
use crate::constants;
|
use crate::{constants, utils::error::Result};
|
||||||
use std::{collections::HashMap, time::Instant};
|
use std::{collections::HashMap, time::Instant};
|
||||||
use sysinfo::{System, SystemExt};
|
use sysinfo::{System, SystemExt};
|
||||||
|
|
||||||
|
@ -11,19 +11,19 @@ pub mod network;
|
||||||
pub mod processes;
|
pub mod processes;
|
||||||
pub mod temperature;
|
pub mod temperature;
|
||||||
|
|
||||||
fn set_if_valid<T: std::clone::Clone>(result: &Result<T, crate::utils::error::BottomError>, value_to_set: &mut T) {
|
fn set_if_valid<T: std::clone::Clone>(result: &Result<T>, value_to_set: &mut T) {
|
||||||
if let Ok(result) = result {
|
if let Ok(result) = result {
|
||||||
*value_to_set = (*result).clone();
|
*value_to_set = (*result).clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_if_valid<T: std::clone::Clone>(result: &Result<T, crate::utils::error::BottomError>, vector_to_push: &mut Vec<T>) {
|
fn push_if_valid<T: std::clone::Clone>(result: &Result<T>, vector_to_push: &mut Vec<T>) {
|
||||||
if let Ok(result) = result {
|
if let Ok(result) = result {
|
||||||
vector_to_push.push(result.clone());
|
vector_to_push.push(result.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
pub list_of_cpu_packages: Vec<cpu::CPUPackage>,
|
pub list_of_cpu_packages: Vec<cpu::CPUPackage>,
|
||||||
pub list_of_io: Vec<disks::IOPackage>,
|
pub list_of_io: Vec<disks::IOPackage>,
|
||||||
|
@ -44,6 +44,9 @@ pub struct DataState {
|
||||||
prev_pid_stats: HashMap<String, (f64, Instant)>,
|
prev_pid_stats: HashMap<String, (f64, Instant)>,
|
||||||
prev_idle: f64,
|
prev_idle: f64,
|
||||||
prev_non_idle: f64,
|
prev_non_idle: f64,
|
||||||
|
prev_net_rx_bytes: u64,
|
||||||
|
prev_net_tx_bytes: u64,
|
||||||
|
prev_net_access_time: Instant,
|
||||||
temperature_type: temperature::TemperatureType,
|
temperature_type: temperature::TemperatureType,
|
||||||
last_clean: Instant, // Last time stale data was cleared
|
last_clean: Instant, // Last time stale data was cleared
|
||||||
}
|
}
|
||||||
|
@ -58,6 +61,9 @@ impl Default for DataState {
|
||||||
prev_pid_stats: HashMap::new(),
|
prev_pid_stats: HashMap::new(),
|
||||||
prev_idle: 0_f64,
|
prev_idle: 0_f64,
|
||||||
prev_non_idle: 0_f64,
|
prev_non_idle: 0_f64,
|
||||||
|
prev_net_rx_bytes: 0,
|
||||||
|
prev_net_tx_bytes: 0,
|
||||||
|
prev_net_access_time: Instant::now(),
|
||||||
temperature_type: temperature::TemperatureType::Celsius,
|
temperature_type: temperature::TemperatureType::Celsius,
|
||||||
last_clean: Instant::now(),
|
last_clean: Instant::now(),
|
||||||
}
|
}
|
||||||
|
@ -70,38 +76,40 @@ impl DataState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(&mut self) {
|
pub fn init(&mut self) {
|
||||||
self.sys.refresh_system();
|
self.sys.refresh_all();
|
||||||
self.sys.refresh_network();
|
|
||||||
if !cfg!(target_os = "linux") {
|
|
||||||
// For now, might be just windows tbh
|
|
||||||
self.sys.refresh_processes();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_data(&mut self) {
|
pub async fn update_data(&mut self) {
|
||||||
self.sys.refresh_system();
|
self.sys.refresh_system();
|
||||||
self.sys.refresh_network();
|
|
||||||
|
|
||||||
if !cfg!(target_os = "linux") {
|
if !cfg!(target_os = "linux") {
|
||||||
// For now, might be just windows tbh
|
// For now, might be just windows tbh
|
||||||
self.sys.refresh_processes();
|
self.sys.refresh_processes();
|
||||||
|
self.sys.refresh_network();
|
||||||
}
|
}
|
||||||
|
|
||||||
// What we want to do: For timed data, if there is an error, just do not add. For other data, just don't update!
|
// What we want to do: For timed data, if there is an error, just do not add. For other data, just don't update!
|
||||||
push_if_valid(&network::get_network_data(&self.sys), &mut self.data.network);
|
push_if_valid(
|
||||||
|
&network::get_network_data(
|
||||||
|
&self.sys,
|
||||||
|
&mut self.prev_net_rx_bytes,
|
||||||
|
&mut self.prev_net_tx_bytes,
|
||||||
|
&mut self.prev_net_access_time,
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
&mut self.data.network,
|
||||||
|
);
|
||||||
push_if_valid(&cpu::get_cpu_data_list(&self.sys), &mut self.data.list_of_cpu_packages);
|
push_if_valid(&cpu::get_cpu_data_list(&self.sys), &mut self.data.list_of_cpu_packages);
|
||||||
|
|
||||||
// TODO: We can convert this to a multi-threaded task...
|
|
||||||
push_if_valid(&mem::get_mem_data_list().await, &mut self.data.memory);
|
push_if_valid(&mem::get_mem_data_list().await, &mut self.data.memory);
|
||||||
push_if_valid(&mem::get_swap_data_list().await, &mut self.data.swap);
|
push_if_valid(&mem::get_swap_data_list().await, &mut self.data.swap);
|
||||||
set_if_valid(
|
set_if_valid(
|
||||||
&processes::get_sorted_processes_list(&self.sys, &mut self.prev_idle, &mut self.prev_non_idle, &mut self.prev_pid_stats).await,
|
&processes::get_sorted_processes_list(&self.sys, &mut self.prev_idle, &mut self.prev_non_idle, &mut self.prev_pid_stats),
|
||||||
&mut self.data.list_of_processes,
|
&mut self.data.list_of_processes,
|
||||||
);
|
);
|
||||||
|
|
||||||
set_if_valid(&disks::get_disk_usage_list().await, &mut self.data.list_of_disks);
|
set_if_valid(&disks::get_disk_usage_list().await, &mut self.data.list_of_disks);
|
||||||
push_if_valid(&disks::get_io_usage_list(false).await, &mut self.data.list_of_io);
|
push_if_valid(&disks::get_io_usage_list(false).await, &mut self.data.list_of_io);
|
||||||
//push_if_valid(&disks::get_io_usage_list(true).await, &mut self.data.list_of_physical_io); // Removed, seems irrelevant for now...
|
|
||||||
set_if_valid(
|
set_if_valid(
|
||||||
&temperature::get_temperature_data(&self.sys, &self.temperature_type).await,
|
&temperature::get_temperature_data(&self.sys, &self.temperature_type).await,
|
||||||
&mut self.data.list_of_temperature_sensor,
|
&mut self.data.list_of_temperature_sensor,
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use sysinfo::{ProcessorExt, System, SystemExt};
|
use sysinfo::{ProcessorExt, System, SystemExt};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CPUData {
|
pub struct CPUData {
|
||||||
pub cpu_name: Box<str>,
|
pub cpu_name: Box<str>,
|
||||||
pub cpu_usage: f64,
|
pub cpu_usage: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CPUPackage {
|
pub struct CPUPackage {
|
||||||
pub cpu_vec: Vec<CPUData>,
|
pub cpu_vec: Vec<CPUData>,
|
||||||
pub instant: Instant,
|
pub instant: Instant,
|
||||||
|
@ -21,7 +21,7 @@ pub fn get_cpu_data_list(sys: &System) -> crate::utils::error::Result<CPUPackage
|
||||||
cpu_vec.push(CPUData {
|
cpu_vec.push(CPUData {
|
||||||
cpu_name: Box::from(cpu.get_name()),
|
cpu_name: Box::from(cpu.get_name()),
|
||||||
cpu_usage: f64::from(cpu.get_cpu_usage()) * 100_f64,
|
cpu_usage: f64::from(cpu.get_cpu_usage()) * 100_f64,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(CPUPackage {
|
Ok(CPUPackage {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use futures::stream::StreamExt;
|
||||||
use heim::units::information;
|
use heim::units::information;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct DiskData {
|
pub struct DiskData {
|
||||||
pub name: Box<str>,
|
pub name: Box<str>,
|
||||||
pub mount_point: Box<str>,
|
pub mount_point: Box<str>,
|
||||||
|
@ -18,7 +18,7 @@ pub struct IOData {
|
||||||
pub write_bytes: u64,
|
pub write_bytes: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct IOPackage {
|
pub struct IOPackage {
|
||||||
pub io_hash: std::collections::HashMap<String, IOData>,
|
pub io_hash: std::collections::HashMap<String, IOData>,
|
||||||
pub instant: Instant,
|
pub instant: Instant,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use heim::units::information;
|
use heim::units::information;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MemData {
|
pub struct MemData {
|
||||||
pub mem_total_in_mb: u64,
|
pub mem_total_in_mb: u64,
|
||||||
pub mem_used_in_mb: u64,
|
pub mem_used_in_mb: u64,
|
||||||
|
|
|
@ -1,23 +1,59 @@
|
||||||
|
use futures::StreamExt;
|
||||||
|
use heim::net;
|
||||||
|
use heim::units::information::byte;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use sysinfo::{NetworkExt, System, SystemExt};
|
use sysinfo::{NetworkExt, System, SystemExt};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone)]
|
||||||
/// Note all values are in bytes...
|
/// Note all values are in bytes...
|
||||||
pub struct NetworkData {
|
pub struct NetworkData {
|
||||||
pub rx : u64,
|
pub rx: u64,
|
||||||
pub tx : u64,
|
pub tx: u64,
|
||||||
pub total_rx : u64,
|
pub total_rx: u64,
|
||||||
pub total_tx : u64,
|
pub total_tx: u64,
|
||||||
pub instant : Instant,
|
pub instant: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_network_data(sys : &System) -> crate::utils::error::Result<NetworkData> {
|
pub async fn get_network_data(
|
||||||
let network_data = sys.get_network();
|
sys: &System, prev_net_rx_bytes: &mut u64, prev_net_tx_bytes: &mut u64, prev_net_access_time: &mut std::time::Instant,
|
||||||
Ok(NetworkData {
|
) -> crate::utils::error::Result<NetworkData> {
|
||||||
rx : network_data.get_income(),
|
if cfg!(target_os = "windows") {
|
||||||
tx : network_data.get_outcome(),
|
let network_data = sys.get_network();
|
||||||
total_rx : 0,
|
|
||||||
total_tx : 0,
|
*prev_net_access_time = Instant::now();
|
||||||
instant : Instant::now(),
|
Ok(NetworkData {
|
||||||
})
|
rx: network_data.get_income(),
|
||||||
|
tx: network_data.get_outcome(),
|
||||||
|
total_rx: 0,
|
||||||
|
total_tx: 0,
|
||||||
|
instant: *prev_net_access_time,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let mut io_data = net::io_counters();
|
||||||
|
let mut net_rx: u64 = 0;
|
||||||
|
let mut net_tx: u64 = 0;
|
||||||
|
|
||||||
|
while let Some(io) = io_data.next().await {
|
||||||
|
if let Ok(io) = io {
|
||||||
|
net_rx += io.bytes_recv().get::<byte>();
|
||||||
|
net_tx += io.bytes_sent().get::<byte>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let cur_time = Instant::now();
|
||||||
|
let elapsed_time = cur_time.duration_since(*prev_net_access_time).as_millis();
|
||||||
|
|
||||||
|
let rx = (((net_rx - *prev_net_rx_bytes) * 1000) as u128 / elapsed_time) as u64;
|
||||||
|
let tx = (((net_tx - *prev_net_tx_bytes) * 1000) as u128 / elapsed_time) as u64;
|
||||||
|
|
||||||
|
*prev_net_rx_bytes = net_rx;
|
||||||
|
*prev_net_tx_bytes = net_tx;
|
||||||
|
*prev_net_access_time = cur_time;
|
||||||
|
Ok(NetworkData {
|
||||||
|
rx,
|
||||||
|
tx,
|
||||||
|
total_rx: *prev_net_rx_bytes,
|
||||||
|
total_tx: *prev_net_tx_bytes,
|
||||||
|
instant: *prev_net_access_time,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ impl Default for ProcessSorting {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Possible process info struct?
|
// Possible process info struct?
|
||||||
#[derive(Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct ProcessData {
|
pub struct ProcessData {
|
||||||
pub pid: u32,
|
pub pid: u32,
|
||||||
pub cpu_usage_percent: f64,
|
pub cpu_usage_percent: f64,
|
||||||
|
@ -168,7 +168,7 @@ fn convert_ps(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_sorted_processes_list(
|
pub fn get_sorted_processes_list(
|
||||||
sys: &System, prev_idle: &mut f64, prev_non_idle: &mut f64, prev_pid_stats: &mut std::collections::HashMap<String, (f64, Instant)>,
|
sys: &System, prev_idle: &mut f64, prev_non_idle: &mut f64, prev_pid_stats: &mut std::collections::HashMap<String, (f64, Instant)>,
|
||||||
) -> crate::utils::error::Result<Vec<ProcessData>> {
|
) -> crate::utils::error::Result<Vec<ProcessData>> {
|
||||||
let mut process_vector: Vec<ProcessData> = Vec::new();
|
let mut process_vector: Vec<ProcessData> = Vec::new();
|
||||||
|
@ -179,6 +179,7 @@ pub async fn get_sorted_processes_list(
|
||||||
let ps_result = Command::new("ps").args(&["-axo", "pid:10,comm:50,%mem:5", "--noheader"]).output()?;
|
let ps_result = Command::new("ps").args(&["-axo", "pid:10,comm:50,%mem:5", "--noheader"]).output()?;
|
||||||
let ps_stdout = String::from_utf8_lossy(&ps_result.stdout);
|
let ps_stdout = String::from_utf8_lossy(&ps_result.stdout);
|
||||||
let split_string = ps_stdout.split('\n');
|
let split_string = ps_stdout.split('\n');
|
||||||
|
//debug!("{:?}", split_string);
|
||||||
if let Ok((cpu_usage, cpu_percentage)) = cpu_usage_calculation(prev_idle, prev_non_idle) {
|
if let Ok((cpu_usage, cpu_percentage)) = cpu_usage_calculation(prev_idle, prev_non_idle) {
|
||||||
let process_stream = split_string.collect::<Vec<&str>>();
|
let process_stream = split_string.collect::<Vec<&str>>();
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use heim::units::thermodynamic_temperature;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use sysinfo::{ComponentExt, System, SystemExt};
|
use sysinfo::{ComponentExt, System, SystemExt};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TempData {
|
pub struct TempData {
|
||||||
pub component_name: Box<str>,
|
pub component_name: Box<str>,
|
||||||
pub temperature: f32,
|
pub temperature: f32,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/// This file is meant to house (OS specific) implementations on how to kill processes.
|
/// This file is meant to house (OS specific) implementations on how to kill processes.
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
|
// TODO: Redo this, also make it update process list on freeze.
|
||||||
|
|
||||||
// Copied from SO: https://stackoverflow.com/a/55231715
|
// Copied from SO: https://stackoverflow.com/a/55231715
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use winapi::{
|
use winapi::{
|
||||||
|
|
|
@ -123,7 +123,7 @@ pub fn update_cpu_data_points(show_avg_cpu: bool, app_data: &data_collection::Da
|
||||||
let mut cpu_collection: Vec<Vec<(f64, f64)>> = Vec::new();
|
let mut cpu_collection: Vec<Vec<(f64, f64)>> = Vec::new();
|
||||||
|
|
||||||
if !app_data.list_of_cpu_packages.is_empty() {
|
if !app_data.list_of_cpu_packages.is_empty() {
|
||||||
// I'm sorry for the if statement but I couldn't be bothered here...
|
// I'm sorry for the following if statement but I couldn't be bothered here...
|
||||||
for cpu_num in (if show_avg_cpu { 0 } else { 1 })..app_data.list_of_cpu_packages.last().unwrap().cpu_vec.len() {
|
for cpu_num in (if show_avg_cpu { 0 } else { 1 })..app_data.list_of_cpu_packages.last().unwrap().cpu_vec.len() {
|
||||||
let mut this_cpu_data: Vec<(f64, f64)> = Vec::new();
|
let mut this_cpu_data: Vec<(f64, f64)> = Vec::new();
|
||||||
|
|
||||||
|
@ -313,7 +313,7 @@ pub fn convert_network_data_points(network_data: &[data_collection::network::Net
|
||||||
format!("TX: {:5.*}GiB/s", 1, num_bytes as f64 / 1024.0 / 1024.0 / 1024.0)
|
format!("TX: {:5.*}GiB/s", 1, num_bytes as f64 / 1024.0 / 1024.0 / 1024.0)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
"0B.0/s".to_string()
|
"0.0B/s".to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
ConvertedNetworkData {
|
ConvertedNetworkData {
|
||||||
|
|
|
@ -169,6 +169,7 @@ fn main() -> error::Result<()> {
|
||||||
}
|
}
|
||||||
futures::executor::block_on(data_state.update_data());
|
futures::executor::block_on(data_state.update_data());
|
||||||
tx.send(Event::Update(Box::from(data_state.data.clone()))).unwrap();
|
tx.send(Event::Update(Box::from(data_state.data.clone()))).unwrap();
|
||||||
|
|
||||||
if first_run {
|
if first_run {
|
||||||
// Fix for if you set a really long time for update periods (and just gives a faster first value)
|
// Fix for if you set a really long time for update periods (and just gives a faster first value)
|
||||||
thread::sleep(Duration::from_millis(250));
|
thread::sleep(Duration::from_millis(250));
|
||||||
|
|
Loading…
Reference in a new issue