Merge branch 'enhance/logger-speed-up'

This commit is contained in:
shenjack 2023-12-02 10:42:37 +08:00
commit f0d7ab21a4
Signed by: shenjack
GPG Key ID: 7B1134A979775551
6 changed files with 102 additions and 51 deletions

View File

@ -11,7 +11,7 @@ import logging
def logging_logger() -> None: def logging_logger() -> None:
logger = logging.getLogger('test') logger = logging.getLogger('test')
logger.setLevel(logging.DEBUG) logger.level = logging.INFO
logger.info('Hello World!') logger.info('Hello World!')
logger.debug('Hello World!') logger.debug('Hello World!')
@ -22,7 +22,7 @@ def logging_logger() -> None:
def lndl_logger() -> None: def lndl_logger() -> None:
logger = Logger.get_logger_by_name('test') logger = Logger.get_logger_by_name('test')
logger.global_level = 0 logger.global_level = 20
logger.info('Hello World!') logger.info('Hello World!')
logger.fine('Hello World!') logger.fine('Hello World!')
@ -53,5 +53,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main()
lndl_logger() lndl_logger()
logging_logger() logging_logger()

View File

@ -1,5 +1,4 @@
[project] [project]
name = "lib-not-dr" name = "lib-not-dr"
description = "A python lib created from Difficult Rocket development" description = "A python lib created from Difficult Rocket development"
readme = "README.md" readme = "README.md"

View File

@ -65,8 +65,7 @@ class LogLevel(Options):
} }
@classmethod @classmethod
def parse_name_level(cls, def parse_name_level(cls, name: str) -> int:
name: str) -> int:
""" """
parse logging name to level int parse logging name to level int
:param name: logging level name :param name: logging level name

View File

@ -4,13 +4,13 @@
# All rights reserved # All rights reserved
# ------------------------------- # -------------------------------
from typing import List, Set, Dict, Optional from typing import List, Set, Dict, Optional, Tuple
from lib_not_dr.logger.logger import Logger from lib_not_dr.logger.logger import Logger
from lib_not_dr.types.options import Options, OptionNameNotDefined
from lib_not_dr.logger.formatter import BaseFormatter from lib_not_dr.logger.formatter import BaseFormatter
from lib_not_dr.logger.outstream import BaseOutputStream from lib_not_dr.logger.outstream import BaseOutputStream
from lib_not_dr.logger import formatter, outstream from lib_not_dr.logger import formatter, outstream, LogLevel
from lib_not_dr.types.options import Options, OptionNameNotDefined
class ConfigStorage(Options): class ConfigStorage(Options):
@ -73,10 +73,26 @@ class ConfigStorage(Options):
cycles_set.update(cycle) cycles_set.update(cycle)
return sorted(cycles_set) # 返回排序后的循环列表 return sorted(cycles_set) # 返回排序后的循环列表
def parse_level(self, level_config: Dict[str, str]) -> int: def parse_level(self, level_config: Dict[str, str]) -> Optional[int]:
""" """
""" """
level_found: Tuple[Optional[int], Optional[str]] = (level_config.get('level'), level_config.get('level_name'))
if all(_l is None for _l in level_found):
# 如果都没有
self.log.warn(f'No level or level_name in config {level_config}, ignored')
return 20
if all(_l is not None for _l in level_found):
# 如果都有 那么使用 level_name
self.log.warn(f'Level and level_name both exist in config {level_config}, using level_name')
# 去掉 level 保留 level_name
level_found = (None, level_found[1],)
if level_found[0] is not None:
# 如果 level 存在 那么使用 level
return level_found[0]
if level_found[1] is not None:
# 如果 level_name 存在 那么使用 level_name
return LogLevel.parse_name_level(level_found[1])
return None
def get_class_by_name(self, config: Dict[str, str], module) -> Optional[type]: def get_class_by_name(self, config: Dict[str, str], module) -> Optional[type]:
""" """
@ -94,6 +110,7 @@ class ConfigStorage(Options):
if class_name not in module.__all__: if class_name not in module.__all__:
self.log.warn(f'Class {class_name} not found in module {module}, ignored') self.log.warn(f'Class {class_name} not found in module {module}, ignored')
return None return None
return getattr(module, class_name) return getattr(module, class_name)
def parse_formatter(self, formatter_config: Dict[str, dict]) -> None: def parse_formatter(self, formatter_config: Dict[str, dict]) -> None:
@ -191,6 +208,10 @@ class ConfigStorage(Options):
continue continue
else: else:
config['formatter'] = self.formatters[config['formatter']] config['formatter'] = self.formatters[config['formatter']]
if level := self.parse_level(config) is not None:
config['level'] = level
if 'level_name' in config:
config.pop('level_name')
# init output # init output
try: try:
output_instance = output_class(**config) output_instance = output_class(**config)
@ -211,9 +232,34 @@ class ConfigStorage(Options):
""" """
env = ConfigStorage() env = ConfigStorage()
for logger_name, config in logger_config.items(): for logger_name, config in logger_config.items():
... # get output for logger
if 'output' in config:
if self.outputs.get(config['output']) is None:
if self.fail_outputs.get(config['output']) is None:
self.log.error(f'Logger {logger_name} output {config["output"]} not found, ignored')
else:
self.log.error(f'Logger {logger_name} require a fail output {config["output"]}, ignored')
env.fail_loggers[logger_name] = config
continue
else:
config['output'] = self.outputs[config['output']]
if level := self.parse_level(config) is not None:
config['level'] = level
if 'level_name' in config:
config.pop('level_name')
# init logger
try:
logger_instance = Logger(**config)
except OptionNameNotDefined as e:
self.log.error(f'Logger {logger_name} init failed, ignored\n'
f'Error: {e}')
env.fail_loggers[logger_name] = config
continue
# add logger
env.loggers[logger_name] = logger_instance
self.merge_storage(env)
return None
def read_dict_config(self, config: Dict[str, dict]) -> None: def read_dict_config(self, config: Dict[str, dict]) -> None:
""" """
Read config from dict Read config from dict

