trends powered by chart.js

master
Steve L. Nyemba 8 years ago
parent fd05da326d
commit eb8f6596e6

BIN
src/.DS_Store vendored

Binary file not shown.

BIN
src/api/.DS_Store vendored

Binary file not shown.

@ -65,7 +65,7 @@ mthread.start()
@app.route('/get/<id>') @app.route('/get/<id>')
def procs(id): def procs(id):
if id in HANDLERS and len(mthread.logs)>0: if id in HANDLERS and len(mthread.logs)>0:
r = ProcessQueue.get(block=True,timeout=15) # r = ProcessQueue.get(block=True,timeout=15)
index = len(mthread.logs) -1 index = len(mthread.logs) -1
r = mthread.logs[index] r = mthread.logs[index]
return json.dumps(r) return json.dumps(r)
@ -75,10 +75,11 @@ def procs(id):
@app.route('/trends') @app.route('/trends')
def trends (): def trends ():
id = request.args.get('id') id = request.args.get('id')
# key = request.args.get('key')
handler = monitor.mapreducer() handler = monitor.mapreducer()
r = handler.filter(id,mthread.logs) r = handler.filter(id,mthread.logs)
r = handler.run(r,handler.mapper,None) r = handler.run(r,handler.mapper,handler.reducer)
print [" **** ",len(r)]
return json.dumps(r) return json.dumps(r)
@app.route('/dashboard') @app.route('/dashboard')
def dashboard(): def dashboard():

Binary file not shown.

@ -58,3 +58,14 @@ input[type=text]{
input[type=text]:focus{ input[type=text]:focus{
border-left-color:#4682B4; border-left-color:#4682B4;
} }
.padding-2x{padding:4px;}
.margin-2x {margin:4px;}
.info {
padding:4px;
margin:4px;
width:40%;
height:300px;
}
.height-quarter{height:25%;}
.width-half {width:47%; }

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -17,14 +17,16 @@ monitor.processes.init = function(x){
var i = jx.dom.get.instance('I') var i = jx.dom.get.instance('I')
i.className = 'fa fa-chevron-right left' i.className = 'fa fa-chevron-right left'
div.innerHTML = label div.innerHTML = label
frame.data = r[label]
frame.data = r[label] frame.label = label
frame.label= label
frame.appendChild(i) frame.appendChild(i)
frame.appendChild(div) frame.appendChild(div)
frame.className = 'menu-item' frame.className = 'menu-item'
frame.onclick = function(){ monitor.processes.render(this.label,this.data)} frame.onclick = function () {
monitor.processes.render(this.label, this.data);
monitor.processes.trend.init(this.label)
}
jx.dom.append('menu',frame) jx.dom.append('menu',frame)
}) })
} }
@ -56,3 +58,70 @@ monitor.processes.render = function(label,data) {
} }
monitor.processes.trend = {}
monitor.processes.trend.init = function (label) {
var httpclient = HttpClient.instance()
var uri = '/trends?id='+label
httpclient.get(uri, function (x) {
var logs = JSON.parse(x.responseText)
// jx.dom.set.attribute(label,'logs',logs)
monitor.processes.trend.render(logs)
})
}
monitor.processes.trend.render = function (logs, key) {
if (key == null) {
key = 'memory_usage'
}
var context = $('#trends_chart')
var conf = { type: 'line' }
conf.data = {}
conf.options = { legend: { position: 'bottom' } }
conf.options.scales = {}
conf.options.scales.yAxes = [{ title: {display:true,text:key},gridLines: {display:false}}]
conf.options.scales.xAxes = [
{
type: 'time',
gridLines: {display:false},
time: {
format:'dd-MMM HH:mm'
}
}
]
// conf.data.labels = x_axis
var p = jx.utils.keys(logs)
conf.data.datasets = [ ]
var labels = []
var i = 0;
for (id in logs) {
var serie = {}
serie.label = id
serie.data = jx.utils.patterns.visitor(logs[id], function (item) {
// x = parseFloat(item['hour'] + '.' + item['minute']).toFixed(2)
x = new Date(item.year,item.month-1,item.day,item.hour,item.minute)
y = item[key]
labels.push(x)
console.log([item.day,item.hour,item.minute])
return {x:x,y:y}
})
serie.backgroundColor = ['transparent']
serie.borderColor = COLORS[i]
serie.borderWidth = 1
++i
conf.data.datasets.push(serie)
}
console.log(labels)
labels = jx.utils.unique(labels)
conf.data.labels = labels
// console.log(conf)
var chart = new Chart(context,conf)
}

