Comparing version 0.2.1 to 0.2.2
@@ -1,4 +0,12 @@ | ||
### 0.2.1-pre | ||
* | ||
### 0.2.2-pre | ||
* Add result timestamp (when check is started) | ||
* Rename http(s) attributes: statusCodes -> statusCode, texts -> text | ||
* All checker attributes handle <attribute> and <attribute>-or | ||
* Add health#clearCache | ||
* All checker attributes handle regular expression | ||
* Add threshold support to resource group | ||
### 0.2.1 | ||
* Add file checker | ||
### 0.2.0 | ||
@@ -5,0 +13,0 @@ * Add result model |
@@ -1,13 +0,27 @@ | ||
var fs = require('fs'), | ||
Result = require('../result'); | ||
var checker = require('../checker'), | ||
fs = require('fs'), | ||
Result = require('../result'), | ||
validator = require('validator'); | ||
/** | ||
* Health check a file resource. | ||
* | ||
* @param {Object} setup: file check setup with fields: | ||
* - uri: a resource URI to check | ||
* - mode: a 3-digit file mode, e.g. 777, 644 | ||
* @param {Function} cb: standard cb(err, result) callback | ||
*/ | ||
function check(setup, cb) { | ||
fs.lstat(setup.uri.replace(/^file\:\/\//, ''), function (err, stats) { | ||
var result = new Result(); | ||
if (err) { | ||
result.addError(err.message); | ||
} else { | ||
var modeString = parseInt(stats.mode.toString(8), 10).toString(); | ||
var mode = modeString.slice(modeString.length - 3, modeString.length); | ||
var modeString = parseInt(stats.mode.toString(8), 10).toString(), | ||
mode = modeString.slice(modeString.length - 3, modeString.length); | ||
checker.checkAttribute('mode', setup, _checkMode(mode), result); | ||
} | ||
result.setStatusByStats(); | ||
@@ -17,9 +31,10 @@ cb(null, result); | ||
} | ||
/* | ||
function _checkMode(result, stats, setup) { | ||
var modeString = parseInt(stats.mode.toString(8), 10).toString(), | ||
mode = modeString.slice(modeString.length - 3, modeString.length); | ||
function _checkMode(actual) { | ||
return function (expected) { | ||
validator.check(actual, 'Mode ' + actual + ' does not match the expected ' + expected).is(new RegExp(expected)); | ||
return 'Mode ' + actual + ' as expected'; | ||
}; | ||
} | ||
*/ | ||
exports.check = check; | ||
exports.check = check; |
@@ -1,3 +0,3 @@ | ||
/*jshint esnext: true */ | ||
var bag = require('bagofrequest'), | ||
checker = require('../checker'), | ||
Result = require('../result'), | ||
@@ -18,4 +18,2 @@ validator = require('validator'); | ||
const CHECKS = [ _checkStatusCodes, _checkTexts ]; | ||
var method = setup.method || 'get', | ||
@@ -30,8 +28,8 @@ opts = { | ||
CHECKS.forEach(function (check) { | ||
check(result, response, setup); | ||
}); | ||
checker.checkAttribute('statusCode', setup, _checkStatusCode(response.statusCode), result); | ||
checker.checkAttribute('text', setup, _checkText(response.body), result); | ||
result.addInfo('headers', response.headers); | ||
result.addInfo('body', response.body); | ||
cb(null, result); | ||
@@ -52,30 +50,16 @@ } | ||
function _checkStatusCodes(result, response, setup) { | ||
try { | ||
if (setup.statusCodes) { | ||
// convert to string because check#isIn does not work with number | ||
for (var i = 0, ln = setup.statusCodes.length; i < ln; i += 1) { | ||
setup.statusCodes[i] = setup.statusCodes[i].toString(); | ||
} | ||
validator.check(response.statusCode, 'Status code ' + response.statusCode + ' does not match the expected ' + setup.statusCodes.join(', ')).isIn(setup.statusCodes); | ||
result.addSuccess('Status code ' + response.statusCode + ' as expected'); | ||
} | ||
} catch (e) { | ||
result.addFailure(e.message); | ||
} | ||
function _checkStatusCode(actual) { | ||
return function (expected) { | ||
validator.check(actual, 'Status code ' + actual + ' does not match the expected ' + expected).is(new RegExp(expected)); | ||
return 'Status code ' + expected + ' as expected'; | ||
}; | ||
} | ||
function _checkTexts(result, response, setup) { | ||
if (setup.texts) { | ||
setup.texts.forEach(function (text) { | ||
try { | ||
validator.check(response.body, 'Text ' + text + ' does not exist in response body').is(new RegExp(text)); | ||
result.addSuccess('Text ' + text + ' exists in response body'); | ||
} catch (e) { | ||
result.addFailure(e.message); | ||
} | ||
}); | ||
} | ||
function _checkText(actual) { | ||
return function (expected) { | ||
validator.check(actual, 'Text ' + expected + ' does not exist in response body').is(new RegExp(expected)); | ||
return 'Text ' + expected + ' exists in response body'; | ||
}; | ||
} | ||
exports.check = check; | ||
exports.check = check; |
@@ -1,2 +0,1 @@ | ||
/*jshint esnext: true */ | ||
var mongodb = require('mongodb'), | ||
@@ -34,2 +33,2 @@ Result = require('../result'); | ||
exports.check = check; | ||
exports.check = check; |
@@ -1,2 +0,1 @@ | ||
/*jshint esnext: true */ | ||
var colors = require('colors'), | ||
@@ -40,2 +39,2 @@ util = require('util'); | ||
exports.format = format; | ||
exports.format = format; |
@@ -1,2 +0,1 @@ | ||
/*jshint esnext: true */ | ||
var util = require('util'); | ||
@@ -38,2 +37,2 @@ | ||
exports.format = format; | ||
exports.format = format; |
@@ -1,2 +0,1 @@ | ||
/*jshint esnext: true */ | ||
var _ = require('lodash'), | ||
@@ -7,2 +6,3 @@ async = require('async'), | ||
fsx = require('fs.extra'), | ||
i18n = require('i18n'), | ||
p = require('path'), | ||
@@ -29,4 +29,13 @@ url = require('url'); | ||
setup: opts.setup || 'health.json', | ||
locale: opts.locale || 'en', | ||
formatter: opts.formatter | ||
}; | ||
i18n.configure({ | ||
locales: ['en', 'id'], | ||
defaultLocale: 'en', | ||
directory: p.join(__dirname,'../locales'), | ||
updateFiles: false | ||
}); | ||
i18n.setLocale(opts.locale); | ||
} | ||
@@ -45,2 +54,9 @@ | ||
/** | ||
* Clear all cached check result for all resources. | ||
*/ | ||
Health.prototype.clearCache = function () { | ||
cache.clear(); | ||
}; | ||
/** | ||
* Execute the checks contained in setup, in parallel. | ||
@@ -76,5 +92,5 @@ * Each result will be cached depends on TTL setting for each URI, | ||
// check time in milliseconds | ||
var endTime = Date.now(); | ||
result.setDuration(endTime - startTime); | ||
result.setTimestamp(new Date(endTime)); | ||
@@ -93,3 +109,3 @@ // apply rules to each single result | ||
} else { | ||
cb(new Error('Unsupported protocol for URI ' + setup.uri)); | ||
cb(new Error(i18n.__('Unsupported protocol for URI %s', setup.uri))); | ||
} | ||
@@ -160,10 +176,26 @@ }); | ||
function _hasSuccess(members) { | ||
var hasSuccess = false; | ||
// threshold is specified as suffix in group name | ||
function _getThreshold(group) { | ||
var threshold; | ||
if (group.match(/\-[0-9]{1,3}$/)) { | ||
var elems = group.split('-'); | ||
threshold = parseInt(elems[elems.length - 1], 10); | ||
} | ||
return threshold; | ||
} | ||
function _isSuccess(members, threshold) { | ||
var successCount = 0; | ||
members.forEach(function (member) { | ||
if (member.isSuccess()) { | ||
hasSuccess = true; | ||
successCount += 1; | ||
} | ||
}); | ||
return hasSuccess; | ||
// if threshold is undefined, it's considered a success as | ||
// long as the calculated threshold is greater than 0 (at least one success). | ||
// if threshold is defined, then it's considered a success | ||
// when the calculated threshold is equal or greater to the threshold | ||
return threshold ? | ||
(successCount * 100 / members.length) >= threshold : | ||
(successCount * 100 / members.length) > 0; | ||
} | ||
@@ -174,12 +206,12 @@ | ||
indices = _.pluck(groups[group], 'index'), | ||
hasSuccess = _hasSuccess(members); | ||
isSuccess = _isSuccess(members, _getThreshold(group)); | ||
indices.forEach(function (index) { | ||
var result = results[index]; | ||
// if there's a success in a group, change all error and fail to warning | ||
if (hasSuccess) { | ||
// if group check is considered a success, change all error and fail to warning | ||
if (isSuccess) { | ||
if (result.isFail() || result.isError()) { | ||
result.warning(); | ||
} | ||
// if there's no success in a group, change warning to fail | ||
// if group check is not considered a success, change warning to fail | ||
} else { | ||
@@ -209,2 +241,2 @@ if (result.isWarning()) { | ||
module.exports = Health; | ||
module.exports = Health; |
@@ -1,2 +0,1 @@ | ||
/*jshint esnext: true */ | ||
const SUCCESS = 'success', | ||
@@ -17,2 +16,3 @@ FAIL = 'fail', | ||
this.uri = undefined; | ||
this.timestamp = undefined; | ||
this.duration = undefined; | ||
@@ -83,2 +83,10 @@ this.successes = []; | ||
Result.prototype.setTimestamp = function (timestamp) { | ||
this.timestamp = timestamp; | ||
}; | ||
Result.prototype.getTimestamp = function () { | ||
return this.timestamp; | ||
}; | ||
Result.prototype.setDuration = function (duration) { | ||
@@ -140,2 +148,14 @@ this.duration = duration; | ||
Result.prototype.addSuccesses = function (successes) { | ||
this.successes = this.successes.concat(successes); | ||
}; | ||
Result.prototype.addFailures = function (failures) { | ||
this.failures = this.failures.concat(failures); | ||
}; | ||
Result.prototype.addErrors = function (errors) { | ||
this.errors = this.errors.concat(errors); | ||
}; | ||
Result.prototype.hasSuccess = function () { | ||
@@ -157,2 +177,2 @@ return this.successes.length > 0; | ||
module.exports = Result; | ||
module.exports = Result; |
@@ -9,3 +9,3 @@ { | ||
], | ||
"version": "0.2.1", | ||
"version": "0.2.2", | ||
"homepage": "http://github.com/cliffano/health", | ||
@@ -38,2 +38,3 @@ "author": "Cliffano Subagio <blah@cliffano.com> (http://blog.cliffano.com)", | ||
"fs.extra": "1.2.1", | ||
"i18n": "0.4.1", | ||
"lodash": "1.3.1", | ||
@@ -40,0 +41,0 @@ "memory-cache": "0.0.5", |
@@ -1,2 +0,2 @@ | ||
Health [![Build Status](https://secure.travis-ci.org/cliffano/health.png?branch=master)](http://travis-ci.org/cliffano/health) [![Dependencies Status](https://david-dm.org/cliffano/health.png)](http://david-dm.org/cliffano/health) | ||
Health [![Build Status](https://secure.travis-ci.org/cliffano/health.png?branch=master)](http://travis-ci.org/cliffano/health) [![Dependencies Status](https://david-dm.org/cliffano/health.png)](http://david-dm.org/cliffano/health) [![Published Version](https://badge.fury.io/js/health.png)](http://badge.fury.io/js/health) | ||
----------- | ||
@@ -52,5 +52,6 @@ <img align="right" src="https://raw.github.com/cliffano/health/master/avatar.jpg" alt="Avatar"/> | ||
[ | ||
{ "name": "google", "uri", "http://google.com", "statusCodes": [ 200 ] }, | ||
{ "name": "gmail", "uri", "https://mail.google.com", "timeout": "1000" }, | ||
{ "name": "mongodb", "uri": "mongodb://somehost:27017", "timeout": 200, "ttl": 30000 } | ||
{ "name": "Google", "uri", "http://google.com", "statusCodes": [ 200 ] }, | ||
{ "name": "GMail", "uri", "https://mail.google.com", "timeout": "1000" }, | ||
{ "name": "MongoDB", "uri": "mongodb://somehost:27017", "timeout": 200, "ttl": 30000 }, | ||
{ "name": "Temp", "uri": "file:///tmp", "mode": "777", "ttl": 360000 } | ||
] | ||
@@ -123,12 +124,12 @@ | ||
<tr> | ||
<td>statusCodes</td> | ||
<td>statusCode</td> | ||
<td>array</td> | ||
<td>An array of acceptable response HTTP status codes, any match means status OK</td> | ||
<td>An array of acceptable response HTTP status codes</td> | ||
<td>http, https</td> | ||
<td>Optional</td> | ||
<td></td> | ||
<td>[ 200, '3xx', 409 ]</td> | ||
<td>[ 200, 409 ]</td> | ||
</tr> | ||
<tr> | ||
<td>texts</td> | ||
<td>text</td> | ||
<td>array</td> | ||
@@ -141,2 +142,11 @@ <td>An array of all texts that must exist in response body, any of them does not exist means status FAIL</td> | ||
</tr> | ||
<tr> | ||
<td>mode</td> | ||
<td>string</td> | ||
<td>3-digit file/directory mode</td> | ||
<td>file</td> | ||
<td>Optional</td> | ||
<td></td> | ||
<td>777, 644</td> | ||
</tr> | ||
</table> |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
32301
24
703
150
11
+ Addedi18n@0.4.1
+ Addeddebug@4.4.0(transitive)
+ Addedi18n@0.4.1(transitive)
+ Addedms@2.1.3(transitive)
+ Addedsprintf@0.1.5(transitive)