Skip to content

Instantly share code, notes, and snippets.

@eric
Last active December 21, 2015 08:09
Show Gist options
  • Save eric/6276431 to your computer and use it in GitHub Desktop.
Save eric/6276431 to your computer and use it in GitHub Desktop.
Get graphs directly from codahale/metrics
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;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment