Coverage for apps / core / logging.py: 93%
14 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-12 10:49 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-12 10:49 +0000
1"""JSON log formatter for production."""
3import json
4import logging
5from datetime import UTC, datetime
8class JSONFormatter(logging.Formatter):
9 """Produces JSON log lines for machine parsing in production."""
11 def format(self, record):
12 log_entry = {
13 "timestamp": datetime.now(UTC).isoformat(),
14 "level": record.levelname,
15 "logger": record.name,
16 "message": record.getMessage(),
17 "module": record.module,
18 }
20 # Add request_id if available
21 if hasattr(record, "request_id"):
22 log_entry["request_id"] = record.request_id
24 # Add extra fields
25 for key in ("username", "ip", "path", "reason", "endpoint", "action", "target_username"):
26 if hasattr(record, key):
27 log_entry[key] = getattr(record, key)
29 if record.exc_info and record.exc_info[1]:
30 log_entry["exception"] = self.formatException(record.exc_info)
32 return json.dumps(log_entry, default=str)