diff options
-rw-r--r-- | LICENSE | 20 | ||||
-rw-r--r-- | index.html | 72 | ||||
-rw-r--r-- | jrrd.js | 73 |
3 files changed, 133 insertions, 32 deletions
@@ -0,0 +1,20 @@ +Copyright (c) 2010 Richard Wall <richard (at) the-moon.net> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -5,6 +5,14 @@ <title>untitled</title> <meta http-equiv="content-type" content="text/html;charset=utf-8" /> <style type="text/css"> + body { + font-family: sans; + } + + form div { + text-align: center; + } + .chart { width:800px; height:200px; @@ -114,11 +122,47 @@ return c; } + var ChartCoordinator = function(ui) { + this.ui = ui; + this.charts = []; + + var self = this; + this.ui.bind('submit', function(e) { + self.update(); + return false; + }); + + this.ui.bind('reset', function(e) { + self.reset(); + return false; + }); + }; + + ChartCoordinator.prototype.update = function() { + var startTime = new Date(this.ui[0].startTime.value); + var endTime = new Date(this.ui[0].endTime.value); + for(var i=0; i<this.charts.length; i++){ + this.charts[i].draw(startTime, endTime); + } + }; + + ChartCoordinator.prototype.setTimeRange = function(startTime, endTime) { + this.ui[0].startTime.value = startTime.toString().split(' ').slice(1,5).join(' '); + this.ui[0].endTime.value = endTime.toString().split(' ').slice(1,5).join(' ');; + this.update(); + }; + + ChartCoordinator.prototype.reset = function() { + this.setTimeRange(new Date(new Date().getTime()-1*60*60*1000), + new Date()); + }; + $(function() { + var cc = new ChartCoordinator($('.chartRangeControl')); var chartTemplate = $('.chart').remove(); - var charts = [ - dnsChartFactory( - chartTemplate.clone().appendTo('.charts')), + cc.charts = [ + //dnsChartFactory( + // chartTemplate.clone().appendTo('.charts')), loadChartFactory( chartTemplate.clone().appendTo('.charts')), @@ -133,23 +177,25 @@ chartTemplate.clone().appendTo('.charts')) ]; - jQuery.each(charts, function(i, chart) { - chart.draw(new Date('10 April 2010 19:30:00'), - new Date()); - }); + cc.reset(); - $('.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); - }); + $('.charts').bind("plotselected", function(event, ranges) { + cc.setTimeRange(new Date(ranges.xaxis.from), + new Date(ranges.xaxis.to)); }); }); </script> </head> <body> + <form method="GET" class="chartRangeControl"> + <div> + <label>Start: <input type="text" name="startTime" /></label> + <label>End: <input type="text" name="endTime" /></label> + <input type="submit" value="Update" /> + <input type="reset" value="Reset" /> + </div> + </form> <div class="charts"> <div class="chart"></div> </div> @@ -1,3 +1,13 @@ +/* Copyright (c) 2010 Richard Wall <richard (at) the-moon.net> + * See LICENSE for details. + * + * Wrappers and convenience fuctions for working with the javascriptRRD, jQuery, + * and flot charting packages. + * + * javascriptRRD - http://javascriptrrd.sourceforge.net/ + * jQuery - http://jquery.com/ + * flot - http://code.google.com/p/flot/ + */ if(typeof jrrd == 'undefined') { var jrrd = {}; @@ -38,46 +48,71 @@ jrrd.downloadBinary = function(url) { return d; }; - +/** + * A wrapper around an instance of javascriptrrd.RRDFile which provides a + * convenient way to query the RRDFile based on time range, RRD data source (DS) + * and RRD consolidation function (CF). + * + * @param startTime: A javascript {Date} instance representing the start of query + * time range, or {null} to return earliest available data. + * @param endTime: A javascript {Date} instance representing the end of query + * time range, or {null} to return latest available data. + * @param dsId: A {String} name of an RRD DS or an {Int} DS index number or + * {null} to return the first available DS. + * @param cfName: A {String} name of an RRD consolidation function + * @return: A flot compatible data series object + **/ jrrd.RrdQuery = function(rrd) { this.rrd = rrd; }; -jrrd.RrdQuery.prototype.getData = function(startTime, endTime, dsId) { +jrrd.RrdQuery.prototype.getData = function(startTime, endTime, dsId, cfName) { var startTimestamp = startTime.getTime()/1000; - var endTimestamp = endTime.getTime()/1000; + + var lastUpdated = this.rrd.getLastUpdate(); + var endTimestamp = lastUpdated; + if(endTime) { + endTimestamp = endTime.getTime()/1000; + // If end time stamp is beyond the range of this rrd then reset it + if(lastUpdated < endTimestamp) { + endTimestamp = lastUpdated; + } + } if(dsId == null) { dsId = 0; } var ds = this.rrd.getDS(dsId); - var consolidationFunc = 'AVERAGE'; - var lastUpdated = this.rrd.getLastUpdate(); - // If end time stamp is beyond the range of this rrd then reset it - if(lastUpdated < endTimestamp) { - endTimestamp = lastUpdated; + if(cfName == null) { + cfName = 'AVERAGE'; } - var bestRRA = null; + + var rra, step, rraRowCount, firstUpdated; for(var i=0; i<this.rrd.getNrRRAs(); i++) { // Look through all RRAs looking for the most suitable // data resolution. var rra = this.rrd.getRRA(i); - if(rra.getCFName() != consolidationFunc) { + // If this rra doesn't use the requested CF then move on to the next. + if(rra.getCFName() != cfName) { continue; } - bestRRA = rra; - var step = rra.getStep(); - var rraRowCount = rra.getNrRows(); - var firstUpdated = lastUpdated - (rraRowCount - 1) * step; + + step = rra.getStep(); + rraRowCount = rra.getNrRows(); + firstUpdated = lastUpdated - (rraRowCount - 1) * step; + // We assume that the RRAs are listed in ascending order of time range, + // therefore the first RRA which contains the range minimum should give + // the highest resolution data for this range. if(firstUpdated <= startTimestamp) { break; } } - - if(!bestRRA) { - throw new Error('Unrecognised consolidation function: ' + consolidationFunc); + // If we got to the end of the loop without ever defining step, it means + // that the CF check never succeded. + if(!step) { + throw new Error('Unrecognised consolidation function: ' + cfName); } var startRow = rraRowCount - parseInt((lastUpdated - startTimestamp)/step) - 1; @@ -87,10 +122,10 @@ jrrd.RrdQuery.prototype.getData = function(startTime, endTime, dsId) { 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]); + flotData.push([timestamp*1000.0, rra.getEl(i, dsIndex)]); timestamp += step; } + return {label: ds.getName(), data: flotData}; }; |