Django cookbook · Beginner

Add health checks and structured logging

Load balancers can't tell if the app is ready, and logs are unstructured text that's hard to search.

Create a free account to save this page, take notes and track your progress. Sign in

Approach

Expose a cheap liveness endpoint and a readiness endpoint that checks the database, and configure LOGGING to emit JSON lines to stdout with request context.

Solution

# ops/views.py
from django.db import connection
from django.http import JsonResponse
from django.views.decorators.cache import never_cache


@never_cache
def live(request):
    return JsonResponse({"status": "ok"})


@never_cache
def ready(request):
    try:
        with connection.cursor() as cursor:
            cursor.execute("SELECT 1")
    except Exception:
        return JsonResponse({"status": "database unavailable"}, status=503)
    return JsonResponse({"status": "ok"})


# settings.py
LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "json": {
            "()": "logging.Formatter",
            "fmt": '{"time": "%(asctime)s", "level": "%(levelname)s", "logger": "%(name)s", "message": "%(message)s"}',
        }
    },
    "handlers": {"stdout": {"class": "logging.StreamHandler", "formatter": "json"}},
    "root": {"handlers": ["stdout"], "level": "INFO"},
    "loggers": {"django.db.backends": {"level": "WARNING"}},
}

Pitfalls

  • Readiness checks that call slow external services, making the whole app "unready" when one dependency blips.
  • Health endpoints behind authentication or ALLOWED_HOSTS mismatches (load balancers use IPs).
  • Logging request bodies with passwords or tokens.

Variations

  • Use python-json-logger or structlog for proper JSON escaping and context variables.
  • Add OpenTelemetry instrumentation for traces across services.

Further reading: Logging

Reference: https://docs.djangoproject.com/en/6.0/topics/logging/

More Django recipes

Was this page helpful?