feat: logger

This commit is contained in:
shenjack 2022-12-29 10:13:26 +08:00
parent ab279cb557
commit dd2d4a3156
2 changed files with 123 additions and 51 deletions

View File

@ -51,13 +51,16 @@ long_time = '%Y-%m-%d %H-%M-%S:%%S'
[Colors] [Colors]
[Colors.main_color] [Colors.main_color]
main_time = '\u001b[38;2;201;222;56m' # 翻了三个月的颜色啊
long_time = '\u001b[38;2;201;222;56m'
short_time = '\u001b[38;2;201;222;56m'
code_line = '\u001b[38;2;0;255;180m' code_line = '\u001b[38;2;0;255;180m'
file_name = '\u001b[38;2;0;255;180m' file_name = '\u001b[38;2;0;255;180m'
info = '\u001b[0m' info = '\u001b[0m'
message = '\u001b[0m' message = '\u001b[0m'
logger = '\u001b[0m' logger = '\u001b[0m'
marker = '\u001b[0m' marker = '\u001b[0m'
# level colors
TRACE.info = '\u001b[38;2;138;173;244m' TRACE.info = '\u001b[38;2;138;173;244m'
FINE.info = '\u001b[35;48;2;44;44;54m' FINE.info = '\u001b[35;48;2;44;44;54m'
DEBUG.info = '\u001b[38;2;133;138;149m' DEBUG.info = '\u001b[38;2;133;138;149m'
@ -68,21 +71,53 @@ long_time = '%Y-%m-%d %H-%M-%S:%%S'
FATAL.logger = '\u001b[38;2;245;189;230m' FATAL.logger = '\u001b[38;2;245;189;230m'
[Colors.fancy_main_color] [Colors.fancy_main_color]
main_time = '\u001b[38;2;201;222;56m' long_time = '\u001b[38;2;201;222;56m'
short_time = '\u001b[38;2;201;222;56m'
file_name = '\u001b[38;2;0;255;180m' file_name = '\u001b[38;2;0;255;180m'
code_line = '\u001b[38;2;0;255;180m' code_line = '\u001b[38;2;0;255;180m'
info = '\u001b[0m' info = '\u001b[0m'
message = '\u001b[0m' message = '\u001b[0m'
logger = '\u001b[0m' logger = '\u001b[0m'
marker = '\u001b[0m' marker = '\u001b[0m'
TRACE.info = '\u001b[38;2;138;173;244m' # level colors
TRACE.message = '\u001b[38;2;138;173;244m' TRACE.info = '\u001b[38;2;138;173;244m'
FINE.info = '\u001b[35;48;2;44;44;54m' TRACE.message = '\u001b[38;2;138;173;244m'
FINE.message = '\u001b[35m' FINE.info = '\u001b[35;48;2;44;44;54m'
DEBUG.info = '\u001b[38;2;133;138;149m' FINE.message = '\u001b[35m'
INFO.info = '\u001b[0m' DEBUG.info = '\u001b[38;2;133;138;149m'
WARNING.info = '\u001b[33m' DEBUG.message = '\u001b[38;2;133;138;149m'
ERROR.info = '\u001b[31m' INFO.info = '\u001b[0m'
FATAL.info = '\u001b[38;2;255;255;0;48;2;120;10;10m' INFO.message = '\u001b[0m'
FATAL.message = '\u001b[38;2;255;255;0;48;2;120;10;10m' WARNING.info = '\u001b[33m'
FATAL.logger = '\u001b[38;2;245;189;230m' WARNING.message = '\u001b[33m'
ERROR.info = '\u001b[31m'
ERROR.message = '\u001b[31m'
FATAL.info = '\u001b[38;2;255;255;0;48;2;120;10;10m'
FATAL.message = '\u001b[38;2;255;255;0;48;2;120;10;10m'
FATAL.logger = '\u001b[38;2;245;189;230m'
[Colors.DiGua_color]
# catppuccin Macchiato
long_time = '\u001b[38;2;202;211;245m'
short_time = '\u001b[38;2;202;211;245m'
file_name = '\u001b[38;2;139;213;202m'
code_line = '\u001b[38;2;166;218;149m'
info = '\u001b[0m'
logger = '\u001b[0m'
message = '\u001b[0m'
marker = '\u001b[0m'
# level colors
TRACE.info = '\u001b[38;2;138;173;244m'
TRACE.message = '\u001b[38;2;138;173;244m'
FINE.info = '\u001b[38;2;198;160;246m'
FINE.message = '\u001b[38;2;198;160;246m'
DEBUG.info = '\u001b[38;2;133;138;149m'
DEBUG.message = '\u001b[38;2;133;138;149m'
ERROR.info = '\u001b[38;2;237;135;150m'
ERROR.message = '\u001b[38;2;237;135;150m'
WARNING.info = '\u001b[38;2;245;169;127m'
WARNING.message = '\u001b[38;2;245;169;127m'
FATAL.info = '\u001b[38;2;255;255;0;48;2;120;10;10m'
FATAL.message = '\u001b[38;2;255;255;0;48;2;120;10;10m'
FATAL.loggger = '\u001b[38;2;245;189;230m'

