Commit 85966b64 authored by Alan W Szlosek Jr's avatar Alan W Szlosek Jr

more work on timeseries logic ... still in flux

parent fb140d57
......@@ -4,8 +4,8 @@
3. Alert when the average is over 50
4. Populate the metric with random integers every 500ms
*/
var Timeseries = require('./lib/timeseries');
var log = require('./lib/log')('example-timeseries', true);
var Harbinger = require('../index');
var log = require('../lib/log')('example-timeseries', true);
var moment = require('moment');
var redis = require('redis');
......@@ -16,7 +16,7 @@ function getRandomInteger(min, max) {
var redisClient = redis.createClient(6379, 'localhost');
// Instantiate a timeseries dataset called "sample" that preserves 60 seconds worth of data
var metric = new Timeseries(redisClient, 'sample', 60);
var metric = new Harbinger.Timeseries(redisClient, 'sample', 60);
var averageInterval;
......@@ -43,10 +43,10 @@ var averageInterval = setInterval(
done();
return;
}
log('Dataset spans ' + secondsSpanned + ' seconds');
log('Dataset spans ' + secondsSpanned + ' seconds. Avg: ' + avg);
if (secondsSpanned == 10 && avg > 50) {
log('Average above 50', avg);
if (secondsSpanned == 10 && avg > 51) {
log('Average above 51', avg);
done();
}
}
......@@ -60,7 +60,7 @@ var averageInterval = setInterval(
var countInterval = setInterval(
function() {
var rand = getRandomInteger(1, 100);
metric.addCount(moment().unix(), rand);
metric.count(moment().unix(), rand);
},
500
);
......
var stats = require('statistics');
var log = require('./log')('timeseries', false);
/*
......@@ -27,23 +28,6 @@ module.exports = Timeseries;
// Use a zset to sum values into time buckets
Timeseries.prototype.addValue = function(secondsBucket, type, value) {
var self = this;
var key = this.key + ':' + type + ':' + secondsBucket;
log('lpush', key, value);
this.redisClient.lpush(
key,
value,
function(err) {
self.redisClient.expire(key, self.cutoff);
}
);
};
Timeseries.prototype.addCount = function(secondsBucket, value) {
this.addValue(secondsBucket, 'count', value);
};
/*
Still unsure how to handle multiple types yet: counters, timers, etc
......@@ -51,9 +35,12 @@ But this method could be used by getAverage() to get the sum and number of items
type: count, timer
*/
Timeseries.prototype.getValues = function(startSeconds, endSeconds, type, callback) {
var self = this;
var earliestSeconds = Number.MAX_SAFE_INTEGER;
// earliestSeconds will be repeatedly updated with the min timestamp value we encounter from Redis.
// Default it to endSeconds in case there is no data
var earliestSeconds = endSeconds; //Number.MAX_SAFE_INTEGER;
var keys = [];
for (var i = startSeconds; i <= endSeconds; i++) {
keys.push( i );
......@@ -97,7 +84,9 @@ Timeseries.prototype.getValues = function(startSeconds, endSeconds, type, callba
Timeseries.prototype.getSum = function(startSeconds, endSeconds, type, callback) {
var self = this;
var earliestSeconds = Number.MAX_SAFE_INTEGER;
// earliestSeconds will be repeatedly updated with the min timestamp value we encounter from Redis.
// Default it to endSeconds in case there is no data
var earliestSeconds = endSeconds;
var keys = [];
for (var i = startSeconds; i <= endSeconds; i++) {
keys.push( i );
......@@ -156,4 +145,105 @@ Timeseries.prototype.getCountAverage = function(startSeconds, endSeconds, callba
);
};
/*
METRIC TYPES
For all metric types, the key prefix includes the second the values are being added
Count
- Believe we can use incrBy
Time
- Believe we need to use a list for these, so we can accurately calculate avg and other stats
*/
// NEW METHODS
Timeseries.prototype.count = function(secondsBucket, count, callback) {
var self = this;
var key = this.key + ':count:' + secondsBucket;
log('incrBy', key, count);
self.redisClient.incrby(
key,
count,
function(err) {
self.redisClient.expire(key, self.cutoff);
callback(err);
}
);
};
Timeseries.prototype.time = function(secondsBucket, value) {
var self = this;
var key = this.key + ':time:' + secondsBucket;
log('lpush', key, value);
this.redisClient.lpush(
key,
value,
function(err) {
self.redisClient.expire(key, self.cutoff);
}
);
};
// Return an array of counts for each seconds bucket from start to end
Timeseries.prototype.getCounts = function(startSeconds, endSeconds, callback) {
var self = this;
var keys = [];
for (var i = startSeconds; i <= endSeconds; i++) {
keys.push( i );
}
var out = [];
var next = function() {
var key;
if (keys.length == 0) {
// Done
// Calculate the average now
callback(null, out);
return;
}
seconds = keys.shift();
key = self.key + ':count:' + seconds;
// Fetch from redis
log('fetching: ', key);
// TODO: should probably use mget instead
self.redisClient.get(key, function(err, value) {
if (err) {
callback(err);
return;
}
if (value) {
out.push( parseInt(value) );
} else {
out.push(0);
}
next();
});
};
// Should perhaps cache the output of this so frequent pulls for this exact interval don't have to recalculate
next();
};
/*
Use this to get sum, mean/average, standard deviation, etc
*/
Timeseries.prototype.getCountStatistics = function(startSeconds, endSeconds, callback) {
this.getCounts(startSeconds, endSeconds, function(err, counts) {
if (err) {
callback(err);
return;
}
callback(null, counts.reduce(stats) );
});
};
/*
*/
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment