A django app that provides health check endpoints for vital services.
It is often useful to get the status of services from the perspective of the application that needs them. django-vitals provides a simple mechanism for writing a running health checks. These checks can then be exposed via an endpoint:
{
"ok": [
"DatabaseCheck",
"CacheCheck",
"StorageCheck"
],
"failed": {}
}Which in the above case, would return a status code of 200
If something is down:
{
"ok": [
"DatabaseCheck",
"CacheCheck",
"StorageCheck"
],
"failed": {
"OtherMicroServiceEndpointCheck": [
"Endpoint http://suchabadsite11112222.com unreachable: Failed to establish a new connection: [Errno -2] Name or service not known"
]
}
}a http code 500 is returned instead.
Subsets of checks can be run by passing the check parameter to the endpoint: ?checks=DatabaseCheck,CacheCheck
This can be particularity useful when used along with load balancers, container orchestration and other infrastructure tools that can take automatic actions when problems arise.
Tested with all combinations of:
- Python 3.4+
- Django 1.8+
Python 2.7 probably works, but I have no interest in testing it. Support will be on a best effort basis.
Install the package from pypi:
pip install django-vitals
Add vitals to INSTALLED_APPS:
INSTALLED_APPS = (
...
'vitals'
...
)Add vitals.urls to your urlconf:
urlpatterns = [
...
url(r'^healthz/', include('vitals.urls', namespace='vitals')),
...
]Visit the url in your browser.
That's it if all you want is the default checks (DatabaseCheck, CacheCheck, StorageCheck)
HTTPCheck is included but not enabled by default.
By default 3 health checks are run: DatabaseCheck, CacheCheck and StorageCheck.
Add VITALS_ENABLED_CHECKS to your settings.py to customize:
VITALS_ENABLED_CHECKS = [
{
'NAME': 'DatabaseCheck',
'CLASS': 'vitals.checks.DatabaseCheck'
},
{
'NAME': 'CacheCheck',
'CLASS': 'vitals.checks.CacheCheck'
},
{
'NAME': 'StorageCheck',
'CLASS': 'vitals.checks.StorageCheck'
},
{
'NAME': 'HTTPCheck',
'CLASS': 'vitals.checks.HTTPCheck',
'OPTIONS': {
'url': 'https://google.com'
}
}
]Options: None
Iterates over every database in settings.DATABASES and attempts to access the list of tables for each.
Options: None
Iterates over every cache in settings.CACHES and attempts to set a value, get it and remove it.
Options: None
Using the default storage backend, attempts to write a small file and delete it.
Options: url
Attempts to GET the url provided by the url option. Will fail if the GET results in anything other than a 200 response code.
You are not limited to the included health checks. To write a custom check, simply subclass BaseHealthCheck
and implement the check() method:
from vitals.checks import BaseHealthCheck
class MyHealthCheck(BaseHealthCheck):
def check(self):
assert 2 == 2Any exceptions thrown by your check will be added as errors. You can also manually add errors using self.add_error(error):
from vitals.checks import BaseHealthCheck
class MyHealthCheck(BaseHealthCheck):
def check(self):
try:
assert 1 == 2
except AssertionError as exc:
self.add_error('Strange error! {}'.format(exc))Arguments can be passed to health checks by setting the OPTIONS key in settings:
VITALS_ENABLED_CHECKS = [
{
'NAME': 'MyFailingHealthCheck',
'CLASS': 'foo.MyHealthCheck',
'OPTIONS': {
'number': 3
}
}
]They will be passed a kwargs to your class constructor:
from vitals.checks import BaseHealthCheck
class MyHealthCheck(BaseHealthCheck):
def __init__(self, *args, **kwargs):
self.number = kwargs.pop('number')
super(MyHealthCheck, self).__init__(*args, **kwargs)
def check(self):
assert self.number == 2Add your custom checks to VITALS_ENABLED_CHECKS in settings.py providing the path to them in the CLASS key.