Skip to content

Commit

Permalink
Merge 8ef8ef9 into f171c9b
Browse files Browse the repository at this point in the history
  • Loading branch information
inadarei committed Aug 9, 2018
2 parents f171c9b + 8ef8ef9 commit 2236f36
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 36 deletions.
33 changes: 29 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ defined in the [healthcheck draft RFC](https://tools.ietf.org/html/draft-inadare

- [x] Express/Connect
- [x] Koa
- [ ] Pure Node, no frameworks
- [x] Pure Node, no frameworks

### Open to Community Contributions

Expand Down Expand Up @@ -84,14 +84,39 @@ app.listen(3535);
```javascript
const Koa = require('koa');
const app = new Koa();
const healthcheck = require("../");

const Router = require('koa-router');
const router = new Router();

const healthcheck = require("maikai");
const check = healthcheck();

app.use(check.koa());
router.get('/hello', (ctx, next) => {
ctx.body = 'Hello, World!';
});

app.use(check.koa())
.use(router.routes())
.use(router.allowedMethods());

app.listen(3535);
```

### Example for no-frameworks, pure Node implementation:

```javascript
const http = require('http');
const healthcheck = require('maikai');

http.createServer( (request, response) => {
const check = healthcheck();
const isHealthCheckCall = check.http(request, response);
if (isHealthCheckCall) return;

response.end("HELLO! This is pretty amaziiiiing");
}).listen(3535);
console.log('Server running on port 3535');
```

## Kubernetes Liveness and Readiness Probes

When implementing [Kubernetes Liveness and Readiness probes](https://cloudplatform.googleblog.com/2018/05/Kubernetes-best-practices-Setting-up-health-checks-with-readiness-and-liveness-probes.html) you may decide that each one of those
Expand Down
File renamed without changes.
11 changes: 11 additions & 0 deletions examples/serverJustHTTP.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const http = require('http');
const healthcheck = require('../');

http.createServer( (request, response) => {
const check = healthcheck();
const isHealthCheckCall = check.http(request, response);
if (isHealthCheckCall) return;

response.end("HELLO! This is pretty amaziiiiing");
}).listen(3535);
console.log('Server running on port 3535');
22 changes: 20 additions & 2 deletions lib/health.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,35 @@ class HealthCheck {
};
}

http(request, response) {
const requestPath = request.url;
if (requestPath !== this.getHealthUri()) return false;

const self = this;

(async function () {
const responseContent = await self.healthResponse(self.opts);
const httpCode = (response.status === STATUS_ERR ) ? 503 : 200;

response.writeHead(httpCode, { 'Content-Type': 'application/health+json; charset=utf-8' });
response.end(JSON.stringify(responseContent));
})();

return true;
}

addCheck (componentName, metricName, checkerPromise) {
const key = `${componentName}:${metricName}`;
this.checks[key] = checkerPromise;
this.checks[key] = {};
this.checks[key].executor = checkerPromise;
}

async healthResponse(opts) {
const response = {};
let overallStatus = STATUS_OK;
for (const prop in this.checks) {
response.details = {};
const details = await this.checks[prop]();
const details = await this.checks[prop].executor();

//require('metalogger')().info("details", details);

Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "maikai",
"version": "0.6.0",
"version": "0.7.0",
"description": "RFC-compliant health check middleware for HTTP APIs and microservices written in Node",
"author": "",
"license": "MIT",
Expand All @@ -16,9 +16,11 @@
"devDependencies": {
"blue-tape": "^1.0.0",
"coveralls": "^3.0.0",
"eslint": "^5.2.0",
"eslint": "^5.3.0",
"express": "^4.11.0",
"fakepromise": "^1.0.5",
"koa": "^2.5.2",
"koa-router": "^7.4.0",
"metalogger": "^2.2.0",
"node-fetch": "^2.2.0",
"nyc": "^12.0",
Expand Down
29 changes: 28 additions & 1 deletion test/acceptance/express-failing-check-basic-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const nf = require('node-fetch');
const log = require('metalogger')();

test('Failing Express Health Check', async t => {
const brokenserver = require('../support/failing-check-server').server;
const brokenserver = getServer();
try {
const util = require('../support/util');
const baseuri = util.serverUri(brokenserver);
Expand All @@ -26,6 +26,33 @@ test('Failing Express Health Check', async t => {
//t.end(); // async tests dont need t.end() because blue-tape.
});

function getServer() {
const express = require('express');
const app = express();
const healthcheck = require('../../lib/health')();

healthcheck.addCheck('backend', 'something', async() => {
const status = {
status : 'fail',
unusualProp : false,
metricValue: 17,
metricUnit: "tps"
};

const fakepromise = require('fakepromise');
const delayedResponse = await fakepromise.promise(50, status);
return delayedResponse;
});
app.use(healthcheck.express());

const server = app.listen(0, function () {
const port = server.address().port;
//log.info(`Test server listening at port ${port} \n`);
});

return server;
}

/*
let res = await request('http://api.froyo.io/names?gender=f', {headers});
Expand Down
6 changes: 5 additions & 1 deletion test/acceptance/express-unknown-response-status-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,15 @@ function getServer() {
const healthcheck = require('../../lib/health')();

healthcheck.addCheck('backend', 'something-malformed', async() => {
return {
const status = {
status : 'nonexistent-status',
metricValue: 17,
metricUnit: "units"
};

const fakepromise = require('fakepromise');
const delayedResponse = await fakepromise.promise(50, status);
return delayedResponse;
});
app.use(healthcheck.express());

Expand Down
78 changes: 78 additions & 0 deletions test/acceptance/express-warn-check-basic-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
const test = require('blue-tape');
const nf = require('node-fetch');
const log = require('metalogger')();
const fakepromise = require('fakepromise');

test('Failing Express Health Check', async t => {
const brokenserver = getServer();
try {
const util = require('../support/util');
const baseuri = util.serverUri(brokenserver);
const uri = `${baseuri}/health`;

const res = await nf(`${baseuri}/health`);
t.equal(res.status, 200, 'correct http status code');
const response = await res.json();

t.same(response.status, 'warn',
'correct status');
t.same(response.details["backend:something"].metricUnit, 'warnps',
'correct payload');

} catch (err) {
t.fail(err);
}
brokenserver.close();

//t.end(); // async tests dont need t.end() because blue-tape.
});

function getServer() {
const express = require('express');
const app = express();
const healthcheck = require('../../lib/health')();

healthcheck.addCheck('backend', 'healthy', async() => {

const status = {
status : 'pass',
metricValue: 'A++',
metricUnit: "grade"
};

const delayedResponse = await fakepromise.promise(50, status);
return delayedResponse;
});

healthcheck.addCheck('backend', 'something', async() => {
const status = {
status : 'warn',
unusualProp : false,
metricValue: 17,
metricUnit: "warnps"
};

const delayedResponse = await fakepromise.promise(50, status);
return delayedResponse;
});
app.use(healthcheck.express());

const server = app.listen(0, function () {
const port = server.address().port;
//log.info(`Test server listening at port ${port} \n`);
});

return server;
}

/*
let res = await request('http://api.froyo.io/names?gender=f', {headers});
//console.log(res);
console.log(res.ok);
console.log(res.status);
console.log(res.statusText);
console.log(res.headers.raw());
console.log(res.headers.get('content-type'));
console.log(await res.json());
*/
70 changes: 70 additions & 0 deletions test/acceptance/http-basic-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const test = require('blue-tape');
const nf = require('node-fetch');

test('Basic Healthy No-Frameworks Health Check', async t => {

// avoid problems if this env var is already set from wherever test was run
process.env.NODE_HEALTH_ENDPOINT_PATH = "";

const server = getServer();
const util = require('../support/util');
const baseuri = util.serverUri(server);

try {
const res = await nf(`${baseuri}/`);
t.equal(res.status, 200, 'proper http status code for /');
t.same(await res.text(), 'Hello, World!',
'proper content for /');

const res2 = await nf(`${baseuri}/health`);
t.equal(res2.status, 200, 'proper http status code for /health');
t.equal(res2.headers.get('content-type'),
'application/health+json; charset=utf-8',
'proper content type for health endpoint');
const response = await res2.json();
t.same(response.status, 'pass',
'healthcheck endpoint status works');
t.same(response.details["backend:http-downstream"].metricUnit, 'pureseconds',
'healthcheck endpoint details work');

} catch (err) {
t.fail(err);
}

server.close();

});

function getServer() {
const http = require('http');
const healthcheck = require('../../');

const server = http.createServer( (request, response) => {
const check = healthcheck();

check.addCheck('backend', 'http-downstream', async() => {
const status = {
status : 'pass',
metricValue: 17,
metricUnit: "pureseconds"
};

const fakepromise = require('fakepromise');
const delayedResponse = await fakepromise.promise(50, status);
return delayedResponse;
});

const isHealthCheckCall = check.http(request, response);
if (isHealthCheckCall) return;

response.end("Hello, World!");
});

server.listen(0, function(err) {
if (err) console.error(err) && process.exit(1);
const port = server.address().port;
//console.log(`Test server listening at port ${port} \n`);
});

return server;
}
22 changes: 20 additions & 2 deletions test/acceptance/koa-basic-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ test('Basic Healthy Koa Health Check', async t => {
const baseuri = util.serverUri(server);

try {
const res = await nf(`${baseuri}/`);
t.equal(res.status, 200, 'proper http status code for /');
t.same(await res.text(), 'Hello, World!',
'proper content for /');

const res2 = await nf(`${baseuri}/health`);
t.equal(res2.status, 200, 'proper http status code for /health');
t.equal(res2.headers.get('content-type'),
Expand All @@ -34,18 +39,31 @@ function getServer() {
const http = require('http');
const Koa = require('koa');
const app = new Koa();
const Router = require('koa-router');
const router = new Router();

router.get('/', (ctx, next) => {
ctx.body = 'Hello, World!';
});

const healthcheck = require('../../lib/health')();

healthcheck.addCheck('backend', 'koa-downstream', async() => {
return {
const status = {
status : 'pass',
metricValue: 17,
metricUnit: "picoseconds"
};

const fakepromise = require('fakepromise');
const delayedResponse = await fakepromise.promise(50, status);
return delayedResponse;
});

app.use(healthcheck.koa());
app
.use(healthcheck.koa())
.use(router.routes())
.use(router.allowedMethods());

const server = http.createServer(app.callback());

Expand Down

0 comments on commit 2236f36

Please sign in to comment.