Skip to content

Instantly share code, notes, and snippets.

@ezietsman
Last active August 29, 2015 14:17
Show Gist options
  • Save ezietsman/097dd1eee738a3ab097c to your computer and use it in GitHub Desktop.
Save ezietsman/097dd1eee738a3ab097c to your computer and use it in GitHub Desktop.
Make graphs of Pings to an IP. For troubleshooting my adsl connection.
'''
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