parent
f12c1467a0
commit
8e7cad9a11
@ -1,38 +0,0 @@
|
|||||||
import smtplib
|
|
||||||
from email.mime.multipart import MIMEMultipart
|
|
||||||
from email.mime.text import MIMEText
|
|
||||||
|
|
||||||
class MailAgent :
|
|
||||||
def __init__(self,conf) :
|
|
||||||
self.uid = conf['uid']
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
self.handler = smtplib.SMTP_SSL(conf['host'],conf['port'])
|
|
||||||
r = self.handler.login(self.uid,conf['password'])
|
|
||||||
#
|
|
||||||
# @TODO: Check the status of the authentication
|
|
||||||
# If not authenticated the preconditions have failed
|
|
||||||
#
|
|
||||||
except Exception,e:
|
|
||||||
print e
|
|
||||||
self.handler = None
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def send(self,**args) :
|
|
||||||
subject = args['subject']
|
|
||||||
message = args['message']
|
|
||||||
to = args['to']
|
|
||||||
if '<' in message and '>' in message :
|
|
||||||
message = MIMEText(message,'html')
|
|
||||||
else:
|
|
||||||
message = MIMEText(message,'plain')
|
|
||||||
message['From'] = self.uid
|
|
||||||
message['To'] = to
|
|
||||||
message['Subject'] = subject
|
|
||||||
return self.handler.sendmail(self.uid,to,message.as_string())
|
|
||||||
def close(self):
|
|
||||||
self.handler.quit()
|
|
||||||
|
|
@ -1,312 +0,0 @@
|
|||||||
"""
|
|
||||||
This file is intended to perfom certain machine learning tasks based on numpy
|
|
||||||
We are trying to keep it lean that's why no sklearn involved yet
|
|
||||||
|
|
||||||
@TODO:
|
|
||||||
Create factory method for the learners implemented here
|
|
||||||
Improve preconditions (size of the dataset, labels)
|
|
||||||
"""
|
|
||||||
from __future__ import division
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
class ML:
|
|
||||||
@staticmethod
|
|
||||||
def Filter (attr,value,data) :
|
|
||||||
#
|
|
||||||
# @TODO: Make sure this approach works across all transport classes
|
|
||||||
# We may have a potential issue of how the data is stored ... it may not scale
|
|
||||||
#
|
|
||||||
value = ML.CleanupName(value)
|
|
||||||
#return [item[0] for item in data if item and attr in item[0] and item[0][attr] == value]
|
|
||||||
#return [[item for item in row if item[attr] == value][0] for row in data]
|
|
||||||
#
|
|
||||||
# We are making the filtering more rescillient, i.e if an item doesn't exist we don't have to throw an exception
|
|
||||||
# This is why we expanded the loops ... fully expressive but rescilient
|
|
||||||
#
|
|
||||||
r = []
|
|
||||||
for row in data :
|
|
||||||
if isinstance(row,list) :
|
|
||||||
for item in row :
|
|
||||||
|
|
||||||
if attr in item and item[attr] == value:
|
|
||||||
r.append(item)
|
|
||||||
else:
|
|
||||||
#
|
|
||||||
# We are dealing with a vector of objects
|
|
||||||
#
|
|
||||||
if attr in row and row[attr] == value:
|
|
||||||
r.append(row)
|
|
||||||
|
|
||||||
return r
|
|
||||||
@staticmethod
|
|
||||||
def Extract(lattr,data):
|
|
||||||
if isinstance(lattr,basestring):
|
|
||||||
lattr = [lattr]
|
|
||||||
# return [[row[id] for id in lattr] for row in data]
|
|
||||||
r = [[row[id] for id in lattr] for row in data]
|
|
||||||
if len(lattr) == 1 :
|
|
||||||
return [x[0] for x in r]
|
|
||||||
else:
|
|
||||||
return r
|
|
||||||
@staticmethod
|
|
||||||
def CleanupName(value) :
|
|
||||||
return value.replace('$','').replace('.+','')
|
|
||||||
@staticmethod
|
|
||||||
def distribution(xo,lock,scale=False) :
|
|
||||||
|
|
||||||
d = []
|
|
||||||
m = {}
|
|
||||||
if scale :
|
|
||||||
xu = np.mean(xo)
|
|
||||||
sd = np.sqrt(np.var(xo))
|
|
||||||
for xi in xo :
|
|
||||||
value = round(xi,2)
|
|
||||||
if scale :
|
|
||||||
value = round((value - xu)/sd,2)
|
|
||||||
id = str(value)
|
|
||||||
lock.acquire()
|
|
||||||
if id in m :
|
|
||||||
index = m[id]
|
|
||||||
d[index][1] += 1
|
|
||||||
else:
|
|
||||||
m[id] = len(d)
|
|
||||||
d.append([value,1])
|
|
||||||
lock.release()
|
|
||||||
del m
|
|
||||||
return d
|
|
||||||
|
|
||||||
"""
|
|
||||||
Implements a multivariate anomaly detection
|
|
||||||
@TODO: determine computationally determine epsilon
|
|
||||||
"""
|
|
||||||
class AnomalyDetection:
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
def split(self,data,index=-1,threshold=0.65) :
|
|
||||||
N = len(data)
|
|
||||||
# if N < LIMIT:
|
|
||||||
# return None
|
|
||||||
|
|
||||||
end = int(N*threshold)
|
|
||||||
train = data[:end]
|
|
||||||
test = data[end:]
|
|
||||||
|
|
||||||
return {"train":train,"test":test}
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
@param key field name by which the data will be filtered
|
|
||||||
@param value field value for the filter
|
|
||||||
@param features features to be used in the analysis
|
|
||||||
@param labels used to assess performance
|
|
||||||
@TODO: Map/Reduce does a good job at filtering
|
|
||||||
"""
|
|
||||||
def learn(self,data,key,value,features,label):
|
|
||||||
|
|
||||||
|
|
||||||
if len(data) < 10:
|
|
||||||
return None
|
|
||||||
xo = ML.Filter(key,value,data)
|
|
||||||
if len(xo) < 10 :
|
|
||||||
return None
|
|
||||||
# attr = conf['features']
|
|
||||||
# label= conf['label']
|
|
||||||
|
|
||||||
yo= ML.Extract([label['name']],xo)
|
|
||||||
xo = ML.Extract(features,xo)
|
|
||||||
yo = self.getLabel(yo,label)
|
|
||||||
#
|
|
||||||
# @TODO: Insure this can be finetuned, training size matters for learning. It's not obvious to define upfront
|
|
||||||
#
|
|
||||||
xo = self.split(xo)
|
|
||||||
yo = self.split(yo)
|
|
||||||
p = self.gParameters(xo['train'])
|
|
||||||
has_cov = np.linalg.det(p['cov']) if p else False #-- making sure the matrix is invertible
|
|
||||||
|
|
||||||
if xo['train'] and has_cov :
|
|
||||||
E = 0.001
|
|
||||||
ACCEPTABLE_FSCORE = 0.6
|
|
||||||
fscore = 0
|
|
||||||
#
|
|
||||||
# We need to find an appropriate epsilon for the predictions
|
|
||||||
# The appropriate epsilon is one that yields an f-score [0.5,1[
|
|
||||||
#
|
|
||||||
|
|
||||||
__operf__ = None
|
|
||||||
perf = None
|
|
||||||
for i in range(0,10):
|
|
||||||
Epsilon = E + (2*E*i)
|
|
||||||
|
|
||||||
if p is None :
|
|
||||||
return None
|
|
||||||
#
|
|
||||||
# At this point we've got enough data for the parameters
|
|
||||||
# We should try to fine tune epsilon for better results
|
|
||||||
#
|
|
||||||
|
|
||||||
px = self.gPx(p['mean'],p['cov'],xo['test'],Epsilon)
|
|
||||||
|
|
||||||
|
|
||||||
__operf__ = self.gPerformance(px,yo['test'])
|
|
||||||
print value,__operf__
|
|
||||||
if __operf__['fscore'] == 1 :
|
|
||||||
continue
|
|
||||||
if perf is None :
|
|
||||||
perf = __operf__
|
|
||||||
elif perf['fscore'] < __operf__['fscore'] and __operf__['fscore'] > ACCEPTABLE_FSCORE :
|
|
||||||
perf = __operf__
|
|
||||||
perf['epsilon'] = Epsilon
|
|
||||||
#
|
|
||||||
# At this point we are assuming we came out of the whole thing with an acceptable performance
|
|
||||||
# The understanding is that error drives performance thus we reject fscore==1
|
|
||||||
#
|
|
||||||
|
|
||||||
if perf and perf['fscore'] > ACCEPTABLE_FSCORE :
|
|
||||||
return {"label":value,"parameters":p,"performance":perf}
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
return None
|
|
||||||
"""
|
|
||||||
This function determines if the preconditions for learning are met
|
|
||||||
For that parameters are passed to the function
|
|
||||||
p
|
|
||||||
"""
|
|
||||||
def canLearn(self,p) :
|
|
||||||
pass
|
|
||||||
def getLabel(self,yo,label_conf):
|
|
||||||
return [ int(len(set(item) & set(label_conf["1"]))>0) for item in yo ]
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
This function will compute the probability density function given a particular event/set of events
|
|
||||||
The return value is [px,yo]
|
|
||||||
@pre xu.shape[0] == sigma[0] == sigma[1]
|
|
||||||
"""
|
|
||||||
def gPx(self,xu,sigma,data,EPSILON=0.01):
|
|
||||||
n = len(data[0])
|
|
||||||
|
|
||||||
r = []
|
|
||||||
a = (2*(np.pi)**(n/2))*np.linalg.det(sigma)**0.5
|
|
||||||
# EPSILON = np.float64(EPSILON)
|
|
||||||
test = np.array(data)
|
|
||||||
for row in test:
|
|
||||||
row = np.array(row)
|
|
||||||
d = np.matrix(row - xu)
|
|
||||||
d.shape = (n,1)
|
|
||||||
|
|
||||||
b = np.exp((-0.5*np.transpose(d)) * (np.linalg.inv(sigma)*d))
|
|
||||||
|
|
||||||
px = float(b/a)
|
|
||||||
r.append([px,int(px < EPSILON)])
|
|
||||||
return r
|
|
||||||
"""
|
|
||||||
This function uses stored learnt information to predict on raw data
|
|
||||||
In this case it will determin if we have an anomaly or not
|
|
||||||
@param xo raw observations (matrix)
|
|
||||||
@param info stored information about this
|
|
||||||
"""
|
|
||||||
def predict(self,xo,info):
|
|
||||||
|
|
||||||
xo = ML.Extract(info['features'],xo)
|
|
||||||
|
|
||||||
if not xo :
|
|
||||||
return None
|
|
||||||
|
|
||||||
sigma = info['parameters']['cov']
|
|
||||||
xu = info['parameters']['mean']
|
|
||||||
epsilon = info['performance']['epsilon']
|
|
||||||
|
|
||||||
return self.gPx(xu,sigma,xo,epsilon)
|
|
||||||
"""
|
|
||||||
This function computes performance metrics i.e precision, recall and f-score
|
|
||||||
for details visit https://en.wikipedia.org/wiki/Precision_and_recall
|
|
||||||
|
|
||||||
"""
|
|
||||||
def gPerformance(self,test,labels) :
|
|
||||||
N = len(test)
|
|
||||||
tp = 0 # true positive
|
|
||||||
fp = 0 # false positive
|
|
||||||
fn = 0 # false negative
|
|
||||||
tn = 0 # true negative
|
|
||||||
for i in range(0,N):
|
|
||||||
tp += 1 if (test[i][1]==labels[i] and test[i][1] == 1) else 0
|
|
||||||
fp += 1 if (test[i][1] != labels[i] and test[i][1] == 1) else 0
|
|
||||||
fn += 1 if (test[i][1] != labels[i] and test[i][1] == 0) else 0
|
|
||||||
tn += 1 if (test[i][1] == labels[i] and test[i][1] == 0) else 0
|
|
||||||
precision = tp /( (tp + fp) if tp + fp > 0 else 1)
|
|
||||||
recall = tp / ((tp + fn) if tp + fn > 0 else 1)
|
|
||||||
|
|
||||||
fscore = (2 * precision * recall)/ ((precision + recall) if (precision + recall) > 0 else 1)
|
|
||||||
return {"precision":precision,"recall":recall,"fscore":fscore}
|
|
||||||
|
|
||||||
"""
|
|
||||||
This function returns gaussian parameters i.e means and covariance
|
|
||||||
The information will be used to compute probabilities
|
|
||||||
"""
|
|
||||||
def gParameters(self,train) :
|
|
||||||
|
|
||||||
n = len(train[0])
|
|
||||||
m = np.transpose(np.array(train))
|
|
||||||
|
|
||||||
u = np.array([ np.mean(m[i][:]) for i in range(0,n)])
|
|
||||||
if np.sum(u) == 0:
|
|
||||||
return None
|
|
||||||
r = np.array([ np.sqrt(np.var(m[i,:])) for i in range(0,n)])
|
|
||||||
#
|
|
||||||
# Before we normalize the data we must insure there's is some level of movement in this application
|
|
||||||
# A lack of movement suggests we may not bave enough information to do anything
|
|
||||||
#
|
|
||||||
if 0 in r :
|
|
||||||
return None
|
|
||||||
#
|
|
||||||
#-- Normalizing the matrix then we will compute covariance matrix
|
|
||||||
#
|
|
||||||
|
|
||||||
m = np.array([ (m[i,:] - u[i])/r[i] for i in range(0,n)])
|
|
||||||
sigma = np.cov(m)
|
|
||||||
sigma = [ list(row) for row in sigma]
|
|
||||||
return {"cov":sigma,"mean":list(u)}
|
|
||||||
|
|
||||||
class AnalyzeAnomaly(AnomalyDetection):
|
|
||||||
def __init__(self):
|
|
||||||
AnomalyDetection.__init__(self)
|
|
||||||
"""
|
|
||||||
This analysis function will include a predicted status because an anomaly can either be
|
|
||||||
- A downtime i.e end of day
|
|
||||||
- A spike and thus a potential imminent crash
|
|
||||||
@param xo matrix of variables
|
|
||||||
@param info information about what was learnt
|
|
||||||
"""
|
|
||||||
def predict(self,xo,info):
|
|
||||||
x = xo[len(xo)-1]
|
|
||||||
r = AnomalyDetection.predict(self,[x],info)
|
|
||||||
#
|
|
||||||
# In order to determine what the anomaly is we compute the slope (idle or crash)
|
|
||||||
# The slope is computed using the covariance / variance of features
|
|
||||||
#
|
|
||||||
if r is not None:
|
|
||||||
N = len(info['features'])
|
|
||||||
xy = ML.Extract(info['features'],xo)
|
|
||||||
xy = np.array(xy)
|
|
||||||
|
|
||||||
vxy= np.array([ np.var(xy[:,i]) for i in range(0,N)])
|
|
||||||
cxy=np.array(info['parameters']['cov'])
|
|
||||||
#cxy=np.cov(np.transpose(xy))
|
|
||||||
if np.sum(vxy) == 0:
|
|
||||||
vxy = cxy
|
|
||||||
|
|
||||||
alpha = cxy/vxy
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
r = {"anomaly":r[0][1],"slope":list(alpha[:,0])}
|
|
||||||
|
|
||||||
return r
|
|
||||||
class Regression:
|
|
||||||
parameters = {}
|
|
||||||
@staticmethod
|
|
||||||
def predict(xo):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __init__(self,config):
|
|
||||||
pass
|
|
@ -1,266 +0,0 @@
|
|||||||
#import multiprocessing
|
|
||||||
from threading import Thread, RLock
|
|
||||||
#from utils import transport
|
|
||||||
from utils.transport import *
|
|
||||||
from utils.ml import AnomalyDetection,ML
|
|
||||||
import time
|
|
||||||
import monitor
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import datetime
|
|
||||||
class BasicWorker(Thread):
|
|
||||||
def __init__(self,config,lock):
|
|
||||||
Thread.__init__(self)
|
|
||||||
self.reader_class = config['store']['class']['read']
|
|
||||||
self.write_class = config['store']['class']['write']
|
|
||||||
self.rw_args = config['store']['args']
|
|
||||||
self.factory = DataSourceFactory()
|
|
||||||
self.lock = lock
|
|
||||||
|
|
||||||
"""
|
|
||||||
This class is intended to collect data given a configuration
|
|
||||||
|
|
||||||
"""
|
|
||||||
class Top(Thread):
|
|
||||||
def __init__(self,_config,lock):
|
|
||||||
Thread.__init__(self)
|
|
||||||
self.lock = lock
|
|
||||||
self.reader_class = _config['store']['class']['read']
|
|
||||||
self.write_class = _config['store']['class']['write']
|
|
||||||
self.rw_args = _config['store']['args']
|
|
||||||
self.factory = DataSourceFactory()
|
|
||||||
|
|
||||||
self.name = 'Zulu-Top'
|
|
||||||
self.quit = False
|
|
||||||
|
|
||||||
|
|
||||||
className = ''.join(['monitor.',_config['monitor']['processes']['class'],'()'])
|
|
||||||
self.handler = eval(className)
|
|
||||||
self.config = _config['monitor']['processes']['config']
|
|
||||||
def stop(self):
|
|
||||||
self.quit = True
|
|
||||||
def run(self):
|
|
||||||
while self.quit == False:
|
|
||||||
print ' ** ',self.name,datetime.datetime.today()
|
|
||||||
for label in self.config :
|
|
||||||
self.lock.acquire()
|
|
||||||
gwriter = self.factory.instance(type=self.write_class,args=self.rw_args)
|
|
||||||
apps = self.config[label]
|
|
||||||
self.handler.init(apps)
|
|
||||||
r = self.handler.composite()
|
|
||||||
|
|
||||||
gwriter.write(label=label,row=r)
|
|
||||||
time.sleep(5)
|
|
||||||
self.lock.release()
|
|
||||||
if 'MONITOR_CONFIG_PATH' in os.environ:
|
|
||||||
#
|
|
||||||
# This suggests we are in development mode
|
|
||||||
#
|
|
||||||
break
|
|
||||||
ELLAPSED_TIME = 60*20
|
|
||||||
time.sleep(ELLAPSED_TIME)
|
|
||||||
print "Exiting ",self.name
|
|
||||||
|
|
||||||
class Learner(Thread) :
|
|
||||||
|
|
||||||
"""
|
|
||||||
This function expects paltform config (store,learner)
|
|
||||||
It will leverage store and learner in order to operate
|
|
||||||
"""
|
|
||||||
def __init__(self,config,lock):
|
|
||||||
Thread.__init__(self)
|
|
||||||
self.name = 'Zulu-Learner'
|
|
||||||
self.lock = lock
|
|
||||||
self.reader_class = config['store']['class']['read']
|
|
||||||
self.write_class = config['store']['class']['write']
|
|
||||||
self.rw_args = config['store']['args']
|
|
||||||
self.features = config['learner']['anomalies']['features']
|
|
||||||
self.yo = config['learner']['anomalies']['label']
|
|
||||||
self.apps = config['learner']['anomalies']['apps']
|
|
||||||
self.factory = DataSourceFactory()
|
|
||||||
self.quit = False
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
self.quit = True
|
|
||||||
"""
|
|
||||||
This function will initiate learning every (x-hour)
|
|
||||||
If there is nothing to learn the app will simply go to sleep
|
|
||||||
"""
|
|
||||||
def run(self):
|
|
||||||
reader = self.factory.instance(type=self.reader_class,args=self.rw_args)
|
|
||||||
data = reader.read()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Let's make sure we extract that which has aleady been learnt
|
|
||||||
#
|
|
||||||
|
|
||||||
if 'learn' in data:
|
|
||||||
r = data['learn']
|
|
||||||
del data['learn']
|
|
||||||
|
|
||||||
r = ML.Extract('label',r)
|
|
||||||
logs = [row[0] for row in r]
|
|
||||||
logs = list(set(logs))
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
|
||||||
logs = []
|
|
||||||
#
|
|
||||||
# In order to address the inefficiencies below, we chose to adopt the following policy
|
|
||||||
# We don't learn that which is already learnt, This measure consists in filtering out the list of the apps that already have learning data
|
|
||||||
#
|
|
||||||
self.apps = list(set(self.apps) - set(logs))
|
|
||||||
while self.quit == False:
|
|
||||||
r = {}
|
|
||||||
lapps = list(self.apps)
|
|
||||||
print ' ** ',self.name,datetime.datetime.today()
|
|
||||||
for key in data :
|
|
||||||
logs = data[key]
|
|
||||||
#
|
|
||||||
# There poor design at this point, we need to make sure things tested don't get tested again
|
|
||||||
# This creates innefficiencies (cartesian product)
|
|
||||||
#
|
|
||||||
for app in lapps:
|
|
||||||
handler = AnomalyDetection()
|
|
||||||
value = handler.learn(logs,'label',app,self.features,self.yo)
|
|
||||||
|
|
||||||
if value is not None:
|
|
||||||
|
|
||||||
if key not in r:
|
|
||||||
r[key] = {}
|
|
||||||
r[key][app] = value
|
|
||||||
i = lapps.index(app)
|
|
||||||
del lapps[i]
|
|
||||||
#
|
|
||||||
# This offers a clean write to the data store upon value retrieved
|
|
||||||
# The removal of the application enables us to improve efficiency (among other things)
|
|
||||||
#
|
|
||||||
value = dict(value,**{"features":self.features})
|
|
||||||
self.lock.acquire()
|
|
||||||
writer = self.factory.instance(type=self.write_class,args=self.rw_args)
|
|
||||||
writer.write(label='learn',row=value)
|
|
||||||
self.lock.release()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Usually this is used for development
|
|
||||||
# @TODO : Remove this and find a healthy way to stop the server
|
|
||||||
#
|
|
||||||
if 'MONITOR_CONFIG_PATH' in os.environ:
|
|
||||||
#
|
|
||||||
# This suggests we are in development mode
|
|
||||||
#
|
|
||||||
break
|
|
||||||
|
|
||||||
TIME_ELLAPSED = 60*120 #-- Every 2 hours
|
|
||||||
time.sleep(TIME_ELLAPSED)
|
|
||||||
print "Exiting ",self.name
|
|
||||||
|
|
||||||
class FileWatchWorker(BasicWorker):
|
|
||||||
def __init__(self,config,lock):
|
|
||||||
BasicWorker.__init__(self,config,lock)
|
|
||||||
self.name = "Zulu-FileWatch"
|
|
||||||
self.config = config ;
|
|
||||||
self.folder_config = config['monitor']['folders']['config']
|
|
||||||
self.quit = False
|
|
||||||
def stop(self):
|
|
||||||
self.quit = True
|
|
||||||
def run(self):
|
|
||||||
TIME_ELAPSED = 60 * 10
|
|
||||||
handler = monitor.FileWatch()
|
|
||||||
ml_handler = ML()
|
|
||||||
while self.quit == False :
|
|
||||||
r = []
|
|
||||||
print ' ** ',self.name,datetime.datetime.today()
|
|
||||||
for id in self.folder_config :
|
|
||||||
folders = self.folder_config [id]
|
|
||||||
handler.init(folders)
|
|
||||||
xo = handler.composite()
|
|
||||||
#
|
|
||||||
# We should perform a distribution analysis of the details in order to have usable data
|
|
||||||
#
|
|
||||||
xrow = {}
|
|
||||||
xrow[id] = []
|
|
||||||
for xo_row in xo:
|
|
||||||
xo_age = [row['age'] for row in xo_row['details']]
|
|
||||||
xo_size= [row['size'] for row in xo_row['details']]
|
|
||||||
xo_row['details'] = {"age":ML.distribution(xo_age,self.lock),"size":ML.distribution(xo_size,self.lock)}
|
|
||||||
|
|
||||||
xo_row['id'] = id
|
|
||||||
xrow[id].append(xo_row)
|
|
||||||
#
|
|
||||||
# Now we can save the file
|
|
||||||
#
|
|
||||||
self.lock.acquire()
|
|
||||||
writer = self.factory.instance(type=self.write_class,args=self.rw_args)
|
|
||||||
writer.write(label='folders',row=xrow)
|
|
||||||
self.lock.release()
|
|
||||||
if 'MONITOR_CONFIG_PATH' in os.environ:
|
|
||||||
#
|
|
||||||
# This suggests we are in development mode
|
|
||||||
#
|
|
||||||
break
|
|
||||||
time.sleep(TIME_ELAPSED)
|
|
||||||
print 'Exiting ',self.name
|
|
||||||
|
|
||||||
"""
|
|
||||||
This class is a singleton designed to start quit dependent threads
|
|
||||||
* monitor is designed to act as a data collection agent
|
|
||||||
* learner is designed to be a learner i.e machine learning model(s)
|
|
||||||
@TODO:
|
|
||||||
- How to move them to processes that can be read by the os (that would allow us to eat our own dog-food)
|
|
||||||
- Additionally we also need to have a pruning thread, to control the volume of data we have to deal with.This instills the "will to live" in the application
|
|
||||||
"""
|
|
||||||
class ThreadManager:
|
|
||||||
|
|
||||||
Pool = {}
|
|
||||||
@staticmethod
|
|
||||||
def start(config):
|
|
||||||
lock = RLock()
|
|
||||||
ThreadManager.Pool['monitor'] = Top(config,lock)
|
|
||||||
ThreadManager.Pool['learner'] = Learner(config,lock)
|
|
||||||
if 'folders' not in config :
|
|
||||||
ThreadManager.Pool['file-watch'] = FileWatchWorker(config,lock)
|
|
||||||
for id in ThreadManager.Pool :
|
|
||||||
thread = ThreadManager.Pool[id]
|
|
||||||
thread.start()
|
|
||||||
@staticmethod
|
|
||||||
def stop():
|
|
||||||
for id in ThreadManager.Pool :
|
|
||||||
thread = ThreadManager.Pool[id]
|
|
||||||
thread.stop()
|
|
||||||
@staticmethod
|
|
||||||
def status():
|
|
||||||
r = {}
|
|
||||||
for id in ThreadManager.Pool :
|
|
||||||
thread = ThreadManager.Pool[id]
|
|
||||||
r[id] = thread.isAlive()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Factory :
|
|
||||||
"""
|
|
||||||
This function will return an instance of an object in the specified in the configuration file
|
|
||||||
"""
|
|
||||||
@staticmethod
|
|
||||||
def instance(id,config):
|
|
||||||
if id in config['monitor'] :
|
|
||||||
className = config['monitor'][id]['class']
|
|
||||||
ref = "".join(["monitor.",className,"()"])
|
|
||||||
ref = eval(ref)
|
|
||||||
return {"class":ref,"config":config['monitor'][id]["config"]}
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ =='__main__' :
|
|
||||||
import utils.params as SYS_ARGS
|
|
||||||
import json
|
|
||||||
PARAMS = SYS_ARGS.PARAMS
|
|
||||||
f = open(PARAMS['path'])
|
|
||||||
CONFIG = json.loads(f.read())
|
|
||||||
f.close()
|
|
||||||
ThreadManager.start(CONFIG)
|
|
||||||
|
|
Loading…
Reference in new issue