diff options
-rwxr-xr-x | ping-monitor.pl | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/ping-monitor.pl b/ping-monitor.pl new file mode 100755 index 0000000..a435cee --- /dev/null +++ b/ping-monitor.pl @@ -0,0 +1,94 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use autodie; +use Data::Dumper; +use Time::HiRes qw(time); +use Statistics::Descriptive; + +=head1 NAME +ping-monitor.pl - Live ping statistics + +=head1 SYNOPSIS + +ping-monitor.pl <host> + +=head1 DESCRIPTION + +ping-monitor.pl provides live mean, median, standard deviation and packet loss +statistics similar to ping(8). The statistics are calculated over the last 10 +seconds by default. + +=cut + + +if (0+@ARGV < 1) { + print "usage: $0 <host>\n"; + exit 0; +} + +my $host = $ARGV[0]; +# a value < 0.2 requires root privileges +my $frequency = 0.2; +# 10 second average +my $window_size = 10/$frequency; + +open my $ping, "-|", "ping -nDOi $frequency -W 1 $host"; + +my @history; +my $last_reply = 0; + +# ensure we are on a clean line for cleaning later +printf "\n"; + +while (<$ping>) { + next if m/^PING /; + + if (m/^\[(?<ts>[0-9.]+)\] \d+ bytes from [^:]+: icmp_seq=\d+ ttl=\d+ time=(?<time>[0-9.]+) ms$/) { + push @history, { + timestamp => $+{ts}, + time => $+{time}, + }; + $last_reply = $+{ts} if $+{ts} > $last_reply; + } elsif (m/^\[(?<ts>[0-9.]+)\] no answer yet for icmp_seq=\d+$/) { + push @history, { + timestamp => $+{ts}, + time => undef, + }; + } + if (0+@history > $window_size) { + splice @history, 0, 1; + } + + my $avg_lost = 0.0; + my $stats = Statistics::Descriptive::Full->new(); + + for my $x (@history) { + $stats->add_data($x->{time}) if defined $x->{time}; + $avg_lost += 1 if not defined $x->{time}; + } + + $avg_lost /= @history if @history > 0; + my $last_reply_diff = 0; + $last_reply_diff = time - $last_reply if $last_reply; + + # clear 1 line + printf "[%dF[0J", 0; + + my @parts; + + if ($stats->mean()) { + push @parts, sprintf "avg/median/stdev time: %0.2fms/%0.2fms/%0.2fms", $stats->mean(), $stats->median(), $stats->standard_deviation(); + } + + push @parts, sprintf "avg loss: %0.2f%%", $avg_lost*100 // 0.0; + + if ($last_reply_diff > 0.5) { + push @parts, sprintf "last reply: %0.3fs ago", $last_reply_diff; + } + + print join(", ", @parts)."\n"; + + #print Dumper(\@history); + #print Dumper($avg_time, $avg_lost, $last_reply); +} |