Source code for elphick.geomet.utils.timer

"""
REF: https://ankitbko.github.io/blog/2021/04/logging-in-python/
"""

import functools
import logging
from datetime import datetime
from typing import Union


[docs] class MyLogger:
[docs] def __init__(self): logging.basicConfig(level=logging.INFO, format=' %(asctime)s - %(levelname)s - %(message)s')
def get_logger(self, name=None): return logging.getLogger(name)
[docs] def get_default_logger(): return MyLogger().get_logger()
[docs] def log_timer(_func=None, *, my_logger: Union[MyLogger, logging.Logger] = None): def decorator_log(func): @functools.wraps(func) def wrapper(*args, **kwargs): logger = get_default_logger() try: if my_logger is None: first_args = next(iter(args), None) # capture first arg to check for `self` logger_params = [ # does kwargs have any logger x for x in kwargs.values() if isinstance(x, logging.Logger) or isinstance(x, MyLogger) ] + [ # # does args have any logger x for x in args if isinstance(x, logging.Logger) or isinstance(x, MyLogger) ] if hasattr(first_args, "__dict__"): # is first argument `self` logger_params = logger_params + [ x for x in first_args.__dict__.values() # does class (dict) members have any logger if isinstance(x, logging.Logger) or isinstance(x, MyLogger) ] h_logger = next(iter(logger_params), MyLogger()) # get the next/first/default logger else: h_logger = my_logger # logger is passed explicitly to the decorator if isinstance(h_logger, MyLogger): logger = h_logger.get_logger(func.__name__) else: logger = h_logger # args_repr = [repr(a) for a in args] # kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items()] # signature = ", ".join(args_repr + kwargs_repr) # logger.debug(f"function {func.__name__} called with args {signature}") except Exception: pass try: _tic = datetime.now() result = func(*args, **kwargs) _toc = datetime.now() logger.info(f"Elapsed time for {func.__name__}: {_toc - _tic}") return result except Exception as e: logger.exception(f"Exception raised in {func.__name__}. exception: {str(e)}") raise e return wrapper if _func is None: return decorator_log else: return decorator_log(_func)