aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs23
-rw-r--r--src/pinger.rs4
-rw-r--r--src/print.rs54
3 files changed, 76 insertions, 5 deletions
diff --git a/src/main.rs b/src/main.rs
index 9181bf6..f6ac365 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -13,8 +13,9 @@ mod stats;
use args::Args;
use ip::parse_ip;
use pinger::{spawn_ping, PingResult};
-use print::{print_ping_line, print_legende_line};
+use print::{print_last_ping_line, print_legende_line, print_ping_line, print_stats};
use state::State;
+use stats::compute_stats;
#[tokio::main]
async fn main() {
@@ -69,9 +70,9 @@ async fn main() {
// Update the state of the received packet
Ok(result) => {
match result {
- PingResult::Ping { rrt, ttl, id } => {
+ PingResult::Ping { rtt, ttl, id } => {
if (id as usize) < states.len() {
- states[id as usize] = State::Received { rtt: rrt, ttl };
+ states[id as usize] = State::Received { rtt: rtt, ttl };
}
}
PingResult::NoPingErr { id: _, ref error } => {
@@ -101,6 +102,22 @@ async fn main() {
// Prints lines based on the state of each ping
print_ping_line(&states);
+ // Print stats
+ if args.stats {
+ if let Some(stats) = compute_stats(&states) {
+ print_stats(&stats);
+ }
+ // Print stats of the last 30 pings
+ // let firstIndex = if states.len() - 30 > 0 {
+ // states.len() - 30
+ // } else {
+ // 0
+ // };
+ // if let Some(stats) = compute_stats(&states[firstIndex..]) {
+ // print_stats(&stats);
+ // }
+ }
+
// Sleep for 1 second before the next ping
// FEAT: Should be configurable via CLI
diff --git a/src/pinger.rs b/src/pinger.rs
index ef87cbf..d7d052b 100644
--- a/src/pinger.rs
+++ b/src/pinger.rs
@@ -5,7 +5,7 @@ use tokio::task;
pub enum PingResult {
NoPingErr { id: u32, error: String },
- Ping { rrt: u64, ttl: u32, id: u32 },
+ Ping { rtt: u64, ttl: u32, id: u32 },
}
pub fn spawn_ping(target: IpAddr, tx: Sender<PingResult>, id: u32) {
@@ -26,7 +26,7 @@ fn do_ping(target: IpAddr, id: u32) -> PingResult {
match result {
Ok(reply) => PingResult::Ping {
- rrt: reply.rtt.as_millis() as u64,
+ rtt: reply.rtt.as_millis() as u64,
ttl: reply.ttl.unwrap_or(0) as u32,
id,
},
diff --git a/src/print.rs b/src/print.rs
index 9d71a78..89acffa 100644
--- a/src/print.rs
+++ b/src/print.rs
@@ -1,6 +1,7 @@
// src/print.rs
use crate::state::State;
+use crate::stats::Stats;
struct SymbolTableElement {
fg: &'static str,
@@ -84,6 +85,32 @@ pub fn print_ping_line(states: &Vec<State>) {
println!("");
}
+pub fn print_last_ping_line(states: &[State], count: usize) {
+ let start_idx = if states.len() > count { states.len() - count } else { 0 };
+ let slice = &states[start_idx..];
+ for state in slice {
+ match state {
+ State::Received { rtt, .. } => {
+ let (fg, bg, symbol) = get_symbol_and_colors_for_rrt(*rtt);
+ print!("{}{}{}{}", fg, bg, symbol, "\x1b[0m");
+ }
+ State::Lost => {
+ let (fg, bg, symbol) = get_symbol_and_colors_for_rrt(250);
+ print!("{}{}{}{}", fg, bg, symbol, "\x1b[0m");
+ }
+ State::NotYetReceived { .. } => {
+ // fg grey, bg black
+ print!("\x1b[35;40m?\x1b[0m");
+ }
+ State::SendError => {
+ print!("!");
+ }
+ }
+ }
+
+ println!("");
+}
+
fn get_symbol_and_colors_for_rrt(rrt: u64) -> (&'static str, &'static str, &'static str) {
let index: usize = if rrt >= 240 {
24
@@ -94,3 +121,30 @@ fn get_symbol_and_colors_for_rrt(rrt: u64) -> (&'static str, &'static str, &'sta
(fg, bg, character)
}
+
+pub fn print_stats(stats: &Stats) {
+ let total = stats.lost + stats.received;
+ let percent_lost = if total > 0 {
+ (stats.lost as f64 / total as f64) * 100.0
+ } else {
+ 0.0
+ };
+
+ let mad_rtt_rounded = stats.mad_rtt.round() as u64;
+ let mean_rtt_round = stats.avg_rtt.round() as u32;
+ let mean_ttl_round = stats.avg_ttl.round() as u32;
+
+ println!(
+ "{}/{} ({:.1}%) | ⌊{}⌋ ⌈{}⌉ [{}] [Δ{}]ms / ⌊{}⌋ ⌈{}⌉ [{}]",
+ stats.lost,
+ total,
+ percent_lost,
+ stats.min_rtt,
+ stats.max_rtt,
+ mean_rtt_round,
+ mad_rtt_rounded,
+ stats.min_ttl,
+ stats.max_ttl,
+ mean_ttl_round
+ );
+}