|
|
|
@ -177,40 +177,45 @@ class DetailProcess(Analysis):
|
|
|
|
|
def reboot(self,rows,conf=None) :
|
|
|
|
|
return np.sum([int(item['label']=='crash') for item in rows]) > 0
|
|
|
|
|
def evaluate(self,name) :
|
|
|
|
|
cmd = "ps -eo pmem,pcpu,vsize,command|grep -E \":app\""
|
|
|
|
|
handler = subprocess.Popen(cmd.replace(":app",name),shell=True,stdout=subprocess.PIPE)
|
|
|
|
|
ostream = handler.communicate()[0].split('\n')
|
|
|
|
|
#xstr = ostream
|
|
|
|
|
ostream = [ self.split(name,row) for row in ostream if row != '' and 'grep' not in row]
|
|
|
|
|
if len(ostream) == 0 or len(ostream[0]) < 4 :
|
|
|
|
|
ostream = [['0','0','0','0',name]]
|
|
|
|
|
r = []
|
|
|
|
|
for row in ostream :
|
|
|
|
|
#
|
|
|
|
|
# Though the comm should only return the name as specified,
|
|
|
|
|
# On OSX it has been observed that the fully qualified path is sometimes returned (go figure)
|
|
|
|
|
#
|
|
|
|
|
row = [float(value) for value in row if value.strip() != '' and name not in value ] +[re.sub('\$|^','',name)]
|
|
|
|
|
r.append(row)
|
|
|
|
|
#
|
|
|
|
|
#cmd = "ps -eo pmem,pcpu,vsize,command|grep -E \":app\""
|
|
|
|
|
fields = ['user','pid','start','time','memory_usage','cpu_usage','memory_available','status','label','command']
|
|
|
|
|
|
|
|
|
|
cmd = "ps -eo user,pid,stime,time,pmem,pcpu,vsize,stat,cmd,command|grep -E \":app\"".replace(":app",name)
|
|
|
|
|
handler = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
|
|
|
|
|
m = handler.communicate()[0].split('\n')
|
|
|
|
|
r = self.format(fields,cmd,m)
|
|
|
|
|
##xstr = ostream
|
|
|
|
|
##ostream = [ self.split(name,row) for row in ostream if row != '' and 'grep' not in row]
|
|
|
|
|
#ostream = [ row.split() for row in ostream if row.strip() != '' and 'grep' not in row]
|
|
|
|
|
#if len(ostream) == 0 or len(ostream[0]) < 4 :
|
|
|
|
|
#ostream = [] #['0','0','0','0',name]]
|
|
|
|
|
#r = []
|
|
|
|
|
#for row in ostream :
|
|
|
|
|
##
|
|
|
|
|
## Though the comm should only return the name as specified,
|
|
|
|
|
## On OSX it has been observed that the fully qualified path is sometimes returned (go figure)
|
|
|
|
|
##
|
|
|
|
|
#row = [float(value) for value in row if value.strip() != '' and name not in value ] +[re.sub('\$|^','',name)]
|
|
|
|
|
#r.append(row)
|
|
|
|
|
##
|
|
|
|
|
# At this point we should aggregate results
|
|
|
|
|
# The aggregation is intended for applications with several processes (e.g: apache2)
|
|
|
|
|
#
|
|
|
|
|
if len(r) > 1:
|
|
|
|
|
m = None
|
|
|
|
|
for row in r:
|
|
|
|
|
if m is None:
|
|
|
|
|
m = row
|
|
|
|
|
else:
|
|
|
|
|
m[3] += row[3]
|
|
|
|
|
m[0] += row[0]
|
|
|
|
|
m[1] += row[1]
|
|
|
|
|
m[2] += row[2]
|
|
|
|
|
m[0] = round((m[0] / m[3]),2)
|
|
|
|
|
m[1] = round((m[1] / m[3]),2)
|
|
|
|
|
m[2] = round((m[2] / m[3]),2)
|
|
|
|
|
|
|
|
|
|
r = [m]
|
|
|
|
|
#if len(r) > 1:
|
|
|
|
|
# m = None
|
|
|
|
|
# for row in r:
|
|
|
|
|
# if m is None:
|
|
|
|
|
# m = row
|
|
|
|
|
# else:
|
|
|
|
|
# m[3] += row[3]
|
|
|
|
|
# m[0] += row[0]
|
|
|
|
|
# m[1] += row[1]
|
|
|
|
|
# m[2] += row[2]
|
|
|
|
|
# m[0] = round((m[0] / m[3]),2)
|
|
|
|
|
# m[1] = round((m[1] / m[3]),2)
|
|
|
|
|
# m[2] = round((m[2] / m[3]),2)
|
|
|
|
|
|
|
|
|
|
# r = [m]
|
|
|
|
|
return r
|
|
|
|
|
def status(self,row):
|
|
|
|
|
x = row['memory_usage']
|
|
|
|
@ -222,20 +227,68 @@ class DetailProcess(Analysis):
|
|
|
|
|
return "idle"
|
|
|
|
|
else:
|
|
|
|
|
return "crash"
|
|
|
|
|
def format(self,row):
|
|
|
|
|
def _format(self,row):
|
|
|
|
|
r= {"memory_usage":row[0],"cpu_usage":row[1],"memory_available":row[2]/1000,"proc_count":row[3],"label":self.cleanup(row[4])}
|
|
|
|
|
status = self.status(r)
|
|
|
|
|
r['status'] = status
|
|
|
|
|
return r
|
|
|
|
|
def _getObject(self,fields,terms):
|
|
|
|
|
r = {}
|
|
|
|
|
value = []
|
|
|
|
|
id = None
|
|
|
|
|
for id in fields :
|
|
|
|
|
index = fields.index(id)
|
|
|
|
|
r[id] = terms[index].strip()
|
|
|
|
|
if re.match('^\d{0,}\.\d{1,}$',r[id]) :
|
|
|
|
|
r[id] = round(float(r[id]),4)
|
|
|
|
|
elif re.match('^[0-9]+$',r[id]) :
|
|
|
|
|
r[id] = int(r[id])
|
|
|
|
|
r[id] = " ".join( terms[index:]).strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r['memory_available'] /= 1000
|
|
|
|
|
r['status'] = self.status(r)
|
|
|
|
|
return r
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def format(self,fields,cmd,matrix):
|
|
|
|
|
"""
|
|
|
|
|
This function will create an associative array given the fields (meta data) provided for the vector output in the matrix
|
|
|
|
|
|
|
|
|
|
@param matrix matrix of outputs for the given command
|
|
|
|
|
@param fields field name for every column (standard for ps)
|
|
|
|
|
@param cmd name of the command that was executed, helps to remove noise
|
|
|
|
|
"""
|
|
|
|
|
r = []
|
|
|
|
|
|
|
|
|
|
xcmd = cmd.split()
|
|
|
|
|
N = len(xcmd)
|
|
|
|
|
for row in matrix :
|
|
|
|
|
n = len(set(row.split()) & set(xcmd))
|
|
|
|
|
if n/N > .5 or len(row.strip()) == 0 or 'grep' in row.split():
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
row = [col for col in row.split() if col.strip() != '' and 'grep' not in col]
|
|
|
|
|
r += [self._getObject(fields,row)]
|
|
|
|
|
if len(r) == 0 :
|
|
|
|
|
obj = {}
|
|
|
|
|
for id in fields :
|
|
|
|
|
obj[id] = 0
|
|
|
|
|
obj['label'] = cmd.split('-E')[1].replace('"','')
|
|
|
|
|
obj['status']= 'crash'
|
|
|
|
|
r = [obj]
|
|
|
|
|
|
|
|
|
|
return r
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def composite(self):
|
|
|
|
|
ma = []
|
|
|
|
|
now = self.getNow()
|
|
|
|
|
for name in self.names:
|
|
|
|
|
|
|
|
|
|
matrix = self.evaluate(name)
|
|
|
|
|
|
|
|
|
|
ma += [ dict(now, **self.format(row)) for row in matrix]
|
|
|
|
|
#matrix = self.evaluate(name)
|
|
|
|
|
ma += self.evaluate(name)
|
|
|
|
|
#ma += [ dict(now, **self.format(row)) for row in matrix]
|
|
|
|
|
|
|
|
|
|
return ma
|
|
|
|
|
"""
|
|
|
|
@ -394,3 +447,7 @@ class FileWatch(Analysis):
|
|
|
|
|
# BEG = len(self.logs) - MAX_SIZE -1
|
|
|
|
|
# self.logs = self.logs[BEG:]
|
|
|
|
|
|
|
|
|
|
p = DetailProcess()
|
|
|
|
|
r = p.evaluate('firefox')
|
|
|
|
|
for item in r :
|
|
|
|
|
print item['label'],item['status']
|