aboutsummaryrefslogblamecommitdiffstats
path: root/tools/profiler/report
blob: 13577fccd45acb52c9df31b3130105a5bdf30a89 (plain) (tree)
















































































































































                                                                                                                                      
#!/usr/bin/python

# profile reporter

import sys, os, operator, string
from optparse import OptionParser
from glob import glob
from subprocess import Popen, PIPE
import tarfile

class GlobalVars:
    def __init__(self):
        pass

class MyWriter:
    def __init__(self, stdout, filename):
        self.stdout = stdout
        self.logfile = file(filename, 'w')
    
    def write(self, text):
        self.stdout.write(text)
        self.logfile.write(text)
    
    def close(self):
        self.stdout.close()
        self.logfile.close()

def parse_options(opts):
    """ parse cmd line opts """

    parser = OptionParser()
    parser.add_option("-f","--filename", dest="filename",
                      help="write report to FILENAME")
    parser.add_option("-t", "--time", dest="rtime",
                      help="set minimum RUNTIME to report", action="store",
                      default=float(0.1), type="float")
    parser.add_option("-i", "--input", dest="rpt_dir",
                      help="define directory of sosreport archives",
                      action="store", default=False)

    GlobalVars.cmdlineopts, GlobalVars.cmdlineargs = parser.parse_args(opts)

    if not GlobalVars.cmdlineopts.rpt_dir:
        raise SystemExit("\nPlease make sure to specify --input FILES\n")
    
def uncompress_reports(fname):
    """ uncompresses the sosreport """
    p = Popen(["xz","-d", fname], stdout=PIPE, stdin=PIPE)
    out, err = p.communicate()
    if err:
        print "Problem extracting %s" % (fname,)
    return

def read_archive(fname):
    """ reads tarfile archive and grabs the sosprofile.log fileobj """
    tar = tarfile.open(os.path.abspath(fname), "r:")
    for tarinfo in tar.getmembers():
        if 'sosprofile.log' in tarinfo.name:
            fobj = tar.extractfile(tarinfo)
            buf = fobj.read()
            tar.close()
            return buf

def timeoutput(secs):
    if secs > 60:
        secs = round(secs) / 60
        return (secs, 'm')
    elif secs < 60:
        return (secs, 's')

def sort_profile():
    """ provide reports on sosreport profiling """
    # uncompress reports from input files
    for rpt in glob(GlobalVars.cmdlineopts.rpt_dir+"/*.xz"):
        uncompress_reports(os.path.abspath(rpt))
    GlobalVars.rpt_count = 0
    GlobalVars.timecount = 0
    GlobalVars.lrc = {}
    for rpt in glob(GlobalVars.cmdlineopts.rpt_dir+"/*.tar"):
        buf = read_archive(rpt)
        time_sorts=[]
        if not buf:
            continue
        for line in buf.split("\n"):
            try:
                cmd, rtime = line.split("time:")
                try:
                    # cmds that span multiple lines still need time calculated
                    cmd = cmd.split(":")[1]
                except IndexError:
                    cmd, rtime = line.split("time:")
                time_sorts.append((cmd.strip(), rtime.strip()))
            except ValueError:
                continue
        time_count = 0
        b_val_count = 0
        write_stats = open(rpt + ".profile_report", 'w') 
        write_stats.write(28 * ' ' + 'SOSreport Profile Report' + 27 * ' ' + "\n")
        write_stats.write(79 * '.' + "\n")
        for a,b in sorted(time_sorts, key=operator.itemgetter(1)):
            b_val = float(b)
            time_count += b_val
            if b_val > float(GlobalVars.cmdlineopts.rtime):
                b_val_count += b_val
                write_stats.write("%-79s %s\n" % (a[:78], b))
                if GlobalVars.lrc.has_key(a) and \
                GlobalVars.lrc[a] < b_val:
                    GlobalVars.lrc[a] = b_val
                else:
                    GlobalVars.lrc[a] = b_val 
        # Keep up with total run time for all reports
        GlobalVars.timecount += time_count
        # Write out totals per report
        write_stats.write(79 * '.' + "\n")
        write_stats.write("Totals:\n")
        secs, fmt = timeoutput(b_val_count)
        write_stats.write("cumulative > %s: \t%f%s\n" % (GlobalVars.cmdlineopts.rtime, secs, fmt))
        secs, fmt = timeoutput(time_count)
        write_stats.write("cumulative total:\t%f%s\n" % (secs,fmt))
        write_stats.close()
        # increment report count so we can get an average runtime
        GlobalVars.rpt_count += 1

if __name__ == "__main__":
    parse_options(sys.argv[1:])
    if GlobalVars.cmdlineopts.filename:
        writer = MyWriter(sys.stdout, GlobalVars.cmdlineopts.filename)
        sys.stdout = writer
    print "Building reports ..."
    sort_profile()
    print 79 * "-"
    print "Total runtime for %d reports is %fs" % (round(GlobalVars.rpt_count, 2), GlobalVars.timecount)
    print "Average total runtime of %d reports is %fs" % (round(GlobalVars.rpt_count, 2), GlobalVars.timecount / GlobalVars.rpt_count)
    print 79 * "-"
    print 
    print "Longest running commands > %s:" % (GlobalVars.cmdlineopts.rtime,)
    print 79 * "-"
    for cmd, rtime in sorted(GlobalVars.lrc.iteritems(), key=operator.itemgetter(1)):
        print "%-75s %s" % (cmd[:69], rtime)

    if GlobalVars.cmdlineopts.filename:
        print 79 * "-"
        print "Report log written to: %s" % (GlobalVars.cmdlineopts.filename,)
        writer.close()