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()