Browse Source

resolution picker

raylu 11 years ago
parent
commit
ba6c2266bc
5 changed files with 70 additions and 23 deletions
  1. 16 2
      api/server.py
  2. 5 1
      web/static/css/stats.ccss
  3. 36 18
      web/static/js/stats.js
  4. 1 1
      web/templates/base.html
  5. 12 1
      web/templates/stats.html

+ 16 - 2
api/server.py

@@ -111,15 +111,29 @@ def get_raw(split, query, environ):
 		c += datetime.timedelta(days=1)
 	return rval
 
+fields = {
+	'cpu': ['user', 'iowait', 'system', 'nice', 'guest', 'guest_nice', 'irq', 'softirq', 'steal', 'idle'],
+	'mem': ['used', 'buffers', 'cached', 'free'],
+	'net': ['bit/s_in', 'bit/s_out', 'err_in', 'err_out', 'drop_in', 'drop_out'],
+}
 def get_stats(split, query, environ):
-	raw = get_raw(split, query, environ)
 	try:
 		interval = int(query.get('interval', 1))
 	except ValueError:
 		raise HTTPException(400, 'interval must be integer')
+	raw = get_raw(split, query, environ)
+	dates = raw.keys()
+	dates.sort()
 	last_val = fileio.gen_template(-1)
 	stats = defaultdict(dict)
-	for date, data in raw.items():
+	for date in dates:
+		data = raw[date]
+		if data is None:
+			for field, subfields in fields.iteritems():
+				for subfield in subfields:
+					stats[field].setdefault(subfield, {})
+					stats[field][subfield][date] = [None] * (1440 / interval)
+			continue
 		for field, subfields in data.items():
 			if field == 'cpu':
 				field_data = {}

+ 5 - 1
web/static/css/stats.ccss

@@ -1,2 +1,6 @@
-#graphs > div:
+.graph_container:
 	display: inline-block
+
+	.rickshaw_graph, .rickshaw_legend:
+		display: inline-block
+		vertical-align: middle

+ 36 - 18
web/static/js/stats.js

@@ -40,19 +40,35 @@ window.addEvent('domready', function() {
 
 	var split = document.location.pathname.split('/');
 	var url = 'http://localhost:8892/v1/' + split[2] + '/stats/' + split[3];
-	var interval = 30;
-	new Request.JSON({
-		'url': url + '?start=2014-04-19&end=2014-04-20&interval=' + interval,
-		'onSuccess': graph_stats,
-	}).get();
+	function get_stats(start, end, interval) {
+		new Request.JSON({
+			'url': url + '?start=' + start + '&end=' + end + '&interval=' + interval,
+			'onSuccess': function(data) {
+				Object.each(data, function(subfields, field) {
+					if (field == 'disk')
+						return;
+					graph_stat(field, subfields, interval);
+				});
+			},
+		}).get();
+	}
 
-	function graph_stats(data) {
-		Object.each(data, function(subfields, field) {
-			if (field == 'disk')
-				return;
-			graph_stat(field, subfields);
-		});
+	var intervals = {
+		1: 15,
+		7: 60,
+		month: 1440,
+	}
+	function change_res() {
+		var days = $('resolution').get('value');
+		if (days == 'month')
+			var start = moment.utc().subtract('months', 1).format('YYYY-MM-DD');
+		else
+			var start = moment.utc().subtract('days', days - 1).format('YYYY-MM-DD');
+		var end = moment.utc().format('YYYY-MM-DD');
+		get_stats(start, end, intervals[days]);
 	}
+	$('resolution').addEvent('change', change_res);
+	change_res();
 
 	var colors = {
 		'cpu': [
@@ -82,20 +98,22 @@ window.addEvent('domready', function() {
 			['drop_out', '#aa3', 'line'],
 		],
 	};
-	function graph_stat(field, subfields) {
+	function graph_stat(field, subfields, interval) {
 		var series = [];
 		colors[field].each(function(subfield_meta) {
 			var subfield = subfield_meta[0];
 			var color = subfield_meta[1];
+			var days = Object.keys(subfields[subfield]).sort();
 			var array = [];
 			var index_start = 0;
-			Object.each(subfields[subfield], function(day_array, k) {
+			days.each(function(day) {
+				var day_array = subfields[subfield][day];
 				if (day_array != null) {
 					array = array.append(day_array.map(function(val, i) {
-						return {'x': index_start + i, 'y': val};
+						return {'x': index_start + i * interval, 'y': val};
 					}));
 				}
-				index_start += 1440 / interval;
+				index_start += 1440;
 			});
 			series.push({
 				'name': field + '.' + subfield,
@@ -108,7 +126,7 @@ window.addEvent('domready', function() {
 		var legend_div = new Element('div');
 		var graph = new Rickshaw.Graph({
 			'element': graph_div,
-			'width': 500,
+			'width': 400,
 			'height': 200,
 			'renderer': field == 'net' ? 'multi' : 'area',
 			'stroke': true,
@@ -124,13 +142,13 @@ window.addEvent('domready', function() {
 		});
 		new Rickshaw.Graph.Axis.Time({
 			'graph': graph,
-			'timeUnit': new Rickshaw.Fixtures.Time().unit('minute'),
+			//'timeUnit': new Rickshaw.Fixtures.Time().unit('minute'),
 		});
 		new Rickshaw.Graph.Axis.Y.Base1024KMGTP({
 			'graph': graph,
 			'tickFormat': Rickshaw.Fixtures.Number.formatBase1024KMGTP,
 		});
 		graph.render();
-		$('graphs').adopt(graph_div, legend_div, new Element('br'));
+		$(field).empty().adopt(graph_div, legend_div);
 	}
 });

+ 1 - 1
web/templates/base.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <head>
-	<title>Sys Vitals</title>
+	<title>sysvitals</title>
 	<link rel="stylesheet" type="text/css" href="/css/base.css" />
 	<script src="//ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools.js"></script>
 	{% block js %}{% end %}

+ 12 - 1
web/templates/stats.html

@@ -3,6 +3,7 @@
 {% block js %}
 	<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.5/d3.js"></script>
 	<script src="//cdnjs.cloudflare.com/ajax/libs/rickshaw/1.4.6/rickshaw.js"></script>
+	<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.6.0/moment.js"></script>
 	<script src="/static/js/stats.js"></script>
 {% end %}
 {% block css %}
@@ -15,5 +16,15 @@
 		<br>
 		<a href="/stats/{{ group_id }}/{{ server['id'] }}">{{ server['hostname'] }}</a>
 	{% end %}
-	<div id="graphs"></div>
+	<p>
+	<select id="resolution">
+		<option value="1" selected>today</option>
+		<option value="7">last 7 days</option>
+		<option value="month">last month</option>
+	</select>
+	</p>
+	{% for i, field in enumerate(['cpu', 'mem', 'net', 'disk']) %}
+		<div id="{{ field }}" class="graph_container"></div>
+		{% if i == 1 %}<br>{% end %}
+	{% end %}
 {% end %}