mirror of
https://github.com/m1ngsama/tracker.git
synced 2025-12-25 02:57:02 +00:00
optimize(ui): enhance CLI output with colors and progress bars
- Add crossterm dependency for TUI features - Implement colored progress bars for system metrics - Add clear screen and cursor reset in continuous mode - Style process table with colors and formatting - Colorize alert thresholds (Green/Yellow/Red)
This commit is contained in:
parent
9fe4543aa6
commit
5b3b0ce156
5 changed files with 77 additions and 16 deletions
|
|
@ -16,6 +16,8 @@ log = "0.4"
|
|||
env_logger = "0.11"
|
||||
csv = "1.3"
|
||||
anyhow = "1.0"
|
||||
crossterm = "0.27"
|
||||
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
use clap::Parser;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use crossterm::{
|
||||
execute,
|
||||
terminal::{Clear, ClearType},
|
||||
cursor::MoveTo,
|
||||
};
|
||||
use std::io::stdout;
|
||||
|
||||
mod config;
|
||||
mod monitor;
|
||||
|
|
@ -44,6 +50,7 @@ fn main() {
|
|||
if args.continuous {
|
||||
log::info!("Starting continuous monitoring mode with {}s interval", args.interval);
|
||||
loop {
|
||||
execute!(stdout(), Clear(ClearType::All), MoveTo(0, 0)).unwrap();
|
||||
monitor.display_stats();
|
||||
thread::sleep(Duration::from_secs(args.interval));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use crate::alert::AlertSystem;
|
|||
use crate::logger::TrackerLogger;
|
||||
use sysinfo::{System, Disks, Networks};
|
||||
use chrono::Local;
|
||||
use crossterm::style::Stylize;
|
||||
|
||||
pub struct SystemMonitor {
|
||||
config: Config,
|
||||
|
|
@ -31,6 +32,23 @@ impl SystemMonitor {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw_bar(&self, percent: f32) -> String {
|
||||
let width = 20;
|
||||
let filled = ((percent / 100.0) * width as f32).round() as usize;
|
||||
let filled = filled.min(width); // Ensure we don't exceed width
|
||||
let empty = width.saturating_sub(filled);
|
||||
|
||||
let bar_str = format!("[{}{}]", "|".repeat(filled), " ".repeat(empty));
|
||||
|
||||
if percent >= 90.0 {
|
||||
bar_str.red().to_string()
|
||||
} else if percent >= 75.0 {
|
||||
bar_str.yellow().to_string()
|
||||
} else {
|
||||
bar_str.green().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_cpu_usage(&mut self) -> f32 {
|
||||
self.sys.refresh_cpu_all();
|
||||
self.sys.global_cpu_usage()
|
||||
|
|
@ -105,20 +123,24 @@ impl SystemMonitor {
|
|||
}
|
||||
|
||||
pub fn display_stats(&mut self) {
|
||||
println!("\n{}", "=".repeat(50));
|
||||
println!("System Tracker - {}", Local::now().format("%Y-%m-%d %H:%M:%S"));
|
||||
println!("{}\n", "=".repeat(50));
|
||||
println!("\n{}", "=".repeat(50).blue());
|
||||
println!("System Tracker - {}", Local::now().format("%Y-%m-%d %H:%M:%S").to_string().cyan().bold());
|
||||
println!("{}\n", "=".repeat(50).blue());
|
||||
|
||||
if self.config.display.show_cpu {
|
||||
let cpu_usage = self.get_cpu_usage();
|
||||
println!("CPU Usage: {:.2}%", cpu_usage);
|
||||
let bar = self.draw_bar(cpu_usage);
|
||||
println!("{:<15} {} {:.2}%", "CPU Usage:".bold(), bar, cpu_usage);
|
||||
self.logger.log_stats("CPU", &format!("{:.2}%", cpu_usage));
|
||||
self.alert_system.check_cpu_alert(cpu_usage);
|
||||
}
|
||||
|
||||
if self.config.display.show_memory {
|
||||
let mem = self.get_memory_info();
|
||||
println!("Memory: {:.2}% ({:.2}GB / {:.2}GB)",
|
||||
let bar = self.draw_bar(mem.percent);
|
||||
println!("{:<15} {} {:.2}% ({:.2}GB / {:.2}GB)",
|
||||
"Memory:".bold(),
|
||||
bar,
|
||||
mem.percent,
|
||||
mem.used as f64 / (1024_f64.powi(3)),
|
||||
mem.total as f64 / (1024_f64.powi(3))
|
||||
|
|
@ -129,7 +151,10 @@ impl SystemMonitor {
|
|||
|
||||
if self.config.display.show_disk {
|
||||
let disk = self.get_disk_usage();
|
||||
println!("Disk: {:.2}% ({:.2}GB / {:.2}GB)",
|
||||
let bar = self.draw_bar(disk.percent);
|
||||
println!("{:<15} {} {:.2}% ({:.2}GB / {:.2}GB)",
|
||||
"Disk:".bold(),
|
||||
bar,
|
||||
disk.percent,
|
||||
disk.used as f64 / (1024_f64.powi(3)),
|
||||
disk.total as f64 / (1024_f64.powi(3))
|
||||
|
|
@ -140,18 +165,21 @@ impl SystemMonitor {
|
|||
|
||||
if self.config.display.show_network {
|
||||
let net = self.get_network_stats();
|
||||
println!("Network: Sent {:.2}MB | Recv {:.2}MB",
|
||||
net.bytes_sent as f64 / (1024_f64.powi(2)),
|
||||
net.bytes_recv as f64 / (1024_f64.powi(2))
|
||||
println!("{:<15} Sent {} | Recv {}",
|
||||
"Network:".bold(),
|
||||
format!("{:.2}MB", net.bytes_sent as f64 / (1024_f64.powi(2))).green(),
|
||||
format!("{:.2}MB", net.bytes_recv as f64 / (1024_f64.powi(2))).green()
|
||||
);
|
||||
self.logger.log_stats("Network", &format!("Sent: {} Recv: {}", net.bytes_sent, net.bytes_recv));
|
||||
}
|
||||
|
||||
if self.config.display.show_processes {
|
||||
println!("\n{}", "Top Processes:".bold().underlined());
|
||||
self.process_monitor.display_processes(self.config.process_limit);
|
||||
}
|
||||
|
||||
if self.config.display.show_temperatures {
|
||||
println!("\n{}", "Temperatures:".bold().underlined());
|
||||
self.temperature_monitor.display_temperatures();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use sysinfo::System;
|
||||
use crossterm::style::Stylize;
|
||||
|
||||
pub struct ProcessMonitor {
|
||||
sys: System,
|
||||
|
|
@ -52,16 +53,37 @@ impl ProcessMonitor {
|
|||
}
|
||||
|
||||
pub fn display_processes(&mut self, limit: usize) {
|
||||
println!("\nTop Processes by CPU Usage:");
|
||||
println!("{:<10}{:<30}{:<10}{:<10}", "PID", "Name", "CPU%", "Memory%");
|
||||
println!("{}", "-".repeat(60));
|
||||
println!("{:<10}{:<30}{:<10}{:<10}",
|
||||
"PID".bold(), "Name".bold(), "CPU%".bold(), "Memory%".bold());
|
||||
println!("{}", "-".repeat(60).blue());
|
||||
|
||||
for proc in self.get_top_processes(limit) {
|
||||
println!("{:<10}{:<30}{:<10.2}{:<10.2}",
|
||||
proc.pid, proc.name, proc.cpu_percent, proc.memory_percent);
|
||||
let cpu = format!("{:.2}", proc.cpu_percent);
|
||||
let mem = format!("{:.2}", proc.memory_percent);
|
||||
|
||||
let cpu_colored = if proc.cpu_percent > 50.0 {
|
||||
cpu.red()
|
||||
} else if proc.cpu_percent > 20.0 {
|
||||
cpu.yellow()
|
||||
} else {
|
||||
cpu.green()
|
||||
};
|
||||
|
||||
let name = if proc.name.len() > 28 {
|
||||
format!("{}...", &proc.name[..25])
|
||||
} else {
|
||||
proc.name.clone()
|
||||
};
|
||||
|
||||
println!("{:<10}{:<30}{:<10}{:<10}",
|
||||
proc.pid,
|
||||
name,
|
||||
cpu_colored,
|
||||
mem
|
||||
);
|
||||
}
|
||||
|
||||
println!("\nTotal Processes: {}", self.get_process_count());
|
||||
println!("\nTotal Processes: {}", self.get_process_count().to_string().cyan());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use crossterm::style::Stylize;
|
||||
|
||||
pub struct TemperatureMonitor;
|
||||
|
||||
impl TemperatureMonitor {
|
||||
|
|
@ -6,7 +8,7 @@ impl TemperatureMonitor {
|
|||
}
|
||||
|
||||
pub fn display_temperatures(&mut self) {
|
||||
println!("\nTemperature sensors not available on this system");
|
||||
println!("{}", "Temperature sensors not available on this system".yellow());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue