Skip to content

Commit a7a6702

Browse files
committed
simple implementation for top summary
1 parent c2c0bab commit a7a6702

File tree

5 files changed

+121
-8
lines changed

5 files changed

+121
-8
lines changed

Cargo.lock

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ uucore = "0.0.28"
6161
walkdir = "2.5.0"
6262
windows = { version = "0.59.0" }
6363
xattr = "1.3.1"
64+
systemstat = "0.2.4"
6465

6566
[dependencies]
6667
clap = { workspace = true }

src/uu/top/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ nix = { workspace = true }
1919
prettytable-rs = { workspace = true }
2020
sysinfo = { workspace = true }
2121
chrono = { workspace = true }
22+
systemstat = { workspace = true }
23+
bytesize = { workspace = true }
2224

2325
[lib]
2426
path = "src/top.rs"

src/uu/top/src/picker.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,19 @@ use std::{
1212
sync::{OnceLock, RwLock},
1313
};
1414
use sysinfo::{Pid, System, Users};
15+
use systemstat::Platform;
1516

1617
static SYSINFO: OnceLock<RwLock<System>> = OnceLock::new();
18+
static SYSTEMSTAT: OnceLock<RwLock<systemstat::System>> = OnceLock::new();
1719

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

24+
pub fn systemstat() -> &'static RwLock<systemstat::System> {
25+
SYSTEMSTAT.get_or_init(|| RwLock::new(systemstat::System::new()))
26+
}
27+
2228
pub(crate) fn pickers(fields: &[String]) -> Vec<Box<dyn Fn(u32) -> String>> {
2329
fields
2430
.iter()

src/uu/top/src/top.rs

Lines changed: 80 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6+
use crate::picker::systemstat;
7+
use bytesize::ByteSize;
68
use clap::{arg, crate_version, value_parser, ArgAction, ArgGroup, ArgMatches, Command};
79
use picker::pickers;
810
use picker::sysinfo;
911
use prettytable::{format::consts::FORMAT_CLEAN, Row, Table};
1012
use std::{thread::sleep, time::Duration};
1113
use sysinfo::{Pid, Users};
14+
use systemstat::{CPULoad, Platform};
1215
use uucore::{
1316
error::{UResult, USimpleError},
1417
format_usage, help_about, help_usage,
@@ -53,8 +56,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
5356
// Must refresh twice.
5457
// https://docs.rs/sysinfo/0.31.2/sysinfo/struct.System.html#method.refresh_cpu_usage
5558
picker::sysinfo().write().unwrap().refresh_all();
59+
let cpu_load = systemstat().read().unwrap().cpu_load_aggregate()?;
5660
sleep(Duration::from_millis(200));
5761
picker::sysinfo().write().unwrap().refresh_all();
62+
let cpu_load = cpu_load.done()?;
5863

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

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

100-
println!("{}", header());
105+
println!("{}", header(cpu_load));
101106
println!("\n");
102107

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

116-
table
117-
.to_string()
118-
.lines()
119-
.map(cutter)
120-
.for_each(|it| println!("{}", it));
121+
table.to_string().lines().map(cutter).for_each(|_| {});
122+
// .for_each(|it| println!("{}", it));
121123

122124
Ok(())
123125
}
@@ -157,9 +159,79 @@ where
157159
}
158160
}
159161

162+
fn format_uptime(duration: Duration) -> String {
163+
let mut num = duration.as_secs();
164+
if num < 60 {
165+
return format!("{} s", num);
166+
}
167+
168+
num /= 60; //to minutes
169+
if num < 60 {
170+
return format!("{} m", num);
171+
}
172+
if num < 600 {
173+
return format!("{}:{:2}", num / 60, num % 60);
174+
}
175+
176+
num /= 60; //to hours
177+
if num < 24 {
178+
format!("{} h", num)
179+
} else {
180+
num /= 24; //to days
181+
format!("{} d", num)
182+
}
183+
}
184+
160185
// TODO: Implement information collecting.
161-
fn header() -> String {
162-
"TODO".into()
186+
fn header(cpu_load: CPULoad) -> String {
187+
let systemstat = systemstat().read().unwrap();
188+
let sysinfo = sysinfo().read().unwrap();
189+
let process = sysinfo.processes();
190+
let mut running_process = 0;
191+
let mut sleeping_process = 0;
192+
let mut stopped_process = 0;
193+
let mut zombie_process = 0;
194+
for (_, process) in process.iter() {
195+
match process.status() {
196+
sysinfo::ProcessStatus::Run => running_process += 1,
197+
sysinfo::ProcessStatus::Sleep => sleeping_process += 1,
198+
sysinfo::ProcessStatus::Stop => stopped_process += 1,
199+
sysinfo::ProcessStatus::Zombie => zombie_process += 1,
200+
_ => {}
201+
};
202+
}
203+
204+
//, {} hi, {} si, {} st
205+
format!(
206+
"top - {} up {}, %n user, load average: {:.2}, {:.2}, {:.2}\n\
207+
Tasks: {} total, {} running, {} sleeping, {} stopped, {} zombie\n\
208+
%Cpu(s): {:.1} us, {:.1} sy, {:.1} ni, {:.1} id, {:.1} wa\n\
209+
MiB Mem : {:8.1} total, {:8.1} free, {:8.1} used, {:8.1} buff/cache\n\
210+
MiB Swap: {:8.1} total, {:8.1} free, {:8.1} used, {:8.1} avail Mem\n",
211+
chrono::Local::now().format("%H:%M:%S"),
212+
format_uptime(systemstat.uptime().unwrap()),
213+
systemstat.load_average().unwrap().one,
214+
systemstat.load_average().unwrap().five,
215+
systemstat.load_average().unwrap().fifteen,
216+
process.len(),
217+
running_process,
218+
sleeping_process,
219+
stopped_process,
220+
zombie_process,
221+
cpu_load.user * 100.0,
222+
cpu_load.system * 100.0,
223+
cpu_load.nice * 100.0,
224+
cpu_load.idle * 100.0,
225+
cpu_load.platform.iowait * 100.0,
226+
ByteSize::b(sysinfo.total_memory()).0 as f64 / bytesize::MIB as f64,
227+
ByteSize::b(sysinfo.free_memory()).0 as f64 / bytesize::MIB as f64,
228+
ByteSize::b(sysinfo.used_memory()).0 as f64 / bytesize::MIB as f64,
229+
ByteSize::b(sysinfo.total_memory() - sysinfo.free_memory()).0 as f64 / bytesize::MIB as f64,
230+
ByteSize::b(sysinfo.total_swap()).0 as f64 / bytesize::MIB as f64,
231+
ByteSize::b(sysinfo.free_swap()).0 as f64 / bytesize::MIB as f64,
232+
ByteSize::b(sysinfo.used_swap()).0 as f64 / bytesize::MIB as f64,
233+
ByteSize::b(sysinfo.total_memory() - sysinfo.free_memory()).0 as f64 / bytesize::MIB as f64,
234+
)
163235
}
164236

165237
// TODO: Implement fields selecting

0 commit comments

Comments
 (0)