#!/usr/bin/env python import re import string import os, sys from pylab import * from optparse import OptionParser DEBUG = 0 def old_fuction(): file = open("xrestop.log","r") lines = file.readlines() re0 = re.compile(r"""(1 - )""") #re1 = re.compile(r"""(1 - )""") re_tb = re.compile(r"""[\t]total bytes : ~(\d*)""") total_bytes = [] for i,l in enumerate(lines): if re0.match(l): m = re_tb.match(lines[i+15]) total_bytes.append(int(m.groups(1)[0])) plot(total_bytes) show() class XClient: def __init__(self, id): self.properties = {} self.properties['res_base'] = id self.prop_list = ['pixmap bytes','other bytes','total bytes'] self.prop_uniq = ['title','res_base'] def __str__(self): return str(self.properties) def get_id(self): return self.properties['res_base'] def add_sample(self, key, value): m_list = self.properties.get(key) if m_list == None: self.properties[key] = [] self.properties[key].append(value) elif type(m_list) == list: self.properties[key].append(value) else: raise ValueError def set_properties(self, props): for k,v in props.items(): if k in self.prop_list: self.add_sample(k,v) elif k in self.prop_uniq: self.properties[k] = v else : # Ignore properties that are not wanted pass def get_mem_samples(self): return self.properties.get('total bytes') def get_mem_samples_kb(self): self.properties['total bytes in kb'] = [] if DEBUG: print "\nDEBUG: XClient properties: \n\t %s" % self.properties for sample in self.properties.get('total bytes'): self.properties['total bytes in kb'].append(sample/1024) return self.properties['total bytes in kb'] def get_title(self): return self.properties.get('title') class XRestopLog: def __init__(self): self.nb_lines_per_xclient = 17 self.lines = [] self.xclients = [] self.nb_xclients = 0 def set_logfile(self, filename): if not os.path.isfile(filename): print "\nERROR : the file %s doesn't exists - " % file file = open(filename,"r") self.lines = file.readlines() file.close() self.nb_xclients = len(self.lines) / self.nb_lines_per_xclient def parse_xrestop_log(self): for i in range(0, len(self.lines), self.nb_lines_per_xclient): # Process 16 lines self._parse_xclient(self.lines[i:i+self.nb_lines_per_xclient]) def _parse_xclient(self, lines): properties = {} # First line is title properties['title'] = string.strip(lines[0]) if DEBUG: print "\nDEBUG: lines read \n\t %s" % lines[1:] # We drop any entry that doesn't respect the complete number of lines if len(lines) < self.nb_lines_per_xclient - 1: return # Ignore the title and the last empty line for l in lines[1:-1]: l = string.strip(l) prop = string.split(l,':') try: prop[0] = prop[0].strip() prop[1] = prop[1].strip() # Remove tild from some records if prop[1][0] == '~': prop[1] = prop[1][1:] # Convert to int if prop[1][0] in string.digits: prop[1] = int(prop[1]) # Save the property in the dictionnary properties[prop[0]] = prop[1] except: print "\nERROR: with the line %s\n" % l continue # search for the xclient, and add properties id = properties.get('res_base') xclient = self.get_xclient_by_id(id) xclient.set_properties(properties) if DEBUG: print "DEBUG: xclient infos:\n%s" % xclient def get_xclient_by_id(self, id): """Return a new xclient if id is not found""" if len(self.xclients) == 0: new_xclient = XClient(id) self.xclients.append(new_xclient) return new_xclient for xclient in self.xclients: if xclient.get_id() == id: return xclient new_xclient = XClient(id) self.xclients.append(new_xclient) return new_xclient def get_xclients(self): return self.xclients class XClientMemoryPlot: def __init__(self, logfiles): self.logs = logfiles self.xclients = [] self.threasold = 0 self.max_title_len = 30 def draw(self): # We parse every log file for logfile in self.logs: # We extract every client for xclient in logfile.get_xclients(): mem_samples = xclient.get_mem_samples_kb() if mem_samples[0] > self.threasold: title = xclient.get_title() title = title[4:-14] if len(title) > self.max_title_len: title = title[:self.max_title_len] print '%s = %s' % (title, mem_samples) line = plot(mem_samples, label=title) legend(loc='best') show() if __name__=="__main__": # Menu menu = "You must provide input files" menu = "%s\n\t ex: mem.py -f firefox-crash.log opera-crash.log" % menu menu = "%s\n\t (hint to generate them : xrestop --delay-time 1 -b | grep -A 15 appname) > mem.log" % menu parser = OptionParser(menu) parser.add_option("-d", "--debug", help="outputs additionnal information while running", action="store_true", dest="debug") parser.add_option("-f", "--files", help="input log files", metavar="\"file1.log file2.log\"", dest="files") # Use debug mode ? (opts, args) = parser.parse_args() if opts.debug == True: DEBUG = 1 if DEBUG: print opts # Get the list of log files to use if not opts.files: parser.error("incorrect or missing arguments") sys.exit(1) files = opts.files.split() if DEBUG: print "\nDEBUG: Number of provided log files: %d" % (len(files)) # We keep every log file name provided to render on a same graphic i=0 logarray = [] while (i < len(files)): if not os.path.isfile(files[i]): print menu sys.exit(1) try: if DEBUG: print "\nDEBUG: Reading file: %s" % (files[i]) logfile = XRestopLog() logfile.set_logfile(files[i]) logfile.parse_xrestop_log() logarray.append(logfile) except: print "\nERROR: Problem with %s - %s" % (files[i], sys.exc_info()[0]) raise sys.exit(1) i=i+1 # We draw every log file on a same graphic mem_plot = XClientMemoryPlot(logarray) mem_plot.draw()