Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 42 additions & 15 deletions src/pyNmonAnalyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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..")
Expand Down
15 changes: 9 additions & 6 deletions src/pyNmonParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}
Expand Down Expand Up @@ -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
Expand All @@ -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"):
Expand Down
19 changes: 11 additions & 8 deletions src/pyNmonPlotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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

Expand Down
15 changes: 10 additions & 5 deletions src/pyNmonReport.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down