Skip to main content

Logging

Overview

SpeedPy uses django-structlog for structured logging. It provides consistent, machine-parseable log output with automatic request context binding.

Configuration

The logging setup in project/settings.py includes three formatters:

  • plain_console — human-readable console output (used by default)
  • json_formatter — JSON output for log aggregation services
  • key_value — key=value format
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"json_formatter": {
"()": structlog.stdlib.ProcessorFormatter,
"processor": structlog.processors.JSONRenderer(),
},
"plain_console": {
"()": structlog.stdlib.ProcessorFormatter,
"processor": structlog.dev.ConsoleRenderer(),
},
},
"handlers": {
"console": {"class": "logging.StreamHandler", "formatter": "plain_console"}
},
"loggers": {"": {"handlers": ["console"], "level": "DEBUG"}},
}

Middleware

The structlog request middleware is included to automatically bind request data (user, IP, request ID) to log entries:

MIDDLEWARE = [
...
"django_structlog.middlewares.RequestMiddleware",
]

DJANGO_STRUCTLOG_CELERY_ENABLED = True
DJANGO_STRUCTLOG_COMMAND_LOGGING_ENABLED = True

Usage

import structlog

logger = structlog.get_logger(__name__)

def my_view(request):
logger.info("processing_request", user_id=request.user.id)
try:
result = do_something()
logger.info("processing_complete", result=result)
except Exception:
logger.exception("processing_failed")

Key practices:

  • Use structlog.get_logger(__name__) at module level
  • Pass context as keyword arguments, not in the message string
  • Use snake_case for event names
  • Use logger.exception() for errors (automatically includes traceback)

Celery Integration

Structlog is also configured for Celery workers in project/celeryapp.py via DjangoStructLogInitStep. This ensures Celery tasks get the same structured logging format.

from django_structlog.celery.steps import DjangoStructLogInitStep

app.steps["worker"].add(DjangoStructLogInitStep)

Switching to JSON in Production

To output JSON logs (for services like Datadog, Elastic, etc.), change the handler formatter:

"handlers": {
"console": {"class": "logging.StreamHandler", "formatter": "json_formatter"}
},