Source code for hydromt.log

"""Implementations related to logging."""

import logging
import logging.handlers
import os
import sys
from functools import wraps

from . import __version__

FMT = "%(asctime)s - %(name)s - %(module)s - %(levelname)s - %(message)s"


[docs] def setuplog( name: str = "hydromt", path: str = None, log_level: int = 20, fmt: str = FMT, append: bool = True, ) -> logging.Logger: """Set up the logging on sys.stdout and file if path is given. Parameters ---------- name : str, optional logger name, by default "hydromt" path : str, optional path to logfile, by default None log_level : int, optional Log level [0-50], by default 20 (info) fmt : str, optional log message formatter append : bool, optional Whether to append (True) or overwrite (False) to a logfile at path, by default True Returns ------- logging.Logger _description_ """ logger = logging.getLogger(name) for _ in range(len(logger.handlers)): logger.handlers.pop().close() # remove and close existing handlers logging.captureWarnings(True) logger.setLevel(log_level) console = logging.StreamHandler(sys.stdout) console.setLevel(log_level) console.setFormatter(logging.Formatter(fmt)) logger.addHandler(console) if path is not None: if append is False and os.path.isfile(path): os.unlink(path) add_filehandler(logger, path, log_level=log_level, fmt=fmt) logger.info(f"HydroMT version: {__version__}") return logger
def add_filehandler(logger, path, log_level=20, fmt=FMT): """Add file handler to logger.""" if not os.path.isdir(os.path.dirname(path)): os.makedirs(os.path.dirname(path)) isfile = os.path.isfile(path) ch = logging.FileHandler(path) ch.setFormatter(logging.Formatter(fmt)) ch.setLevel(log_level) logger.addHandler(ch) if isfile: logger.debug(f"Appending log messages to file {path}.") else: logger.debug(f"Writing log messages to new file {path}.") def logged(logger): """Define a decorator that logs the execution of a function. This decorator logs the input arguments, output, and any raised exceptions of the decorated function using the provided logger. Parameters ---------- logger : Logger The logger object used to log the function execution. Returns ------- wrap : callable The decorator function that wraps the decorated function. """ def wrap(function): @wraps(function) def wrapper(*args, **kwargs): f = function.__name__ logger.debug(f"{f} - args={args} kwargs={kwargs}") try: response = function(*args, **kwargs) except Exception as error: e = error.__class__.__name__ emsg = str(error) logger.error(f"{f} - raised {e} with error '{emsg}'") raise logger.debug(f"{f} - return={response}") return response return wrapper return wrap