Source code for NuRadioReco.utilities.logging

import logging

LOGGING_STATUS = 25


[docs]class NuRadioLogger(logging.Logger): """ Custom logging class for NuRadio modules and applications. It adds a custom log level STATUS, which has level=`LOGGING_STATUS` as defined in `logging.py` (as of February 2024, its value is 25). The associated `status()` call is also implemented. """ def __init__(self, name): super().__init__(name) # Add STATUS as the level name, to be used in message formatting logging.addLevelName(LOGGING_STATUS, "STATUS")
[docs] def status(self, message, *args, **kwargs): if self.isEnabledFor(LOGGING_STATUS): self._log(LOGGING_STATUS, message, args, **kwargs)
[docs]def addLoggingLevel(levelName, levelNum, methodName=None): """ Comprehensively adds a new logging level to the `logging` module and the currently configured logging class. `levelName` becomes an attribute of the `logging` module with the value `levelNum`. `methodName` becomes a convenience method for both `logging` itself and the class returned by `logging.getLoggerClass()` (usually just `logging.Logger`). If `methodName` is not specified, `levelName.lower()` is used. To avoid accidental clobberings of existing attributes, this method will raise an `AttributeError` if the level name is already an attribute of the `logging` module or if the method name is already present Examples -------- >>> addLoggingLevel('TRACE', logging.DEBUG - 5) >>> logging.getLogger(__name__).setLevel("TRACE") >>> logging.getLogger(__name__).trace('that worked') >>> logging.trace('so did this') >>> logging.TRACE 5 Notes ----- This function was taken from `this answer <https://stackoverflow.com/questions/2183233/how-to-add-a-custom-loglevel-to-pythons-logging-facility/35804945#35804945>`_ """ if not methodName: methodName = levelName.lower() if hasattr(logging, levelName): raise AttributeError('{} already defined in logging module'.format(levelName)) if hasattr(logging, methodName): raise AttributeError('{} already defined in logging module'.format(methodName)) if hasattr(logging.getLoggerClass(), methodName): raise AttributeError('{} already defined in logger class'.format(methodName)) # This method was inspired by the answers to Stack Overflow post # http://stackoverflow.com/q/2183233/2988730, especially # http://stackoverflow.com/a/13638084/2988730 def logForLevel(self, message, *args, **kwargs): if self.isEnabledFor(levelNum): self._log(levelNum, message, args, **kwargs) def logToRoot(message, *args, **kwargs): logging.log(levelNum, message, *args, **kwargs) logging.addLevelName(levelNum, levelName) setattr(logging, levelName, levelNum) setattr(logging.getLoggerClass(), methodName, logForLevel) setattr(logging, methodName, logToRoot)
def _setup_logger(name="NuRadioReco", level=None): """ Set up the parent logger which all module loggers should pass their logs on to. If this one already exists, nothing is done and the logger is returned as is. Otherwise, a single new `logging.StreamHandler()` with a custom formatter is added. Notes ----- This function is only meant to be called once, on import, as part of the `__init__.py` scripts of the base packages NuRadioReco and NuRadioMC. It is not meant nor necessary to call this function from a module or user script. Parameters ---------- name : str, default="NuRadioReco" The name of the base logger level : int, default=25 The logging level to use for the base logger """ logger = logging.getLogger(name) if len(logger.handlers) > 0: # method hasHandlers() also checks parents -> ends up at root logger # Don't change the logger if it already exists logger.warning(f"Logger {name} already has handlers. Not changing anything, returning the existing logger...") return logger logger.propagate = False # Create a StreamHandler with fancy formatter handler = logging.StreamHandler() handler.setFormatter(get_fancy_formatter()) handler.setLevel(1) # we want the handler to be accepting all records from child loggers # Then add our custom handler to the logger logger.addHandler(handler) # Finally, set the logging level if level is not None: logger.setLevel(level=level) else: logger.setLevel(LOGGING_STATUS) return logger
[docs]def get_fancy_formatter(): """ Returns the formatter used in the NuRadio logger. Returns ------- formatter : logging.Formatter """ class CustomFormatter(logging.Formatter): def __init__(self, format, datefmt): super().__init__(datefmt=datefmt) grey = "\033[38;1m" yellow = "\033[33;1m" purple = "\033[35;1m" green = "\033[32;1m" red = "\033[31;1m" reset = "\033[0m" self.FORMATS = { logging.DEBUG: grey + "%(levelname)s - " + reset + format, logging.INFO: green + "%(levelname)s - " + reset + format, LOGGING_STATUS: yellow + "%(levelname)s - " + reset + format, logging.WARNING: purple + "%(levelname)s - " + reset + format, logging.ERROR: red + "%(levelname)s - " + reset + format, logging.CRITICAL: red + "%(levelname)s - " + reset + format } def format(self, record): log_fmt = self.FORMATS.get(record.levelno) formatter = logging.Formatter(log_fmt) return formatter.format(record) formatter = CustomFormatter( format='\033[33m%(asctime)s - \033[32m%(name)s - \033[0m%(message)s', datefmt="%H:%M:%S" ) return formatter
[docs]def set_general_log_level(level): """ Set the logging level of the NuRadioMC and NuRadioReco loggers to `level`. Parameters ---------- level : int The desired logging level """ nrr_logger = logging.getLogger("NuRadioReco") nrr_logger.setLevel(level) nrmc_logger = logging.getLogger("NuRadioMC") nrmc_logger.setLevel(level)