cek / src /pycek_public /logger.py
praiteri's picture
first commit
843a502
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")