#!/usr/bin/env python import re import string import os, sys from pylab import * from optparse import OptionParser DEBUG = 0 class Application: def __init__(self): self.rss = 0 self.vsize = 0 def get_mem_samples(self): return self.vsize class Log: def __init__(self, filename): self.lines = [] self.entry = [] self.nb_entry = 0 self.entries = [] self.title = "" 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() def parse_app_log(self): for i in range(0, len(self.lines)): self._parse_entry(self.lines[i]) if DEBUG: print "DEBUG: read %d values" % len(self.entries) def _parse_entry(self, line): properties = {} prop = {} values = line.split() self.title = values[0] application = Application() if DEBUG: print "DEBUG: title : %s " % self.title try: prop[0] = values[1].strip() prop[1] = values[2].strip() if DEBUG: print "DEBUG: pops : %s - %s" % (prop[0], prop[1]) # Convert to int if prop[0][0] in string.digits: prop[0] = int(prop[0]) if prop[1][0] in string.digits: prop[1] = int(prop[1]) application.rss = prop[0] application.vsize = prop[1] except: print "\nERROR: with the line %s\n%s" % (line, sys.exc_info()) if DEBUG: print "DEBUG: converted values: rss: %s - vsize: %s" % (application.rss, application.vsize) self.entries.append(application) def get_data(self): return self.entries class ApplicationPlot: def __init__(self, logfiles): self.logs = logfiles self.xclients = [] self.threasold = 0 self.max_title_len = 30 def draw(self): mem_samples = [] # We parse every log file for logfile in self.logs: # We extract every client for app in logfile.get_data(): mem_samples.append(app.get_mem_samples()) if mem_samples > self.threasold: title = logfile.title 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: appmem.py -f firefox-crash.log opera-crash.log" % menu menu = "%s\n\t (hint to generate them : appmem.sh appname1 appname2) > 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 = Log(files[i]) logfile.parse_app_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 = ApplicationPlot(logarray) mem_plot.draw()