Skip to content

Commit

Permalink
Merge pull request #1 from firstandthird/pre-rel
Browse files Browse the repository at this point in the history
First
  • Loading branch information
dawnerd authored Jan 6, 2018
2 parents 3004587 + a39c749 commit f61bb03
Show file tree
Hide file tree
Showing 9 changed files with 311 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 2
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
3 changes: 3 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.editorconfig
.node-version
test
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
language: node_js
node_js:
- "9"
- "8"

after_script: "npm run coveralls"
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,29 @@
# hapi-healthcheck
server monitoring


### Options:
- `token` - Optional token to secure the endpoint.
- `endpoint` - Route to use. Defaults to `/health`
- `checks` - array objects for each check.
- `name` - Name of the check, used as the key in the response json.
- `method` - server method to call. Will be called as `async method(request, options)`. Function should return json.
- `options` - optional data to pass to the method.

### Example output:

```json
{
"host": "sorrynotsorry.local",
"env": "test",
"uptime": 0,
"cpu": { "user": 384085, "system": 48978 },
"memory": {
"rss": 47497216,
"heapTotal": 32874496,
"heapUsed": 18066608,
"external": 518509
},
"customCheck": { "test": 1 }
}
```
54 changes: 54 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const async = require('async');
const Boom = require('boom');
const str2fn = require('str2fn');

const defaults = {
token: false,
endpoint: '/health',
checks: []
};

const register = function(server, options) {
const settings = Object.assign({}, defaults, options);

server.route({
method: 'get',
path: settings.endpoint,
async handler(request, h) {
if (settings.token && settings.token !== request.query.token) {
throw Boom.unauthorized();
}

const output = {
host: server.info.host,
env: process.env.NODE_ENV,
uptime: Math.floor(process.uptime()),
cpu: process.cpuUsage(),
memory: process.memoryUsage()
};

await async.each(settings.checks, async check => {
if (!check.name || !check.method) {
throw new Boom('Invalid check');
}

output[check.name] = await str2fn.execute(
check.method,
server.methods,
{
request,
options: check.options
}
);
});

return output;
}
});
};

exports.plugin = {
once: true,
pkg: require('./package.json'),
register
};
52 changes: 52 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "hapi-healthcheck",
"version": "1.0.0",
"description": "Server monitoring",
"main": "index.js",
"scripts": {
"test": "lab --leaks -e test -c ",
"coveralls": "lab -r lcov | coveralls"
},
"engine": {
"node": ">=8.0.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/firstandthird/hapi-healthcheck.git"
},
"keywords": [
"hapi",
"healthcheck",
"monitoring"
],
"eslintConfig": {
"extends": "firstandthird",
"rules": {
"no-underscore-dangle": 0
},
"parserOptions": {
"ecmaVersion": 2017
}
},
"author": "First+Third",
"license": "MIT",
"bugs": {
"url": "https://github.com/firstandthird/hapi-healthcheck/issues"
},
"homepage": "https://github.com/firstandthird/hapi-healthcheck#readme",
"dependencies": {
"async": "^2.6.0",
"boom": "^7.1.1",
"str2fn": "^3.0.0"
},
"devDependencies": {
"code": "^5.1.2",
"coveralls": "^3.0.0",
"eslint": "^4.11.0",
"eslint-config-firstandthird": "^4.0.1",
"eslint-plugin-import": "^2.6.1",
"hapi": "^17.2.0",
"lab": "^15.1.2",
"nodemon": "^1.14.7"
}
}
158 changes: 158 additions & 0 deletions test/healthcheck.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
const hapi = require('hapi');
const Lab = require('lab');
const lab = exports.lab = Lab.script();
const code = require('code');
const wreck = require('wreck');
const hapiHealthcheck = require('../index.js');
let server;

lab.beforeEach(() => {
server = new hapi.Server({ port: 8000 });
});

lab.afterEach(async () => {
await server.stop();
});

lab.test('default options', async() => {
await server.register(hapiHealthcheck);
await server.start();

const result = await wreck.get('http://localhost:8000/health', { json: 'force' });

code.expect(result.payload).to.be.an.object();
code.expect(result.payload.host).to.equal(server.info.host);
code.expect(result.payload.env).to.equal(process.env.NODE_ENV);
code.expect(result.payload.uptime).to.exist();
code.expect(result.payload.cpu).to.be.an.object();
code.expect(result.payload.memory).to.be.an.object();
});

lab.test('token enabled but not passed', async() => {
await server.register({
plugin: hapiHealthcheck,
options: {
token: '1234'
}
});
await server.start();

try {
await wreck.get('http://localhost:8000/health', { json: 'force' });
} catch (e) {
code.expect(e.output.statusCode).to.equal(401);
}
});

lab.test('token passed', async() => {
await server.register({
plugin: hapiHealthcheck,
options: {
token: '1234'
}
});
await server.start();

const result = await wreck.get('http://localhost:8000/health?token=1234', { json: 'force' });

code.expect(result.payload).to.be.an.object();
code.expect(result.payload.host).to.equal(server.info.host);
code.expect(result.payload.env).to.equal(process.env.NODE_ENV);
code.expect(result.payload.uptime).to.exist();
code.expect(result.payload.cpu).to.be.an.object();
code.expect(result.payload.memory).to.be.an.object();
});


lab.test('custom checks', async() => {
server.method('get.test', () => ({
test: 1
}));

server.method('get.test2', (request, options) => ({
test: options.testNumber
}));

await server.register({
plugin: hapiHealthcheck,
options: {
checks: [
{
name: 'test1',
method: 'get.test'
},
{
name: 'test2',
method: 'get.test2(request, options)',
options: {
testNumber: 2
}
}
]
}
});
await server.start();

const result = await wreck.get('http://localhost:8000/health', { json: 'force' });

code.expect(result.payload).to.be.an.object();
code.expect(result.payload.host).to.equal(server.info.host);
code.expect(result.payload.env).to.equal(process.env.NODE_ENV);
code.expect(result.payload.uptime).to.exist();
code.expect(result.payload.cpu).to.be.an.object();
code.expect(result.payload.memory).to.be.an.object();
code.expect(result.payload.test1).to.be.an.object();
code.expect(result.payload.test1.test).to.equal(1);
code.expect(result.payload.test2).to.be.an.object();
code.expect(result.payload.test2.test).to.equal(2);
});

lab.test('check missing name', async() => {
server.method('get.test', () => ({
test: 1
}));

await server.register({
plugin: hapiHealthcheck,
options: {
checks: [
{
method: 'get.test'
}
]
}
});
await server.start();

try {
await wreck.get('http://localhost:8000/health', { json: 'force' });
code.fail('something wrong');
} catch (e) {
code.expect(e).to.exist();
}
});

lab.test('check missing method', async() => {
server.method('get.test', () => ({
test: 1
}));

await server.register({
plugin: hapiHealthcheck,
options: {
checks: [
{
name: 'test'
}
]
}
});
await server.start();

try {
await wreck.get('http://localhost:8000/health', { json: 'force' });
code.fail('something wrong');
} catch (e) {
code.expect(e).to.exist();
}
});

0 comments on commit f61bb03

Please sign in to comment.