| 40 | return 'Vertical' not in record.getMessage() |
| 41 | |
| 42 | class Logger: |
| 43 | LOGS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data', 'logs') |
| 44 | |
| 45 | def __init__(self, name, level=logging.DEBUG, enable_file_logging=True): |
| 46 | self.logger = logging.getLogger(name) |
| 47 | self.logger.setLevel(level) |
| 48 | self.logger.propagate = False # Prevent duplicate logs via root logger |
| 49 | self.enable_file_logging = enable_file_logging |
| 50 | |
| 51 | vertical_filter = VerticalFilter() |
| 52 | |
| 53 | if _HAS_RICH: |
| 54 | # Define custom log level styles |
| 55 | custom_theme = Theme({ |
| 56 | "debug": "yellow", |
| 57 | "info": "blue", |
| 58 | "warning": "yellow", |
| 59 | "error": "bold red", |
| 60 | "critical": "bold magenta", |
| 61 | "success": "bold green" |
| 62 | }) |
| 63 | |
| 64 | console = Console(theme=custom_theme) |
| 65 | |
| 66 | # Create console handler with rich and set level |
| 67 | console_handler = RichHandler(console=console, show_time=False, show_level=False, show_path=False, log_time_format="%Y-%m-%d %H:%M:%S") |
| 68 | else: |
| 69 | # Fallback to plain StreamHandler when rich is not available (e.g. Pager) |
| 70 | console_handler = logging.StreamHandler() |
| 71 | |
| 72 | console_handler.setLevel(level) |
| 73 | console_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S') |
| 74 | console_handler.setFormatter(console_formatter) |
| 75 | |
| 76 | # Add filter to console handler |
| 77 | console_handler.addFilter(vertical_filter) |
| 78 | |
| 79 | # Add console handler to the logger |
| 80 | self.logger.addHandler(console_handler) |
| 81 | |
| 82 | if self.enable_file_logging: |
| 83 | # Ensure the log folder exists |
| 84 | os.makedirs(self.LOGS_DIR, exist_ok=True) |
| 85 | log_file_path = os.path.join(self.LOGS_DIR, f"{name}.log") |
| 86 | |
| 87 | # Create file handler and set level |
| 88 | file_handler = RotatingFileHandler(log_file_path, maxBytes=5*1024*1024, backupCount=2) |
| 89 | file_handler.setLevel(level) |
| 90 | file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S') |
| 91 | file_handler.setFormatter(file_formatter) |
| 92 | |
| 93 | # Add filter to file handler |
| 94 | file_handler.addFilter(vertical_filter) |
| 95 | |
| 96 | # Add file handler to the logger |
| 97 | self.logger.addHandler(file_handler) |
| 98 | |
| 99 | def set_level(self, level): |
no outgoing calls
no test coverage detected