[docs]classLogger:"""Cache and configure :py:class:`logging.Logger` instances by *name*."""_instances:dict[str,"Logger"]={}def__new__(cls,name:str|None=None):# noqa: D401key=nameor__name__ifkeynotincls._instances:cls._instances[key]=super().__new__(cls)returncls._instances[key]
def_setup_logger(self):"""Configure the logger with the log level from environment variable."""# Default log level if not specified in environmentdefault_level=logging.INFO# Get log level from environment variablelog_level_str=os.environ.get("LOG_LEVEL","INFO").upper()log_level=getattr(logging,log_level_str,default_level)# Configure the loggerself.logger.setLevel(log_level)# Create console handler and set levelch=logging.StreamHandler()ch.setLevel(log_level)# Create formatter and add it to the handlerformatter=logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s",datefmt="%Y-%m-%d %H:%M:%S",)ch.setFormatter(formatter)# Remove any existing handlers to avoid duplicate logsifself.logger.hasHandlers():self.logger.handlers.clear()# Add the handler to the loggerself.logger.addHandler(ch)
[docs]defget_logger(self)->logging.Logger:"""Get the configured logger instance."""returnself.logger
# Create a default logger instance
[docs]defget_logger(name:str|None=None)->logging.Logger:"""Get a logger instance with the given name. Args: name: The name of the logger. If None, uses the module's name. Returns: A configured logging.Logger instance. """returnLogger(name).get_logger()