"""This module contains logging utility functions.We provide utilities for setting up a logger and logging in a distributedsetting."""from__future__importannotationsimportloggingimportosimportsysimportwarningsfromtermcolorimportcoloredfromvis4d.common.distributedimportrank_zero_onlyfromvis4d.common.typingimportArgsTypefromvis4d.config.typingimportExperimentConfigdef_debug(*args:ArgsType,stacklevel:int=2,**kwargs:ArgsType)->None:"""Function used to log debug-level messages."""log=logging.getLogger(__name__)kwargs["stacklevel"]=stacklevellog.debug(*args,**kwargs)
[docs]@rank_zero_onlydefrank_zero_debug(*args:ArgsType,stacklevel:int=4,**kwargs:ArgsType)->None:"""Function used to log debug-level messages only on global rank 0."""_debug(*args,stacklevel=stacklevel,**kwargs)
def_info(*args:ArgsType,stacklevel:int=2,**kwargs:ArgsType)->None:"""Function used to log info-level messages."""kwargs["stacklevel"]=stacklevellog=logging.getLogger(__name__)log.info(*args,**kwargs)
[docs]@rank_zero_onlydefrank_zero_info(*args:ArgsType,stacklevel:int=4,**kwargs:ArgsType)->None:"""Function used to log info-level messages only on global rank 0."""_info(*args,stacklevel=stacklevel,**kwargs)
def_warn(message:str|Warning,stacklevel:int=2,**kwargs:ArgsType)->None:"""Function used to log warn-level messages."""warnings.warn(message,stacklevel=stacklevel,**kwargs)
[docs]@rank_zero_onlydefrank_zero_warn(message:str|Warning,stacklevel:int=4,**kwargs:ArgsType)->None:"""Function used to log warn-level messages only on global rank 0."""_warn(message,stacklevel=stacklevel,**kwargs)
class_ColorFormatter(logging.Formatter):"""Formatter for terminal messages with colors."""defformatMessage(self,record:logging.LogRecord)->str:"""Add appropriate color to log message."""log=super().formatMessage(record)ifrecord.levelno==logging.WARNING:prefix=colored("WARNING","red",attrs=["blink"])elifrecord.levelnoin[logging.ERROR,logging.CRITICAL]:prefix=colored("ERROR","red",attrs=["blink","underline"])else:returnlogreturnprefix+" "+log
[docs]@rank_zero_onlydefsetup_logger(logger:logging.Logger,filepath:None|str=None,color:bool=True,std_out_level:int=logging.INFO,)->None:"""Configure logging for Vis4D. Args: logger (logging.Logger): The logger instance to be configured. filepath (None | str, optional): The filepath to the log file that stores the console output. Defaults to None. color (bool, optional): Whether to use a colored console output. Defaults to True. std_out_level (int, optional): Which logging level to output to the console. Defaults to logging.INFO. Note that all levels will be logged to file. """# get logger, remove handlers to re-define behaviorforhinlogger.handlers:logger.removeHandler(h)# console loggerplain_formatter=logging.Formatter("[%(asctime)s] Vis4D %(levelname)s: %(message)s",datefmt="%m/%d %H:%M:%S",)ch=logging.StreamHandler(stream=sys.stdout)ch.setLevel(std_out_level)ifcolor:formatter=_ColorFormatter(colored("[%(asctime)s Vis4D]: ","green")+"%(message)s",datefmt="%m/%d %H:%M:%S",)ch.setFormatter(formatter)else:ch.setFormatter(plain_formatter)logger.addHandler(ch)# file loggeriffilepathisnotNone:os.makedirs(os.path.dirname(filepath),exist_ok=True)fh=logging.FileHandler(filepath)fh.setLevel(logging.DEBUG)fh.setFormatter(plain_formatter)logger.addHandler(fh)
[docs]@rank_zero_onlydefdump_config(config:ExperimentConfig,config_file:str)->None:"""Dump the configuration to a file. Args: config (ExperimentConfig): The configuration to dump. config_file (str): The path to the file to dump the configuration to. """config.dump(config_file)