It seems to somewhat work on my machine

This commit is contained in:
Lucien Cartier-Tilet 2021-12-09 06:02:04 +01:00
parent 7099e9d7df
commit bb44f85e42
Signed by: phundrak
GPG Key ID: BD7789E705CB8DCA
6 changed files with 222 additions and 26 deletions

35
Cargo.lock generated
View File

@ -2,6 +2,15 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "atty" name = "atty"
version = "0.2.14" version = "0.2.14"
@ -140,6 +149,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "humansize"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.7.0" version = "1.7.0"
@ -217,6 +232,15 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "output_vt100"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "proc-macro-error" name = "proc-macro-error"
version = "1.0.4" version = "1.0.4"
@ -254,7 +278,10 @@ dependencies = [
name = "pumo-system-info" name = "pumo-system-info"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ansi_term",
"clap", "clap",
"humansize",
"output_vt100",
"serde", "serde",
"serde_json", "serde_json",
"sysinfo", "sysinfo",
@ -308,18 +335,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.130" version = "1.0.131"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.130" version = "1.0.131"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -10,7 +10,10 @@ publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
sysinfo = "0.21" sysinfo = "0.21.2"
clap = { version = "3.0.0-rc.0", default-features = false, features = ["std", "derive", "color"] } clap = { version = "3.0.0-rc.0", default-features = false, features = ["std", "derive", "color"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0.131", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0.72"
output_vt100 = "0.1.2"
ansi_term = "0.12.1"
humansize = "1.1.1"

View File

@ -24,7 +24,7 @@ conditions; see the GPL-3.0 license or newer
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[clap(name="Pumo System Info",about,version,author,after_long_help=AFTER_HELP)] #[clap(name="Pumo System Info",about,version,author,after_long_help=AFTER_HELP)]
pub struct Args { pub struct Args {
#[clap(short, long)] #[clap(short, long, help="JSON output")]
pub json: bool, pub json: bool,
#[clap(short, long, default_value_t = 75)] #[clap(short, long, default_value_t = 75)]
@ -33,6 +33,9 @@ pub struct Args {
#[clap(short, long, default_value_t = 90)] #[clap(short, long, default_value_t = 90)]
pub critical_level: u8, pub critical_level: u8,
#[clap(short = 'W', long, default_value_t = 72)] #[clap(short = 'W', long, default_value_t = 72, help="Width of the console output")]
pub width: u8, pub width: usize,
#[clap(short, long, help="Display seconds in uptime")]
pub seconds: bool,
} }

View File

@ -14,8 +14,159 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
mod sysinfo;
pub fn print_cli() { use crate::sysinfo::{Machine, Memory};
use crate::args::Args;
fn get_uptime(mut uptime: u64, seconds: bool) -> String {
let mut uptime_str = String::new();
let minute_length = 60_u64;
let hour_length = minute_length * 60;
let day_length = hour_length * 24;
let days = uptime / day_length;
uptime %= day_length;
if days > 0 {
uptime_str.push_str(format!("{} days ", days).as_str());
}
let hours = uptime / hour_length;
uptime %= hour_length;
if days > 0 || hours > 0 {
uptime_str.push_str(format!("{} hours ", hours).as_str());
}
let minutes = uptime / minute_length;
uptime_str.push_str(format!("{} minutes", minutes).as_str());
if seconds {
uptime %= minute_length;
uptime_str.push_str(format!(" {} seconds", uptime).as_str());
}
uptime_str
}
fn get_name_max_width(disks: &[Memory]) -> usize {
disks
.iter()
.max_by(|x, y| x.name.len().cmp(&y.name.len()))
.unwrap()
.name
.len()
}
fn print_ramp(
memory: &Memory,
left_margin: usize,
total_width: usize,
) -> String {
use ansi_term::{Color, Style};
use humansize::{FileSize, file_size_opts as foptions};
let humansize_option = foptions::FileSizeOpts {
decimal_places: 1,
decimal_zeroes: 1,
space: false,
..foptions::CONVENTIONAL
};
let ramp_length = total_width - left_margin - 28;
let full = (ramp_length as f32 * memory.percentage()) as usize;
let empty = ramp_length - full;
let percentage = memory.percentage() * 100_f32;
let warning = percentage >= 75_f32;
let critical = percentage >= 90_f32;
let fg = if critical {
Color::Red
} else if warning {
Color::Yellow
} else {
Color::Green
};
let mut ramp = String::from("[");
for _ in 0..full {
ramp.push_str(Style::new().fg(fg).paint("=").to_string().as_str());
}
for _ in 0..empty {
ramp.push('=');
}
ramp.push_str(
format!(
"] {:>6} / {:>6} ",
memory
.used()
.file_size(&humansize_option)
.unwrap()
.replace("B", ""),
memory
.size
.file_size(&humansize_option)
.unwrap()
.replace("B", "")
)
.as_str(),
);
let percentage_str = Style::new().fg(fg).paint(format!("{:3.0}%", percentage)).to_string();
ramp.push_str(format!("({}%)", percentage_str).as_str());
ramp
}
pub fn print_cli(machine: Machine, args: Args) {
let width = args.width;
let mut separator = String::from("");
for _ in 0..width {
separator.push('=');
}
let left_max_width = "Hostname".len().max(get_name_max_width(&machine.disks));
let uptime = get_uptime(machine.uptime, args.seconds);
let right_width = machine.kernel.len().max(uptime.len()) + 3;
println!("{}", separator);
println!("{0:.<1$}: {2}{3:>4$}.: {5}",
"OS",
left_max_width,
machine.os,
"Kernel",
width as usize - (left_max_width + 2 + machine.os.len()) - right_width,
machine.kernel
);
println!("{0:.<1$}: {2}{3:>4$}.: {5}",
"Hostname",
left_max_width,
machine.hostname,
"Uptime",
width as usize - (left_max_width + 2 + machine.hostname.len()) - right_width,
uptime
);
println!("{0:.<1$}: {2}",
"Mem",
left_max_width,
print_ramp(&machine.ram, left_max_width, width)
);
println!("{0:.<1$}: {2}",
"Swap",
left_max_width,
print_ramp(&machine.swap, left_max_width, width)
);
for disk in machine.disks {
println!("{0:.<1$}: {2}",
disk.name,
left_max_width,
print_ramp(&disk, left_max_width, width)
);
}
println!("{}", separator);
} }

View File

@ -16,14 +16,18 @@
mod sysinfo; mod sysinfo;
mod args; mod args;
mod cli;
use clap::Parser; use clap::Parser;
fn main() { fn main() {
output_vt100::init();
let args = args::Args::parse(); let args = args::Args::parse();
let machine = sysinfo::Machine::new(); let machine = sysinfo::Machine::new();
if args.json { if args.json {
println!("{}", serde_json::to_string(&machine).unwrap()); println!("{}", serde_json::to_string(&machine).unwrap());
} else { } else {
cli::print_cli(machine, args);
} }
} }

View File

@ -18,27 +18,35 @@ use serde::Serialize;
use sysinfo::{System, SystemExt, DiskExt}; use sysinfo::{System, SystemExt, DiskExt};
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
struct Memory { pub struct Memory {
name: String, pub name: String,
size: u64, pub size: u64,
available: u64 pub available: u64
} }
impl Memory { impl Memory {
pub fn new(name: String, size: u64, available: u64) -> Self { pub fn new(name: String, size: u64, available: u64) -> Self {
Self { name, size, available } Self { name, size, available }
} }
pub fn used(&self) -> u64 {
self.size - self.available
}
pub fn percentage(&self) -> f32 {
self.used() as f32 / self.size as f32
}
} }
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct Machine { pub struct Machine {
os: String, pub os: String,
kernel: String, pub kernel: String,
hostname: String, pub hostname: String,
uptime: u64, pub uptime: u64,
ram: Memory, pub ram: Memory,
swap: Memory, pub swap: Memory,
disks: Vec<Memory>, pub disks: Vec<Memory>,
} }
impl Machine { impl Machine {
@ -50,14 +58,14 @@ impl Machine {
.iter() .iter()
.map(|x| { .map(|x| {
Memory::new( Memory::new(
x.name().to_str().unwrap().to_string(), x.mount_point().to_str().unwrap().to_string(),
x.total_space(), x.total_space(),
x.available_space(), x.available_space(),
) )
}) })
.collect::<Vec<Memory>>(); .collect::<Vec<Memory>>();
let ram = Memory::new("RAM".into(), sys.available_memory(), sys.available_memory()); let ram = Memory::new("RAM".into(), sys.total_memory() * 1000, sys.available_memory() * 1000);
let swap = Memory::new("Swap".into(), sys.total_swap(), sys.free_swap()); let swap = Memory::new("Swap".into(), sys.total_swap() * 1000, sys.free_swap() * 1000);
Self { Self {
os: sys.name().unwrap(), os: sys.name().unwrap(),
kernel: sys.kernel_version().unwrap(), kernel: sys.kernel_version().unwrap(),