| #!/usr/bin/env python |
| |
| ## |
| ## chewie.py |
| ## chews browser http log. draws graph of connections |
| ## Be sure there is only one pageload in the log. |
| ## |
| ## you'll want to |
| ## sudo apt-get install python-matplotlib |
| ## before running this |
| ## |
| |
| import sys, pylab |
| |
| # can't just use a dict, because there can be dups |
| class Queue: |
| def __init__(self): |
| self.queue = [] |
| |
| def add(self, url, time): |
| self.queue.append([url, time]) |
| |
| def get(self, url): |
| for x in range(len(self.queue)): |
| rec = self.queue[x] |
| if rec[0] == url: |
| del self.queue[x] |
| return rec[1] |
| |
| ## pull out request lag -- queue to start to done |
| def lag(): |
| |
| font = {'color': '#909090', 'fontsize': 6} |
| extractMe = { |
| 'RequestQueue.queueRequest': "Q", |
| 'Connection.openHttpConnection()': "O", |
| 'Request.sendRequest()': "S", |
| 'Request.requestSent()': "T", |
| 'processRequests()': 'R', |
| 'Request.readResponse():': "D", # done |
| 'clearPipe()': 'U', # unqueue |
| 'Request.readResponse()': 'B', # read data block |
| 'Request.readResponseStatus():': 'HR', # read http response line |
| 'hdr': 'H', # http header |
| } |
| keys = extractMe.keys() |
| |
| f = open(sys.argv[1], "r") |
| |
| t0 = None |
| |
| # thread, queued, opened, send, sent, reading, read, uri, server, y |
| # 0 1 2 3 4 5 6 7 8 9 |
| vals = [] |
| |
| queued = Queue() |
| opened = {"http0": None, |
| "http1": None, |
| "http2": None, |
| "http3": None, |
| "http4": None, |
| "http5": None} |
| active = {"http0": [], |
| "http1": [], |
| "http2": [], |
| "http3": [], |
| "http4": [], |
| "http5": []} |
| connectionCount = 0 |
| byteCount = 0 |
| killed = [[], []] |
| |
| while (True): |
| line = f.readline() |
| if len(line) == 0: break |
| |
| splitup = line.split() |
| |
| # http only |
| if splitup[0] != "V/http": continue |
| |
| x = splitup[3:] |
| |
| # filter to named lines |
| if x[2] not in keys: continue |
| x[2] = extractMe[x[2]] |
| |
| # normalize time |
| if t0 == None: t0 = int(x[0]) |
| x[0] = int(x[0]) - t0 |
| |
| thread, action = x[1], x[2] |
| if action == "Q": |
| time, url = x[0], x[3] |
| queued.add(url, time) |
| elif action == "O": |
| # save opened time and server for this thread, so we can stuff it in l8r |
| time, thread, host = x[0], x[1], x[4] |
| opened[thread] = [time, host, connectionCount] |
| connectionCount += 1 |
| elif action == "S": |
| time, thread, url = x[0], x[1], x[3] |
| opentime, host, connection = opened[thread] |
| qtime = queued.get(url) |
| record = [thread, qtime, opentime, time, None, None, None, url, host, connection] |
| active[thread].append(record) |
| elif action == "T": |
| time, thread = x[0], x[1] |
| record = active[thread][-1] |
| record[4] = time |
| elif action == "R": |
| print x |
| if x[3] in ["sleep", "no", "wait"]: continue |
| time, thread, = x[0], x[1] |
| record = active[thread][0] |
| record[5] = time |
| elif action == 'U': |
| thread = x[1] |
| record = active[thread][0] |
| killed[0].append(record[9]) |
| killed[1].append(x[0]) |
| queued.add(record[7], record[1]) |
| del active[thread][0] |
| elif action == "D": |
| time, thread = x[0], x[1] |
| record = active[thread][0] |
| record[6] = time |
| vals.append(record) |
| del active[thread][0] |
| print record |
| # print record[3] / 1000, record[6] / 1000, record[7] |
| elif action == "B": |
| byteCount += int(x[3]) |
| elif action == "HR": |
| byteCount += int(x[2]) |
| |
| f.close() |
| |
| rng = range(connectionCount) |
| |
| opened = [] |
| drawn = [False for x in rng] |
| for val in vals: |
| y= val[9] |
| if not drawn[y]: |
| drawn[y] = True |
| opened.append(val[2]) |
| pylab.text(0, y - 0.25, "%s %s %s" % (val[9], val[0][4], val[8]), font) |
| |
| # define limits |
| # pylab.plot([vals[-1][6]], rng) |
| |
| print opened, rng |
| pylab.plot(opened, rng, 'ro') |
| pylab.plot(killed[1], killed[0], 'rx') |
| |
| for val in vals: |
| thread, queued, opened, send, sent, reading, read, uri, server, y = val |
| # send arrow |
| arrow = pylab.Arrow(send, y, sent - send, 0) |
| arrow.set_facecolor("g") |
| ax = pylab.gca() |
| ax.add_patch(arrow) |
| # read arrow |
| arrow = pylab.Arrow(reading, y, read - reading, 0) |
| arrow.set_facecolor("r") |
| ax = pylab.gca() |
| ax.add_patch(arrow) |
| |
| caption = \ |
| "\nrequests: %s\n" % len(vals) + \ |
| "byteCount: %s\n" % byteCount + \ |
| "data rate: %s\n" % (1000 * byteCount / vals[-1][6])+ \ |
| "connections: %s\n" % connectionCount |
| |
| pylab.figtext(0.82, 0.30, caption, bbox=dict(facecolor='lightgrey', alpha=0.5)) |
| |
| # print lines, [[x, x] for x in range(len(vals))] |
| # pylab.plot(lines, [[x, x] for x in range(len(vals))], 'r-') |
| |
| pylab.grid() |
| pylab.show() |
| |
| if __name__ == '__main__': lag() |