Add | adding config paser

This commit is contained in:
shenjack 2023-11-26 21:57:39 +08:00
parent 5b359f22de
commit 108b92da23
Signed by: shenjack
GPG Key ID: 7B1134A979775551
3 changed files with 157 additions and 2 deletions

View File

@ -0,0 +1,148 @@
# -------------------------------
# Difficult Rocket
# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
# All rights reserved
# -------------------------------
from typing import List, Union, Optional, TYPE_CHECKING, Dict
from lib_not_dr.logger.logger import Logger
from lib_not_dr.types.options import Options, OptionNameNotDefined
from lib_not_dr.logger.formatter import (MainFormatter,
StdFormatter,
BaseFormatter)
from lib_not_dr.logger.outstream import (BaseOutputStream,
StdioOutputStream,
FileCacheOutputStream)
from lib_not_dr.logger import formatter, outstream
class ConfigStorage(Options):
name = 'LoggerConfigStorage'
# 存储 logger, formatter, output 的字典
loggers: Dict[str, Logger] = {}
formatters: Dict[str, BaseFormatter] = {}
outputs: Dict[str, BaseOutputStream] = {}
# 存储失败的 logger, formatter, output 的字典
fail_loggers: Dict[str, dict] = {}
fail_formatters: Dict[str, dict] = {}
fail_outputs: Dict[str, dict] = {}
default_logger: Logger = Logger.get_logger_by_name('root')
log: Logger = Logger.get_logger_by_name('logger-storage')
def have_formatter(self, formatter_name: str) -> bool:
return formatter_name in self.formatters
def have_output(self, output_name: str) -> bool:
return output_name in self.outputs
def have_logger(self, logger_name: str) -> bool:
return logger_name in self.loggers
def merge_storage(self, other_storage: 'ConfigStorage') -> None:
"""
Merge storage
:param other_storage:
:return:
"""
self.loggers.update(other_storage.loggers)
self.formatters.update(other_storage.formatters)
self.outputs.update(other_storage.outputs)
self.fail_loggers.update(other_storage.fail_loggers)
self.fail_formatters.update(other_storage.fail_formatters)
self.fail_outputs.update(other_storage.fail_outputs)
@staticmethod
def circle_require_check(require_dict: Dict[str, List[str]]) -> List[str]:
"""
Check circle require
:param require_dict:
:return:
"""
circle_require = []
for key, value in require_dict.items():
for require in value:
if require in require_dict and key in require_dict[require]:
circle_require.append(key)
return circle_require
def parse_formatter(self, formatter_config: Dict[str]) -> 'ConfigStorage':
"""
Parse formatter config
:param formatter_config:
:return:
"""
env = ConfigStorage()
formatter_wait: Dict[str, dict] = formatter_config.get('Formatter', {})
# Check circle require
formatter_require = {}
for key, value in formatter_wait.items():
if 'sub_formatter' in value:
formatter_require[key] = value['sub_formatter']
else:
formatter_require[key] = []
circle_require = self.circle_require_check(formatter_require)
if len(circle_require) > 0:
for formatter_name in circle_require:
self.log.error(f'Formatter {formatter_name} require circle, ignored')
env.fail_formatters[formatter_name] = formatter_wait[formatter_name]
formatter_wait.pop(formatter_name)
# Parse formatter
ensure = 1000
while len(formatter_wait) > 0:
for key, value in formatter_wait.items():
key: str
value: dict
formatter_name = key
# check class
if 'class' not in value:
self.log.warn(f'Formatter {formatter_name} has no class, ignored')
env.fail_formatters[formatter_name] = value
continue
formatter_class = value.pop('class')
# check class exist
if formatter_class not in formatter.__all__:
self.log.warn(f'Formatter {formatter_name} class {formatter_class} not found, ignored')
env.fail_formatters[formatter_name] = value
continue
formatter_class = getattr(formatter, formatter_class)
# ensure sub formatter exist
if 'sub_formatter' in value:
for fmt in value['sub_formatter']:
if not env.have_formatter(fmt):
formatter_wait[formatter_name] = value
continue
# init formatter
try:
formatter_instance = formatter_class(**value)
except OptionNameNotDefined as e:
self.log.error(f'Formatter {formatter_name} class {formatter_class} init failed, ignored\n'
f'Error: {e}')
env.fail_formatters[formatter_name] = value
continue
# add formatter
env.formatters[formatter_name] = formatter_instance
formatter_wait.pop(formatter_name)
ensure -= 1
if ensure <= 0:
self.log.error('Formatter parse failed, ignored')
# add all left formatter to fail formatter
env.fail_formatters.update(formatter_wait)
break
return env
def read_dict_config(self, config: Dict[str, dict]) -> None:
"""
Read config from dict
:param config:
:return:
"""
dict_env = self.parse_formatter(config.get('Formatter', {}))
self.merge_storage(dict_env)
storage = ConfigStorage()

View File

@ -207,17 +207,22 @@ class StdFormatter(BaseFormatter):
TraceColorFormatter(), TraceColorFormatter(),
MessageColorFormatter()] MessageColorFormatter()]
default_template: str = '[${log_time}][${level}]|${logger_name}:${logger_tag}|${messages}'
def __init__(self, def __init__(self,
enable_color: bool = True, enable_color: bool = True,
sub_formatter: Optional[List[BaseFormatter]] = None, sub_formatter: Optional[List[BaseFormatter]] = None,
main_formatter: Optional[MainFormatter] = None, main_formatter: Optional[MainFormatter] = None,
color_formatters: Optional[List[BaseFormatter]] = None, color_formatters: Optional[List[BaseFormatter]] = None,
default_template: Optional[str] = None,
**kwargs) -> None: **kwargs) -> None:
""" """
Initialize the StdFormatter Initialize the StdFormatter
:param enable_color: enable color :param enable_color: enable color
:param sub_formatter: list of sub formatter :param sub_formatter: list of sub formatter
:param main_formatter: main formatter
:param color_formatters: list of color formatter :param color_formatters: list of color formatter
:param default_template: default template
:param kwargs: other options :param kwargs: other options
""" """
# 同 structures.LogMessage.__init__ 的注释 (逃) # 同 structures.LogMessage.__init__ 的注释 (逃)
@ -230,6 +235,8 @@ class StdFormatter(BaseFormatter):
self.main_formatter = main_formatter self.main_formatter = main_formatter
else: else:
self.main_formatter = MainFormatter() self.main_formatter = MainFormatter()
if default_template is not None:
self.default_template = default_template
super().__init__(**kwargs) super().__init__(**kwargs)
def _format(self, message: FormattingMessage) -> FormattingMessage: def _format(self, message: FormattingMessage) -> FormattingMessage:

View File

@ -20,7 +20,7 @@ class Logger(Options):
outputs: List[BaseOutputStream] = [StdioOutputStream()] outputs: List[BaseOutputStream] = [StdioOutputStream()]
log_name: str = 'root' logger_name: str = 'root'
enable: bool = True enable: bool = True
level: int = 20 # info level: int = 20 # info
@ -122,7 +122,7 @@ class Logger(Options):
flush=flush, flush=flush,
level=level, level=level,
log_time=log_time, log_time=log_time,
logger_name=self.log_name, logger_name=self.logger_name,
logger_tag=tag, logger_tag=tag,
stack_trace=stack_trace) stack_trace=stack_trace)
if level >= 30: # WARN if level >= 30: # WARN