Home | History | Annotate | Download | only in axl
      1 #!/usr/bin/env python
      2 
      3 ##
      4 ## chewie.py
      5 ## chews browser http log.  draws graph of connections
      6 ## Be sure there is only one pageload in the log.
      7 ##
      8 ## you'll want to
      9 ##   sudo apt-get install python-matplotlib
     10 ## before running this
     11 ##
     12 
     13 import sys, pylab
     14 
     15 # can't just use a dict, because there can be dups
     16 class Queue:
     17     def __init__(self):
     18         self.queue = []
     19 
     20     def add(self, url, time):
     21         self.queue.append([url, time])
     22 
     23     def get(self, url):
     24         for x in range(len(self.queue)):
     25             rec = self.queue[x]
     26             if rec[0] == url:
     27                 del self.queue[x]
     28                 return rec[1]
     29 
     30 ## pull out request lag -- queue to start to done
     31 def lag():
     32 
     33     font = {'color': '#909090', 'fontsize': 6}
     34     extractMe = {
     35         'RequestQueue.queueRequest': "Q",
     36         'Connection.openHttpConnection()': "O",
     37         'Request.sendRequest()': "S",
     38         'Request.requestSent()': "T",
     39         'processRequests()': 'R',
     40         'Request.readResponse():': "D",         # done
     41         'clearPipe()': 'U',	                    # unqueue
     42         'Request.readResponse()': 'B',          # read data block
     43         'Request.readResponseStatus():': 'HR',  # read http response line
     44         'hdr': 'H',                             # http header
     45         }
     46     keys = extractMe.keys()
     47 
     48     f = open(sys.argv[1], "r")
     49 
     50     t0 = None
     51 
     52     # thread, queued, opened, send, sent, reading, read, uri, server, y
     53     # 0       1       2       3     4     5        6     7    8       9
     54     vals = []
     55 
     56     queued = Queue()
     57     opened = {"http0": None,
     58               "http1": None,
     59               "http2": None,
     60               "http3": None,
     61               "http4": None,
     62               "http5": None}
     63     active = {"http0": [],
     64               "http1": [],
     65               "http2": [],
     66               "http3": [],
     67               "http4": [],
     68               "http5": []}
     69     connectionCount = 0
     70     byteCount = 0
     71     killed = [[], []]
     72 
     73     while (True):
     74         line = f.readline()
     75         if len(line) == 0: break
     76 
     77         splitup = line.split()
     78 
     79         # http only
     80         if splitup[0] != "V/http": continue
     81 
     82         x = splitup[3:]
     83 
     84         # filter to named lines
     85         if x[2] not in keys: continue
     86         x[2] = extractMe[x[2]]
     87 
     88         # normalize time
     89         if t0 == None: t0 = int(x[0])
     90         x[0] = int(x[0]) - t0
     91 
     92         thread, action = x[1], x[2]
     93         if action == "Q":
     94             time, url = x[0], x[3]
     95             queued.add(url, time)
     96         elif action == "O":
     97             # save opened time and server for this thread, so we can stuff it in l8r
     98             time, thread, host = x[0], x[1], x[4]
     99             opened[thread] = [time, host, connectionCount]
    100             connectionCount += 1
    101         elif action == "S":
    102             time, thread, url = x[0], x[1], x[3]
    103             opentime, host, connection = opened[thread]
    104             qtime = queued.get(url)
    105             record = [thread, qtime, opentime, time, None, None, None, url, host, connection]
    106             active[thread].append(record)
    107         elif action == "T":
    108             time, thread = x[0], x[1]
    109             record = active[thread][-1]
    110             record[4] = time
    111         elif action == "R":
    112             print x
    113             if x[3] in ["sleep", "no", "wait"]: continue
    114             time, thread, = x[0], x[1]
    115             record = active[thread][0]
    116             record[5] = time
    117         elif action == 'U':
    118             thread = x[1]
    119             record = active[thread][0]
    120             killed[0].append(record[9])
    121             killed[1].append(x[0])
    122             queued.add(record[7], record[1])
    123             del active[thread][0]
    124         elif action == "D":
    125             time, thread = x[0], x[1]
    126             record = active[thread][0]
    127             record[6] = time
    128             vals.append(record)
    129             del active[thread][0]
    130             print record
    131             # print record[3] / 1000, record[6] / 1000, record[7]
    132         elif action == "B":
    133             byteCount += int(x[3])
    134         elif action == "HR":
    135             byteCount += int(x[2])
    136 
    137     f.close()
    138 
    139     rng = range(connectionCount)
    140 
    141     opened = []
    142     drawn = [False for x in rng]
    143     for val in vals:
    144         y= val[9]
    145         if not drawn[y]:
    146             drawn[y] = True
    147             opened.append(val[2])
    148             pylab.text(0, y - 0.25, "%s %s %s" % (val[9], val[0][4], val[8]), font)
    149 
    150     # define limits
    151     # pylab.plot([vals[-1][6]], rng)
    152 
    153     print opened, rng
    154     pylab.plot(opened, rng, 'ro')
    155     pylab.plot(killed[1], killed[0], 'rx')
    156 
    157     for val in vals:
    158         thread, queued, opened, send, sent, reading, read, uri, server, y = val
    159         # send arrow
    160         arrow = pylab.Arrow(send, y, sent - send, 0)
    161         arrow.set_facecolor("g")
    162         ax = pylab.gca()
    163         ax.add_patch(arrow)
    164         # read arrow
    165         arrow = pylab.Arrow(reading, y, read - reading, 0)
    166         arrow.set_facecolor("r")
    167         ax = pylab.gca()
    168         ax.add_patch(arrow)
    169 
    170     caption = \
    171             "\nrequests: %s\n" % len(vals) + \
    172             "byteCount: %s\n" % byteCount + \
    173             "data rate: %s\n" % (1000 * byteCount / vals[-1][6])+ \
    174             "connections: %s\n" % connectionCount
    175 
    176     pylab.figtext(0.82, 0.30, caption, bbox=dict(facecolor='lightgrey', alpha=0.5))
    177 
    178     # print lines, [[x, x] for x in range(len(vals))]
    179     # pylab.plot(lines, [[x, x] for x in range(len(vals))], 'r-')
    180 
    181     pylab.grid()
    182     pylab.show()
    183 
    184 if __name__ == '__main__': lag()
    185