Skip to content

Commit

Permalink
First version of WebPageTest poller. It retrieves docTime from WebPag…
Browse files Browse the repository at this point in the history
…eTest service
  • Loading branch information
RobinBressan authored and PopDaph committed May 23, 2014
1 parent 05a5be9 commit 8657179
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 8 deletions.
21 changes: 19 additions & 2 deletions app/dashboard/views/_data.ejs
Expand Up @@ -17,7 +17,13 @@
<h2>Data - Pings</h2>
<table class="table ping" style="display:none">
<thead>
<tr><th>Date</th><th>Status</th><th>Response time</th><th class="error">Error</th></tr>
<tr>
<th>Date</th>
<th>Status</th>
<th>Response time</th>
<th>Details</th>
<th class="error">Error</th>
</tr>
</thead>
<tbody></tbody>
</table>
Expand All @@ -39,6 +45,13 @@
{{ if (ping.isUp && !ping.isResponsive) { }}<span class="label label-warning">Slow</span>{{ } }}
</td>
<td>{{= parseInt(ping.time) }}ms</td>
<td>
{{ if (ping.details
&& ping.details.url
&& /^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(ping.details.url)) { }}
<a href="{{= ping.details.url }}">See report</a>
{{ } }}
</td>
<td class="error">{{= ping.error || '' }}</td>
</tr>
</script>
Expand All @@ -62,7 +75,11 @@ $(document).ready(function() {
if (type == 'hour') {
// display pings
$.each(stats, function(key, stat) {
lines.unshift(ejs.render(ping_template, { ping: stat }));
// if(stat.details && stat.details.url && /^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(stat.details.url)) {
// lines.unshift(ejs.render(ping_template, { ping: stat, pingUrl: stat.details.url }));
// }else{
lines.unshift(ejs.render(ping_template, { ping: stat }));
//}
});
$('#data .stat').hide();
$('#data .ping tbody').html(lines.join(''));
Expand Down
4 changes: 3 additions & 1 deletion config/default.yaml
Expand Up @@ -5,7 +5,7 @@ mongodb:
database: uptime
user: root
password:
connectionString: mongodb://localhost/uptime # alternative to setting server, database, user and password separately
connectionString: # alternative to setting server, database, user and password separately

monitor:
name: origin
Expand Down Expand Up @@ -52,3 +52,5 @@ verbose: true # only used in dev

webPageTest:
server: 'http://webpagetest.org'
key:
testOptions:
10 changes: 5 additions & 5 deletions lib/monitor.js
Expand Up @@ -122,15 +122,15 @@ Monitor.prototype.pollCheck = function(check, callback) {
} catch (unknownPollerError) {
return self.createPing(unknownPollerError, check, now, 0, details, callback);
}
var pollerCallback = function(err, time, res) {
var pollerCallback = function(err, time, res, pollerDetails) {
if (err) {
return self.createPing(err, check, now, time, details, callback);
return self.createPing(err, check, now, time, pollerDetails || details, callback);
}
try {
self.emit('pollerPolled', check, res, details);
self.createPing(null, check, now, time, details, callback);
self.emit('pollerPolled', check, res, pollerDetails || details);
self.createPing(null, check, now, time, pollerDetails || details, callback);
} catch (error) {
return self.createPing(error, check, now, time, details, callback);
return self.createPing(error, check, now, time, pollerDetails || details, callback);
}
};
try {
Expand Down
1 change: 1 addition & 0 deletions lib/pollers/pollerCollection.js
Expand Up @@ -7,6 +7,7 @@ PollerCollection.prototype.addDefaultPollers = function() {
this.add(require('./http/httpPoller.js'));
this.add(require('./https/httpsPoller.js'));
this.add(require('./udp/udpPoller.js'));
this.add(require('./webpagetest/webPageTestPoller.js'));
};

PollerCollection.prototype.add = function(poller) {
Expand Down
105 changes: 105 additions & 0 deletions lib/pollers/webpagetest/webPageTestPoller.js
@@ -0,0 +1,105 @@
/**
* Module dependencies.
*/

var util = require('util');
var url = require('url');
var BasePoller = require('../basePoller');
var WebPageTest = require('webpagetest');
var config = require('config');

/**
* WebPageTest Poller, to perform WebPageTest analysis on web pages
*
* @param {Mixed} Poller Target (e.g. URL)
* @param {Number} Poller timeout in milliseconds. Without response before this duration, the poller stops and executes the error callback.
* @param {Function} Error/success callback
* @api public
*/
function WebPageTestPoller(target, timeout, callback) {
WebPageTestPoller.super_.call(this, target, timeout, callback);
}

util.inherits(WebPageTestPoller, BasePoller);

WebPageTestPoller.type = 'webpagetest';

WebPageTestPoller.validateTarget = function(target) {
return url.parse(target).protocol == 'http:';
};

WebPageTestPoller.prototype.initialize = function() {
this.timeout = 999999; // We can't know a test duration
this.wpt = new WebPageTest(config.webPageTest.server || 'www.webpagetest.org', config.webPageTest.key);
};

/**
* Launch the actual polling
*
* @api public
*/
WebPageTestPoller.prototype.poll = function() {
WebPageTestPoller.super_.prototype.poll.call(this);
this.debug('WebPageTest start test [target='+this.target+']');
this.wpt.runTest(this.target, config.webPageTest.testOptions | {}, this.onTestStartedCallback.bind(this));
};

/**
* Test started callback
*
* @api private
*/
WebPageTestPoller.prototype.onTestStartedCallback = function(err,data){
this.testId = data.data.testId;
if(data.data.userUrl){
this.userUrl = data.data.userUrl;
}
this.debug('WebPageTest test started [testId='+this.testId+']');
this.checkTestStatus();
};

/**
* TestStatus callback
*
* @api private
*/
WebPageTestPoller.prototype.checkTestStatus = function(){
var self = this;
this.wpt.getTestStatus(this.testId, function(err, data) {
if(err){
self.debug('WebPageTest checkTestStatus error');
self.timer.stop();
}else if(data && data.statusCode == 200){
self.wpt.getTestResults(self.testId, function(err, data) {
var docTime = parseInt(data.response.data.average.firstView.docTime);
self.debug('WebPageTestResults received [docTime='+docTime+']');
self.timer.stop();
if(self.userUrl){
self.callback(null, docTime, {}, { url: self.userUrl });
}else{
self.callback(null, docTime, {});
}
});
}else{
self.testStatusTimeout = setTimeout(self.checkTestStatus.bind(self), 5000);
}
});
};

/**
* Timeout callback
*
* @api private
*/
WebPageTestPoller.prototype.timeoutReached = function() {
this.debug('WebPageTestPoller timeoutReached call');
WebPageTestPoller.super_.prototype.timeoutReached.call(this);
var self = this;
if(typeof this.timeout != undefined){
this.wpt.cancelTest(this.testId, function(err,data){
self.debug('WebPageTest test started [testId='+self.testId+']');
});
}
};

module.exports = WebPageTestPoller;

0 comments on commit 8657179

Please sign in to comment.