diff --git a/src/pyNmonAnalyzer.py b/src/pyNmonAnalyzer.py index c8c6fb8..2813180 100644 --- a/src/pyNmonAnalyzer.py +++ b/src/pyNmonAnalyzer.py @@ -36,7 +36,11 @@ class pyNmonAnalyzer: bbbInfo = [] args = [] - stdReport = [('CPU_ALL', ['user', 'sys', 'wait'], 'stackedGraph: true, fillGraph: true'), ('DISKBUSY', ['sda1', 'sdb1'], ''), ('MEM', ['memtotal', 'active'], ''), ('NET', ['eth0'], '')] + # Default Settings + stdReport = [ ('CPU_ALL', ['user', 'sys', 'wait'], 'stackedGraph: true, fillGraph: true'), + ('DISKBUSY', ['sda1', 'sdb1'], ''), + ('MEM', ['memtotal', 'active'], ''), + ('NET', ['eth0'], '')] def __init__(self, args=None, raw_args=None): if args is None and raw_args is None: @@ -53,20 +57,6 @@ def __init__(self, args=None, raw_args=None): self.saveReportConfig(self.stdReport, configFname=self.args.confFname) sys.exit() - if self.args.buildReport: - # check whether specified report config exists - if os.path.exists(self.args.confFname) == False: - log.warn("looks like the specified config file(\""+self.args.confFname+"\") does not exist.") - ans = raw_input("\t Would you like us to write the default file out for you? [y/n]:") - - if ans.strip().lower() == "y": - self.saveReportConfig(self.stdReport, configFname=self.args.confFname) - log.warn("Wrote default config to report.config.") - log.warn("Please adjust report.config to ensure the correct devices will be graphed.") - else: - log.warn("\nNOTE: you could try using the default config file with: -r report.config") - sys.exit() - # check ouput dir, if not create if os.path.exists(self.args.outdir) and self.args.overwrite: try: @@ -90,9 +80,46 @@ def __init__(self, args=None, raw_args=None): self.nmonParser = pyNmonParser.pyNmonParser(self.args.input_file, self.args.outdir, self.args.overwrite) self.processedData = self.nmonParser.parse() + if self.args.buildReport: + # check whether specified report config exists + if os.path.exists(self.args.confFname) == False: + log.warn("looks like the specified config file(\""+self.args.confFname+"\") does not exist.") + ans = raw_input("\t Would you like us to generate a template configuration file for you? [y/n]: ") + + if ans.strip().lower() == "y": + question = "Would you like a minimal config or one based on your input file?" + question += "\n\t [m]inimal - Basic report showing CPU, Network, Memory and Diskbusy" + question += "\n\t [c]ustom - Report configuration listing all available parameters, adding some reasonable defaults" + question += "\nPlease choose an option from above: " + ans = raw_input(question) + if ans.strip().lower() == "c": + reportConfiguration=[] + for stat in sorted(self.nmonParser.knownStats.keys()): + if len(self.nmonParser.knownStats[stat]) > 0: + if "CPU" in stat: + reportConfiguration.append( (stat, ['user','sys','wait'] , 'stackedGraph: true, fillGraph: true') ) + elif "MEM" == stat: + reportConfiguration.append( (stat, ['memtotal','active'] , '') ) + else: + reportConfiguration.append( (stat, self.nmonParser.knownStats[stat], '') ) + + self.saveReportConfig(reportConfiguration, configFname=self.args.confFname) + log.warn("Wrote default config to report.config.") + log.warn("Please adjust report.config to ensure the correct devices will be graphed.") + elif ans.strip().lower() == "m": + self.saveReportConfig(self.stdReport, configFname=self.args.confFname) + log.warn("Wrote default config to report.config.") + log.warn("Please adjust report.config to ensure the correct devices will be graphed.") + else: + log.warn("Unknown option: \'%s\'" % ans.strip()) + else: + log.warn("\nNOTE: you could try using the default config file with: -r report.config") + sys.exit() + if self.args.outputCSV or "inter" in self.args.reportType.lower(): log.info("Preparing CSV files..") self.outputData("csv") + if self.args.buildReport: if "stat" in self.args.reportType.lower(): log.info("Preparing static Report..") diff --git a/src/pyNmonParser.py b/src/pyNmonParser.py index 9529fd7..f74b939 100644 --- a/src/pyNmonParser.py +++ b/src/pyNmonParser.py @@ -27,6 +27,7 @@ def __init__(self, fname="./test.nmon",outdir="./data/",overwrite=False,debug=Fa self.fname = fname self.outdir = outdir self.debug = debug + self.knownStats = {} # Holds final 2D arrays of each stat self.processedData = {} @@ -117,12 +118,14 @@ def processLine(self,header,line): # two columns and then the real one therefore we skip the first row pass else: + # A new stat being added + self.knownStats[line[0]] = [] for h in line[1:]: - # make it an array - tmp=[] - tmp.append(h) - header.append(tmp) - self.processedData[line[0]]=header + # initialize an array of each header + header.append([h]) + self.knownStats[line[0]].append(h) + self.knownStats[line[0]] = self.knownStats[line[0]][1:] + self.processedData[line[0]] = header def parse(self): # TODO: check fname @@ -132,7 +135,7 @@ def parse(self): l=l.strip() bits=l.split(',') self.processLine(bits[0],bits) - + return self.processedData def output(self,outType="csv"): diff --git a/src/pyNmonPlotter.py b/src/pyNmonPlotter.py index 16061e7..962787a 100644 --- a/src/pyNmonPlotter.py +++ b/src/pyNmonPlotter.py @@ -64,14 +64,14 @@ def plotStats(self, todoList, isAIX=False): for stat, fields, plotOpts in todoList: if "CPU" in stat: # parse NMON date/timestamps and produce datetime objects - times = [datetime.datetime.strptime(d, "%d-%b-%Y %H:%M:%S") for d in self.processedData["CPU_ALL"][0][1:]] + times = [datetime.datetime.strptime(d, "%d-%b-%Y %H:%M:%S") for d in self.processedData[stat][0][1:]] values=[] - values.append((self.processedData["CPU_ALL"][1][1:],"usr")) - values.append((self.processedData["CPU_ALL"][2][1:],"sys")) - values.append((self.processedData["CPU_ALL"][3][1:],"wait")) + values.append((self.processedData[stat][1][1:],"usr")) + values.append((self.processedData[stat][2][1:],"sys")) + values.append((self.processedData[stat][3][1:],"wait")) data=(times,values) - fname = self.plotStat(data, xlabel="Time", ylabel="CPU load (%)", title="CPU vs Time", isPrct=True, stacked=True) + fname = self.plotStat(data, xlabel="Time", ylabel="CPU load (%)", title=stat+" vs Time", isPrct=True, stacked=True) outFiles.append(fname) elif "DISKBUSY" in stat: @@ -121,26 +121,29 @@ def plotStats(self, todoList, isAIX=False): fname = self.plotStat(data, xlabel="Time", ylabel="Memory in MB", title="Memory vs Time", isPrct=False, yrange=[0,max(total)*1.2]) outFiles.append(fname) - elif "NET" in stat: + elif "NET" == stat: # parse NMON date/timestamps and produce datetime objects times = [datetime.datetime.strptime(d, "%d-%b-%Y %H:%M:%S") for d in self.processedData["CPU_ALL"][0][1:]] values=[] read=np.array([]) write=np.array([]) - for i in self.processedData["NET"]: + highVal=0 + for i in self.processedData[stat]: colTitle = i[:1][0] for iface in fields: if iface in colTitle and "read" in colTitle: read = np.array([float(x) for x in i[1:]]) + highVal=max(highVal, max(read)) values.append((read,colTitle)) elif iface in colTitle and "write" in colTitle: write = np.array([float(x) for x in i[1:]]) + highVal=max(highVal, max(write)) values.append((write,colTitle)) data=(times,values) - fname = self.plotStat(data, xlabel="Time", ylabel="Network KB/s", title="Net vs Time", yrange=[0,max(max(read),max(write))*1.2]) + fname = self.plotStat(data, xlabel="Time", ylabel="Network KB/s", title=stat+" vs Time", yrange=[0,np.max(highVal)*1.2]) outFiles.append(fname) return outFiles diff --git a/src/pyNmonReport.py b/src/pyNmonReport.py index 1d41c40..40e3044 100644 --- a/src/pyNmonReport.py +++ b/src/pyNmonReport.py @@ -100,11 +100,16 @@ def createInteractiveReport(reportConfig, outPath, data=None, dygraphLoc="http:/ # match anything that contains a key from reportConfig if i.lower() in c[0].lower(): headings.append(c[0]) - numericArray = [ float(x) for x in c[1:] ] - if max(numericArray) > localMax or localMax == None: - localMax = max(numericArray) - if min(numericArray) < localMin or localMin == None: - localMin = min(numericArray) + try: + numericArray = [ float(x) for x in c[1:] ] + + if max(numericArray) > localMax or localMax == None: + localMax = max(numericArray) + if min(numericArray) < localMin or localMin == None: + localMin = min(numericArray) + except: + pass + displayCols.append(headings) localMin = (0.0 if localMin==None else localMin) localMax = (0.0 if localMax==None else localMax)