monitoring kit
bendn 11 months ago
parent ece78d1 · commit b83feea
-rw-r--r--Cargo.toml2
-rw-r--r--battery/src/charge.rs3
-rw-r--r--cpu/src/cpu.rs22
-rw-r--r--cpu/src/temps.rs22
-rw-r--r--gpu/src/intel.rs22
-rw-r--r--grapher/src/lib.rs7
-rw-r--r--memory/src/main.rs3
-rw-r--r--ping/Cargo.toml21
-rw-r--r--ping/src/ping.rs133
9 files changed, 204 insertions, 31 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 643d3ad..831e40f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
[workspace]
-members = ["cpu", "grapher", "memory", "gpu", "battery"]
+members = ["cpu", "grapher", "memory", "gpu", "battery", "ping"]
resolver = "3"
[profile.release]
diff --git a/battery/src/charge.rs b/battery/src/charge.rs
index ecba756..66cd98d 100644
--- a/battery/src/charge.rs
+++ b/battery/src/charge.rs
@@ -11,6 +11,7 @@
use anyhow::*;
use grapher::{truncwrite, Grapher};
use std::array;
+use std::convert::identity;
use std::fs::read_to_string as read;
use std::io::Write;
use std::io::{stdout, Read};
@@ -71,7 +72,7 @@ fn main() -> Result<()> {
}
}
- g.draw(|_| None)?;
+ g.draw(|_| None, identity)?;
let current = fetch("POWER_SUPPLY_CAPACITY", str::parse::<f64>)?;
let whs = fetch("POWER_SUPPLY_ENERGY_NOW", str::parse::<f64>)? / 1e6;
let usage = fetch("POWER_SUPPLY_POWER_NOW", str::parse::<f64>)? / 1e6;
diff --git a/cpu/src/cpu.rs b/cpu/src/cpu.rs
index 459eef3..00feb75 100644
--- a/cpu/src/cpu.rs
+++ b/cpu/src/cpu.rs
@@ -11,6 +11,7 @@ use comat::cwrite;
use cpu::*;
use grapher::Grapher;
use std::array;
+use std::convert::identity;
use std::io::Write;
use std::io::{stdout, Read};
use std::thread::sleep;
@@ -62,16 +63,19 @@ fn main() -> Result<()> {
}
}
- g.draw(|y| {
- Some(
- inter(
- [243, 64, 64].map(|x| x as f32 / 255.0), // red
- [228, 197, 63].map(|x| x as f32 / 255.0), // yellow
- y as f32 / (h - 1) as f32,
+ g.draw(
+ |y| {
+ Some(
+ inter(
+ [243, 64, 64].map(|x| x as f32 / 255.0), // red
+ [228, 197, 63].map(|x| x as f32 / 255.0), // yellow
+ y as f32 / (h - 1) as f32,
+ )
+ .map(|x| (x * 255.0) as u8),
)
- .map(|x| (x * 255.0) as u8),
- )
- })?;
+ },
+ identity,
+ )?;
write!(g.buffer, "{}{}", White.fg_str(), cursor::Goto(1, 1))?;
let name = &*info.name;
diff --git a/cpu/src/temps.rs b/cpu/src/temps.rs
index ea0031f..485b427 100644
--- a/cpu/src/temps.rs
+++ b/cpu/src/temps.rs
@@ -4,6 +4,7 @@ use comat::cwrite;
use cpu::*;
use grapher::Grapher;
use std::array;
+use std::convert::identity;
use std::io::Write;
use std::io::{stdout, Read};
use std::thread::sleep;
@@ -55,16 +56,19 @@ fn main() -> Result<()> {
}
}
- g.draw(|y| {
- Some(
- inter(
- [228, 197, 63].map(|x| x as f32 / 255.0), // yellow
- [0x5c, 0xc7, 0xdd].map(|x| x as f32 / 255.0), // blue
- y as f32 / (h - 1) as f32,
+ g.draw(
+ |y| {
+ Some(
+ inter(
+ [228, 197, 63].map(|x| x as f32 / 255.0), // yellow
+ [0x5c, 0xc7, 0xdd].map(|x| x as f32 / 255.0), // blue
+ y as f32 / (h - 1) as f32,
+ )
+ .map(|x| (x * 255.0) as u8),
)
- .map(|x| (x * 255.0) as u8),
- )
- })?;
+ },
+ identity,
+ )?;
write!(g.buffer, "{}{}", White.fg_str(), cursor::Goto(1, 1))?;
let name = &*info.name;
diff --git a/gpu/src/intel.rs b/gpu/src/intel.rs
index da71f72..1352fb0 100644
--- a/gpu/src/intel.rs
+++ b/gpu/src/intel.rs
@@ -16,6 +16,7 @@ use comat::cwrite;
use grapher::Grapher;
use parking_lot::Mutex;
use std::array;
+use std::convert::identity;
use std::ffi::{c_char, CStr};
use std::fmt::Display;
use std::fs::{read_dir, read_to_string as read};
@@ -172,16 +173,19 @@ fn main() -> Result<()> {
}
}
- g.draw(|y| {
- Some(
- inter(
- [243, 64, 64].map(|x| x as f32 / 255.0), // red
- [228, 197, 63].map(|x| x as f32 / 255.0), // yellow
- y as f32 / (h - 1) as f32,
+ g.draw(
+ |y| {
+ Some(
+ inter(
+ [243, 64, 64].map(|x| x as f32 / 255.0), // red
+ [228, 197, 63].map(|x| x as f32 / 255.0), // yellow
+ y as f32 / (h - 1) as f32,
+ )
+ .map(|x| (x * 255.0) as u8),
)
- .map(|x| (x * 255.0) as u8),
- )
- })?;
+ },
+ identity,
+ )?;
write!(g.buffer, "{}{}", White.fg_str(), cursor::Goto(1, 1))?;
let [f_req, f_act, irq, _rc6, power_gpu, power_package, busy] = *last.lock();
diff --git a/grapher/src/lib.rs b/grapher/src/lib.rs
index 354e41d..b6d2df2 100644
--- a/grapher/src/lib.rs
+++ b/grapher/src/lib.rs
@@ -31,7 +31,11 @@ impl Grapher {
self.data.pop_back();
}
- pub fn draw(&mut self, mut color: impl FnMut(u16) -> Option<[u8; 3]>) -> Result<&mut Vec<u8>> {
+ pub fn draw(
+ &mut self,
+ mut color: impl FnMut(u16) -> Option<[u8; 3]>,
+ mut mapping: impl FnMut(f64) -> f64,
+ ) -> Result<&mut Vec<u8>> {
let Grapher {
buffer: output,
data,
@@ -57,6 +61,7 @@ impl Grapher {
.map(|column| {
let mut data = [vec![false; (h * 4) as usize], vec![false; (h * 4) as usize]];
for (e, c) in zip(column, &mut data) {
+ let e = mapping(*e);
let clen = c.len();
c[clen - ((h as f64 * e * 4.0).round().min(h as f64 * 4.0) as usize)..]
.fill(true);
diff --git a/memory/src/main.rs b/memory/src/main.rs
index 94497a6..afb1d1c 100644
--- a/memory/src/main.rs
+++ b/memory/src/main.rs
@@ -4,6 +4,7 @@ use comat::cwrite;
use grapher::Grapher;
use std::array;
use std::collections::HashMap;
+use std::convert::identity;
use std::fs::read_to_string as read;
use std::io::Write;
use std::io::{stdout, Read};
@@ -57,7 +58,7 @@ fn main() -> Result<()> {
}
let [tot, used] = info()?.map(|x| x as f64 / (1024. * 1024.));
let tot = tot.round();
- g.draw(|_| None)?;
+ g.draw(|_| None, identity)?;
write!(g.buffer, "{}{}", White.fg_str(), cursor::Goto(1, 1))?;
let fps = (1f32 / d).round();
diff --git a/ping/Cargo.toml b/ping/Cargo.toml
new file mode 100644
index 0000000..55b4516
--- /dev/null
+++ b/ping/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "ping"
+version = "1.0.0"
+edition = "2021"
+authors = ["bend-n <[email protected]>"]
+repository = "https://github.com/bend-n/monitorkit"
+license = "MIT"
+rust-version = "1.85"
+
+[dependencies]
+anyhow = "1.0.97"
+termion = "4.0.4"
+grapher = { path = "../grapher" }
+ping-rs = "0.1.2"
+oneshot = { version = "0.1.11", default-features = false, features = ["std"] }
+
+
+[[bin]]
+name = "ping"
+doc = false
+path = "src/ping.rs"
diff --git a/ping/src/ping.rs b/ping/src/ping.rs
new file mode 100644
index 0000000..ec9a055
--- /dev/null
+++ b/ping/src/ping.rs
@@ -0,0 +1,133 @@
+#![feature(
+ generic_arg_infer,
+ import_trait_associated_functions,
+ string_deref_patterns,
+ let_chains,
+ iter_array_chunks,
+ array_chunks,
+ portable_simd,
+ iter_chain
+)]
+use anyhow::*;
+use grapher::{truncwrite, Grapher};
+use ping_rs::PingError;
+use std::array;
+use std::io::Write;
+use std::io::{stdout, Read};
+use std::net::{IpAddr, ToSocketAddrs};
+use std::result::Result::Ok as Rok;
+use std::thread::sleep;
+use std::time::Duration;
+use termion::color::*;
+use termion::cursor::Hide;
+use termion::raw::IntoRawMode;
+use termion::screen::IntoAlternateScreen;
+use termion::{async_stdin, clear, cursor, style};
+fn ping(x: IpAddr) -> Result<u32> {
+ match ping_rs::send_ping(&x, Duration::from_secs(2), b"", None) {
+ Rok(x) => Ok(x.rtt),
+ Err(PingError::TimedOut | PingError::IoPending) => Ok(!0),
+ Err(x) => bail!("{x:?}"),
+ }
+}
+
+fn resolve(host: &str) -> Result<IpAddr> {
+ (host, 80)
+ .to_socket_addrs()
+ .context("resolve")?
+ .map(|x| x.ip())
+ .next()
+ .ok_or(anyhow!("no resolution"))
+}
+
+fn main() -> Result<()> {
+ let who = std::env::args().nth(1).ok_or(anyhow!("who to ping?"))?;
+ let ip = resolve(&who)?;
+ eprintln!("pinging {ip}");
+ let _ = ping(ip)?;
+ let [mut max, mut sum, mut points, mut dropped] = [0; _];
+ let mut min = !0;
+
+ let (tx, rx) = std::sync::mpsc::channel::<u32>();
+ let (ftx, frx) = oneshot::channel::<()>();
+ std::thread::spawn(move || {
+ let result = ping(ip).unwrap();
+ tx.send(result).unwrap();
+ _ = ftx.send(());
+ loop {
+ std::thread::sleep(Duration::from_millis(100u64.saturating_sub(result as _)));
+ let result = ping(ip).unwrap();
+ tx.send(result).unwrap();
+ }
+ });
+ frx.recv()?;
+
+ let mut g = Grapher::new()?;
+
+ let mut stdout = stdout().into_raw_mode()?.into_alternate_screen()?;
+ let mut stdin = async_stdin();
+ write!(stdout, "{}{}{}", Hide, clear::All, style::Reset).unwrap();
+ 'out: loop {
+ let mut key = 0;
+ while stdin.read(array::from_mut(&mut key)).unwrap() != 0 {
+ match key {
+ b'q' => break 'out,
+ _ => (),
+ }
+ }
+
+ let r = rx.try_recv();
+ if let Rok(r) = r
+ && r != !0
+ {
+ sum += r;
+ points += 1;
+ min = min.min(r);
+ max = max.max(r);
+ } else {
+ dropped += 1;
+ }
+ let avg = sum / points;
+ let mut r = r.unwrap_or(avg);
+ if r == !0 {
+ r = avg;
+ }
+
+ let dat = g.data.iter().copied().filter(|&x| x != 0.0);
+ let sum = dat
+ .clone()
+ .filter(|&x| x != 0.0)
+ .map(|x| x - avg as f64)
+ .sum::<f64>();
+ let dev = (sum / (dat.count()) as f64).abs();
+
+ g.push_point(r as f64);
+ g.draw(
+ |_| None,
+ |x| {
+ match max {
+ ..90 => x / 100.0,
+ ..240 => x / 250.0,
+ ..490 => x / 500.0,
+ ..990 => x / 1000.0,
+ _ => x / (max as f64 + 10.0),
+ }
+ .min(1.0)
+ },
+ )?;
+
+ write!(g.buffer, "{}{}", White.fg_str(), cursor::Goto(1, 1))?;
+ truncwrite!(
+ g.buffer,
+ " {who} ({ip}) ── last {r}ms ── min {min} avg {avg} max {max} dev ±{dev:.2}ms ── dropped {dropped} /{points}pckts ({:.1}%)",
+ (dropped as f64 /points as f64)*100.0,
+ )?;
+ write!(stdout, "{}", Rgb(40, 185, 119).fg_string())?;
+ stdout.write_all(&g.buffer)?;
+ stdout.flush()?;
+
+ sleep(Duration::from_millis(100));
+ }
+ println!("\x1B[?7l");
+ Ok(())
+}