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-IDin / 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_pathcreated 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 headers —
X-Request-IDpresent
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
21c676262c96013eca94c80744461ce0a96afe92a8c15106fd7b4afea4cf2687
|
|
| MD5 |
73ff5b6485b30b3243ecdbf87bbcf0f0
|
|
| BLAKE2b-256 |
202fe2f9bfc37a426581104e3c4f20f28d0100b65f899bec8a56775ecdb5f2f7
|
File details
Details for the file django_logpilot-0.1.0-py3-none-any.whl.
File metadata
- Download URL: django_logpilot-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a55646b072a1966d5d1765bbc474ffa2ca0968cb382193a40666c41d1060387
|
|
| MD5 |
afa9878e7a6ed3ede9676ab1c3a01411
|
|
| BLAKE2b-256 |
083c63a19880544a576d1831eace94003c9442dfbd876b4c756e9ed54e772e2f
|