import logging import os from logging.handlers import RotatingFileHandler import traceback def exception_to_str(e: Exception, max_lines: int = 12) -> str: """ Convert an exception to a string, limiting the number of lines. """ exception_message = "\n".join(str(e).splitlines()[:2]) stack_trace = "".join(traceback.format_tb(e.__traceback__)) exception_str = exception_message + "\n" + stack_trace lines = exception_str.splitlines() if len(lines) > max_lines: exception_str = "\n".join(lines[:max_lines]) + "\n... (truncated)" return exception_str # Configure logger def setup_logger(name: str) -> logging.Logger: log_level = os.getenv("LOG_LEVEL", "INFO").upper() log_file = os.getenv("LOG_FILE", "app.log") max_bytes = int(os.getenv("LOG_MAX_BYTES", 10 * 1024 * 1024)) # 10 MB backup_count = int(os.getenv("LOG_BACKUP_COUNT", 5)) logger = logging.getLogger(name) logger.setLevel(log_level) # Console handler console_handler = logging.StreamHandler() console_handler.setLevel(log_level) console_formatter = logging.Formatter( "%(asctime)s - %(name)s - %(levelname)s - %(message)s" ) console_handler.setFormatter(console_formatter) # Rotating file handler file_handler = RotatingFileHandler( log_file, maxBytes=max_bytes, backupCount=backup_count ) file_handler.setLevel(log_level) file_formatter = logging.Formatter( "%(asctime)s - %(name)s - %(levelname)s - %(message)s" ) file_handler.setFormatter(file_formatter) # Add handlers logger.addHandler(console_handler) logger.addHandler(file_handler) logger.propagate = False return logger