File size: 3,094 Bytes
858bf77
 
 
 
 
2ca99e2
858bf77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2ca99e2
 
858bf77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import os
import sys
from enum import Enum
from logging import Formatter, LogRecord, getLogger, StreamHandler, FileHandler
from pathlib import Path
from typing import Optional

from colorama import Fore, Style


class LoggerTarget(Enum):
    CONSOLE = "console"
    FILE = "file"
    BOTH = "both"


class ColorFormatter(Formatter):
    COLORS_LEVEL = {
        "DEBUG": Fore.CYAN,
        "INFO": Fore.GREEN,
        "WARNING": Fore.YELLOW,
        "ERROR": Fore.RED,
        "CRITICAL": Fore.MAGENTA + Style.BRIGHT,
    }

    def format(self, record: LogRecord):
        original_levelname = record.levelname
        color = self.COLORS_LEVEL.get(original_levelname, "")
        record.levelname = f"{color}{original_levelname}{Style.RESET_ALL}"
        formatted = super().format(record)
        return formatted


class CoreLogger:
    def __init__(
        self,
        name: str = "app",
        level: str = "INFO",
        fmt: Optional[str] = None,
        datefmt: Optional[str] = None,
        log_to_console: bool = True,
        log_to_file: bool = False,
    ):
        self.logger = getLogger(name)
        self.logger.setLevel(level)
        self.log_to_console = log_to_console
        self.log_to_file = log_to_file
        self.logger.propagate = False

        self.fmt = fmt or "%(asctime)s | %(levelname)-8s | %(message)s"
        self.datefmt = datefmt or "%Y-%m-%d %H:%M:%S"

        self.logger_file_path = Path(__file__).resolve().parents[2]
        self.logger_file_path = self.logger_file_path / "logs" / "app.log"

        formatter = Formatter(self.fmt, self.datefmt)

        color_formatter = ColorFormatter(self.fmt, self.datefmt)

        if self.log_to_console:
            console_handler = StreamHandler(sys.stdout)
            console_handler.setFormatter(color_formatter)
            self.logger.addHandler(console_handler)

        if self.log_to_file:
            log_file_path = Path(self.logger_file_path).resolve()
            log_file_path.parent.mkdir(parents=True, exist_ok=True)
            fh = FileHandler(log_file_path, encoding="utf-8")
            fh.setFormatter(formatter)
            self.logger.addHandler(fh)

    def debug(self, message: str):
        self.logger.debug(message)

    def info(self, message: str):
        self.logger.info(message)

    def warning(self, message: str):
        self.logger.warning(message)

    def error(self, message: str):
        self.logger.error(message)

    def clear_log(self, target: LoggerTarget = LoggerTarget.BOTH):
        if target in (LoggerTarget.CONSOLE, LoggerTarget.BOTH) and self.log_to_console:
            os.system("cls" if sys.platform.startswith("win") else "clear")

        if target in (LoggerTarget.FILE, LoggerTarget.BOTH) and self.log_to_file:
            log_file_path = Path(self.logger_file_path).resolve()
            if log_file_path.exists():
                with log_file_path.open("w", encoding="utf-8") as f:
                    f.truncate(0)


if __name__ == "__main__":
    logger = CoreLogger(log_to_console=True, log_to_file=True)
    logger.info("test")