#!/usr/bin/python import re import sys def ParseLine(line): m = re.search(r'^\[(\d*):(\d*):(\d*).*\] XXX (.*)$', line) if not m: return None parsed = {} parsed['t'] = int(m.group(3)) msg = m.group(4) m = re.search(r'^Received request \[(.*)\] (.*)\s*$', msg) if m: parsed['type'] = 'request' parsed['phase'] = 'start' parsed['id'] = m.group(1) parsed['hostname'] = m.group(2) return parsed m = re.search(r'^Finished request \[(.*)\] (.*)\s*$', msg) if m: parsed['type'] = 'request' parsed['phase'] = 'end' parsed['id'] = m.group(1) parsed['hostname'] = m.group(2) return parsed m = re.search(r'^Canceled request \[(.*)\] (.*)\s*$', msg) if m: parsed['type'] = 'request' parsed['phase'] = 'end' parsed['cancelled'] = True parsed['id'] = m.group(1) parsed['hostname'] = m.group(2) return parsed m = re.search(r'^Running resolve for (.*) \[@(.*)\]\s*$', msg) if m: parsed['type'] = 'thread' parsed['phase'] = 'start' parsed['hostname'] = m.group(1) parsed['id'] = m.group(2) return parsed m = re.search(r'^Completed resolve for (.*) \[@(.*)\]\s*$', msg) if m: parsed['type'] = 'thread' parsed['phase'] = 'end' parsed['hostname'] = m.group(1) parsed['id'] = m.group(2) return parsed return None def ParseFile(path): f = open(path, 'r') entries = [] for line in f: parsed = ParseLine(line) if parsed: entries.append(parsed) f.close() return entries def FindEndEntry(entries, start_index): start_entry = entries[start_index] for i in range(start_index + 1, len(entries)): e = entries[i] if (e['phase'] == 'end' and e['type'] == start_entry['type'] and e['id'] == start_entry['id'] and e['hostname'] == start_entry['hostname']): return e return None def GetGroupEntries(entries): grouped = [] for i in range(len(entries)): e1 = entries[i] if e1['phase'] == 'start': # Clone e1 (mostly). e = {} for prop in ['id', 'type', 'hostname', 't']: e[prop] = e1[prop] # Find the end entry, and update end information. e2 = FindEndEntry(entries, i) if e2: e['dt'] = e2['t'] - e1['t'] e['cancelled'] = e2.get('cancelled', False) e2['phase'] = '' # Make sure it isn't re-used later. grouped.append(e) return grouped def FindMaxTime(entries): t_max = 0 for e in entries: t_max = max(t_max, e['t'] + e.get('dt', 0)) return t_max row_height = 40 max_width = 800 def PrintEntryRow(entries, i, max_t): entry = entries[i] min_width = 2 top_px = i * row_height left_px = int(entry['t'] * max_width / max_t) dt = entry.get('dt', max_t - entry['t']) width_px = max(min_width, int(dt * max_width / max_t)) caption_offset_x = width_px + 15 caption_offset_y = 4 # Print a box on the timeline. bg = '' if entry['type'] == 'request': bg = 'blue' if entry['type'] == 'thread': bg = 'purple' if entry.get('cancelled', False): bg = 'red' print ('