Skip to main content

Production-ready logging and alerting for Django with minimal setup.

Project description

django-logpilot

Production-ready logging for Django with minimal setup.

Logpilot configures sensible defaults so you get readable logs in development, structured JSON in production, optional rotating files, and a request ID on every response—without spending an afternoon on LOGGING dictionaries.

Alerting hooks exist in settings for upcoming releases; today the focus is great logging out of the box.


What you get

  • Console and optional file output with rotation
  • Text or JSON format (switch per environment)
  • Request ID middleware (X-Request-ID in / out) wired into log lines
  • Root logger configured so your app’s logging.getLogger(__name__) calls show up alongside Django’s logs
  • Sensitive key redaction helper for dict-shaped data you choose to log
  • Parent directories for file_path created automatically when possible

Requirements

  • Python 3.10+
  • Django 4.2+

Install

From PyPI:

pip install django-logpilot

To try a local checkout of this repo inside another project:

pip install -e /absolute/path/to/django-logpilot

Example settings (try the full stack)

Add this to your Django settings.py (adjust INSTALLED_APPS / MIDDLEWARE if you already have entries—merge lists, don’t duplicate).

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "django_logpilot",
]

MIDDLEWARE = [
    "django_logpilot.middleware.RequestIdMiddleware",
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

# Leave handlers empty so Logpilot can apply its own config at startup.
# (See “Already using LOGGING?” below if you have a custom dict.)
LOGGING = {}

DJANGO_LOGPILOT = {
    "format": "text",
    "level": "DEBUG",
    "outputs": ["console", "file"],
    "file_path": str(BASE_DIR / "logs" / "app.log"),
    "file_max_bytes": 5 * 1024 * 1024,
    "file_backup_count": 3,
    "request_id_header": "X-Request-ID",
    "request_id_response_header": "X-Request-ID",
    "redact_keys": (
        "password",
        "secret",
        "token",
        "authorization",
        "cookie",
        "api_key",
    ),
    "alerts": {
        "enabled": False,
        "min_level": "ERROR",
        "deduplicate_for": 300,
        "channels": [],
        "slack_webhook": None,
        "email_backend": None,
    },
}

Then run the dev server and hit any page. Check:

  • Terminal — log lines with your chosen format
  • logs/app.log — same records (after the first write)
  • Response headersX-Request-ID present

To exercise your own log lines in a view or signal:

import logging

logger = logging.getLogger(__name__)

def some_view(request):
    logger.info("Hello from the app")
    ...

For JSON lines (typical in production), set "format": "json".


What actually gets logged?

Logpilot attaches handlers to the root logger (and to key django / django.request loggers). Any code that uses the standard library logging and propagates to the root—almost all app code with logging.getLogger(__name__)—will appear in console and file, subject to the configured level (DEBUG, INFO, etc.).


Settings reference (DJANGO_LOGPILOT)

Key Default Description
format "text" "text" (human-readable) or "json" (one JSON object per line).
level "INFO" Level for the root and attached Django loggers.
outputs ["console"] "console", "file", or both.
file_path None Required when "file" is in outputs. Parent dirs are created if missing.
file_max_bytes 10485760 Rotate after this many bytes (default 10 MiB).
file_backup_count 5 Rotated files to keep.
request_id_header "X-Request-ID" Incoming header to reuse a trace id.
request_id_response_header "X-Request-ID" Outgoing header with the active id.
redact_keys built-in list Substrings matched against dict keys (case-insensitive) in redact_mapping().
alerts see defaults Reserved for Slack/email and deduplication; delivery is not active in early releases.

Built-in redact_keys include: password, secret, token, authorization, cookie, set-cookie, api_key, apikey, credit_card.


Already using Django LOGGING?

  • If LOGGING["handlers"] is non-empty, Logpilot does not overwrite your configuration (so existing projects stay safe).
  • To add Logpilot’s handlers and formatters on top of your dict:
DJANGO_LOGPILOT_MERGE_LOGGING = True

If you define handlers manually, every name in "filters": [...] must exist under LOGGING["filters"]. Logpilot’s own handlers do not rely on a custom filter for request IDs (formatters read context set by middleware), which avoids common KeyError mistakes when merging configs.


Redacting structured data

Logpilot does not automatically scan request bodies. When you log a dict, wrap it:

from django_logpilot.redaction import redact_mapping

logger.info("signup payload: %s", redact_mapping({"email": "a@b.com", "password": "x"}))

Troubleshooting

Issue What to do
No Logpilot output You likely have custom LOGGING handlers. Use DJANGO_LOGPILOT_MERGE_LOGGING = True or simplify LOGGING for a test.
KeyError: 'logpilot_request_id' Remove old copy-pasted "filters": ["logpilot_request_id"] from custom handlers, or define that filter under LOGGING["filters"].
Cannot create log file The process needs write permission to the parent path (e.g. not /var/log/... without the right user).

Package status

0.1.x — early. Defaults and APIs may still move; pin a version in production until 1.0.


Developing django-logpilot itself

git clone <your-repo-url>
cd django-logpilot
python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
pytest

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_logpilot-0.1.0.tar.gz (12.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_logpilot-0.1.0-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

Details for the file django_logpilot-0.1.0.tar.gz.

File metadata

  • Download URL: django_logpilot-0.1.0.tar.gz
  • Upload date:
  • Size: 12.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for django_logpilot-0.1.0.tar.gz
Algorithm Hash digest
SHA256 21c676262c96013eca94c80744461ce0a96afe92a8c15106fd7b4afea4cf2687
MD5 73ff5b6485b30b3243ecdbf87bbcf0f0
BLAKE2b-256 202fe2f9bfc37a426581104e3c4f20f28d0100b65f899bec8a56775ecdb5f2f7

See more details on using hashes here.

File details

Details for the file django_logpilot-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_logpilot-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7a55646b072a1966d5d1765bbc474ffa2ca0968cb382193a40666c41d1060387
MD5 afa9878e7a6ed3ede9676ab1c3a01411
BLAKE2b-256 083c63a19880544a576d1831eace94003c9442dfbd876b4c756e9ed54e772e2f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page