Skip to content

Commit

Permalink
Fix bug with separate monitor not aggregating qos scores
Browse files Browse the repository at this point in the history
Separate Monitor class and configuration in two. Now the monitor only
communicates with the REST API, and the checks themselves.
  • Loading branch information
fzaninotto committed Apr 17, 2012
1 parent d0afe4b commit 874d72e
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 49 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ Uptime Changelog

To be released, V1.2
--------------------

* Split Monitor class and configuration, to fix polling when `autoStartMonitor` is false
* Fixed failure to add check in the dashboard when the protocol wasn't set
* Added UDP poller (bolgovr)

Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,12 @@ Uptime uses [node-config](https://github.com/lorenwest/node-config) to allow YAM
name: origin
apiUrl: 'http://localhost:8082/api'
pollingInterval: 10000 # ten seconds
timeout: 5000 # five seconds

analyzer:
updateInterval: 60000 # one minute
qosAggregationInterval: 600000 # ten minutes
timeout: 5000 # five seconds
pingHistory: 8035200000 # three months
pingHistory: 8035200000 # three months

autoStartMonitor: true

Expand Down
4 changes: 4 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var mongoose = require('mongoose'),
socketIo = require('socket.io'),
path = require('path'),
monitor = require('./lib/monitor'),
analyzer = require('./lib/analyzer'),
CheckEvent = require('./models/checkEvent');

// configure mongodb
Expand All @@ -18,6 +19,9 @@ if (config.autoStartMonitor) {
m.start();
}

a = analyzer.createAnalyzer(config.analyzer);
a.start();

var app = module.exports = express.createServer();

// Site
Expand Down
6 changes: 4 additions & 2 deletions config/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ monitor:
name: origin
apiUrl: 'http://localhost:8082/api'
pollingInterval: 10000 # ten seconds
timeout: 5000 # five seconds

analyzer:
updateInterval: 60000 # one minute
qosAggregationInterval: 600000 # ten minutes
timeout: 5000 # five seconds
pingHistory: 8035200000 # three months
pingHistory: 8035200000 # three months

autoStartMonitor: true

Expand Down
92 changes: 92 additions & 0 deletions lib/analyzer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* Module dependencies.
*/
var Check = require('../models/check'),
CheckEvent = require('../models/checkEvent'),
Ping = require('../models/ping');

/**
* Analyzer constructor
*
* The analyzer aggregates the ping data into QoS scores for checks and tags.
*
* The constructor expects a configuration object as parameter, with these properties:
* updateInterval: Interval between each update of the QoS score in milliseconds, defaults to 1 minute
* qosAggregationInterval: Interval between each daily and hourly aggregation the QoS score in milliseconds, defaults to 1 hour
* oldestHistory: Oldest ping and checkEvent age to keep in milliseconds, defaults to 3 months
*
* @param {Object} Monitor configuration
* @api public
*/
function Analyzer(config) {
config.updateInterval = config.updateInterval || 60 * 1000;
config.qosAggregationInterval = config.qosAggregationInterval || 60 * 60 * 1000;
config.oldestHistory = config.oldestHistory || 3 * 31 * 24 * 60 * 60 * 1000;
this.config = config;
}

/**
* Start the analysis of all checks.
*
* The polling actually starts after the pollingInterval set to the constructor.
*
* @api public
*/
Analyzer.prototype.start = function() {
// schedule updates
this.intervalForUpdate = setInterval(this.updateAllChecks.bind(this), this.config.updateInterval);
this.intervalForAggregation = setInterval(this.aggregateQos.bind(this), this.config.qosAggregationInterval);
}

/**
* Stop the analysis of all checks
*
* @api public
*/
Analyzer.prototype.stop = function() {
clearInterval(this.intervalForUpdate);
clearInterval(this.intervalForAggregation);
}

/**
* Update the QoS scores for each check once
*
* @api private
*/
Analyzer.prototype.updateAllChecks = function() {
Ping.updateLast24HoursQos.apply(Ping);
Ping.updateLastHourQos.apply(Ping);
}

/**
* Aggregate the QoS scores for each check
*
* @api private
*/
Analyzer.prototype.aggregateQos = function() {
var CheckHourlyStat = require('../models/checkHourlyStat');
CheckHourlyStat.updateLastDayQos.apply(CheckHourlyStat);
CheckHourlyStat.updateLastMonthQos.apply(CheckHourlyStat);
var TagHourlyStat = require('../models/tagHourlyStat');
TagHourlyStat.updateLastDayQos.apply(TagHourlyStat);
TagHourlyStat.updateLastMonthQos.apply(TagHourlyStat);
Ping.cleanup(this.config.oldestHistory);
CheckEvent.cleanup(this.config.oldestHistory);
}

/**
* Create an analyzer to update the check and tag qos scores.
*
* Example:
*
* m = analyzer.createAnalyzer({ updateInterval: 60000});
* m.start();
* // the analysis starts, every 60 seconds
* m.stop();
*
* @param {Object} Configuration object
* @api public
*/
exports.createAnalyzer = function(config) {
return new Analyzer(config);
}
57 changes: 12 additions & 45 deletions lib/monitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,26 @@
* Module dependencies.
*/
var http = require('http'),
url = require('url'),
Check = require('../models/check'),
CheckEvent = require('../models/checkEvent'),
Ping = require('../models/ping');
url = require('url');

/**
* Monitor constructor
*
* @param {Number} Interval between each poll in milliseconds, defaults to 10 seconds
* @param {Number} Interval between each update of the QoS score in milliseconds, defaults to 1 minute
* @param {Number} Interval between each daily and hourly aggregation the QoS score in milliseconds, defaults to 1 hour
* @param {Number} Request timeout in milliseconds, defaults to 5 seconds
* @param {Number} Oldest ping and checkEvent age to keep in milliseconds, defaults to 3 months
* The monitor pings the checks regularily and saves the response status and time.
* The monitor doesn't interact with the model classes directly, but instead uses
* the REST HTTP API. This way, the monitor can run on a separate process, so that the
* ping measurements don't get distorted by a heavy usage of the GUI.
*
* The constructor expects a configuration object as parameter, with these properties:
* pollingInterval: Interval between each poll in milliseconds, defaults to 10 seconds
* timeout: Request timeout in milliseconds, defaults to 5 seconds
*
* @param {Object} Monitor configuration
* @api public
*/
function Monitor(config) {
config.pollingInterval = config.pollingInterval || 10 * 1000;
config.updateInterval = config.updateInterval || 60 * 1000;
config.qosAggregationInterval = config.qosAggregationInterval || 60 * 60 * 1000;
config.timeout = config.timeout || 5 * 1000;
config.oldestHistory = config.oldestHistory || 3 * 31 * 24 * 60 * 60 * 1000;
config.proxy = config.proxy || {};
this.config = config;
}

Expand All @@ -39,9 +37,6 @@ Monitor.prototype.start = function() {
this.pollChecksNeedingPoll();
// schedule future polls
this.intervalForPoll = setInterval(this.pollChecksNeedingPoll.bind(this), this.config.pollingInterval);
// schedule updates
this.intervalForUpdate = setInterval(this.updateAllChecks.bind(this), this.config.updateInterval);
this.intervalForAggregation = setInterval(this.aggregateQos.bind(this), this.config.qosAggregationInterval);
console.log('Monitor ' + this.config.name + ' started');
}

Expand All @@ -51,9 +46,7 @@ Monitor.prototype.start = function() {
* @api public
*/
Monitor.prototype.stop = function() {
clearInterval(this.config.intervalForPoll);
clearInterval(this.config.intervalForUpdate);
clearInterval(this.config.intervalForAggregation);
clearInterval(this.intervalForPoll);
}

/**
Expand Down Expand Up @@ -144,32 +137,6 @@ Monitor.prototype.createPing = function(check, error, time, callback) {
req.end();
}

/**
* Update the QoS scores for each check once
*
* @api private
*/
Monitor.prototype.updateAllChecks = function() {
Ping.updateLast24HoursQos.apply(Ping);
Ping.updateLastHourQos.apply(Ping);
}

/**
* Aggregate the QoS scores for each check
*
* @api private
*/
Monitor.prototype.aggregateQos = function() {
var CheckHourlyStat = require('../models/checkHourlyStat');
CheckHourlyStat.updateLastDayQos.apply(CheckHourlyStat);
CheckHourlyStat.updateLastMonthQos.apply(CheckHourlyStat);
var TagHourlyStat = require('../models/tagHourlyStat');
TagHourlyStat.updateLastDayQos.apply(TagHourlyStat);
TagHourlyStat.updateLastMonthQos.apply(TagHourlyStat);
Ping.cleanup(this.config.oldestHistory);
CheckEvent.cleanup(this.config.oldestHistory);
}

/**
* Create a monitor to poll all checks at a given interval.
*
Expand Down

0 comments on commit 874d72e

Please sign in to comment.