Django Logging
Django-CFG’s Logging Module provides auto-configuring structured logging for the django_cfg namespace. It sets up modular per-module log files with daily rotation and optionally persists WARNING-and-above events to Cloudflare D1 for centralized storage, deduplication, and analysis.
Features
- Modular log files — separate rotating file per
django_cfg.*logger underlogs/djangocfg/ - Daily rotation —
TimedRotatingFileHandlerwith midnight rotation and configurable retention - Debug-aware levels —
DEBUGto files in dev mode,WARNINGto console in production - D1 persistence — optional sync of
WARNING+events to Cloudflare D1 with upsert-increment deduplication - Fingerprint deduplication — repeated occurrences increment a counter instead of creating new rows
- Sanitized extra context — reserved
LogRecordattributes inextra={}are automatically prefixed withctx_ - Telegram alerts — optional real-time error notifications (when
django_telegramis configured)
Quick Start
from django_cfg.modules.django_logging import get_logger
logger = get_logger("django_cfg.myapp")
logger.debug("Processing started")
logger.info("User created", extra={"user_id": 42})
logger.warning("Rate limit approaching", extra={"endpoint": "/api/users"})
logger.error("Payment failed", extra={"order_id": "ORD-123"})get_logger() automatically detects the caller’s file path to build the logger name when called without arguments from within django_cfg code:
# In a file at django_cfg/modules/my_module/service.py
logger = get_logger()
# auto-resolves to: django_cfg.my_module (or similar based on path)
# Explicit name
logger = get_logger("django_cfg.payments.stripe")Configuration
Configure in your extension’s __cfg__.py or on the DjangoConfig:
from django_cfg.modules.django_logging import DjangoLoggingConfig
class MyExtensionSettings:
logging = DjangoLoggingConfig(
enabled=True,
d1_enabled=True,
d1_min_level="WARNING",
file_enabled=True,
file_rotation_days=30,
telegram_alerts_enabled=False,
cleanup_days=90,
normalization_enabled=True,
)DjangoLoggingConfig Fields
| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | True | Enable or disable the module |
d1_enabled | bool | True | Sync events to Cloudflare D1 (requires django_cf) |
d1_min_level | str | "WARNING" | Minimum level for D1 sync: WARNING, ERROR, CRITICAL |
file_enabled | bool | True | Enable file logging |
file_rotation_days | int | 30 | Days of log files to retain (1–365) |
telegram_alerts_enabled | bool | False | Send Telegram alerts on ERROR+ |
cleanup_days | int | 90 | D1 event TTL in days (1–365) |
normalization_enabled | bool | True | Strip dynamic values before computing fingerprints |
Log File Layout
On startup, DjangoLogger creates the following directory structure in the project root:
logs/
├── django.log # All Django logs (rotation: daily, keep 30 days)
└── djangocfg/
├── core.log # django_cfg.core.*
├── email.log # django_cfg.email.*
├── telegram.log # django_cfg.telegram.*
└── <module>.log # One file per django_cfg.* sub-namespace
/tmp/djangocfg/
└── debug.log # Always-on debug mirror (set DJANGO_LOG_TO_TMP=false to disable)Log level per handler:
| Handler | Dev (DEBUG=True) | Production |
|---|---|---|
| Console | DEBUG | WARNING |
logs/django.log | DEBUG | INFO |
logs/djangocfg/<module>.log | DEBUG | INFO |
/tmp/djangocfg/debug.log | DEBUG | DEBUG |
Public API
get_logger(name="")
Returns a configured logging.Logger instance. Auto-detects caller path when called without arguments from within django_cfg code.
from django_cfg.modules.django_logging import get_logger
logger = get_logger("django_cfg.payments")sanitize_extra(extra)
Prefixes any key in extra that conflicts with Python’s reserved LogRecord attributes (e.g., module, message, name) with ctx_ to prevent KeyError.
from django_cfg.modules.django_logging import sanitize_extra
safe = sanitize_extra({"module": "myapp", "user_id": 42})
# {"ctx_module": "myapp", "user_id": 42}
logger.info("Event", extra=safe)clean_old_logs(days=30, logs_dir=None)
Deletes log files older than days from the logs/ directory. Returns a stats dict:
from django_cfg.modules.django_logging import clean_old_logs
stats = clean_old_logs(days=7)
# {"deleted": 12, "bytes": 45678, "human_readable": "0.04 MB"}is_enabled()
Returns True if D1 persistence is active (d1_enabled=True and django_cf is ready):
from django_cfg.modules.django_logging import is_enabled
if is_enabled():
print("D1 log sync is active")get_service() / reset_service()
Lifecycle management for the LogSyncService (D1 persistence backend). reset_service() clears the cached instance and is intended for use in tests.
D1 Persistence
When d1_enabled=True and the django_cf module is configured with Cloudflare credentials, log events at d1_min_level and above are pushed to a D1 log_events table via LogSyncService.push_log_event().
The D1 schema uses fingerprint + api_url as the composite primary key. Repeated events with the same fingerprint increment occurrence_count and update last_seen rather than creating duplicate rows.
D1 table columns:
| Column | Type | Description |
|---|---|---|
fingerprint | TEXT (PK) | Hash of normalized message + logger + level |
api_url | TEXT (PK) | Source API URL for multi-tenant isolation |
level | TEXT | Log level name |
logger_name | TEXT | Logger name |
message | TEXT | Log message |
module | TEXT | Source module filename |
func_name | TEXT | Source function name |
stack_trace | TEXT | Exception traceback |
extra | TEXT (JSON) | Extra context dict |
occurrence_count | INTEGER | Number of times this fingerprint was seen |
is_resolved | INTEGER | Whether the issue has been marked resolved |
first_seen | TEXT | ISO timestamp of first occurrence |
last_seen | TEXT | ISO timestamp of most recent occurrence |
Streamlit Log Viewer
When the Streamlit admin panel is enabled, a log events page is available at the “Log Events” tab. It queries the D1 log_events table and provides filtering by level, logger name, and resolved status.
Environment Variable
Set DJANGO_LOG_TO_TMP=false to disable the /tmp/djangocfg/debug.log mirror:
DJANGO_LOG_TO_TMP=false python manage.py runserverSee Also
- Django-CF Module — Cloudflare D1 integration required for D1 persistence
- Telegram Module — Telegram alert notifications