Attempt fixes at chrome frame tests redness.
[chromium-blink-merge.git] / tools / net / netlog.py
blobf66d5f04afc897b97502076d17b2397b14c5e66f
1 #!/usr/bin/env python
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Parse NetLog output and reformat it to display in Gnuplot."""
8 import math
9 import optparse
10 import os
11 import re
12 import sys
15 class Entry(object):
16 """A single NetLog line/entry."""
18 def __init__(self, line):
19 self.id = -1
20 self.info = ''
21 self.time = 0
23 time_offset = line.find('t=')
24 if time_offset >= 0:
25 tmp = line[time_offset + 2:].split(None, 1)
26 self.time = tmp[0][:-3] + '.' + tmp[0][-3:]
27 if len(tmp) > 1:
28 self.info = tmp[1]
29 else:
30 self.info = line
31 self.info = re.sub('\[dt=[0-9 ?]*\]', '', self.info)
32 self.info = self.info.strip()
35 class Object(object):
36 """A set of Entries that belong to the same NetLog Object."""
38 def __init__(self, line, id_offset):
39 self.id = line[id_offset + 4:].rstrip(')')
40 self.type = line.split(None, 1)[0]
41 self.entries = []
43 def SpaceOutEntries(self):
44 self.__FindGroups(self.__SpaceRange)
46 def SetRotation(self):
47 self.__FindGroups(self.__SetRotationRange)
49 def __FindGroups(self, proc):
50 first = 0
51 for i in range(len(self.entries)):
52 if self.entries[first].time != self.entries[i].time:
53 proc(first, i - 1)
54 first = i
55 proc(first, len(self.entries) - 1)
57 def __SpaceRange(self, start, end):
58 if end > start:
59 gap = math.floor(100/(end - start + 2))
60 for i in range(start + 1, end + 1):
61 self.entries[i].time += '%02d'%(gap * (i - start))
63 def __SetRotationRange(self, start, end):
64 for i in range(start, end + 1):
65 self.entries[i].rotation = 85 - (i - start) * 15
68 def Parse(stream):
69 """Parse the NetLog into python objects."""
71 result = []
72 request_section = 0
73 obj = None
74 entry = None
76 for line in stream:
77 line = line.strip()
78 if line.startswith('Requests'):
79 request_section = 1
80 elif line.startswith('Http cache'):
81 request_section = 0
83 if request_section:
84 id_offset = line.find('(id=')
85 if id_offset >= 0:
86 obj = Object(line, id_offset)
87 result.append(obj)
88 elif line.startswith('(P) t=') or line.startswith('t='):
89 entry = Entry(line)
90 obj.entries.append(entry)
91 elif line.find('source_dependency') >= 0:
92 new_entry = Entry(line)
93 new_entry.time = entry.time
94 new_entry.id = line.split(':')[1].split(',')[0]
95 obj.entries.append(new_entry)
96 new_entry = Entry('t=%s '%entry.time.replace('.', ''))
97 obj.entries.append(new_entry)
98 elif line.startswith('-->'):
99 entry.info = entry.info + ' ' + line[4:]
101 return result
104 def GnuplotRenderNetlog(netlog, filename, labels):
105 """Render a list of NetLog objects into Gnuplot format."""
107 output = open(filename, 'w')
109 commands = []
110 data = []
111 types = []
113 commands.append('file="%s"'%filename)
114 commands.append('set key bottom')
115 commands.append('set xdata time')
116 commands.append('set timefmt "%s"')
117 commands.append('set datafile separator ","')
118 commands.append('set xlabel "Time (s)"')
119 commands.append('set ylabel "Netlog ID"')
121 plot = []
122 index = 1
123 for obj in netlog:
124 if obj.type not in types:
125 types.append(obj.type)
126 type_num = types.index(obj.type)
127 plot.append('file index %d using 1:2 with linespoints lt %d notitle'%(
128 index, type_num))
129 obj.SetRotation()
130 for entry in obj.entries:
131 graph_id = obj.id
132 if entry.id > 0:
133 graph_id = entry.id
134 data.append('%s,%s'%(entry.time, graph_id))
135 info = entry.info.replace('"', '')
136 if info and labels:
137 commands.append('set label "%s" at "%s", %s rotate by %d'%(
138 info, entry.time, obj.id, entry.rotation))
139 data.append('\n')
140 index += 1
142 for entry_type in types:
143 plot.insert(0, '1/0 lt %d title "%s"'%(types.index(entry_type), entry_type))
144 commands.append('plot ' + ','.join(plot))
145 commands.append('exit')
146 result = '\n'.join(commands) + '\n\n\n' + '\n'.join(data)
148 output.write(result)
149 output.close()
150 os.system('gnuplot %s -'%filename)
153 def main(_):
154 parser = optparse.OptionParser('usage: %prog [options] dump_file')
155 parser.add_option_group(
156 optparse.OptionGroup(parser, 'Additional Info',
157 'When run, the script will generate a file that can '
158 'be passed to gnuplot, but will also start gnuplot '
159 'for you; left click selects a zoom region, u '
160 'unzooms, middle click adds a marker, and q quits.'))
161 parser.add_option('-o', '--output', dest='output', help='Output filename')
162 parser.add_option('-l', '--labels', action='store_true', help='Output labels')
163 options, args = parser.parse_args()
164 if not args:
165 parser.error('Must specify input dump_file.')
166 if not options.output:
167 options.output = args[0] + '.gnuplot'
169 netlog = Parse(open(args[0]))
170 GnuplotRenderNetlog(netlog, options.output, options.labels)
171 return 0
174 if '__main__' == __name__:
175 sys.exit(main(sys.argv))