Add | adding config paser
This commit is contained in:
parent
5b359f22de
commit
108b92da23
148
src/lib_not_dr/logger/config.py
Normal file
148
src/lib_not_dr/logger/config.py
Normal 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()
|
@ -207,17 +207,22 @@ class StdFormatter(BaseFormatter):
|
||||
TraceColorFormatter(),
|
||||
MessageColorFormatter()]
|
||||
|
||||
default_template: str = '[${log_time}][${level}]|${logger_name}:${logger_tag}|${messages}'
|
||||
|
||||
def __init__(self,
|
||||
enable_color: bool = True,
|
||||
sub_formatter: Optional[List[BaseFormatter]] = None,
|
||||
main_formatter: Optional[MainFormatter] = None,
|
||||
color_formatters: Optional[List[BaseFormatter]] = None,
|
||||
default_template: Optional[str] = None,
|
||||
**kwargs) -> None:
|
||||
"""
|
||||
Initialize the StdFormatter
|
||||
:param enable_color: enable color
|
||||
:param sub_formatter: list of sub formatter
|
||||
:param main_formatter: main formatter
|
||||
:param color_formatters: list of color formatter
|
||||
:param default_template: default template
|
||||
:param kwargs: other options
|
||||
"""
|
||||
# 同 structures.LogMessage.__init__ 的注释 (逃)
|
||||
@ -230,6 +235,8 @@ class StdFormatter(BaseFormatter):
|
||||
self.main_formatter = main_formatter
|
||||
else:
|
||||
self.main_formatter = MainFormatter()
|
||||
if default_template is not None:
|
||||
self.default_template = default_template
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def _format(self, message: FormattingMessage) -> FormattingMessage:
|
||||
|
@ -20,7 +20,7 @@ class Logger(Options):
|
||||
|
||||
outputs: List[BaseOutputStream] = [StdioOutputStream()]
|
||||
|
||||
log_name: str = 'root'
|
||||
logger_name: str = 'root'
|
||||
|
||||
enable: bool = True
|
||||
level: int = 20 # info
|
||||
@ -122,7 +122,7 @@ class Logger(Options):
|
||||
flush=flush,
|
||||
level=level,
|
||||
log_time=log_time,
|
||||
logger_name=self.log_name,
|
||||
logger_name=self.logger_name,
|
||||
logger_tag=tag,
|
||||
stack_trace=stack_trace)
|
||||
if level >= 30: # WARN
|
||||
|
Loading…
Reference in New Issue
Block a user