Skip to content
Browse files

Add new uptime claculator

  • Loading branch information...
1 parent 0a397ad commit 9eb3bebecef4c0d0f13f80e64262d88a68a3a081 @fzaninotto committed Sep 21, 2012
Showing with 191 additions and 0 deletions.
  1. +65 −0 lib/uptimeCalculator.js
  2. +4 −0 makefile
  3. +3 −0 package.json
  4. +117 −0 test/lib/test_uptimeCalculator.js
  5. +2 −0 test/mocha.opts
View
65 lib/uptimeCalculator.js
@@ -0,0 +1,65 @@
+var Ping = require('../models/ping');
+var CheckEvent = require('../models/checkEvent');
+
+var UptimeCalculator = function(check) {
+ this.check = check;
+}
+
+UptimeCalculator.prototype.getUptimePeriods = function(begin, end, callback) {
+ var self = this;
+ this.getPingBeforeTime(begin, function(err1, ping) {
+ if (err1) return callback(err1);
+ if (!ping) return callback(null, []);
+ CheckEvent.find()
+ .where('check').equals(self.check)
+ .where('timestamp').gte(begin).lte(end)
+ .sort({ timestamp: 1 })
+ .find(function(err2, checkEvents) {
+ if (err2) return callback(err2);
+ var periods = [];
+ var isUp = ping.isUp; // initial state
+ var currentPeriod = isUp ? [begin] : [];
+ checkEvents.forEach(function(checkEvent) {
+ switch (checkEvent.message) {
+ case 'up':
+ if (isUp) break; // check passes up while it was already up: ignore
+ // beginning of an uptime period
+ currentPeriod.push(checkEvent.timestamp.getTime());
+ isUp = true;
+ break;
+ case 'down':
+ if (!isUp) break; // check passes down while it was already down: ignore
+ // end of an uptime period
+ currentPeriod.push(checkEvent.timestamp.getTime());
+ periods.push(currentPeriod);
+ currentPeriod = [];
+ isUp = false;
+ break;
+ }
+ })
+ if (isUp) {
+ // check was up until the end
+ currentPeriod.push(end);
+ periods.push(currentPeriod);
+ };
+ callback(null, periods);
+ });
+ });
+}
+
+/**
+ * Get the last ping preceding a given timestamp
+ *
+ * This determines the state of a check at a given time.
+ *
+ * @api public
+ */
+UptimeCalculator.prototype.getPingBeforeTime = function(timestamp, callback) {
+ Ping.find()
+ .where('check').equals(this.check)
+ .where('timestamp').lte(timestamp)
+ .sort({ timestamp: -1 })
+ .findOne(callback);
+}
+
+module.exports = UptimeCalculator;
View
4 makefile
@@ -0,0 +1,4 @@
+test:
+ NODE_ENV=test mocha test/*/*.js
+
+.PHONY: test
View
3 package.json
@@ -14,6 +14,9 @@
"async": "0.1.22",
"socket.io": "0.9.10"
},
+ "devDependencies": {
+ "should": "1.1.0"
+ },
"keywords": ["uptime", "monitoring", "api", "check"],
"repository": "https://github.com/fzaninotto/uptime",
"license": "MIT",
View
117 test/lib/test_uptimeCalculator.js
@@ -0,0 +1,117 @@
+var should = require('should');
+var async = require('async');
+var mongoose = require('../../bootstrap');
+var UptimeCalculator = require('../../lib/uptimeCalculator');
+var Check = require('../../models/check');
+var CheckEvent = require('../../models/checkEvent');
+var Ping = require('../../models/ping');
+
+var check1, check2, now; // fixtures
+
+describe('uptimeCalculator', function() {
+
+ before(function(done) {
+ async.parallel([
+ function(cb) { Ping.collection.drop(cb) },
+ function(cb) { Check.collection.drop(cb) },
+ function(cb) { CheckEvent.collection.drop(cb) },
+ ], done);
+ });
+
+ before(function() {
+ now = Date.now();
+ });
+
+ before(function(done) {
+ check1 = new Check();
+ check1.save(function(err) {
+ if (err) throw (err);
+ async.series([
+ function(cb) { Ping.createForCheck(false, now - 3000, 100, check1, 'dummy1', '', cb); },
+ function(cb) { Ping.createForCheck(false, now - 2000, 100, check1, 'dummy2', '', cb); },
+ function(cb) { Ping.createForCheck(true, now - 1000, 100, check1, 'dummy3', '', cb); },
+ function(cb) { Ping.createForCheck(true, now, 100, check1, 'dummy4', '', cb); },
+ function(cb) { Ping.createForCheck(true, now + 1000, 100, check1, 'dummy5', '', cb); },
+ function(cb) { Ping.createForCheck(false, now + 2000, 100, check1, 'dummy6', '', cb); },
+ function(cb) { Ping.createForCheck(true, now + 3000, 100, check1, 'dummy7', '', cb); },
+ ], done);
+ });
+ });
+
+ before(function(done) {
+ check2 = new Check();
+ check2.save(done);
+ });
+
+ describe('#getPingBeforeTime', function() {
+
+ it('should return nothing for new Checks', function(done) {
+ var calculator = new UptimeCalculator(check2);
+ calculator.getPingBeforeTime(now, function(err, ping) {
+ if (err) throw (err);
+ should.not.exist(ping);
+ done();
+ });
+ });
+
+ it('should return the latest ping', function(done) {
+ var calculator = new UptimeCalculator(check1);
+ calculator.getPingBeforeTime(now, function(err, ping) {
+ if (err) throw (err);
+ ping.monitorName.should.eql('dummy4');
+ done();
+ });
+ });
+
+ });
+
+ describe('#getUptimePeriods', function() {
+
+ it('should return empty array when there is no ping', function(done) {
+ var calculator = new UptimeCalculator(check2);
+ calculator.getUptimePeriods(Date.now(), Date.now() + 1000, function(err, periods) {
+ if (err) throw (err);
+ periods.should.eql([]);
+ done();
+ });
+ });
+
+ it('should return the correct period for not finished check', function(done) {
+ var calculator = new UptimeCalculator(check1);
+ calculator.getUptimePeriods(now + 3000, now + 6000, function(err, periods) {
+ if (err) throw (err);
+ periods.should.eql([ [now + 3000, now + 6000] ]);
+ done();
+ });
+ });
+
+ it('should return the correct period for not started check', function(done) {
+ var calculator = new UptimeCalculator(check1);
+ calculator.getUptimePeriods(now - 6000, now - 3000, function(err, periods) {
+ if (err) throw (err);
+ periods.should.eql([ ]);
+ done();
+ });
+ });
+
+ it('should return the correct period for crossing checks', function(done) {
+ var calculator = new UptimeCalculator(check1);
+ calculator.getUptimePeriods(now - 6000, now, function(err, periods) {
+ if (err) throw (err);
+ periods.should.eql([ [ now - 1000, now ]]);
+ done();
+ });
+ });
+
+ it('should return the correct periods', function(done) {
+ var calculator = new UptimeCalculator(check1);
+ calculator.getUptimePeriods(now - 3000, now + 3000, function(err, periods) {
+ if (err) throw (err);
+ periods.should.eql([ [now - 1000, now + 2000], [now + 3000, now + 3000] ]);
+ done();
+ });
+ });
+
+ });
+
+});
View
2 test/mocha.opts
@@ -0,0 +1,2 @@
+--reporter spec
+--slow 20ms

0 comments on commit 9eb3beb

Please sign in to comment.
Something went wrong with that request. Please try again.