Steve L. Nyemba 8 лет назад
Родитель
Сommit
eb8f6596e6

BIN
src/api/.DS_Store


+ 4 - 3
src/api/index.py

@@ -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():

BIN
src/api/static/.DS_Store


+ 11 - 0
src/api/static/css/default.css

@@ -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%; }

BIN
src/api/static/js/.DS_Store


BIN
src/api/static/js/chart.js/.DS_Store


Разница между файлами не показана из-за своего большого размера
+ 14868 - 0
src/api/static/js/chart.js/chart.bundle.js


Разница между файлами не показана из-за своего большого размера
+ 2 - 0
src/api/static/js/colors.js


+ 74 - 5
src/api/static/js/dashboard.js

@@ -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)
+
+}

+ 20 - 6
src/api/templates/dashboard.html

@@ -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>
+			<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>

+ 18 - 6
src/monitor.py

@@ -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: