summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml1
-rw-r--r--TODO.md4
-rw-r--r--src/app/data_collection/cpu.rs (renamed from src/widgets/cpu.rs)4
-rw-r--r--src/app/data_collection/disks.rs (renamed from src/widgets/disks.rs)0
-rw-r--r--src/app/data_collection/mem.rs (renamed from src/widgets/mem.rs)0
-rw-r--r--src/app/data_collection/mod.rs6
-rw-r--r--src/app/data_collection/network.rs (renamed from src/widgets/network.rs)4
-rw-r--r--src/app/data_collection/processes.rs (renamed from src/widgets/processes.rs)16
-rw-r--r--src/app/data_collection/temperature.rs (renamed from src/widgets/temperature.rs)0
-rw-r--r--src/app/mod.rs (renamed from src/widgets/mod.rs)10
-rw-r--r--src/main.rs121
11 files changed, 102 insertions, 64 deletions
diff --git a/Cargo.toml b/Cargo.toml
index ba5fbff1..d357f593 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,6 +8,7 @@ edition = "2018"
[dependencies]
chrono = "0.4.9"
+clap = "2.33.0"
crossterm = "0.10.2"
futures-preview = "0.3.0-alpha.18"
fern = "0.5"
diff --git a/TODO.md b/TODO.md
index 65388e30..b97e0a71 100644
--- a/TODO.md
+++ b/TODO.md
@@ -10,9 +10,11 @@
* Add custom error because it's really messy
+* Scrolling event
+
* Keybindings
-* FIX PROCESSES AHHHHHH
+~~* FIX PROCESSES AHHHHHH~~
* Refactor everything because it's a mess
diff --git a/src/widgets/cpu.rs b/src/app/data_collection/cpu.rs
index f6c7f31d..e2a00272 100644
--- a/src/widgets/cpu.rs
+++ b/src/app/data_collection/cpu.rs
@@ -4,7 +4,7 @@ use sysinfo::{ProcessorExt, System, SystemExt};
#[derive(Clone)]
pub struct CPUData {
pub cpu_name : Box<str>,
- pub cpu_usage : u32,
+ pub cpu_usage : f64,
}
#[derive(Clone)]
@@ -20,7 +20,7 @@ pub fn get_cpu_data_list(sys : &System) -> Result<CPUPackage, heim::Error> {
for cpu in cpu_data {
cpu_vec.push(CPUData {
cpu_name : Box::from(cpu.get_name()),
- cpu_usage : (cpu.get_cpu_usage() * 100_f32).ceil() as u32,
+ cpu_usage : f64::from(cpu.get_cpu_usage()) * 100_f64,
})
}
diff --git a/src/widgets/disks.rs b/src/app/data_collection/disks.rs
index dcfe58fe..dcfe58fe 100644
--- a/src/widgets/disks.rs
+++ b/src/app/data_collection/disks.rs
diff --git a/src/widgets/mem.rs b/src/app/data_collection/mem.rs
index c7c06f8d..c7c06f8d 100644
--- a/src/widgets/mem.rs
+++ b/src/app/data_collection/mem.rs
diff --git a/src/app/data_collection/mod.rs b/src/app/data_collection/mod.rs
new file mode 100644
index 00000000..fdbd4bcd
--- /dev/null
+++ b/src/app/data_collection/mod.rs
@@ -0,0 +1,6 @@
+pub mod cpu;
+pub mod disks;
+pub mod mem;
+pub mod network;
+pub mod processes;
+pub mod temperature;
diff --git a/src/widgets/network.rs b/src/app/data_collection/network.rs
index 24a89678..b54e93dd 100644
--- a/src/widgets/network.rs
+++ b/src/app/data_collection/network.rs
@@ -5,6 +5,8 @@ use sysinfo::{NetworkExt, System, SystemExt};
pub struct NetworkData {
pub rx : u64,
pub tx : u64,
+ pub total_rx : u64,
+ pub total_tx : u64,
pub instant : Instant,
}
@@ -13,6 +15,8 @@ pub fn get_network_data(sys : &System) -> Result<NetworkData, heim::Error> {
Ok(NetworkData {
rx : network_data.get_income(),
tx : network_data.get_outcome(),
+ total_rx : 0,
+ total_tx : 0,
instant : Instant::now(),
})
}
diff --git a/src/widgets/processes.rs b/src/app/data_collection/processes.rs
index e0d43dcd..e4bb0bd4 100644
--- a/src/widgets/processes.rs
+++ b/src/app/data_collection/processes.rs
@@ -52,10 +52,14 @@ fn vangelis_cpu_usage_calculation(prev_idle : &mut f64, prev_non_idle : &mut f64
let total_delta : f64 = total - prev_total;
let idle_delta : f64 = idle - *prev_idle;
+ debug!("Vangelis function: CPU PERCENT: {}", (total_delta - idle_delta) / total_delta * 100_f64);
+
*prev_idle = idle;
*prev_non_idle = non_idle;
- Ok(total_delta - idle_delta)
+ let result = if total_delta - idle_delta != 0_f64 { total_delta - idle_delta } else { 1_f64 };
+
+ Ok(result) // This works, REALLY damn well. The percentage check is within like 2% of the sysinfo one.
}
fn get_ordering<T : std::cmp::PartialOrd>(a_val : T, b_val : T, reverse_order : bool) -> std::cmp::Ordering {
@@ -96,16 +100,18 @@ fn get_process_cpu_stats(pid : u32) -> std::io::Result<f64> {
let stat_results = std::fs::read_to_string(path)?;
let val = stat_results.split_whitespace().collect::<Vec<&str>>();
- let utime = val[13].parse::<f64>().unwrap_or(-1_f64);
- let stime = val[14].parse::<f64>().unwrap_or(-1_f64);
+ let utime = val[13].parse::<f64>().unwrap_or(0_f64);
+ let stime = val[14].parse::<f64>().unwrap_or(0_f64);
+
+ debug!("PID: {}, utime: {}, stime: {}", pid, utime, stime);
- Ok(utime + stime)
+ Ok(utime + stime) // This seems to match top...
}
fn linux_cpu_usage(pid : u32, cpu_usage : f64, previous_pid_stats : &mut HashMap<String, f64>) -> std::io::Result<f64> {
// Based heavily on https://stackoverflow.com/a/23376195 and https://stackoverflow.com/a/1424556
let before_proc_val : f64 = if previous_pid_stats.contains_key(&pid.to_string()) {
- *previous_pid_stats.get(&pid.to_string()).unwrap_or(&-1_f64)
+ *previous_pid_stats.get(&pid.to_string()).unwrap_or(&0_f64)
}
else {
0_f64
diff --git a/src/widgets/temperature.rs b/src/app/data_collection/temperature.rs
index d1c49c1a..d1c49c1a 100644
--- a/src/widgets/temperature.rs
+++ b/src/app/data_collection/temperature.rs
diff --git a/src/widgets/mod.rs b/src/app/mod.rs
index a2fc252a..c07b3884 100644
--- a/src/widgets/mod.rs
+++ b/src/app/mod.rs
@@ -1,9 +1,5 @@
-pub mod cpu;
-pub mod disks;
-pub mod mem;
-pub mod network;
-pub mod processes;
-pub mod temperature;
+pub mod data_collection;
+use data_collection::{cpu, disks, mem, network, processes, temperature};
use std::collections::HashMap;
use sysinfo::{System, SystemExt};
@@ -46,7 +42,7 @@ pub struct DataState {
pub data : Data,
sys : System,
stale_max_seconds : u64,
- prev_pid_stats : HashMap<String, f64>,
+ prev_pid_stats : HashMap<String, f64>, // TODO: Purge list?
prev_idle : f64,
prev_non_idle : f64,
}
diff --git a/src/main.rs b/src/main.rs
index 1d8207f8..9a578c10 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,19 +4,20 @@ use std::{io, sync::mpsc, thread, time::Duration};
use tui::{
backend::CrosstermBackend,
layout::{Constraint, Direction, Layout},
- style::{Color, Style},
+ style::{Color, Modifier, Style},
widgets::{Axis, Block, Borders, Chart, Dataset, Marker, Row, Table, Widget},
Terminal,
};
-mod widgets;
+mod app;
+use app::data_collection;
#[macro_use]
extern crate log;
enum Event<I> {
Input(I),
- Update(Box<widgets::Data>),
+ Update(Box<app::Data>),
}
const STALE_MAX_SECONDS : u64 = 60;
@@ -30,7 +31,7 @@ async fn main() -> Result<(), io::Error> {
let tick_rate_in_milliseconds : u64 = 250;
let update_rate_in_milliseconds : u64 = 1000; // TODO: Must set a check to prevent this from going into negatives!
- let mut app = widgets::App::new("rustop");
+ let mut app = app::App::new("rustop");
let log = init_logger();
@@ -53,7 +54,7 @@ async fn main() -> Result<(), io::Error> {
}
// Event loop
- let mut data_state = widgets::DataState::default();
+ let mut data_state = app::DataState::default();
data_state.init();
data_state.set_stale_max_seconds(STALE_MAX_SECONDS);
{
@@ -70,7 +71,10 @@ async fn main() -> Result<(), io::Error> {
terminal.clear()?;
- let mut app_data = widgets::Data::default();
+ let mut app_data = app::Data::default();
+ let mut swap_data : Vec<(f64, f64)> = Vec::new();
+ let mut mem_data : Vec<(f64, f64)> = Vec::new();
+
loop {
if let Ok(recv) = rx.recv_timeout(Duration::from_millis(tick_rate_in_milliseconds)) {
match recv {
@@ -87,16 +91,22 @@ async fn main() -> Result<(), io::Error> {
}
if app.to_be_resorted {
- widgets::processes::sort_processes(&mut app_data.list_of_processes, &app.process_sorting_type, app.process_sorting_reverse);
+ data_collection::processes::sort_processes(&mut app_data.list_of_processes, &app.process_sorting_type, app.process_sorting_reverse);
app.to_be_resorted = false;
}
try_debug(&log, "Input event complete.");
+
+ // Only update processes
}
Event::Update(data) => {
try_debug(&log, "Update event fired!");
app_data = *data;
- widgets::processes::sort_processes(&mut app_data.list_of_processes, &app.process_sorting_type, app.process_sorting_reverse);
+ data_collection::processes::sort_processes(&mut app_data.list_of_processes, &app.process_sorting_type, app.process_sorting_reverse);
try_debug(&log, "Update event complete.");
+
+ // Convert all data into tui components
+ mem_data = update_mem_data_points(&app_data);
+ swap_data = update_swap_data_points(&app_data);
}
}
if app.should_quit {
@@ -105,14 +115,33 @@ async fn main() -> Result<(), io::Error> {
}
// Draw!
- draw_data(&mut terminal, &app_data)?;
+ // TODO: We should change this btw! It should not redraw everything on every tick!
+ draw_data(&mut terminal, &app_data, &mem_data, &swap_data)?;
}
Ok(())
}
-fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_data : &widgets::Data) -> Result<(), io::Error> {
- // Convert data into tui components
+fn update_temp_row(app_data : &app::Data) {
+}
+
+fn update_process_row(app_data : &app::Data) {
+}
+
+fn update_cpu_data_points(app_data : &app::Data) {
+}
+
+fn update_mem_data_points(app_data : &app::Data) -> Vec<(f64, f64)> {
+ convert_mem_data(&app_data.memory)
+}
+
+fn update_swap_data_points(app_data : &app::Data) -> Vec<(f64, f64)> {
+ convert_mem_data(&app_data.swap)
+}
+
+fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_data : &app::Data, mem_data : &[(f64, f64)], swap_data : &[(f64, f64)]) -> Result<(), io::Error> {
+ const COLOUR_LIST : [Color; 6] = [Color::LightCyan, Color::LightMagenta, Color::LightRed, Color::LightGreen, Color::LightYellow, Color::LightBlue];
+
let temperature_rows = app_data.list_of_temperature.iter().map(|sensor| {
Row::StyledData(
vec![sensor.component_name.to_string(), sensor.temperature.to_string() + "C"].into_iter(), // TODO: Change this based on temperature type
@@ -134,6 +163,32 @@ fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_data :
)
});
+ let mut dataset_vector : Vec<Dataset> = Vec::new();
+ let mut data_vector : Vec<Vec<(f64, f64)>> = Vec::new();
+
+ if !app_data.list_of_cpu_packages.is_empty() {
+ for cpu_num in 0..app_data.list_of_cpu_packages.last().unwrap().cpu_vec.len() {
+ let mut this_cpu_data : Vec<(f64, f64)> = Vec::new();
+ let current_time = std::time::Instant::now();
+
+ for cpu in &app_data.list_of_cpu_packages {
+ this_cpu_data.push((STALE_MAX_SECONDS as f64 - current_time.duration_since(cpu.instant).as_secs_f64(), cpu.cpu_vec[cpu_num].cpu_usage));
+ }
+
+ data_vector.push(this_cpu_data);
+ }
+
+ for (i, data) in data_vector.iter().enumerate() {
+ dataset_vector.push(
+ Dataset::default()
+ .name(&*(app_data.list_of_cpu_packages.last().unwrap().cpu_vec[i].cpu_name))
+ .marker(Marker::Braille)
+ .style(Style::default().fg(COLOUR_LIST[i % COLOUR_LIST.len()]))
+ .data(&data),
+ )
+ }
+ }
+
let process_rows = app_data.list_of_processes.iter().map(|process| {
Row::StyledData(
vec![
@@ -200,24 +255,15 @@ fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_data :
// CPU usage graph
{
+ debug!("Drawing CPU...");
let x_axis : Axis<String> = Axis::default().style(Style::default().fg(Color::White)).bounds([0.0, 60.0]);
let y_axis = Axis::default().style(Style::default().fg(Color::White)).bounds([0.0, 100.0]).labels(&["0.0", "50.0", "100.0"]);
+
Chart::default()
.block(Block::default().title("CPU Usage").borders(Borders::ALL))
.x_axis(x_axis)
.y_axis(y_axis)
- .datasets(&[
- Dataset::default()
- .name("CPU0")
- .marker(Marker::Braille)
- .style(Style::default().fg(Color::Cyan))
- .data(&convert_cpu_data(0, &app_data.list_of_cpu_packages)),
- Dataset::default()
- .name("CPU1")
- .marker(Marker::Braille)
- .style(Style::default().fg(Color::LightMagenta))
- .data(&convert_cpu_data(1, &app_data.list_of_cpu_packages)),
- ])
+ .datasets(&dataset_vector)
.render(&mut f, top_chunks[0]);
}
@@ -230,16 +276,8 @@ fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_data :
.x_axis(x_axis)
.y_axis(y_axis)
.datasets(&[
- Dataset::default()
- .name("MEM")
- .marker(Marker::Braille)
- .style(Style::default().fg(Color::Cyan))
- .data(&convert_mem_data(&app_data.memory)),
- Dataset::default()
- .name("SWAP")
- .marker(Marker::Braille)
- .style(Style::default().fg(Color::LightGreen))
- .data(&convert_mem_data(&app_data.swap)),
+ Dataset::default().name("MEM").marker(Marker::Braille).style(Style::default().fg(Color::Cyan)).data(&mem_data),
+ Dataset::default().name("SWAP").marker(Marker::Braille).style(Style::default().fg(Color::LightGreen)).data(&swap_data),
])
.render(&mut f, top_chunks[1]);
}
@@ -278,22 +316,7 @@ fn draw_data<B : tui::backend::Backend>(terminal : &mut Terminal<B>, app_data :
Ok(())
}
-// TODO: Remove this count, this is for testing, lol
-fn convert_cpu_data(count : usize, cpu_data : &[widgets::cpu::CPUPackage]) -> Vec<(f64, f64)> {
- let mut result : Vec<(f64, f64)> = Vec::new();
- let current_time = std::time::Instant::now();
-
- for data in cpu_data {
- result.push((
- STALE_MAX_SECONDS as f64 - current_time.duration_since(data.instant).as_secs() as f64,
- f64::from(data.cpu_vec[count + 1].cpu_usage),
- ));
- }
-
- result
-}
-
-fn convert_mem_data(mem_data : &[widgets::mem::MemData]) -> Vec<(f64, f64)> {
+fn convert_mem_data(mem_data : &[app::data_collection::mem::MemData]) -> Vec<(f64, f64)> {
let mut result : Vec<(f64, f64)> = Vec::new();
let current_time = std::time::Instant::now();