/* Copyright (c) 2010 Richard Wall * 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 = {}; } jrrd.downloadBinary = function(url) { var d = new MochiKit.Async.Deferred(); $.ajax({ url: url, dataType: 'text', cache: false, beforeSend: function(request) { try { request.overrideMimeType('text/plain; charset=x-user-defined'); } catch(e) { // IE doesn't support overrideMimeType } }, success: function(data) { try { d.callback(new BinaryFile(data)); } catch(e) { d.errback(e); } }, error: function(xhr, textStatus, errorThrown) { // Special case for IE which handles binary data slightly // differently. if(textStatus == 'parsererror') { if (typeof xhr.responseBody != 'undefined') { return this.success(xhr.responseBody); } } d.errback(new Error(xhr.status)); } }); 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, cfName) { var startTimestamp = startTime.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); if(cfName == null) { cfName = 'AVERAGE'; } var rra, step, rraRowCount, firstUpdated; for(var i=0; i -1 && this.lastUpdate < endTimestamp )) { this._download = jrrd.downloadBinary(this.url) .addCallback( function(self, 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.lastUpdate = rrd.getLastUpdate(); return rrd; }, this); } // 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(startTime, endTime, dsId, rrd) { return new jrrd.RrdQuery(rrd).getData(startTime, endTime, dsId); }, startTime, endTime, dsId); // Add a pair of callbacks to the current download which will callback the // result which we setup above. this._download.addBoth( function(ret, res) { if(res instanceof Error) { ret.errback(res); } else { ret.callback(res); } return res; }, ret); return ret; }; jrrd.RrdQueryDsProxy = function(rrdQuery, dsId) { this.rrdQuery = rrdQuery; this.dsId = dsId; }; jrrd.RrdQueryDsProxy.prototype.getData = function(startTime, endTime) { return this.rrdQuery.getData(startTime, endTime, this.dsId); }; jrrd.Chart = function(template, options) { this.template = template; this.options = jQuery.extend(true, {}, options); this.data = []; var self = this; $('.legend tr', this.template[0]).live('click', function(e) { self.switchDataEnabled($(this).children('.legendLabel').text()); self.draw(); }); this.options['legend'] = { 'labelFormatter': function(label, series) { return self.legendLabelFormatter(label, series); } }; }; jrrd.Chart.prototype.legendLabelFormatter = function(label, series) { for(var i=0; i', label, ''].join(''); } else { return label; } } } return 'unknown: ' + label; }; jrrd.Chart.prototype.addData = function(label, db, enabled) { if(typeof enabled == 'undefined') { enabled = true; } this.data.push([label, db, enabled]); }; jrrd.Chart.prototype.switchDataEnabled = function(label) { for(var i=0; i