| 66 | |
| 67 | |
| 68 | class Logger: |
| 69 | def __init__(self, |
| 70 | name="default", |
| 71 | colorize=False, |
| 72 | log_path=None, |
| 73 | stream=sys.stdout, |
| 74 | level=INFO): |
| 75 | self.name = name |
| 76 | |
| 77 | # get the logger object; keep it hidden as there's no need to directly access it |
| 78 | self.__logger = logging.getLogger(f"_logger-{name}") |
| 79 | self.__logger.propagate = False |
| 80 | |
| 81 | self.setLevel(level.lower()) |
| 82 | |
| 83 | # use the custom formatter |
| 84 | self.__formatter = _Formatter( |
| 85 | colorize=colorize, |
| 86 | fmt= |
| 87 | "[%(process)d][%(asctime)s.%(msecs)03d @ %(funcName)s] %(message)s", |
| 88 | datefmt="%y-%m-%d %H:%M:%S", |
| 89 | ) |
| 90 | |
| 91 | # install default handler |
| 92 | self.__stream_to_handler = {} |
| 93 | self.clear_handlers() |
| 94 | self.__main_handler = self.add_handler(stream) |
| 95 | |
| 96 | fh = logging.FileHandler(log_path, "w") |
| 97 | self.__logger.addHandler(fh) |
| 98 | # sh = logging.StreamHandler() |
| 99 | # self.__logger.addHandler(sh) |
| 100 | |
| 101 | # install logging functions |
| 102 | self.debug = self.__logger.debug |
| 103 | self.info = self.__logger.info |
| 104 | self.warning = self.__logger.warning |
| 105 | self.error = self.__logger.error |
| 106 | self.critical = self.__logger.critical |
| 107 | |
| 108 | def log_function(self): |
| 109 | def wrapper(func): |
| 110 | def func_wrapper(*args, **kwargs): |
| 111 | self.__logger.info( |
| 112 | f"calling <{func.__name__}>\n\t args: {args}\n\tkwargs: {kwargs}" |
| 113 | ) |
| 114 | out = func(*args, **kwargs) |
| 115 | self.__logger.info(f"exiting <{func.__name__}>") |
| 116 | return out |
| 117 | |
| 118 | return func_wrapper |
| 119 | |
| 120 | return wrapper |
| 121 | |
| 122 | def setLevel(self, level: Union[str, int]) -> None: |
| 123 | if isinstance(level, int): |
| 124 | self.__logger.setLevel(level) |
| 125 | else: |