from __future__ import annotations import logging import sys import structlog from app.core.config import settings def configure_logging() -> None: pre_chain = [ structlog.contextvars.merge_contextvars, structlog.stdlib.add_log_level, structlog.processors.TimeStamper(fmt="iso"), ] is_prod = settings.ENV == "production" if is_prod: renderer = structlog.processors.JSONRenderer() else: renderer = structlog.dev.ConsoleRenderer(colors=True) pre_chain.insert(0, structlog.stdlib.add_logger_name) structlog.configure( processors=[ structlog.stdlib.filter_by_level, *pre_chain, structlog.stdlib.ProcessorFormatter.wrap_for_formatter, ], logger_factory=structlog.stdlib.LoggerFactory(), wrapper_class=structlog.stdlib.BoundLogger, cache_logger_on_first_use=True, ) formatter = structlog.stdlib.ProcessorFormatter( foreign_pre_chain=pre_chain, processors=[ structlog.stdlib.ProcessorFormatter.remove_processors_meta, renderer, ], ) handler = logging.StreamHandler(sys.stdout) handler.setFormatter(formatter) root_logger = logging.getLogger() root_logger.handlers = [handler] root_logger.setLevel(settings.LOG_LEVEL.upper()) for lib in ( "uvicorn.access", "uvicorn.error", "multipart", "httpx", "httpcore", "redis", "PIL", "asyncio", ): logging.getLogger(lib).setLevel(logging.WARNING)