Tutorial Part 2: Auto-generating conn-check config for a Django app =================================================================== Hello World (again) ------------------- Let's assume that you've actually created the ``Hello World`` service from :doc:`part 1 ` as a `Django app `_, and you think to yourself: *"Hang on, aren't all these connections I want conn-check to check for me already defined in my Django settings module?"* conn-check-configs ------------------ Yes, yes they are, and with the handy-dandy `conn-check-configs `_ package you can automatically generate conn-check config YAML from a range of standard Django settings values (in theory from other environments too, such as `Juju `_, but for now just Django). exempli gratia -------------- Given the following ``settings.py`` in our *HWaaS* app: .. code-block:: python INSTALLED_APPS = [ 'hwaas' ] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'HOST': 'gibson.hwass.internal', 'NAME': 'hwaas_production', 'PASSWORD': '123456asdf', 'PORT': 11211, 'USER': 'hwaas', } CACHES = { 'default': { 'LOCATION': 'freeside.hwaas.internal:11211', 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', }, } PROXY_HOST = 'countzero.hwaas.internal' PROXY_PORT = 8080 TRANSLATE_API_KEY = 'BLAH' We can create a ``settings-to-conn-check.py`` script with the least possible effort like so: .. code-block:: python #!/usr/bin/env python from conn_check_configs.django import run if __name__ == '__main__': run() This will output *postgresql* and *memcached* checks to similar our hand-written config: .. code-block:: sh $ chmod +x settings-to-conn-check.py $ ./settings-to-conn-check.py -f cc-config.yaml -m hwaas.settings $ cat cc-config.yaml .. code-block:: yaml - type: postgresql database: hwaas_production host: gibson.hwaas.internal port: 5432 username: hwaas password: 123456asdf - type: memcached host: freeside.hwaas.internal port: 11211 Customising generated checks ---------------------------- In order to generate the checks we need for Squid / Google Translate API, we can add some custom callbacks: .. code-block:: python #!/usr/bin/env python from conn_check_configs.django import run, EXTRA_CHECK_MAKERS def make_proxied_translate_check(settings, options): checks = [] if settings['PROXY_HOST']: checks.append({ 'type': 'http', 'url': 'https://www.googleapis.com/language/translate/v2?q=' 'Hello%20World&target=de&source=en&key={}'.format( settings['TRANSLATE_API_KEY']), 'proxy_host': settings['PROXY_HOST'], 'proxy_port': int(settings.get('PROXY_PORT', 8080)), 'expected_code': 200, }) return checks EXTRA_CHECK_MAKERS.append(make_proxied_translate_check) if __name__ == '__main__': run() In the above we define a callable which takes 2 params, ``settings`` which is a wrapper around the Django settings module, and ``options`` which is an object containing the command line arguments that were passed to the script. The ``settings`` module is not the direct settings module but a dict-like wrapper so that you can access the settings just a like a dict (using indices, ``.get`` method, etc.) To ensure ``make_proxied_translate_check`` is collected and called by the main ``run`` function we add it to the ``EXTRA_CHECK_MAKERS`` list. The above generates our required HTTP check: .. code-block:: yaml - type: http url: https://www.googleapis.com/language/translate/v2?q=Hello%20World&target=de&source=en&key=BLAH proxy_host: countzero.hwaas.internal proxy_port: 8080 expected_code: 200 A note on statstd checks ------------------------ Getting more operational visibility on how *HWaaS* runs would be great, wouldn't it? So let's add some metrics collection using `StatsD `_, and as luck would have it we can get a lot for *nearly free* with the `django-statsd `_, after adding it to our dependencies we update our ``settings.py`` to include: .. code-block:: python INSTALLED_APPS = [ 'hwaas' 'django_statsd', ] MIDDLEWARE_CLASSES = [ 'django_statsd.middleware.GraphiteMiddleware', ] STATSD_CLIENT = 'django_statsd.clients.normal' STATSD_HOST = 'bigend.hwaas.internal' STATSD_PORT = 10021 **Note**: You don't actually need the django-statsd app to have conn-check-configs generate statsd checks, only the use of ``STATSD_HOST`` and ``STATSD_PORT`` in your settings module matters. Another run of our ``settings-to-conn-check.py`` script will result in the extra statsd check: .. code-block:: yaml - type: udp host: bigend.hwaas.internal port: 10021 send: conncheck.test:1|c expect: As you can see this is just a generic UDP check that attempts to send an incremental counter metric to the statsd host. Unfortunately the fire-and-forget nature of this use of statsd/UDP will not error in a number of common situations (the simplest being that statsd is not running on the target host, or even a routing issue along the way). It will catch simple problems such as not being able to open up the local UDP port to send from, but that's usually not enough. If you use a third-party implementation of statsd, such as `txStatsD `_ then you might have the ability to define a pair of health check strings, for example by changing the send and expect values in the ``STATSD_CHECK`` dict we can send and expect different strings: .. code-block:: python #!/usr/bin/env python from conn_check_configs.django import run, STATSD_CHECK STATSD_CHECK['send'] = 'Hakuna' STATSD_CHECK['expect'] = 'Matata' if __name__ == '__main__': run() Which generates this check: .. code-block:: yaml - type: udp host: bigend.hwaas.internal port: 10021 send: Hakuna expect: Matata In the above we would configure our txStatD (for example) instance to respond to the string ``Hakuna`` with the string ``Matata``, which would catch pretty much all the possible issues with contacting our metrics service.