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>')
def procs(id):
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
r = mthread.logs[index]
return json.dumps(r)
@ -75,10 +75,11 @@ def procs(id):
@app.route('/trends')
def trends ():
id = request.args.get('id')
# key = request.args.get('key')
handler = monitor.mapreducer()
r = handler.filter(id,mthread.logs)
r = handler.run(r,handler.mapper,None)
print [" **** ",len(r)]
r = handler.run(r,handler.mapper,handler.reducer)
return json.dumps(r)
@app.route('/dashboard')
def dashboard():

Binary file not shown.

@ -58,3 +58,14 @@ input[type=text]{
input[type=text]:focus{
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')
i.className = 'fa fa-chevron-right left'
div.innerHTML = label
frame.data = r[label]
frame.label= label
div.innerHTML = label
frame.data = r[label]
frame.label = label
frame.appendChild(i)
frame.appendChild(div)
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)
})
}
@ -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">
<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/dom.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/colors.js"></script>
<script src="{{context}}/static/js/dashboard.js"></script>
<title>iMonitor</title>
<script>
@ -25,16 +26,29 @@
<div class="left">Monitoring</div>
<div class="right">Trends</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 id="menu" class="menu"></div>
</div>
<div class="left height-quarter">
<div class="grid">
<div class="left info border">
<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 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>

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

Loading…
Cancel
Save