aboutsummaryrefslogtreecommitdiffstats
path: root/tools/profiler/report
blob: 13577fccd45acb52c9df31b3130105a5bdf30a89 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/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()