"""structlog configuration. Never log message contents (Loi 25).""" from __future__ import annotations import logging import sys import structlog REDACT_KEYS = {"content", "message", "text", "code", "prompt", "email", "authorization"} def _redact(_: object, __: str, event_dict: dict) -> dict: for key in list(event_dict): if key.lower() in REDACT_KEYS: value = event_dict[key] event_dict[key] = f"" return event_dict def configure_logging(level: str = "INFO", json_output: bool = True) -> None: logging.basicConfig(level=level, stream=sys.stdout, format="%(message)s") renderer = structlog.processors.JSONRenderer() if json_output else structlog.dev.ConsoleRenderer() structlog.configure( processors=[ structlog.contextvars.merge_contextvars, structlog.processors.add_log_level, structlog.processors.TimeStamper(fmt="iso"), _redact, renderer, ], wrapper_class=structlog.make_filtering_bound_logger(getattr(logging, level.upper(), 20)), logger_factory=structlog.PrintLoggerFactory(), cache_logger_on_first_use=True, ) def get_logger(name: str) -> structlog.stdlib.BoundLogger: return structlog.get_logger(name)