Skip to content

Commit

Permalink
simple implementation for top summary
Browse files Browse the repository at this point in the history
  • Loading branch information
Bluemangoo committed Jan 13, 2025
1 parent c2c0bab commit a7a6702
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 8 deletions.
32 changes: 32 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ uucore = "0.0.28"
walkdir = "2.5.0"
windows = { version = "0.59.0" }
xattr = "1.3.1"
systemstat = "0.2.4"

[dependencies]
clap = { workspace = true }
Expand Down
2 changes: 2 additions & 0 deletions src/uu/top/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ nix = { workspace = true }
prettytable-rs = { workspace = true }
sysinfo = { workspace = true }
chrono = { workspace = true }
systemstat = { workspace = true }
bytesize = { workspace = true }

[lib]
path = "src/top.rs"
Expand Down
6 changes: 6 additions & 0 deletions src/uu/top/src/picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,19 @@ use std::{
sync::{OnceLock, RwLock},
};
use sysinfo::{Pid, System, Users};
use systemstat::Platform;

static SYSINFO: OnceLock<RwLock<System>> = OnceLock::new();
static SYSTEMSTAT: OnceLock<RwLock<systemstat::System>> = OnceLock::new();

pub fn sysinfo() -> &'static RwLock<System> {
SYSINFO.get_or_init(|| RwLock::new(System::new_all()))
}

pub fn systemstat() -> &'static RwLock<systemstat::System> {
SYSTEMSTAT.get_or_init(|| RwLock::new(systemstat::System::new()))
}

pub(crate) fn pickers(fields: &[String]) -> Vec<Box<dyn Fn(u32) -> String>> {
fields
.iter()
Expand Down
88 changes: 80 additions & 8 deletions src/uu/top/src/top.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

use crate::picker::systemstat;
use bytesize::ByteSize;
use clap::{arg, crate_version, value_parser, ArgAction, ArgGroup, ArgMatches, Command};
use picker::pickers;
use picker::sysinfo;
use prettytable::{format::consts::FORMAT_CLEAN, Row, Table};
use std::{thread::sleep, time::Duration};
use sysinfo::{Pid, Users};
use systemstat::{CPULoad, Platform};
use uucore::{
error::{UResult, USimpleError},
format_usage, help_about, help_usage,
Expand Down Expand Up @@ -53,8 +56,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
// Must refresh twice.
// https://docs.rs/sysinfo/0.31.2/sysinfo/struct.System.html#method.refresh_cpu_usage
picker::sysinfo().write().unwrap().refresh_all();
let cpu_load = systemstat().read().unwrap().cpu_load_aggregate()?;
sleep(Duration::from_millis(200));
picker::sysinfo().write().unwrap().refresh_all();
let cpu_load = cpu_load.done()?;

let settings = Settings::new(&matches);

Expand Down Expand Up @@ -97,7 +102,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
table
};

println!("{}", header());
println!("{}", header(cpu_load));
println!("\n");

let cutter = {
Expand All @@ -113,11 +118,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
}
};

table
.to_string()
.lines()
.map(cutter)
.for_each(|it| println!("{}", it));
table.to_string().lines().map(cutter).for_each(|_| {});
// .for_each(|it| println!("{}", it));

Ok(())
}
Expand Down Expand Up @@ -157,9 +159,79 @@ where
}
}

fn format_uptime(duration: Duration) -> String {
let mut num = duration.as_secs();
if num < 60 {
return format!("{} s", num);
}

num /= 60; //to minutes
if num < 60 {
return format!("{} m", num);
}
if num < 600 {
return format!("{}:{:2}", num / 60, num % 60);
}

num /= 60; //to hours
if num < 24 {
format!("{} h", num)
} else {
num /= 24; //to days
format!("{} d", num)
}
}

// TODO: Implement information collecting.
fn header() -> String {
"TODO".into()
fn header(cpu_load: CPULoad) -> String {
let systemstat = systemstat().read().unwrap();
let sysinfo = sysinfo().read().unwrap();
let process = sysinfo.processes();
let mut running_process = 0;
let mut sleeping_process = 0;
let mut stopped_process = 0;
let mut zombie_process = 0;
for (_, process) in process.iter() {
match process.status() {
sysinfo::ProcessStatus::Run => running_process += 1,
sysinfo::ProcessStatus::Sleep => sleeping_process += 1,
sysinfo::ProcessStatus::Stop => stopped_process += 1,
sysinfo::ProcessStatus::Zombie => zombie_process += 1,
_ => {}
};
}

//, {} hi, {} si, {} st
format!(
"top - {} up {}, %n user, load average: {:.2}, {:.2}, {:.2}\n\
Tasks: {} total, {} running, {} sleeping, {} stopped, {} zombie\n\
%Cpu(s): {:.1} us, {:.1} sy, {:.1} ni, {:.1} id, {:.1} wa\n\
MiB Mem : {:8.1} total, {:8.1} free, {:8.1} used, {:8.1} buff/cache\n\
MiB Swap: {:8.1} total, {:8.1} free, {:8.1} used, {:8.1} avail Mem\n",
chrono::Local::now().format("%H:%M:%S"),
format_uptime(systemstat.uptime().unwrap()),
systemstat.load_average().unwrap().one,
systemstat.load_average().unwrap().five,
systemstat.load_average().unwrap().fifteen,
process.len(),
running_process,
sleeping_process,
stopped_process,
zombie_process,
cpu_load.user * 100.0,
cpu_load.system * 100.0,
cpu_load.nice * 100.0,
cpu_load.idle * 100.0,
cpu_load.platform.iowait * 100.0,
ByteSize::b(sysinfo.total_memory()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.free_memory()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.used_memory()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.total_memory() - sysinfo.free_memory()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.total_swap()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.free_swap()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.used_swap()).0 as f64 / bytesize::MIB as f64,
ByteSize::b(sysinfo.total_memory() - sysinfo.free_memory()).0 as f64 / bytesize::MIB as f64,
)
}

// TODO: Implement fields selecting
Expand Down

0 comments on commit a7a6702

Please sign in to comment.