Source code for masterpiece.log

"""
Author: Juha Meskanen
Date: 2024-10-26
"""

import logging
import argparse
import sys
from logging.handlers import TimedRotatingFileHandler


[docs] class Log(logging.Logger): """ Default `logging.Logger`-based logger implementation for logging events to the MasterPiece application log and/or the console. TODO: While `logging.Logger` is the de facto logging implementation in Python, many Python components have undergone repeated deprecations. As a result, we should not assume that it will remain stable. Abstracting the logger API is a simple process that takes just a few minutes. By investing this small amount of time, we can shield our application code from potential quirks and deprecations introduced by third-party libraries, ensuring greater stability and flexibility in the long run. """ # move these into a abstract base class for loggers DEBUG: int = logging.DEBUG INFO: int = logging.INFO WARNING: int = logging.WARNING ERROR: int = logging.ERROR CRITICAL: int = logging.CRITICAL
[docs] def __init__(self, name: str, level: int = INFO) -> None: """Creates and initializes default logger with the given name and logging level. Typically the name is the name of the application. Args: name: name of the logger level: logging level, the default is logging.DEBUG """ super().__init__(name, level) parser = argparse.ArgumentParser(add_help=False) parser.add_argument( "-f", "--log_name", type=str, default=name + ".log", help="Name of the log file", ) parser.add_argument( "-l", "--log_level", type=int, default=logging.DEBUG, help="Logging level" ) args, remaining_argv = parser.parse_known_args() sys.argv = [sys.argv[0]] + remaining_argv self.setLevel(args.log_level) # Set the logging level here # Create file formatter file_formatter = logging.Formatter( "%(asctime)s [%(levelname)-5.5s] %(message)-0.280s" ) # Create a timed rotating file handler file_handler = TimedRotatingFileHandler( args.log_name, when="midnight", interval=1, backupCount=7 ) file_handler.setFormatter(file_formatter) self.addHandler(file_handler) # Create console formatter console_formatter = logging.Formatter("[%(levelname)-5.5s] %(message)-0.280s") console_handler = logging.StreamHandler() console_handler.setFormatter(console_formatter) self.addHandler(console_handler)
[docs] def close(self) -> None: """Close all handlers to free resources.""" for handler in self.handlers: handler.close() self.removeHandler(handler)
[docs] @classmethod def parse_level(cls, level: str) -> int: """Map the given symbolic log level to log level value. Args: level (str): DEBUG, WARNING, INFO, ERROR etc. Returns: int: Log.DEBUG etc. """ if level == "DEBUG": return cls.DEBUG elif level == "INFO": return cls.INFO elif level == "WARNING": return cls.WARNING elif level == "ERROR": return cls.ERROR else: return cls.INFO