Get metrics from codahale/metrics in realtime.
Requires obfuscurity/tasseo#64
Get metrics from codahale/metrics in realtime.
Requires obfuscurity/tasseo#64
| function MetricsDatasource(metricsUrl, options) { | |
| this.metricCache = new MetricCache(new MetricFetcher(metricsUrl)); | |
| } | |
| MetricsDatasource.prototype = { | |
| refresh: function(metrics, period) { | |
| var self = this; | |
| self.metricCache.setPeriod(period * 60); | |
| self.metricCache.refresh(function() { | |
| _.each(metrics, function(metric) { | |
| var dataset = self.metricCache.get(metric.target); | |
| metric.update(_.map(dataset, function(datum) { | |
| return { x: datum.time, y: datum.value } | |
| })) | |
| }) | |
| }) | |
| } | |
| } | |
| function MetricFetcher(url) { | |
| this.url = url; | |
| } | |
| MetricFetcher.prototype = { | |
| refresh: function(cb) { | |
| $.ajax({ | |
| dataType: 'json', | |
| error: function(xhr, textStatus, errorThrown) { console.log(errorThrown); }, | |
| url: this.url, | |
| success: _.bind(function(data) { | |
| this.latestMetrics = this.flattenMetrics(data) | |
| cb.call(this.latestMetrics) | |
| }, this) | |
| }) | |
| }, | |
| flattenMetrics: function(data, prefix) { | |
| var result = {}; | |
| var hasType = _.has(data, 'type'); | |
| _.each(data, function(value, key) { | |
| var metricName = _.isUndefined(prefix) ? key : prefix + "." + key; | |
| if (hasType) { | |
| if (_.isNumber(value)) { | |
| result[metricName] = value; | |
| } | |
| } else if (_.isObject(value)) { | |
| _.extend(result, this.flattenMetrics(value, metricName)) | |
| } | |
| }, this); | |
| return result; | |
| } | |
| } | |
| function MetricCache(metricFetcher, options) { | |
| this.metricFetcher = metricFetcher; | |
| this.options = _.extend({}, { | |
| period: 60 * 5 // 5 minutes | |
| }, options) | |
| this.period = this.options.period | |
| this.cache = {} | |
| this._metricNames = {} | |
| } | |
| MetricCache.prototype = { | |
| refresh: function(callback) { | |
| var self = this; | |
| this.metricFetcher.refresh(function() { | |
| self.update() | |
| if (callback) { | |
| callback.call() | |
| } | |
| }) | |
| }, | |
| setPeriod: function(period) { | |
| this.period = period; | |
| }, | |
| get: function(name) { | |
| if (!_.has(this.cache, name)) { | |
| this.cache[name] = this.blankData(); | |
| } | |
| return this.cache[name]; | |
| }, | |
| metricNames: function() { | |
| return _.keys(this._metricNames); | |
| }, | |
| update: function() { | |
| var now = this.unixtime(); | |
| var oldest = now - this.period; | |
| var newMetric = false; | |
| _.each(this.metricFetcher.latestMetrics, function(value, name) { | |
| if (!this._metricNames[name]) { | |
| this._metricNames[name] = true | |
| newMetric = true; | |
| } | |
| // Only fill in metrics that we've had requests for | |
| if (_.has(this.cache, name)) { | |
| this.cache[name].push({ value: value, time: now }) | |
| this.cache[name] = _.reject(this.cache[name], function(record) { | |
| return record.time < oldest; | |
| }) | |
| } | |
| }, this) | |
| if (newMetric) { | |
| $(this).trigger("metric:added") | |
| } | |
| }, | |
| unixtime: function() { | |
| return Math.floor(new Date() / 1000) | |
| }, | |
| blankData: function() { | |
| var now = this.unixtime(); | |
| var data = [] | |
| for (var i = now - this.period; i < now; i += 5) { | |
| data.push({ value: 0, time: i }) | |
| } | |
| return data; | |
| } | |
| } |