4729698049
git-subtree-dir: paste-framework git-subtree-split: 34e8684c4bc3cebbe177509f42ab4ef5b5425a7a
161 lines
5.6 KiB
Python
161 lines
5.6 KiB
Python
"""
|
|
实现对日志文件的配置封装,详细参考 getLogger 方法。
|
|
输出日志使用 echo_log 方法。
|
|
输出到日志文件使用 logToFile 方法。
|
|
"""
|
|
|
|
import logging
|
|
import sys
|
|
import traceback
|
|
from logging import handlers
|
|
from typing import Any, Union, Optional
|
|
|
|
from paste.core import config
|
|
|
|
logger_config_name = 'logger.default'
|
|
"""
|
|
默认配置字段名称,当在 getLogger 方法中设置了不同名称后,该变量会被修改。
|
|
"""
|
|
|
|
paste_logger: Optional[logging.Logger] = None
|
|
"""
|
|
全局日志对象,获取日志对象时初始化。
|
|
"""
|
|
|
|
|
|
def set_logger_config(config_name: str):
|
|
"""
|
|
设置新的日志配置名称。
|
|
|
|
:param config_name: 日志配置名称
|
|
"""
|
|
global logger_config_name
|
|
if config_name != logger_config_name:
|
|
logger_config_name = config_name
|
|
|
|
|
|
def get_logger():
|
|
"""
|
|
取得日志对象。先根据配置,更新系统日志配置。若配置了额外的日志文件、格式、层级,则增加响应的日志输出。
|
|
|
|
注意:除非额外配置,否则都使用与系统日志相同的配置参数。
|
|
|
|
配置结构参考::
|
|
|
|
{
|
|
"logger": {
|
|
"basic": {
|
|
"filename": "sys_log.log",
|
|
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
"level": 20
|
|
},
|
|
"filename": "zb_data_log.log",
|
|
"name": "ZbData"
|
|
}
|
|
}
|
|
"""
|
|
global paste_logger
|
|
|
|
if paste_logger is None:
|
|
# 系统日志基本配置
|
|
_log_base_cfg: dict = config.get_config(f'{logger_config_name}.basic', {})
|
|
# 系统日志文件
|
|
_base_log_file = _log_base_cfg.get('filename', '')
|
|
_base_log_format = _log_base_cfg.get('format', '')
|
|
_base_formatter = logging.Formatter(_base_log_format)
|
|
_base_level = _log_base_cfg.get('level', logging.INFO)
|
|
|
|
# 日志名称,若不配置,则使用名称:SQL_ALEX
|
|
_log_name = config.get_config(f'{logger_config_name}.name', 'SQL_ALEX')
|
|
# 日志文件最大值
|
|
_log_max_bytes = config.get_config(f'{logger_config_name}.max_bytes', 0)
|
|
# 日志文件备份数量
|
|
_log_backup_count = config.get_config(f'{logger_config_name}.backup_count', 0)
|
|
# 日志格式,若不配置,则使用 base 中的配置
|
|
_log_format = config.get_config(f'{logger_config_name}.format', _base_log_format)
|
|
_formatter = logging.Formatter(_log_format)
|
|
# 日志层级,若不配置,则使用 base 中的配置
|
|
_log_level = config.get_config(f'{logger_config_name}.level', _base_level)
|
|
# 日志文件
|
|
_log_file = config.get_config(f'{logger_config_name}.filename', '')
|
|
|
|
# 更新系统日志基本配置
|
|
logging.basicConfig(**_log_base_cfg)
|
|
# 重新绑定系统日志文件句柄
|
|
_base_log_file_handler: Optional[handlers.RotatingFileHandler] = None
|
|
if _base_log_file not in (None, ''):
|
|
_base_log_file_handler = handlers.RotatingFileHandler(
|
|
_base_log_file, maxBytes=_log_max_bytes, backupCount=_log_backup_count
|
|
)
|
|
_base_log_file_handler.setFormatter(_base_formatter)
|
|
logging.root.handlers = [_base_log_file_handler]
|
|
|
|
# 创建日志对象
|
|
paste_logger = logging.Logger(name=_log_name, level=_log_level)
|
|
# 绑定日志文件句柄
|
|
if _log_file not in ('', None):
|
|
# 若配置了日志文件,则创建文件句柄
|
|
_file_handler = handlers.RotatingFileHandler(
|
|
_log_file, maxBytes=_log_max_bytes, backupCount=_log_backup_count
|
|
)
|
|
_file_handler.setFormatter(_formatter)
|
|
paste_logger.addHandler(_file_handler)
|
|
else:
|
|
# 若未配置,则使用系统日志文件
|
|
if _base_log_file_handler is not None:
|
|
paste_logger.addHandler(_base_log_file_handler)
|
|
|
|
# 绑定控制台输出
|
|
_console_handler = logging.StreamHandler()
|
|
_console_handler.setFormatter(_formatter)
|
|
paste_logger.addHandler(_console_handler)
|
|
|
|
return paste_logger
|
|
|
|
|
|
def echo_log(msg: Union[str, Exception], level: int = logging.INFO, is_log_exc: bool = False):
|
|
"""
|
|
输出日志文本。默认输出到日志文件,但是可能不便于查询,这里应该考虑支持输出到日志数据库。
|
|
|
|
:param msg: 消息内容,当是 Exception 对象时,从 args 中取出第一项作为消息
|
|
:param level: 消息等级
|
|
:param is_log_exc: 是否输出异常的 Traceback 信息到日志文件
|
|
"""
|
|
_root = logging.root
|
|
_logging = get_logger()
|
|
_log_level = level
|
|
if isinstance(msg, Exception):
|
|
_log_level = logging.ERROR
|
|
if len(msg.args) > 0 and isinstance(msg.args[0], str):
|
|
msg = msg.args[0]
|
|
else:
|
|
msg = str(msg)
|
|
|
|
_logging.log(level=_log_level, msg=msg)
|
|
if is_log_exc:
|
|
exception_to_file()
|
|
|
|
|
|
def exception_to_file():
|
|
"""
|
|
自动检测异常,并输出异常的 Traceback 信息到日志文件。
|
|
"""
|
|
_, _, tb = sys.exc_info()
|
|
if tb is not None:
|
|
_msg_list = ['Traceback: \n\n'] + traceback.format_tb(tb)
|
|
log_to_file(msg=''.join(_msg_list), level=logging.ERROR)
|
|
|
|
|
|
def log_to_file(msg: Any, level: int = logging.INFO):
|
|
"""
|
|
输出消息到日志文件。
|
|
|
|
:param msg: 消息
|
|
:param level: 消息等级
|
|
"""
|
|
_logger = get_logger()
|
|
_record = _logger.makeRecord(name=_logger.name, level=level, fn=__file__, lno=0, args=(), exc_info=None, msg=msg)
|
|
for hdl in _logger.handlers:
|
|
if isinstance(hdl, logging.FileHandler):
|
|
hdl.handle(_record)
|