Spaces:
Running
Running
| import sys | |
| import logging | |
| import colorama | |
| from colorama import Fore, Style | |
| # Initialize colorama to work on Windows too | |
| colorama.init() | |
| # Define custom VERBOSE level (between DEBUG-10 and INFO-20) | |
| VERBOSE = 15 | |
| logging.addLevelName(VERBOSE, 'VERBOSE') | |
| RESULT = 25 | |
| logging.addLevelName(RESULT, 'RESULT') | |
| class ColoredFormatter(logging.Formatter): | |
| """Custom formatter that adds colors to log messages based on level with fixed width""" | |
| COLORS = { | |
| 'DEBUG': Fore.CYAN + Style.BRIGHT, | |
| 'VERBOSE': Fore.BLUE + Style.BRIGHT, | |
| 'INFO': Fore.GREEN + Style.BRIGHT, | |
| 'RESULT' : Fore.RESET + Style.BRIGHT, | |
| 'WARNING': Fore.YELLOW + Style.BRIGHT, | |
| 'ERROR': Fore.RED + Style.BRIGHT, | |
| 'CRITICAL': Fore.MAGENTA + Style.BRIGHT | |
| } | |
| LEVEL_NAME_WIDTH = 8 | |
| def format(self, record): | |
| # Save original levelname and message | |
| orig_levelname = record.levelname | |
| orig_msg = record.msg | |
| # Determine the color for the level | |
| color_code = self.COLORS.get(orig_levelname, '') | |
| # Calculate padding for levelname | |
| padding = ' ' * (self.LEVEL_NAME_WIDTH - len(orig_levelname)) | |
| # Apply color to levelname with padding | |
| record.levelname = f"{color_code}{orig_levelname}{padding}{Style.RESET_ALL}" | |
| # Apply color to the message as well | |
| record.msg = f"{color_code}{orig_msg}{Style.RESET_ALL}" | |
| # Format the message | |
| result = super().format(record) | |
| # Restore original values | |
| record.levelname = orig_levelname | |
| record.msg = orig_msg | |
| return result | |
| class ColoredLogger(logging.Logger): | |
| """Custom logger class with verbose method""" | |
| def verbose(self, msg, *args, **kwargs): | |
| """Log at custom VERBOSE level""" | |
| if self.isEnabledFor(VERBOSE): | |
| self._log(VERBOSE, msg, args, **kwargs) | |
| def result(self, msg, *args, **kwargs): | |
| """Log at custom RESULT level""" | |
| if self.isEnabledFor(RESULT): | |
| self._log(RESULT, msg, args, **kwargs) | |
| # logging.Logger.result = custom_logging | |
| def setup_logger(name='colored_logger', level="INFO"): | |
| """Set up and return a colored logger instance""" | |
| # Register our custom logger class | |
| logging.setLoggerClass(ColoredLogger) | |
| # Create logger | |
| logger = logging.getLogger(name) | |
| # Set logger level | |
| try: | |
| logger.setLevel(getattr(logging, level.upper())) | |
| except AttributeError: | |
| logger.setLevel(logging.INFO) # Default to INFO if invalid level | |
| # Create console handler | |
| console_handler = logging.StreamHandler(sys.stdout) | |
| console_handler.setLevel(level) | |
| # Create formatter | |
| formatter = ColoredFormatter( | |
| # fmt='%(asctime)s - %(levelname)s - %(message)s', | |
| # datefmt='%Y-%m-%d %H:%M:%S' | |
| fmt='%(levelname)8s - %(message)s' | |
| ) | |
| # Add formatter to handler | |
| console_handler.setFormatter(formatter) | |
| # Add handler to logger | |
| logger.addHandler(console_handler) | |
| return logger | |
| # Example usage | |
| if __name__ == '__main__': | |
| logger = setup_logger() | |
| # Test all log levels including new VERBOSE level | |
| logger.debug("This is a debug message") | |
| logger.verbose("This is a verbose message") # New verbose level | |
| logger.info("This is an info message") | |
| logger.warning("This is a warning message") | |
| logger.error("This is an error message") | |
| logger.critical("This is a critical message") | |