Collect and run healthchecks¶
Given you have healthchecks, there are two main ways to collect and run healthchecks:
- run a shell command:
- using hospital-cli command;
- using nose;
- using py.test.
- perform GET requests to a web service: using hospital.wsgi module...
- with Chaussette, Gunicorn or Circus;
- with twod.wsgi and Django;
- as a (basic) standalone server with builtin hospital-serve command.
If you want to setup another runner, notice that you can use the is_healthcheck() function to verify whether an object is a healthcheck or not.
hospital-cli¶
You can use hospital-cli to collect and run healthchecks in a shell session:
$ hospital-cli hospital.healthchecks.predictable
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
See hospital-cli --help for detailed usage and options.
Nose¶
Here are guidelines to collect and run healthchecks with Nose test runner [1]. In the examples below, we run health checks of hospital project.
$ nosetests --all-modules --attr='is_healthcheck' hospital.healthchecks.predictable
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
Reciprocally, you may want to skip healthchecks when you run tests. With nose, it could be:
$ nosetests --all-modules --attr='!is_healthcheck' hospital.healthchecks
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
Tip
–all-modules option [2] makes Nose collect tests in all modules. Without the option, it would have collected modules or packages named “tests”, and not “healthchecks”.
py.test¶
hospital provides a pytest plugin to run healthchecks. It registers a pytest marker [3] called “healthcheck”.
$ py.test -m healthcheck foo
======================================== test session starts ========================================
platform darwin -- Python 2.7.5 -- py-1.4.20 -- pytest-2.5.2
plugins: hospital
collected 3 items
foo/test_foo.py ..
============================= 1 tests deselected by "-m 'healthcheck'" ==============================
============================== 2 passed, 1 deselected in 0.01 seconds ===============================
In the example above, we see that three tests were collected, and two of those were health checks.
Tests that use hospital’s healthcheck() decorator are automatically marked with @pytest.mark.healthcheck.
As another example, here is how to run only non-healthchecks:
$ py.test -m "not healthcheck" foo
======================================== test session starts ========================================
platform darwin -- Python 2.7.5 -- py-1.4.20 -- pytest-2.5.2
plugins: hospital
collected 3 items
foo/test_foo.py .
=========================== 2 tests deselected by "-m 'not healthcheck'" ============================
============================== 1 passed, 2 deselected in 0.01 seconds ===============================
hospital-serve¶
hospital.wsgi embeds a basic HTTP server:
$ hospital-serve hospital.healthchecks.predictable
Serving on 0.0.0.0 port 1515...
See hospital-serve --help for detailed usage and options.
Each time you perform a GET on the server’s root, healthchecks are collected and run.
The status code of the response is 200 in case all healthchecks passed, else it is 500.
$ curl -X GET -I http://localhost:1515/
HTTP/1.0 200 OK
Date: Fri, 28 Feb 2014 13:19:08 GMT
Server: WSGIServer/0.1 Python/2.7.5+
Content-Type: application/json; charset=utf-8
Content-Length: 520
The output is JSON:
{
"status": "pass",
"details": [
{
"test": "Health checks are collected.",
"status": "pass"
}
],
"summary": {
"skip": 0,
"pass": 1,
"expected_failure": 0,
"error": 0,
"fail": 0,
"total": 1,
"unexpected_success": 0
}
}
Gunicorn¶
You can use hospital.wsgi.application WSGI endpoint with Gunicorn. Setup the list of healthchecks to run in HEALTHCHECKS environment variable (space separated).
export HEALTHCHECKS='hospital.healthchecks.predictable'
gunicorn -w 4 hospital.wsgi:application
Which can also be written in a single line:
HEALTHCHECKS='hospital.healthchecks.predictable' gunicorn -w 4 hospital.wsgi:application
See Gunicorn documentation [4] for details.
Chaussette¶
You can use hospital.wsgi.application WSGI endpoint with Chaussette. Setup the list of healthchecks to run in HEALTHCHECKS environment variable (space separated).
export HEALTHCHECKS='hospital.healthchecks.predictable'
chaussette hospital.wsgi.application
Which can also be written in a single line:
HEALTHCHECKS='hospital.healthchecks.predictable' chaussette hospital.wsgi.application
See Chaussette documentation [5] for details.
Circus¶
Here is a sample Circus configuration serving “hospital.healthchecks.predictable” healthchecks on port 2014, using Chaussette and a virtual environnement.
[watcher:yourproject-healthchecks]
# Service command.
cmd = bin/chaussette --fd $(circus.sockets.yourproject-healthchecks) hospital.wsgi.application
numprocesses = 1
use_sockets = True
copy_env = True
working_dir = path/to/your-virtualenv
# Stdout logs.
stdout_stream.class = FileStream
stdout_stream.filename = /var/log/chaussette/wsgi_healthchecks_out.log
stdout_stream.time_format = [%Y/%m/%d | %H:%M:%S]
# Stderr logs.
stderr_stream.class = FileStream
stderr_stream.filename = /var/log/chaussette/wsgi_healthchecks_err.log
stderr_stream.time_format = [%Y/%m/%d | %H:%M:%S]
[socket:yourproject-healthchecks]
host = 127.0.0.1
port = 2014
[env:yourproject-healthchecks]
HEALTHCHECKS = hospital.healthchecks.predictable
See Circus documentation [6] for details.
twod.wsgi and Django¶
You can use twod.wsgi and hospital.wsgi.HealthCheckApp to serve healthchecks with Django [7]. In your project’s urls.py module:
from django.core.urlresolvers import patterns
from twod.wsgi import make_wsgi_view
from hospital.wsgi import HealthCheckApp
urlpatterns = patterns('',
# ...
(r'^healthchecks(/.*)$', make_wsgi_view(HealthCheckApp(discover=['hospital.healthchecks.predictable']))),
# ...
)
See twod.wsgi documentation [8] for details.
Notes & references
[1] | https://pypi.python.org/pypi/nose |
[2] | http://nose.readthedocs.org/en/latest/usage.html#cmdoption–all-modules |
[3] | http://pytest.org/latest/mark.html |
[4] | http://gunicorn.org/ |
[5] | https://pypi.python.org/pypi/chaussette |
[6] | https://circus.readthedocs.org/en/latest/ |
[7] | https://www.djangoproject.com/ |
[8] | https://pythonhosted.org/twod.wsgi/embedded-apps.html |