File size: 2,104 Bytes
b400ace | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | import logging
from typing import Union
from rich.console import Console
from rich.logging import RichHandler
FORMAT = "%(message)s"
# TODO: set logging level from config.json dynamically
logging.basicConfig(
level=logging.INFO,
format="%(message)s",
datefmt="[%X]",
handlers=[RichHandler(rich_tracebacks=True)],
)
class Logger:
def __init__(
self,
name,
level: Union[int, str] = logging.NOTSET,
message_format="%(message)s",
date_format="[%X]",
):
self.log = logging.getLogger(name)
self.log.setLevel(level)
self.log.__format__ = message_format
self.log.__date_format__ = date_format
def debug(self, *msg: object, sep=" ", end="\n") -> None:
return self.logutil("debug", *msg, sep=sep)
def info(self, *msg: object, sep=" ", end="\n") -> None:
return self.logutil("info", *msg, sep=sep)
def warning(self, *msg: object, sep=" ", end="\n") -> None:
return self.logutil("warning", *msg, sep=sep)
def error(self, *msg: object, sep=" ", end="\n") -> None:
return self.logutil("error", *msg, sep=sep)
def critical(self, *msg: object, sep=" ", end="\n") -> None:
return self.logutil("critical", *msg, sep=sep)
def stringify(func):
def inner(self, method_type: str, *msg: object, sep=" "):
nmsg = []
for v in msg:
if not isinstance(v, str):
v = str(v)
nmsg.append(v)
return func(self, method_type, *nmsg, sep=sep)
return inner
# set stack level to 3 so that the caller of this function is logged, not this function itself.
# stack-frame - self.log.debug - logutil - stringify - log method - caller
@stringify
def logutil(self, method_type: str, *msg: object, sep=" ") -> None:
func = getattr(self.log, method_type, None)
if not func:
raise AttributeError(f"Logger has no method {method_type}")
return func(sep.join(msg), stacklevel=4)
logger = Logger(__name__)
console = Console()
|