diff options
Diffstat (limited to 'jrrd.js')
-rw-r--r-- | jrrd.js | 149 |
1 files changed, 143 insertions, 6 deletions
@@ -4,15 +4,27 @@ * 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/ + * Designed to work well with the RRD files generated by Collectd: + * - http://collectd.org/ + * + * Requirements: + * - JavascriptRRD: http://javascriptrrd.sourceforge.net/ + * - jQuery: http://jquery.com/ + * - Flot: http://code.google.com/p/flot/ + * - MochiKit.Async: http://www.mochikit.com/ */ if(typeof jrrd == 'undefined') { var jrrd = {}; } +/** + * Download a binary file asynchronously using the jQuery.ajax function + * + * @param url: The url of the object to be downloaded + * @return: A I{MochiKit.Async.Deferred} which will callback with an instance of + * I{javascriptrrd.BinaryFile} + **/ jrrd.downloadBinary = function(url) { var d = new MochiKit.Async.Deferred(); @@ -68,6 +80,20 @@ jrrd.RrdQuery = function(rrd, unit) { }; jrrd.RrdQuery.prototype.getData = function(startTime, endTime, dsId, cfName) { + /** + * Generate a Flot compatible data object containing rows between start and + * end time. The rows are taken from the first RRA whose data spans the + * requested time range. + * + * @param startTime: The I{Date} start time + * @param endTime: The I{Date} end time + * @param dsId: An index I{Number} or key I{String} identifying the RRD + * datasource (DS). + * @param cfName: The name I{String} of an RRD consolidation function (CF) + * eg AVERAGE, MIN, MAX + * @return: A Flot compatible data series I{Object} + * eg {label:'', data:[], unit: ''} + **/ var startTimestamp = startTime.getTime()/1000; var lastUpdated = this.rrd.getLastUpdate(); @@ -130,7 +156,13 @@ jrrd.RrdQuery.prototype.getData = function(startTime, endTime, dsId, cfName) { return {label: ds.getName(), data: flotData, unit: this.unit}; }; - +/** + * A wrapper around RrdQuery which provides asynchronous access to the data in a + * remote RRD file. + * + * @param url: The url I{String} of a remote RRD file + * @param unit: The unit suffix I{String} of this data eg 'bit/sec' + **/ jrrd.RrdQueryRemote = function(url, unit) { this.url = url; this.unit = unit; @@ -139,6 +171,14 @@ jrrd.RrdQueryRemote = function(url, unit) { }; jrrd.RrdQueryRemote.prototype.getData = function(startTime, endTime, dsId) { + /** + * Return a Flot compatible data series asynchronously. + * + * @param startTime: The start time I{Date} + * @param endTime: The end time I{Date} + * @returns: A I{MochiKit.Async.Deferred} which calls back with a flot data + * series object I{Object} + **/ var endTimestamp = endTime.getTime()/1000; // Download the rrd if there has never been a download or if the last @@ -180,7 +220,13 @@ jrrd.RrdQueryRemote.prototype.getData = function(startTime, endTime, dsId) { return ret; }; - +/** + * Wraps a I{RrdQueryRemote} to provide access to a different RRD DSs within a + * single RrdDataSource. + * + * @param rrdQuery: An I{RrdQueryRemote} + * @param dsId: An index or keyname of an RRD DS + **/ jrrd.RrdQueryDsProxy = function(rrdQuery, dsId) { this.rrdQuery = rrdQuery; this.dsId = dsId; @@ -188,21 +234,43 @@ jrrd.RrdQueryDsProxy = function(rrdQuery, dsId) { }; jrrd.RrdQueryDsProxy.prototype.getData = function(startTime, endTime) { + /** + * Call I{RrdQueryRemote.getData} with a particular dsId + **/ return this.rrdQuery.getData(startTime, endTime, this.dsId); }; +/** + * A class for creating a Flot chart from a series of RRD Queries + * + * @param template: A I{jQuery} containing a single element into which the chart + * will be drawn + * @param options: An I{Object} containing Flot options which describe how the + * chart should be drawn. + **/ jrrd.Chart = function(template, options) { this.template = template; this.options = jQuery.extend(true, {yaxis: {}}, options); this.data = []; var self = this; + + // Listen for clicks on the legend items - onclick enable / disable the + // corresponding data source. $('.legend tr', this.template[0]).live('click', function(e) { self.switchDataEnabled($(this).children('.legendLabel').text()); self.draw(); }); + this.options['yaxis']['ticks'] = function(axis) { + /** + * Choose a suitable SI multiplier based on the min and max values from + * the axis and then generate appropriate yaxis tick labels. + * + * @param axis: An I{Object} with min and max properties + * @return: An array of ~5 tick labels + **/ var siPrefixes = { 0: '', 1: 'K', @@ -250,6 +318,16 @@ jrrd.Chart = function(template, options) { }; jrrd.Chart.prototype.addData = function(label, db, enabled) { + /** + * Add details of a remote RRD data source whose data will be added to this + * chart. + * + * @param label: A I{String} label for this data which will be shown in the + * chart legend + * @param db: The url of the remote RRD database + * @param enabled: true if you want this data plotted on the chart, false + * if not. + **/ if(typeof enabled == 'undefined') { enabled = true; } @@ -257,6 +335,12 @@ jrrd.Chart.prototype.addData = function(label, db, enabled) { }; jrrd.Chart.prototype.switchDataEnabled = function(label) { + /** + * Enable / Disable a single data source + * + * @param label: The label I{String} of the data source to be enabled / + * disabled + **/ for(var i=0; i<this.data.length; i++) { if(this.data[i][0] == label) { this.data[i][2] = !this.data[i][2]; @@ -265,12 +349,26 @@ jrrd.Chart.prototype.switchDataEnabled = function(label) { }; jrrd.Chart.prototype.setTimeRange = function(startTime, endTime) { + /** + * Alter the time range of this chart and redraw + * + * @param startTime: The start time I{Date} + * @param endTime: The end time I{Date} + **/ this.startTime = startTime; this.endTime = endTime; this.draw(); } jrrd.Chart.prototype.draw = function() { + /** + * Draw the chart + * A 'chart_loading' event is triggered before the data is requested + * A 'chart_loaded' event is triggered when the chart has been drawn + * + * @return: A I{MochiKit.Async.Deferred} which calls back with the chart + * data when the chart has been rendered. + **/ this.template.trigger('chart_loading'); var result; var results = []; @@ -333,6 +431,7 @@ jrrd.Chart.prototype.draw = function() { 'text-align': 'right'}); self.template.append(yaxisUnitLabel); yaxisUnitLabel.position(self.template.position()); + return data; }, this) .addErrback( function(self, failure) { @@ -347,6 +446,15 @@ jrrd.Chart.prototype.draw = function() { jrrd.Chart.fromRecipe = function(template, recipe) { + /** + * A factory function to generate a I{Chart} from a recipe + * + * @param template: A I{jQuery} containing the element in which the chart is + * drawn. + * @param A recipe I{Object} eg + * {title: '', data: [rrdUrl, rrdDs, label, unit], options: {}} + * @return: A I{Chart} instance + **/ template.find('.title').text(recipe['title']); var c = new jrrd.Chart(template.find('.chart'), recipe['options']); var dataDict = {}; @@ -365,20 +473,33 @@ jrrd.Chart.fromRecipe = function(template, recipe) { } +/** + * Presents the user with a form and a timeline with which they can choose a + * time range and co-ordinates the refreshing of a series of charts. + * + * @param ui: A one element I{jQuery} containing an input form and placeholders + * for the timeline and for the series of charts. + **/ jrrd.ChartCoordinator = function(ui) { this.ui = ui; this.charts = []; var self = this; + + // Update the time ranges and redraw charts when the form is submitted this.ui.bind('submit', function(e) { self.update(); return false; }); + // Reset all the charts to the default time range when the reset button is + // pressed. this.ui.bind('reset', function(e) { self.reset(); return false; }); + + // Style and configuration of the range timeline var rangePreviewOptions = { grid: { borderWidth: 1 @@ -400,12 +521,15 @@ jrrd.ChartCoordinator = function(ui) { var MONTH = DAY * 31; var YEAR = DAY * 365; + // Dummy data for the range timeline var data = [ [now - WEEK, null], [now, null]]; - this.rangePreview = $.plot(this.ui.find('.range-preview'), [data], rangePreviewOptions); + this.rangePreview = $.plot(this.ui.find('.range-preview'), [data], + rangePreviewOptions); + // When a selection is made on the range timeline, redraw all the charts. this.ui.bind("plotselected", function(event, ranges) { self.setTimeRange(new Date(ranges.xaxis.from), new Date(ranges.xaxis.to)); @@ -413,6 +537,10 @@ jrrd.ChartCoordinator = function(ui) { }; jrrd.ChartCoordinator.prototype.update = function() { + /** + * Grab the start and end time from the ui form, highlight the range on the + * range timeline and set the time range of all the charts and redraw. + **/ var startTime = new Date(this.ui[0].startTime.value); var endTime = new Date(this.ui[0].endTime.value); var ranges = { @@ -428,12 +556,21 @@ jrrd.ChartCoordinator.prototype.update = function() { }; jrrd.ChartCoordinator.prototype.setTimeRange = function(startTime, endTime) { + /** + * Set the start and end time fields in the form and trigger an update + * + * @param startTime: The start time I{Date} + * @param endTime: The end time I{Date} + **/ 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(); }; jrrd.ChartCoordinator.prototype.reset = function() { + /** + * Reset all charts and the input form to the default time range - last hour + **/ this.setTimeRange(new Date(new Date().getTime()-1*60*60*1000), new Date()); }; |