# app/observability/logging.py # Structured logging with structlog import sys import logging import structlog from app.config import get_settings def setup_logging() -> None: """Configure structured logging for the application.""" settings = get_settings() # Configure structlog structlog.configure( processors=[ structlog.contextvars.merge_contextvars, structlog.processors.add_log_level, structlog.processors.StackInfoRenderer(), structlog.dev.set_exc_info, structlog.processors.TimeStamper(fmt="iso"), structlog.processors.JSONRenderer() if settings.is_production else structlog.dev.ConsoleRenderer(colors=True), ], wrapper_class=structlog.make_filtering_bound_logger( logging.getLevelName(settings.log_level) ), context_class=dict, logger_factory=structlog.PrintLoggerFactory(), cache_logger_on_first_use=True, ) # Silence noisy third-party loggers for logger_name in ["uvicorn.access", "httpx", "httpcore"]: logging.getLogger(logger_name).setLevel(logging.WARNING) def get_logger(name: str | None = None) -> structlog.BoundLogger: """Get a structured logger instance.""" return structlog.get_logger(name or __name__)