Skip to content

Commit

Permalink
Health check for Connect.
Browse files Browse the repository at this point in the history
Usage:

    var connect = require('connect');
    var healthCheck = require('tagged-health-check');
    var app = connect();

    // Default health check on `/health.json`:
    app.use(healthCheck());

    // Custom health check path:
    app.use(healthCheck('/my/custom/health.json');

The health check responds with the following data:

    {
      "status": "OK",
      "arch": "x64",
      "pid": 1234,
      "uptime": 456,
      "memory": {
        "rss": 15208448,
        "heapTotal": 7195904,
        "heapUsed": 3183048
      }
    }
  • Loading branch information
Hector Virgen committed Aug 6, 2014
1 parent e60d7dd commit aa23ebf
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 85 deletions.
8 changes: 4 additions & 4 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ var path = require('path');

module.exports = function(grunt) {
var TEST_RUNNER = path.join(process.cwd(), 'test', 'test_runner');
var ALL_TESTS = 'test/**/*_test.js';
var ALL_TESTS = 'test/**/*_test.coffee';

// NPM tasks, alphabetical
grunt.loadNpmTasks('grunt-contrib-clean');
Expand All @@ -20,7 +20,7 @@ module.exports = function(grunt) {
// Documentation
docco: {
main: {
src: ['lib/**/*.js'],
src: ['lib/**/*.coffee', 'lib/**/*.js'],
options: {
output: 'docs/'
}
Expand Down Expand Up @@ -76,8 +76,8 @@ module.exports = function(grunt) {
spawn: false
},
files: [
'lib/**/*.js',
'test/**/*.js'
'lib/**/*.coffee',
'test/**/*.coffee'
],
tasks: ['mochaTest:test']
}
Expand Down
88 changes: 27 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,36 @@
Tagged NPM Seed
===============
Health check for Connect.
=========================

A blueprint for creating NPM packages.
Installation:
-------------

## Files and Directory Structure
$ npm install tagged-health-check

The following describes the various files in this repo and the directory structure.
Usage:
------

**Note:** Files and directories prefixed by `*` are auto-generated and excluded from the
repository via `.gitignore`.
The health check can be registered as middleware in any Connect app:

.
├── Gruntfile.js # grunt task configuration
├── README.md # this file
├── *docs # autogenerated documentation
│   └── *index.html # each JS file in `./lib` has a corresponding HTML file for documentation
├── lib # all code for this library will be placed here
│   └── index.js # main entry point for your npm package
├── *node_modules # all dependencies will be installed here by npm
├── package.json # description of this package for npm, including dependency lists
└── test # unit test configuration, reports, and specs
├── *coverage.html # code coverage report
├── lib # specs go here, preferably with a 1:1 mapping to code in `./lib`
│   └── index_test.js # example spec for `./lib/index.js`
├── mocha.opts # runtime options for mocha
└── test_runner.js # configures mocha environment (e.g. chai, sinon, etc.)
var connect = require('connect');
var healthCheck = require('tagged-health-check');
var app = connect();

## What's Included?
// Default health check on `/health.json`:
app.use(healthCheck());

### Grunt
// Custom health check path:
app.use(healthCheck('/my/custom/health.json');

Grunt is a JavaScript task runner to automate common actions. The Tagged NPM Package Seed
supports the following built-in grunt tasks:
The health check responds with the following data:

**test**

Runs all unit tests through mocha.

$ grunt test

**coverage**

Runs all unit tests and generates a code coverage report in `./test/coverage.html`

$ grunt coverage

**watch**

Automatically runs mocha tests each time a file changes in `./lib` or `./test`.

$ grunt watch

**docs**

Generates documentation for all JS files within `./lib` using docco. Documentation is
written to `./docs`.

$ grunt docs

**clean**

Deletes all auto-generated files, including `./docs` and `./test/coverage.html`

### Mocha, Sinon, Chai, Blanket

The ultimate TDD environment for node. Place your specs in `./test/lib`, and run `grunt test`
to run them.

See `./test/lib/index_test.js` for examples.
{
"status": "OK",
"arch": "x64",
"pid": 1234,
"uptime": 456,
"memory": {
"rss": 15208448,
"heapTotal": 7195904,
"heapUsed": 3183048
}
}
19 changes: 19 additions & 0 deletions lib/health_check.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Middleware for connect that responds with a health check
# if the request path matches the provided path
middleware = (path, req, res, next) ->
return next() if req.path != path

res.send
status: 'OK'
arch: process.arch
pid: process.pid
uptime: process.uptime()
memory: process.memoryUsage()

# Returns a middleware function
# bound with the provided path.
# If omitted, the path defaults to `/health.json`.
factory = (path = '/health.json') -> middleware.bind @, path

# Expose the factory
module.exports = factory
4 changes: 2 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// Whatever is exported here will be available to the consumers of your npm module.
module.exports = {};
require('coffee-script');
module.exports = require('./health_check');
19 changes: 11 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
{
"name": "tagged-npm-seed",
"version": "0.0.0",
"description": "Tagged's seed project for NPM packages",
"name": "tagged-health",
"version": "0.0.1",
"description": "Health check middleware for connect",
"main": "lib/index.js",
"scripts": {
"test": "grunt test"
},
"repository": {
"type": "git",
"url": "https://github.com/tagged/npm-seed.git"
"url": "https://github.com/tagged/connect-health-check.git"
},
"keywords": [
"api",
"tagged",
"client"
"health",
"connect"
],
"author": "Web Team Awesome",
"license": "MIT",
"bugs": {
"url": "https://github.com/tagged/npm-seed/issues"
"url": "https://github.com/tagged/connect-health-check/issues"
},
"homepage": "https://github.com/tagged/npm-seed",
"homepage": "https://github.com/tagged/connect-health-check",
"devDependencies": {
"blanket": "^1.1.6",
"chai": "^1.9.1",
Expand All @@ -31,5 +31,8 @@
"grunt-mocha-test": "^0.11.0",
"mocha": "^1.20.1",
"sinon": "^1.10.3"
},
"dependencies": {
"coffee-script": "^1.7.1"
}
}
74 changes: 74 additions & 0 deletions test/lib/health_check_test.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
healthCheck = require "#{LIB_DIR}/health_check"

describe 'healthCheck', ->
describe 'middleware', ->
beforeEach ->
@req = path: '/'
@res = send: sinon.spy()
@next = sinon.spy()

it 'is a function', ->
healthCheck.should.be.a 'function'

it 'returns a function', ->
healthCheck().should.be.a 'function'

describe 'default route', ->
beforeEach ->
@middleware = healthCheck() # use default options

it 'calls `next()` if `req.path` does not match default `/health.json`', ->
@middleware @req, @res, @next
@next.called.should.be.true

it 'responds with health object if path matches default `/health.json`', ->
@req.path = '/health.json'
@middleware @req, @res, @next
@res.send.calledOnce.should.be.true
@res.send.lastCall.args[0].should.be.an 'object'

describe 'configurable route', ->
beforeEach ->
@middleware = healthCheck '/test/health.json' # configurable route

it 'responds with health object if path matches configured route', ->
@req.path = '/test/health.json'
@middleware @req, @res, @next
@res.send.calledOnce.should.be.true
@res.send.lastCall.args[0].should.be.an 'object'

it 'calls next() if path does not match default `/health.json`', ->
@req.path = '/health.json' # should not match, because the default was overwritten
@middleware @req, @res, @next
@next.called.should.be.true

describe 'health object', ->
beforeEach ->
@middleware = healthCheck() # use default options
@req.path = '/health.json' # ensure health object is returned
sinon.stub(process, 'uptime').returns('uptime_canary')
sinon.stub(process, 'memoryUsage').returns('memory_canary');

afterEach ->
process.uptime.restore()
process.memoryUsage.restore()

it 'contains `status` property set to "OK"', ->
@middleware @req, @res, @next
@res.send.lastCall.args[0].should.have.property 'status', 'OK'

it 'contains `arch` property set to `process.arch`', ->
@middleware @req, @res, @next
@res.send.lastCall.args[0].should.have.property 'arch', process.arch

it 'contains `pid` property set to `process.pid`', ->
@middleware @req, @res, @next
@res.send.lastCall.args[0].should.have.property 'pid', process.pid

it 'contains `uptime` property set to `process.uptime()`', ->
@middleware @req, @res, @next
@res.send.lastCall.args[0].should.have.property 'uptime', 'uptime_canary'

it 'contains `memory` property set to `process.memoryUsage()`', ->
@middleware @req, @res, @next
@res.send.lastCall.args[0].should.have.property 'memory', 'memory_canary'
10 changes: 0 additions & 10 deletions test/lib/index_test.js

This file was deleted.

1 change: 1 addition & 0 deletions test/test_runner.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require('coffee-script');
var path = require('path');

// Use constant to help with resolving path to lib code within test files
Expand Down

0 comments on commit aa23ebf

Please sign in to comment.