View File

@ -16,6 +16,7 @@ import time
import enum import enum
import atexit import atexit
import inspect import inspect
import warnings
import threading import threading
import dataclasses import dataclasses
@ -23,7 +24,7 @@ from types import FrameType
from logging import NOTSET, DEBUG from logging import NOTSET, DEBUG
from typing import NamedTuple, Optional, Type, Union, Dict, Iterable, Any, List from typing import NamedTuple, Optional, Type, Union, Dict, Iterable, Any, List
Version = '1.0.0' Version = '1.1.0'
# os.system('') # os.system('')
color_support = True color_support = True
@ -60,8 +61,8 @@ color_reset_suffix = "\033[0m"
re_find_color_code = r'\033\[[^\f\n\r\t\vm]*m' re_find_color_code = r'\033\[[^\f\n\r\t\vm]*m'
re_color_code = re.compile(re_find_color_code) re_color_code = re.compile(re_find_color_code)
re_find_formats = re.compile(r'\{\w+}')
re_find_level_code = r'' # re_find_level_code = r''
""" """
OFF > FATAL > ERROR > WARN > INFO > FINE > FINER > DEBUG > TRACE > ALL OFF > FATAL > ERROR > WARN > INFO > FINE > FINER > DEBUG > TRACE > ALL
@ -250,7 +251,7 @@ class LogFileConf:
file_cache_time: Union[int, float] = 1 file_cache_time: Union[int, float] = 1
class Message_content(NamedTuple): class Message_content(NamedTuple):
"""用于存储 log 信息的不可变元组""" """用于存储 log 信息的不可变元组"""
log_time: float log_time: float
text: str text: str
@ -342,16 +343,6 @@ class ListCache:
self.cache.clear() self.cache.clear()
class FormatterTemplate:
"""用于格式化 log 信息的模板类"""
def __init__(self, formats: dict):
self.formats = formats
def format(self, message: str) -> str:
raise NotImplementedError('There is a formatter that not implemented')
class ColorCodeEnum(enum.Enum): class ColorCodeEnum(enum.Enum):
main_time = "main_time" main_time = "main_time"
code_line = "code_line" code_line = "code_line"
@ -362,32 +353,86 @@ class ColorCodeEnum(enum.Enum):
marker = "marker" marker = "marker"
class FormatCodeEnum(enum.Enum):
long_time: str = '%Y-%m-%d %H-%M-%S:%%S'
short_time: str = '%Y-%m-%d %H-%M-%S'
logger_name: str = '{logger_name}'
level: str = '{level}'
fine_name: str = '{file_name}'
code_line: str = '{code_line}'
marker: str = '{marker}'
message: str = '{message}'
class FormatterConfig(NamedTuple):
""" Named Tuple 真好用 """
support_color: bool
format: str
formats: Dict[str, str]
color: Dict[str, Union[str, Dict[str, str]]]
class FormatterTemplate:
"""用于格式化 log 信息的模板类"""
def __init__(self, configs: FormatterConfig):
self.configs = configs
def format(self, message: Message_content) -> str:
raise NotImplementedError('There is a formatter that not implemented')
class StdFormatter(FormatterTemplate): class StdFormatter(FormatterTemplate):
""" 一个标准的格式化类 """ """ 一个标准的格式化类 """
def __init__(self, formats: dict, configs: dict): def __init__(self, configs: FormatterConfig):
super().__init__(formats=formats) super().__init__(configs=configs)
self.configs = configs
... ...
def format_time(self, input_time: Optional[float] = None) -> Dict[str, str]: def format_time(self, input_time: Optional[float] = None) -> Dict[str, str]:
millisecond = str((input_time - int(input_time)) * 1000) millisecond = str((input_time - int(input_time)) * 1000)
long_time = time.strftime( long_time = time.strftime(self.configs.formats['long_time'].replace('%%S', millisecond))
self.formats['long_time'].replace('%%S', millisecond)) short_time = time.strftime(self.configs.formats['short_time'].replace('%%S', millisecond))
short_time = time.strftime(
self.formats['short_time'].replace('%%S', millisecond))
return {'long_time': long_time, 'short_time': short_time} return {'long_time': long_time, 'short_time': short_time}
def get_color_code(self, level: str, content: ColorCodeEnum) -> str: def get_color_code(self, level: str, content: ColorCodeEnum) -> str:
assert content in ColorCodeEnum assert content in ColorCodeEnum
if content in self.configs[level]: if content in self.configs.color[level]:
return self.configs[level][content.name].replace("\\u001b", '\u001b') return self.configs.color[level][content.name].replace("\\u001b", '\u001b')
return self.configs[content.name].replace('\\u001b', '\u001b') return self.configs.color[content.name].replace('\\u001b', '\u001b')
def color_format(self, message: Message_content) -> Message_content: """
format 支持的内容: 帮我写一下说明呗
{long_time}: 长时间
{short_time}: 短时间
{logger_name}: logger 名称
{level}: 记录等级
{file_name}: 文件名
{code_line}: 代码行
{marker}: 标记
{message}: 消息
"""
def color_format(self, message: Message_content) -> str:
if not self.configs.support_color:
return self.format(message=message)
times = self.format_time(input_time=message.log_time) times = self.format_time(input_time=message.log_time)
need_colors = [x for x in re_find_formats.findall(self.configs.format)]
new_message = self.configs.format
for need_color in need_colors:
if not hasattr(FormatCodeEnum, need_color[1:-1]):
warnings.warn(f'logger config wrong! get {need_color}')
continue
color_code = color_reset_suffix
if need_color[1:-1] in self.configs.color[level_name_map[message.level]]:
color_code = self.configs.color[level_name_map[message.level]][need_color[1:-1]]
elif need_color[1:-1] in self.configs.color:
color_code = self.configs.color[need_color[1:-1]]
new_message.replace(need_color, f'{color_code}{need_color}{color_reset_suffix}')
def format(self, message: Message_content) -> Message_content:
def format(self, message: Message_content) -> str:
times = self.format_time(input_time=message.log_time) times = self.format_time(input_time=message.log_time)
... ...
@ -472,7 +517,7 @@ class StdHandler(StreamHandlerTemplate):
super().__init__(level=level, formatter=formatter) super().__init__(level=level, formatter=formatter)
def write(self, message: Message_content) -> bool: def write(self, message: Message_content) -> bool:
print(self.formatter.format(message.text), end=message.end, flush=message.flush) print(self.formatter.format(message), end=message.end, flush=message.flush)
return True return True
def close(self) -> bool: def close(self) -> bool:
@ -541,7 +586,9 @@ class CachedFileHandler(StreamHandlerTemplate):
def write(self, message: Message_content) -> bool: def write(self, message: Message_content) -> bool:
self.len += 1 self.len += 1
self.cache_stream.write(message.text) formatted_message = self.formatter.format(message)
formatted_message = f'{formatted_message}{message.end}'
self.cache_stream.write(formatted_message)
if message.flush or self.len >= self.file_conf.file_cache_len: if message.flush or self.len >= self.file_conf.file_cache_len:
if not self.flush(): if not self.flush():
self.flush() self.flush()
@ -1083,16 +1130,6 @@ if __name__ == "__main__":
for x in range(5): for x in range(5):
test_logger(logger) test_logger(logger)
test_logger(a_logger) test_logger(a_logger)
import rtoml
parse_config = rtoml.dumps(logger_configs, pretty=True)
import pprint
sys.stdout.write(rtoml.dumps(logger_configs, pretty=True))
print('-----------------')
sys.stdout.write(rtoml.dumps(logger_configs, pretty=False))
print('-----------------')
pprint.pprint(rtoml.loads(parse_config))
print(Message_content(log_time=time.time(), text='aaa', level=4, marker='abc', end='abc', flush=False, print(Message_content(log_time=time.time(), text='aaa', level=4, marker='abc', end='abc', flush=False,
frame=inspect.currentframe())) frame=inspect.currentframe()))
print(ColorCodeEnum.code_line.name) print(ColorCodeEnum.code_line.name)