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.
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]]
name = "atty"
version = "0.2.14"
@ -140,6 +149,12 @@ dependencies = [
"libc",
]
[[package]]
name = "humansize"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026"
[[package]]
name = "indexmap"
version = "1.7.0"
@ -217,6 +232,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "output_vt100"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
dependencies = [
"winapi",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@ -254,7 +278,10 @@ dependencies = [
name = "pumo-system-info"
version = "0.1.0"
dependencies = [
"ansi_term",
"clap",
"humansize",
"output_vt100",
"serde",
"serde_json",
"sysinfo",
@ -308,18 +335,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.130"
version = "1.0.131"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.130"
version = "1.0.131"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2"
dependencies = [
"proc-macro2",
"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
[dependencies]
sysinfo = "0.21"
sysinfo = "0.21.2"
clap = { version = "3.0.0-rc.0", default-features = false, features = ["std", "derive", "color"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde = { version = "1.0.131", features = ["derive"] }
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)]
#[clap(name="Pumo System Info",about,version,author,after_long_help=AFTER_HELP)]
pub struct Args {
#[clap(short, long)]
#[clap(short, long, help="JSON output")]
pub json: bool,
#[clap(short, long, default_value_t = 75)]
@ -33,6 +33,9 @@ pub struct Args {
#[clap(short, long, default_value_t = 90)]
pub critical_level: u8,
#[clap(short = 'W', long, default_value_t = 72)]
pub width: u8,
#[clap(short = 'W', long, default_value_t = 72, help="Width of the console output")]
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
// 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 args;
mod cli;
use clap::Parser;
fn main() {
output_vt100::init();
let args = args::Args::parse();
let machine = sysinfo::Machine::new();
if args.json {
println!("{}", serde_json::to_string(&machine).unwrap());
} else {
cli::print_cli(machine, args);
}
}

View File

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