@ -7,12 +7,13 @@
<link href="{{context}}/static/css/fa/css/font-awesome.min.css" rel="stylesheet" type="text/css"> <link href="{{context}}/static/css/fa/css/font-awesome.min.css" rel="stylesheet" type="text/css">
<script src="{{ context }}/static/js/jquery/jquery.min.js"></script> <script src="{{ context }}/static/js/jquery/jquery.min.js"></script>
<script src="{{context}}/static/js/chart.js/chart.bundle.js"></script>
<script src="{{context}}/static/js/jx/rpc.js"></script> <script src="{{context}}/static/js/jx/rpc.js"></script>
<script src="{{context}}/static/js/jx/dom.js"></script> <script src="{{context}}/static/js/jx/dom.js"></script>
<script src="{{context}}/static/js/jx/utils.js"></script> <script src="{{context}}/static/js/jx/utils.js"></script>
<script src="{{ context }}/static/js/jsgrid/jsgrid.js"></script> <script src="{{ context }}/static/js/jsgrid/jsgrid.js"></script>
<script src="{{context}}/static/js/colors.js"></script>
<script src="{{context}}/static/js/dashboard.js"></script> <script src="{{context}}/static/js/dashboard.js"></script>
<title>iMonitor</title> <title>iMonitor</title>
<script> <script>
@ -25,16 +26,29 @@
<div class="left">Monitoring</div> <div class="left">Monitoring</div>
<div class="right">Trends</div> <div class="right">Trends</div>
</div> </div>
<div class="left small border"> <div class="left small" style="width:15%">
<div><input id="find_scope" type="text" placeholder="Find Context"></div> <div><input id="find_scope" type="text" placeholder="Find Context"></div>
<div id="menu" class="menu"></div> <div id="menu" class="menu"></div>
</div> </div>
<div class="left height-quarter"> <div class="left info border">
<div class="grid">
<div class="small" style="text-transform:capitalize">Monitoring <span id="latest_processes_label"></span></div> <div class="small" style="text-transform:capitalize">Monitoring <span id="latest_processes_label"></span></div>
<div id="latest_processes" class="small"></div> <div id="latest_processes" class="grid small"></div>
</div>
</div> </div>
<div class="left info border">
<div class="small">History of Processes <span id="trend_info"></span>
</div>
<div class="menu">
<div class="left menu-item small padding-2x margin-2x"><i class="fa fa-chevron-right"></i> CPU used</div>
<div class="left menu-item small padding-2x margin-2x"><i class="fa fa-chevron-right"></i> Mem. Used</div>
<div class="left menu-item small padding-2x margin-2x"><i class="fa fa-chevron-right"></i> Mem. Avail</div>
</div>
<canvas id="trends_chart" class="small grid">
</canvas>
</div>
</body> </body>

@ -22,7 +22,7 @@ class Analysis:
self.logs.append(object) self.logs.append(object)
def init(self): def init(self):
d = datetime.datetime.now() d = datetime.datetime.now()
self.now = {"month":d.month,"year":d.year, "day":d.day,"hour":d.hour} self.now = {"month":d.month,"year":d.year, "day":d.day,"hour":d.hour,"minute":d.minute}
""" """
This class is designed to analyze environment variables. Environment variables can either be folders, files or simple values This class is designed to analyze environment variables. Environment variables can either be folders, files or simple values
The class returns a quantifiable assessment of the environment variables (expected 100%) The class returns a quantifiable assessment of the environment variables (expected 100%)
@ -57,6 +57,7 @@ class Env(Analysis):
return 0 return 0
def composite (self): def composite (self):
Analysis.init(self)
r = [ self.evaluate(id) for id in self.values] ; r = [ self.evaluate(id) for id in self.values] ;
N = len(r) N = len(r)
n = sum(r) n = sum(r)
@ -90,6 +91,7 @@ class Sandbox(Analysis):
This function returns the ratio of existing modules relative to the ones expected This function returns the ratio of existing modules relative to the ones expected
""" """
def composite(self): def composite(self):
Analysis.init(self)
required_modules= self.get_requirements() required_modules= self.get_requirements()
sandbox_modules = self.get_sandbox_requirements() sandbox_modules = self.get_sandbox_requirements()
N = len(required_modules) N = len(required_modules)
@ -115,6 +117,7 @@ class ProcessCounter(Analysis):
return int(handler.communicate()[0].replace("\n","") ) return int(handler.communicate()[0].replace("\n","") )
def composite(self): def composite(self):
Analysis.init(self)
r = {} r = {}
for name in self.names : for name in self.names :
r[name] = self.evaluate(name) r[name] = self.evaluate(name)
@ -168,11 +171,14 @@ class DetailProcess(Analysis):
else: else:
return "crash" return "crash"
def format(self,row): def format(self,row):
r= {"memory_usage":row[0],"cpu_usage":row[1],"memory_available":row[2]/1000,"label":row[3]} r= {"memory_usage":row[0],"cpu_usage":row[1],"memory_available":row[2]/1000,"label":row[3]}
status = self.status(r) status = self.status(r)
r['status'] = status r['status'] = status
return dict(self.now,**r) return dict(self.now,**r)
def composite(self): def composite(self):
Analysis.init(self)
print ' **** ',self.now
#value = self.evaluate(self.name) #value = self.evaluate(self.name)
#row= {"memory_usage":value[0],"cpu_usage":value[1]} #row= {"memory_usage":value[0],"cpu_usage":value[1]}
#return row #return row
@ -209,8 +215,8 @@ class Monitor (Thread):
self.queue.put(r) self.queue.put(r)
self.prune() self.prune()
self.queue.task_done() self.queue.task_done()
HALF_HOUR = 60*15
time.sleep(10) time.sleep(HALF_HOUR)
def prune(self) : def prune(self) :
MAX_ENTRIES = 1000 MAX_ENTRIES = 1000
if len(self.logs) > MAX_ENTRIES : if len(self.logs) > MAX_ENTRIES :
@ -230,14 +236,20 @@ class mapreducer:
if reducer is not None: if reducer is not None:
r = [reducer(self.store[key]) for key in self.store] r = {}
for key in self.store:
beg = len(self.store[key]) - 101 if len(self.store[key]) > 100 else 0
end = beg + 100
r[key] = self.store[key][beg:end]
# r = [reducer(self.store[key]) for key in self.store]
else: else:
r = self.store r = self.store
return r return r
def mapper(self,row,emit): def mapper(self,row,emit):
[emit(item['label'],item) for item in row ] [emit(_matrix['label'],_matrix) for _matrix in row ]
def reducer(self,values): def reducer(self,values):
return value beg = len(values)-101 if len(values) > 100 else 0
return values[beg:]
def emit(self,key,content): def emit(self,key,content):
if key not in self.store: if key not in self.store:

Loading…
Cancel
Save