import logging from typing import Mapping, Optional from lightning_utilities.core.rank_zero import rank_prefixed_message, rank_zero_only class RankedLogger(logging.LoggerAdapter): """A multi-GPU-friendly python command line logger.""" def __init__( self, name: str = __name__, rank_zero_only: bool = False, extra: Optional[Mapping[str, object]] = None, log_file: str = "log.txt", # 添加日志文件名参数 ) -> None: logger = logging.getLogger(name) # 设置日志格式 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 添加文件处理器 file_handler = logging.FileHandler(log_file) file_handler.setFormatter(formatter) logger.addHandler(file_handler) super().__init__(logger=logger, extra=extra) self.rank_zero_only = rank_zero_only def log(self, level: int, msg: str, rank: Optional[int] = None, *args, **kwargs) -> None: """Delegate a log call to the underlying logger, after prefixing its message with the rank of the process it's being logged from. If `'rank'` is provided, then the log will only occur on that rank/process. :param level: The level to log at. Look at `logging.__init__.py` for more information. :param msg: The message to log. :param rank: The rank to log at. :param args: Additional args to pass to the underlying logging function. :param kwargs: Any additional keyword args to pass to the underlying logging function. """ if self.isEnabledFor(level): msg, kwargs = self.process(msg, kwargs) current_rank = getattr(rank_zero_only, "rank", None) if current_rank is None: raise RuntimeError("The `rank_zero_only.rank` needs to be set before use") msg = rank_prefixed_message(msg, current_rank) if self.rank_zero_only: if current_rank == 0: self.logger.log(level, msg, *args, **kwargs) else: if rank is None: self.logger.log(level, msg, *args, **kwargs) elif current_rank == rank: self.logger.log(level, msg, *args, **kwargs)