diff options
author | Richard Wall <richard@aziz> | 2010-04-10 14:51:38 +0100 |
---|---|---|
committer | Richard Wall <richard@aziz> | 2010-04-10 14:51:38 +0100 |
commit | 7bda611c65b63b8f9dd1d46033dabb190984f3a9 (patch) | |
tree | fd0167801834a2363dae577ee4f2b59d8a41caeb | |
parent | 4d6175bf99b670d913c4a713014790be673cbff9 (diff) |
Add support for multiple DS data sources and update all charts when a selection is made. Only allow one ongoing rrd download
-rw-r--r-- | index.html | 115 | ||||
-rw-r--r-- | jrrd.js | 90 |
2 files changed, 138 insertions, 67 deletions
@@ -16,7 +16,7 @@ <script type="text/javascript" src="jrrd.js"></script> <script type="text/javascript"> - var graphOptions = { + var baseOptions = { grid: { clickable: true }, @@ -24,12 +24,10 @@ mode: 'x' }, series: { - stack: true, points: { show: false }, lines: { show: true, steps: false, - fill: 0.5, shadowSize: 0, lineWidth: 1 }, @@ -40,71 +38,90 @@ } }; - var Chart = function(template) { - var self = this; + var fillOptions = jQuery.extend(true, { + series: { + stack: true, + lines: { + fill: 0.5 + } + } + }, baseOptions); - this.template = template; - this.data = []; + function cpuChartFactory(template) { + var c = new jrrd.Chart(template, fillOptions); + data = 'cpu-user.rrd cpu-system.rrd cpu-wait.rrd'.split(' ').reverse(); - this.template.bind('plotclick', function(event, pos, item) { - if (item) { - console.log(['X: ' + new Date(item.datapoint[0]), - 'Y: ' + item.datapoint[1]]); - } + jQuery.each(data, function(i, el) { + var url = 'data/localhost/cpu-0/' + el; + var label = el.split('.')[0].split('-')[1]; + c.addData(label, new jrrd.RrdQueryRemote(url)); }); + return c; + } - this.template.bind("plotselected", function(event, ranges) { - var startTime = new Date(ranges.xaxis.from); - var endTime = new Date(ranges.xaxis.to); - self.draw(startTime, endTime); - console.log("You selected " + startTime + " to " + endTime); + function memoryChartFactory(template) { + var c = new jrrd.Chart(template, fillOptions); + data = 'memory-free.rrd memory-cached.rrd memory-used.rrd memory-buffered.rrd'.split(' ').reverse(); + + jQuery.each(data, function(i, el) { + var url = 'data/localhost/memory/' + el; + var label = el.split('.')[0].split('-')[1]; + c.addData(label, new jrrd.RrdQueryRemote(url)); }); + return c; + } + + var RrdQueryDsProxy = function(rrdQuery, dsId) { + this.rrdQuery = rrdQuery; + this.dsId = dsId; }; - Chart.prototype.addData = function(label, db) { - this.data.push([label, db]); + RrdQueryDsProxy.prototype.getData = function(startTime, endTime) { + return this.rrdQuery.getData(startTime, endTime, this.dsId); }; - Chart.prototype.draw = function(startTime, endTime) { - var self = this; + function loadChartFactory(template) { + var c = new jrrd.Chart(template, baseOptions); + var data = new jrrd.RrdQueryRemote('data/localhost/load/load.rrd'); + var rrdDSs = ['shortterm', 'midterm', 'longterm']; + jQuery.each(rrdDSs, function(i, rrdDS) { + c.addData(rrdDS, new RrdQueryDsProxy(data, rrdDS)); + }); + return c; + } - var results = []; - for(var i=0; i<this.data.length; i++) { - results.push(this.data[i][1].getData(startTime, endTime)); - } + $(function() { + var chartTemplate = $('.chart').remove(); + var charts = [ + loadChartFactory( + chartTemplate.clone().appendTo('.charts')), - return MochiKit.Async.gatherResults(results) - .addCallback( - function(data) { - for(var i=0; i<data.length; i++) { - data[i].label = self.data[i][0]; - } - var plot = $.plot(self.template, data, graphOptions); - }) - .addErrback( - function(failure) { - $('.container').text('error: ' + failure.message); - }); - }; + cpuChartFactory( + chartTemplate.clone().appendTo('.charts')), - $(function() { - var c = new Chart($('.container')); - //data = 'memory-free.rrd memory-cached.rrd memory-used.rrd memory-buffered.rrd'.split(' ').reverse(); - data = 'cpu-user.rrd cpu-system.rrd cpu-wait.rrd'.split(' ').reverse(); + memoryChartFactory( + chartTemplate.clone().appendTo('.charts')) + ]; - jQuery.each(data, function(i, el) { - var url = 'data/localhost/cpu-0/' + el; - var label = el.split('.')[0].split('-')[1]; - c.addData(label, new jrrd.RrdQueryRemote(url)); + jQuery.each(charts, function(i, chart) { + chart.draw(new Date('7 April 2010 09:30:00'), + new Date('7 April 2010 15:00:00')); }); - c.draw(new Date('7 April 2010 09:30:00'), - new Date('7 April 2010 15:00:00')); + $('.chart').bind("plotselected", function(event, ranges) { + var startTime = new Date(ranges.xaxis.from); + var endTime = new Date(ranges.xaxis.to); + jQuery.each(charts, function(i, chart) { + chart.draw(startTime, endTime); + }); + }); }); </script> </head> <body> - <div class="container" style="width:100%; height:200px;"></div> + <div class="charts"> + <div class="chart" style="width:800px; height:200px; float: right; clear: right;"></div> + </div> </body> </html> @@ -51,7 +51,6 @@ jrrd.RrdQuery.prototype.getData = function(startTime, endTime, dsId) { dsId = 0; } var ds = this.rrd.getDS(dsId); - var consolidationFunc = 'AVERAGE'; var lastUpdated = this.rrd.getLastUpdate(); @@ -77,12 +76,12 @@ jrrd.RrdQuery.prototype.getData = function(startTime, endTime, dsId) { throw new Error('Unrecognised consolidation function: ' + consolidationFunc); } - startRow = rraRowCount - parseInt((lastUpdated - startTimestamp)/step); - endRow = rraRowCount - parseInt((lastUpdated - endTimestamp)/step); + var startRow = rraRowCount - parseInt((lastUpdated - startTimestamp)/step); + var endRow = rraRowCount - parseInt((lastUpdated - endTimestamp)/step); - flotData = []; - timestamp = firstUpdated + (startRow - 1) * step; - dsIndex = ds.getIdx(); + var flotData = []; + var timestamp = firstUpdated + (startRow - 1) * step; + var dsIndex = ds.getIdx(); for (var i=startRow; i<=endRow; i++) { var val = bestRRA.getEl(i, dsIndex); flotData.push([timestamp*1000.0, val]); @@ -94,30 +93,85 @@ jrrd.RrdQuery.prototype.getData = function(startTime, endTime, dsId) { jrrd.RrdQueryRemote = function(url) { this.url = url; - this.rrd = null; + this.lastUpdate = 0; + this._download = null; }; -jrrd.RrdQueryRemote.prototype.getData = function(startTime, endTime) { +jrrd.RrdQueryRemote.prototype.getData = function(startTime, endTime, dsId) { var endTimestamp = endTime.getTime()/1000; - var d, self = this; - if(!this.rrd || this.rrd.getLastUpdate() < endTimestamp) { - d = jrrd.downloadBinary(this.url) + var self = this; + + // Download the rrd if there has never been a download or if the last + // completed download had a lastUpdated timestamp less than the requested + // end time. + // Don't start another download if one is already in progress. + if(!this._download || (this._download.fired > -1 && this.lastUpdate < endTimestamp )) { + this._download = jrrd.downloadBinary(this.url) .addCallback( function(binary) { + // Upon successful download convert the resulting binary + // into an RRD file and pass it on to the next callback + // in the chain. var rrd = new RRDFile(binary); - self.rrd = rrd; + self.lastUpdate = rrd.getLastUpdate(); return rrd; }); - } else { - d = new MochiKit.Async.Deferred() - d.callback(this.rrd); } - d.addCallback( + // Set up a deferred which will call getData on the local RrdQuery object + // returning a flot compatible data object to the caller. + var ret = new MochiKit.Async.Deferred().addCallback( function(rrd) { - return new jrrd.RrdQuery(rrd).getData(startTime, endTime); + return new jrrd.RrdQuery(rrd).getData(startTime, endTime, dsId); }); - return d; + // Add a pair of callbacks to the current download which will callback the + // result which we setup above. + this._download.addCallbacks( + function(res) { + ret.callback(res); + return res; + }, + function(err) { + ret.errback(err); + return err; + }); + + return ret; +}; + + +jrrd.Chart = function(template, options) { + var self = this; + + this.template = template; + this.options = options; + this.data = []; +}; + +jrrd.Chart.prototype.addData = function(label, db) { + this.data.push([label, db]); +}; + +jrrd.Chart.prototype.draw = function(startTime, endTime) { + var self = this; + + var results = []; + for(var i=0; i<this.data.length; i++) { + results.push(this.data[i][1].getData(startTime, endTime)); + } + + return MochiKit.Async.gatherResults(results) + .addCallback( + function(data) { + for(var i=0; i<data.length; i++) { + data[i].label = self.data[i][0]; + } + var plot = $.plot(self.template, data, self.options); + }) + .addErrback( + function(failure) { + self.template.text('error: ' + failure.message); + }); }; |