Last active
August 29, 2015 14:17
-
-
Save ezietsman/097dd1eee738a3ab097c to your computer and use it in GitHub Desktop.
Make graphs of Pings to an IP. For troubleshooting my adsl connection.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
Pynger: | |
App that pings a given IP address and saves the pings in the file. | |
Usage: | |
pynger.py [ip] | |
ip: the IP address to be pinged. If this is left empty it will default to | |
the ADSL router I hit first. | |
To stop the app, hit ctrl-c | |
This will save the plot as a png and a text file with timestamps and pings | |
in ms will be written to a file. | |
''' | |
import sys | |
import time | |
import datetime | |
import subprocess | |
from collections import namedtuple | |
import matplotlib.style | |
matplotlib.style.use('ggplot') | |
import matplotlib.pyplot as plt | |
class Pinger(object): | |
''' | |
Class that handles sending pings and returning the stats | |
''' | |
def __init__(self, ip): | |
''' | |
Initialise the pinger | |
ip: ip address to which this pinger sends packets. <str> | |
''' | |
self.ip = ip | |
self.pings = [] | |
def ping(self): | |
''' | |
Sends a ping to the IP. | |
Adds the ping to self.pings. | |
Returns the last ping as namedtuple. | |
''' | |
cmd = ['ping', '-c', '1', '-q', '-t', '1', self.ip] | |
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, | |
stderr=subprocess.PIPE) | |
pings, error = proc.communicate() | |
if error: | |
pings = -1.0 | |
else: | |
pings = pings.split('\n')[-2].split('=')[-1] | |
pings = pings.split('/')[0].strip() | |
p = namedtuple('Ping', ['timestamp', 'latency']) | |
p.timestamp = datetime.datetime.now() | |
p.latency = float(pings) | |
self.pings.append(p) | |
return p | |
def save_to_file(self): | |
''' | |
Save pings to text file in the format: | |
timestamp ping | |
where timestamp is in iso format and ping in ms. If the ping wasn't | |
received it is saved as -1. | |
file is named by ip address | |
''' | |
with open('{}.txt'.format(self.ip), 'a') as outputfile: | |
# write a header if the file doesn't exist | |
if not outputfile.tell(): | |
outputfile.write("# Pings to IP: {}\n".format(self.ip)) | |
outputfile.write("# DATE TIME PING (ms)\n") | |
for p in self.pings: | |
outputfile.write("{} {}\n".format(p.timestamp, p.latency)) | |
class PingPlotter(object): | |
''' | |
Realtime plotter | |
''' | |
def __init__(self): | |
''' | |
Initialise the matplotlib plotter | |
''' | |
plt.ion() | |
self.fig = plt.figure() | |
self.ax1 = self.fig.add_subplot(111) | |
self.line, = self.ax1.plot([], [], linewidth=2) | |
plt.ylabel('Ping (ms)') | |
plt.xlabel('Time') | |
plt.subplots_adjust(left=0.1, bottom=0.1) | |
plt.show() | |
def update(self, pinger): | |
''' | |
Update the plots. | |
pinger: instance of pinger class | |
''' | |
# get times and latencies as lists | |
timestamps = [p.timestamp for p in pinger.pings] | |
latency = [p.latency for p in pinger.pings] | |
plt.title('Pings to {}'.format(pinger.ip)) | |
self.line.set_xdata(timestamps) | |
self.line.set_ydata(latency) | |
self.ax1.relim() | |
self.ax1.autoscale_view() | |
plt.gcf().autofmt_xdate() | |
plt.draw() | |
if __name__ == "__main__": | |
# Default to the MWEB IP if none given | |
if len(sys.argv) < 2: | |
pinger = Pinger('197.84.96.137') | |
else: | |
ip = sys.argv[1] | |
pinger = Pinger(ip) | |
plotter = PingPlotter() | |
while True: | |
try: | |
pinger.ping() | |
plotter.update(pinger) | |
time.sleep(0.5) | |
except KeyboardInterrupt: | |
pinger.save_to_file() | |
plt.savefig('{}-pings.png'.format(pinger.ip)) | |
sys.exit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment