mirror of
https://github.com/ClementTsang/bottom
synced 2024-11-26 06:00:21 +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"
|
||||
rayon = "1.3"
|
||||
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"
|
||||
winapi = "0.3"
|
||||
tui = {version = "0.8", features = ["crossterm"], default-features = false }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! 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 sysinfo::{System, SystemExt};
|
||||
|
||||
|
@ -11,19 +11,19 @@ pub mod network;
|
|||
pub mod processes;
|
||||
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 {
|
||||
*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 {
|
||||
vector_to_push.push(result.clone());
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Data {
|
||||
pub list_of_cpu_packages: Vec<cpu::CPUPackage>,
|
||||
pub list_of_io: Vec<disks::IOPackage>,
|
||||
|
@ -44,6 +44,9 @@ pub struct DataState {
|
|||
prev_pid_stats: HashMap<String, (f64, Instant)>,
|
||||
prev_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,
|
||||
last_clean: Instant, // Last time stale data was cleared
|
||||
}
|
||||
|
@ -58,6 +61,9 @@ impl Default for DataState {
|
|||
prev_pid_stats: HashMap::new(),
|
||||
prev_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,
|
||||
last_clean: Instant::now(),
|
||||
}
|
||||
|
@ -70,38 +76,40 @@ impl DataState {
|
|||
}
|
||||
|
||||
pub fn init(&mut self) {
|
||||
self.sys.refresh_system();
|
||||
self.sys.refresh_network();
|
||||
if !cfg!(target_os = "linux") {
|
||||
// For now, might be just windows tbh
|
||||
self.sys.refresh_processes();
|
||||
}
|
||||
self.sys.refresh_all();
|
||||
}
|
||||
|
||||
pub async fn update_data(&mut self) {
|
||||
self.sys.refresh_system();
|
||||
self.sys.refresh_network();
|
||||
|
||||
if !cfg!(target_os = "linux") {
|
||||
// For now, might be just windows tbh
|
||||
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!
|
||||
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);
|
||||
|
||||
// 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_swap_data_list().await, &mut self.data.swap);
|
||||
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,
|
||||
);
|
||||
|
||||
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(true).await, &mut self.data.list_of_physical_io); // Removed, seems irrelevant for now...
|
||||
set_if_valid(
|
||||
&temperature::get_temperature_data(&self.sys, &self.temperature_type).await,
|
||||
&mut self.data.list_of_temperature_sensor,
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use std::time::Instant;
|
||||
use sysinfo::{ProcessorExt, System, SystemExt};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CPUData {
|
||||
pub cpu_name: Box<str>,
|
||||
pub cpu_usage: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CPUPackage {
|
||||
pub cpu_vec: Vec<CPUData>,
|
||||
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_name: Box::from(cpu.get_name()),
|
||||
cpu_usage: f64::from(cpu.get_cpu_usage()) * 100_f64,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
Ok(CPUPackage {
|
||||
|
|
|
@ -2,7 +2,7 @@ use futures::stream::StreamExt;
|
|||
use heim::units::information;
|
||||
use std::time::Instant;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct DiskData {
|
||||
pub name: Box<str>,
|
||||
pub mount_point: Box<str>,
|
||||
|
@ -18,7 +18,7 @@ pub struct IOData {
|
|||
pub write_bytes: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IOPackage {
|
||||
pub io_hash: std::collections::HashMap<String, IOData>,
|
||||
pub instant: Instant,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use heim::units::information;
|
||||
use std::time::Instant;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MemData {
|
||||
pub mem_total_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 sysinfo::{NetworkExt, System, SystemExt};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
/// Note all values are in bytes...
|
||||
pub struct NetworkData {
|
||||
pub rx : u64,
|
||||
pub tx : u64,
|
||||
pub total_rx : u64,
|
||||
pub total_tx : u64,
|
||||
pub instant : Instant,
|
||||
pub rx: u64,
|
||||
pub tx: u64,
|
||||
pub total_rx: u64,
|
||||
pub total_tx: u64,
|
||||
pub instant: Instant,
|
||||
}
|
||||
|
||||
pub fn get_network_data(sys : &System) -> crate::utils::error::Result<NetworkData> {
|
||||
let network_data = sys.get_network();
|
||||
Ok(NetworkData {
|
||||
rx : network_data.get_income(),
|
||||
tx : network_data.get_outcome(),
|
||||
total_rx : 0,
|
||||
total_tx : 0,
|
||||
instant : Instant::now(),
|
||||
})
|
||||
pub async fn get_network_data(
|
||||
sys: &System, prev_net_rx_bytes: &mut u64, prev_net_tx_bytes: &mut u64, prev_net_access_time: &mut std::time::Instant,
|
||||
) -> crate::utils::error::Result<NetworkData> {
|
||||
if cfg!(target_os = "windows") {
|
||||
let network_data = sys.get_network();
|
||||
|
||||
*prev_net_access_time = 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?
|
||||
#[derive(Clone, Default)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ProcessData {
|
||||
pub pid: u32,
|
||||
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)>,
|
||||
) -> crate::utils::error::Result<Vec<ProcessData>> {
|
||||
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_stdout = String::from_utf8_lossy(&ps_result.stdout);
|
||||
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) {
|
||||
let process_stream = split_string.collect::<Vec<&str>>();
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use heim::units::thermodynamic_temperature;
|
|||
use std::cmp::Ordering;
|
||||
use sysinfo::{ComponentExt, System, SystemExt};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TempData {
|
||||
pub component_name: Box<str>,
|
||||
pub temperature: f32,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/// This file is meant to house (OS specific) implementations on how to kill processes.
|
||||
use std::process::Command;
|
||||
|
||||
// TODO: Redo this, also make it update process list on freeze.
|
||||
|
||||
// Copied from SO: https://stackoverflow.com/a/55231715
|
||||
#[cfg(target_os = "windows")]
|
||||
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();
|
||||
|
||||
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() {
|
||||
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)
|
||||
}
|
||||
} else {
|
||||
"0B.0/s".to_string()
|
||||
"0.0B/s".to_string()
|
||||
};
|
||||
|
||||
ConvertedNetworkData {
|
||||
|
|
|
@ -169,6 +169,7 @@ fn main() -> error::Result<()> {
|
|||
}
|
||||
futures::executor::block_on(data_state.update_data());
|
||||
tx.send(Event::Update(Box::from(data_state.data.clone()))).unwrap();
|
||||
|
||||
if first_run {
|
||||
// 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));
|
||||
|
|
Loading…
Reference in a new issue