"""Central logging configuration utilities.""" from __future__ import annotations import importlib import logging from . import settings JsonFormatter = None try: _json_module = importlib.import_module("pythonjsonlogger.json") JsonFormatter = getattr(_json_module, "JsonFormatter", None) except Exception: try: _json_module = importlib.import_module("pythonjsonlogger.jsonlogger") JsonFormatter = getattr(_json_module, "JsonFormatter", None) except Exception: JsonFormatter = None class RequestContextFilter(logging.Filter): """Inject request metadata into log records when a request context exists.""" def filter(self, record: logging.LogRecord) -> bool: try: from flask import has_request_context, request if has_request_context(): rid = getattr(request, "request_id", None) or request.environ.get("HTTP_X_REQUEST_ID") record.request_id = rid record.remote_addr = request.remote_addr record.path = request.path record.method = request.method else: record.request_id = None record.remote_addr = None record.path = None record.method = None except Exception: record.request_id = None record.remote_addr = None record.path = None record.method = None return True def configure_logging() -> None: """Configure root logging handlers and optional JSON formatting.""" logging.basicConfig( level=logging.INFO, format="[%(asctime)s] %(levelname)s in %(module)s: %(message)s", ) if settings.ENABLE_JSON_LOGS and JsonFormatter is not None: try: handler = logging.getLogger().handlers[0] handler.setFormatter(JsonFormatter("%(asctime)s %(levelname)s %(name)s %(message)s")) except Exception: logging.exception("Failed to initialize JSON log formatter") try: for handler in logging.getLogger().handlers: handler.addFilter(RequestContextFilter()) except Exception: pass