From 108b92da23e08aa8d38ba7e9d692cead011af37f Mon Sep 17 00:00:00 2001 From: shenjack <3695888@qq.com> Date: Sun, 26 Nov 2023 21:57:39 +0800 Subject: [PATCH] Add | adding config paser --- src/lib_not_dr/logger/config.py | 148 ++++++++++++++++++++ src/lib_not_dr/logger/formatter/__init__.py | 7 + src/lib_not_dr/logger/logger.py | 4 +- 3 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 src/lib_not_dr/logger/config.py diff --git a/src/lib_not_dr/logger/config.py b/src/lib_not_dr/logger/config.py new file mode 100644 index 0000000..6c2f591 --- /dev/null +++ b/src/lib_not_dr/logger/config.py @@ -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() diff --git a/src/lib_not_dr/logger/formatter/__init__.py b/src/lib_not_dr/logger/formatter/__init__.py index 34f3fcb..cd315e5 100644 --- a/src/lib_not_dr/logger/formatter/__init__.py +++ b/src/lib_not_dr/logger/formatter/__init__.py @@ -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: diff --git a/src/lib_not_dr/logger/logger.py b/src/lib_not_dr/logger/logger.py index 020edbc..b4bbd5f 100644 --- a/src/lib_not_dr/logger/logger.py +++ b/src/lib_not_dr/logger/logger.py @@ -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