View File

@ -7,7 +7,7 @@
import time import time
import inspect import inspect
from types import FrameType from types import FrameType
from typing import List, Optional from typing import List, Optional, Union
from lib_not_dr.logger import LogLevel from lib_not_dr.logger import LogLevel
from lib_not_dr.types.options import Options from lib_not_dr.types.options import Options
@ -89,7 +89,7 @@ class Logger(Options):
output.level = level output.level = level
def make_log(self, def make_log(self,
messages: List[str], messages: Union[list, tuple],
tag: Optional[str] = None, tag: Optional[str] = None,
end: str = '\n', end: str = '\n',
split: str = ' ', split: str = ' ',
@ -148,7 +148,9 @@ class Logger(Options):
from lib_not_dr.logger.config import storage from lib_not_dr.logger.config import storage
if storage.have_logger(name): if storage.have_logger(name):
return storage.loggers[name] return storage.loggers[name]
return Logger(logger_name=name) _logger = Logger(logger_name=name)
storage.loggers[name] = _logger
return _logger
def info(self, def info(self,
*message, *message,
@ -159,7 +161,7 @@ class Logger(Options):
stack_trace: Optional[FrameType] = None) -> None: stack_trace: Optional[FrameType] = None) -> None:
if not self.log_for(LogLevel.info): if not self.log_for(LogLevel.info):
return return
self.make_log(messages=list(message), self.make_log(messages=message,
tag=tag, tag=tag,
end=end, end=end,
split=split, split=split,
@ -176,7 +178,7 @@ class Logger(Options):
stack_trace: Optional[FrameType] = None) -> None: stack_trace: Optional[FrameType] = None) -> None:
if not self.log_for(LogLevel.trace): if not self.log_for(LogLevel.trace):
return return
self.make_log(messages=list(message), self.make_log(messages=message,
tag=tag, tag=tag,
end=end, end=end,
split=split, split=split,
@ -193,7 +195,7 @@ class Logger(Options):
stack_trace: Optional[FrameType] = None) -> None: stack_trace: Optional[FrameType] = None) -> None:
if not self.log_for(LogLevel.fine): if not self.log_for(LogLevel.fine):
return return
self.make_log(messages=list(message), self.make_log(messages=message,
tag=tag, tag=tag,
end=end, end=end,
split=split, split=split,
@ -210,7 +212,7 @@ class Logger(Options):
stack_trace: Optional[FrameType] = None) -> None: stack_trace: Optional[FrameType] = None) -> None:
if not self.log_for(LogLevel.debug): if not self.log_for(LogLevel.debug):
return return
self.make_log(messages=list(message), self.make_log(messages=message,
tag=tag, tag=tag,
end=end, end=end,
split=split, split=split,
@ -227,7 +229,7 @@ class Logger(Options):
stack_trace: Optional[FrameType] = None) -> None: stack_trace: Optional[FrameType] = None) -> None:
if not self.log_for(LogLevel.warn): if not self.log_for(LogLevel.warn):
return return
self.make_log(messages=list(message), self.make_log(messages=message,
tag=tag, tag=tag,
end=end, end=end,
split=split, split=split,
@ -244,7 +246,7 @@ class Logger(Options):
stack_trace: Optional[FrameType] = None) -> None: stack_trace: Optional[FrameType] = None) -> None:
if not self.log_for(LogLevel.error): if not self.log_for(LogLevel.error):
return return
self.make_log(messages=list(message), self.make_log(messages=message,
tag=tag, tag=tag,
end=end, end=end,
split=split, split=split,
@ -261,7 +263,7 @@ class Logger(Options):
stack_trace: Optional[FrameType] = None) -> None: stack_trace: Optional[FrameType] = None) -> None:
if not self.log_for(LogLevel.fatal): if not self.log_for(LogLevel.fatal):
return return
self.make_log(messages=list(message), self.make_log(messages=message,
tag=tag, tag=tag,
end=end, end=end,
split=split, split=split,

View File

@ -16,9 +16,7 @@ __all__ = ['LogMessage',
'FormattingMessage'] 'FormattingMessage']
class LogMessage(Options): class LogMessage:
name = 'LogMessage'
# 消息内容本身的属性 # 消息内容本身的属性
messages: List[str] = [] messages: List[str] = []
end: str = '\n' end: str = '\n'
@ -41,8 +39,7 @@ class LogMessage(Options):
log_time: Optional[float] = None, log_time: Optional[float] = None,
logger_name: Optional[str] = 'root', logger_name: Optional[str] = 'root',
logger_tag: Optional[str] = None, logger_tag: Optional[str] = None,
stack_trace: Optional[FrameType] = None, stack_trace: Optional[FrameType] = None) -> None:
**kwargs) -> None:
""" """
Init for LogMessage Init for LogMessage
:param messages: message list for log :param messages: message list for log
@ -54,28 +51,38 @@ class LogMessage(Options):
:param logger_name: name of logger :param logger_name: name of logger
:param logger_tag: tag of logger :param logger_tag: tag of logger
:param stack_trace: stack trace of logger :param stack_trace: stack trace of logger
:param kwargs: other options
""" """
# 为了方便使用 单独覆盖了 __init__ 方法来提供代码补全的选项 # 20231128 23:23
if messages is None: # 因为 Options 的初始化太慢了 所以改为不继承 直接编写
messages = []
super().__init__(messages=messages,
end=end,
split=split,
flush=flush,
level=level,
log_time=log_time,
logger_name=logger_name,
logger_tag=logger_tag,
stack_trace=stack_trace,
**kwargs)
def init(self, **kwargs) -> bool: self.messages = messages if messages is not None else []
if self.log_time is None: self.end = end
self.log_time = time.time_ns() self.split = split
if not isinstance(self.flush, bool) and self.flush is not None: self.level = level
self.flush = True if self.flush else False self.logger_name = logger_name
return False self.logger_tag = logger_tag
self.stack_trace = stack_trace
if log_time is None:
log_time = time.time_ns()
self.log_time = log_time
if not isinstance(flush, bool) and flush is not None:
flush = True if flush else False
self.flush = flush
def option(self) -> Dict[str, Union[str, int, float, bool]]:
return {
'messages': self.messages,
'end': self.end,
'split': self.split,
'flush': self.flush,
'level': self.level,
'log_time': self.log_time,
'logger_name': self.logger_name,
'logger_tag': self.logger_tag,
'stack_trace': self.stack_trace,
}
def format_message(self) -> str: def format_message(self) -> str:
if self.split is None: if self.split is None:
@ -98,6 +105,3 @@ class LogMessage(Options):
FormattingMessage = Tuple[LogMessage, Dict[str, Union[str, Path]]] FormattingMessage = Tuple[LogMessage, Dict[str, Union[str, Path]]]
if __name__ == '__main__':
print(LogMessage().as_markdown())