import re
import sys
import types
from typing_extensions import Any, Callable, Protocol, cast
from .base import GenericLogger, Logger, LogLevel
[文档]
class LazyLogMethod(Protocol):
[文档]
def __call__(
self,
msg: str,
*arg_getters: Callable[[], Any],
level: LogLevel,
with_exc: bool = False,
) -> None:
"""懒惰日志抽象方法
继承并实现该类的 __call__ 方法,即可用于日志器修补
:param msg: 日志消息
:param level: 日志等级
:param with_exc: 输出时是否附加异常信息
"""
raise NotImplementedError
[文档]
def logger_patch(logger: Any, lazy_meth: LazyLogMethod) -> GenericLogger:
"""对指定的日志器进行修补操作,使其可以被用于 melobot 内部的日志记录
:param logger: 任意已经实现 `debug`, `info`, `warning`, `error`, `critical`, `exception` 接口的日志器
:param lazy_meth: 修补方法
"""
setattr(logger, Logger.generic_lazy.__name__, lazy_meth)
setattr(logger, Logger.generic_obj.__name__, types.MethodType(Logger.generic_obj, logger))
return cast(GenericLogger, logger)
[文档]
class StandardPatch(LazyLogMethod):
"""用于修补 logging.Logger 的日志修补"""
[文档]
def __init__(self, logger: Any) -> None:
"""初始化一个标准日志器修补
:param logger: 标准日志器对象(`logging.Logger`)
"""
super().__init__()
self.logger = logger
[文档]
def __call__(
self,
msg: str,
*arg_getters: Callable[[], Any],
level: LogLevel,
with_exc: bool = False,
) -> None:
if not self.logger.isEnabledFor(level):
return
exc = sys.exc_info() if with_exc else None
self.logger._log(level, msg, tuple(g() for g in arg_getters), exc_info=exc)
[文档]
class LoguruPatch(LazyLogMethod):
"""用于修补 loguru 日志器的日志修补"""
[文档]
def __init__(self, logger: Any) -> None:
"""初始化一个 loguru 日志器修补
:param logger: loguru 日志器对象
"""
super().__init__()
self.logger = logger
self.pattern = re.compile(r"%(?:[-+# 0]*\d*(?:\.\d+)?[hlL]?[diouxXeEfFgGcrs%])")
[文档]
def __call__(
self,
msg: str,
*arg_getters: Callable[[], Any],
level: LogLevel,
with_exc: bool = False,
) -> None:
logger = self.logger.opt(lazy=True)
msg = self.pattern.sub("{}", msg)
if with_exc:
logger.exception(msg, *arg_getters)
return
match level:
case LogLevel.DEBUG:
logger.debug(msg, *arg_getters)
case LogLevel.INFO:
logger.info(msg, *arg_getters)
case LogLevel.WARNING:
logger.warning(msg, *arg_getters)
case LogLevel.ERROR:
logger.error(msg, *arg_getters)
case LogLevel.CRITICAL:
logger.critical(msg, *arg_getters)
case _:
raise ValueError(f"无效的日志等级:{level}")
[文档]
class StructlogPatch(LazyLogMethod):
"""用于修补 structlog 日志器的日志修补"""
[文档]
def __init__(self, logger: Any) -> None:
"""初始化一个 structlog 日志器修补
:param logger: structlog 日志器对象
"""
super().__init__()
self.logger = logger
[文档]
def __call__(
self,
msg: str,
*arg_getters: Callable[[], Any],
level: LogLevel,
with_exc: bool = False,
) -> None:
args = tuple(g() for g in arg_getters)
logger = self.logger
if with_exc:
logger.exception(msg, *args)
return
match level:
case LogLevel.DEBUG:
logger.debug(msg, *args)
case LogLevel.INFO:
logger.info(msg, *args)
case LogLevel.WARNING:
logger.warning(msg, *args)
case LogLevel.ERROR:
logger.error(msg, *args)
case LogLevel.CRITICAL:
logger.critical(msg, *args)
case _:
raise ValueError(f"无效的日志等级:{level}")