Source code for astromodels.utils.logging

# If threeml is not installed, we create our own log,
# otherwise, just print to the 3ML one!

import logging
import logging.handlers as handlers
from contextlib import contextmanager
from pathlib import Path

from rich.console import Console
from rich.logging import RichHandler
from rich.theme import Theme

from astromodels.utils.configuration import astromodels_config

from .file_utils import _get_data_file_path

try:

    from threeML.config.config import threeML_config

    has_threeml = True

except ImportError:

    has_threeml = False


DEBUG_NODE_LEVEL = 9
logging.addLevelName(DEBUG_NODE_LEVEL, "DEBUG_NODE")


[docs] def debug_node(self, message, *args, **kws): if self.isEnabledFor(DEBUG_NODE_LEVEL): # Yes, logger takes its '*args' as 'args'. self._log(DEBUG_NODE_LEVEL, message, args, **kws)
logging.Logger.debug_node = debug_node
[docs] def get_path_of_log_dir(): # we use the 3ML log path to simplify things # a more clever solution could be found if has_threeml: user_log: Path = Path(threeML_config.logging.path).expanduser() else: user_log: Path = Path(astromodels_config.logging.path).expanduser() # Create it if doesn't exist if not user_log.exists(): user_log.mkdir(parents=True) return user_log
_log_file_names = ["usr.log", "dev.log"]
[docs] def get_path_of_log_file(log_file: str) -> Path: """ returns the path of the log files """ assert log_file in _log_file_names, f"{log_file} is not one of {_log_file_names}" return get_path_of_log_dir() / log_file
[docs] class LogFilter(object): def __init__(self, level): self.__level = level
[docs] def filter(self, logRecord): return logRecord.levelno != self.__level
# now create the developer handler that rotates every day and keeps # 10 days worth of backup astromodels_dev_log_handler = handlers.TimedRotatingFileHandler( get_path_of_log_file("dev.log"), when="D", interval=1, backupCount=10 ) # lots of info written out _dev_formatter = logging.Formatter( "%(asctime)s | %(name)s | %(levelname)s| %(funcName)s | %(lineno)d | %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) astromodels_dev_log_handler.setFormatter(_dev_formatter) astromodels_dev_log_handler.setLevel(logging.DEBUG) # now set up the usr log which will save the info astromodels_usr_log_handler = handlers.TimedRotatingFileHandler( get_path_of_log_file("usr.log"), when="D", interval=1, backupCount=10 ) astromodels_usr_log_handler.setLevel(logging.INFO) # lots of info written out _usr_formatter = logging.Formatter( "%(asctime)s | %(levelname)s | %(message)s", datefmt="%Y-%m-%d %H:%M:%S" ) astromodels_usr_log_handler.setFormatter(_usr_formatter) _console_formatter = logging.Formatter( " %(message)s", datefmt="%H:%M:%S", ) _theme = {} # Banner _theme["h1"] = "deep_sky_blue3" _theme["status.spinner"] = "cyan2" _theme["status.text"] = "deep_sky_blue4" _theme["repr.filename"] = "blue" _theme["repr.number"] = "white" _theme["repr.path"] = "grey37" _theme["repr.str"] = "grey37" _theme["repr.tag_name"] = "white" _theme["repr.url"] = "not bold not italic underline grey84" _theme["log.time"] = "green1" _theme["log.message"] = f"{astromodels_config.logging.message_style}" _theme["logging.level.debug"] = f"{astromodels_config.logging.debug_style}" _theme["logging.level.error"] = f"{astromodels_config.logging.error_style}" _theme["logging.level.info"] = f"{astromodels_config.logging.info_style}" _theme["logging.level.warning"] = f"{astromodels_config.logging.warn_style}" _theme["logging.level.degub_node"] = "light_goldenrod1" # mytheme = Theme().read(_get_data_file_path("log_theme.ini")) mytheme = Theme(_theme) console = Console(theme=mytheme) astromodels_console_log_handler = RichHandler( level="INFO", rich_tracebacks=True, markup=True, console=console ) astromodels_console_log_handler.setFormatter(_console_formatter) astromodels_console_log_handler.setLevel("INFO") warning_filter = LogFilter(logging.WARNING)
[docs] @contextmanager def silence_console_log(): """ temporarily silence the console and progress bars """ current_console_logging_level = astromodels_console_log_handler.level current_usr_logging_level = astromodels_usr_log_handler.level astromodels_console_log_handler.setLevel(logging.CRITICAL) astromodels_usr_log_handler.setLevel(logging.CRITICAL) try: yield finally: astromodels_console_log_handler.setLevel(current_console_logging_level) astromodels_usr_log_handler.setLevel(current_usr_logging_level)
[docs] def silence_warnings(): """ supress warning messages in console and file usr logs """ astromodels_usr_log_handler.addFilter(warning_filter) astromodels_console_log_handler.addFilter(warning_filter)
[docs] def activate_warnings(): """ supress warning messages in console and file usr logs """ astromodels_usr_log_handler.removeFilter(warning_filter) astromodels_console_log_handler.removeFilter(warning_filter)
[docs] def update_logging_level(level): astromodels_console_log_handler.setLevel(level)
[docs] def setup_logger(name): # A logger with name name will be created # and then add it to the print stream log = logging.getLogger(name) # this must be set to allow debug messages through log.setLevel(DEBUG_NODE_LEVEL) # add the handlers log.addHandler(astromodels_dev_log_handler) log.addHandler(astromodels_console_log_handler) log.addHandler(astromodels_usr_log_handler) # we do not want to duplicate teh messages in the parents log.propagate = False return log