import logging.config import structlog import sys def setup_logging(filename: str = "", level: str = "DEBUG"): """ Configure stdlib logging + structlog. - File handler: RotatingFileHandler (10 MB, 10 backups) - Console: colored """ timestamper = structlog.processors.TimeStamper(fmt="iso") pre_chain = [ structlog.stdlib.add_log_level, timestamper, ] config_dict = { "version": 1, "disable_existing_loggers": False, "formatters": { "plain": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.dev.ConsoleRenderer(colors=False), "foreign_pre_chain": pre_chain, }, "colored": { "()": structlog.stdlib.ProcessorFormatter, "processor": structlog.dev.ConsoleRenderer(colors=True), "foreign_pre_chain": pre_chain, }, }, "handlers": { "default": { "level": level, "class": "logging.StreamHandler", "formatter": "colored", "stream": "ext://sys.stdout", }, }, "loggers": { "": { "handlers": ["default"], "level": level, "propagate": True, }, }, } if filename: config_dict["handlers"]["file"] = { "level": level, "class": "logging.handlers.RotatingFileHandler", "filename": filename, "maxBytes": 10 * 1024 * 1024, # 10 MB "backupCount": 10, "formatter": "plain", } config_dict["loggers"][""]["handlers"].append("file") logging.config.dictConfig(config_dict) structlog.configure( processors=[ structlog.stdlib.add_log_level, structlog.stdlib.PositionalArgumentsFormatter(), timestamper, structlog.processors.StackInfoRenderer(), structlog.processors.format_exc_info, structlog.stdlib.ProcessorFormatter.wrap_for_formatter, ], logger_factory=structlog.stdlib.LoggerFactory(), wrapper_class=structlog.stdlib.BoundLogger, cache_logger_on_first_use=True, ) logger = structlog.get_logger() def handle_exception(exc_type, exc_value, exc_traceback): if issubclass(exc_type, KeyboardInterrupt): sys.__excepthook__(exc_type, exc_value, exc_traceback) return logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)) sys.excepthook = handle_exception if filename: logger.info("Logger initialized", log_file=filename) return logger