You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现带自定义extra参数的logging.Logger子类化?

自定义logging.Logger子类传入extra参数的设计方案

当需要向自定义logging.Logger子类的构造函数传入自定义extra参数时,可参考以下实现方案:

一、自定义Logger子类实现

import logging
from enum import Enum

# 假设cfg为全局配置对象,需提前定义
cfg = {}

class CustomFileFormatter(logging.Formatter):
    # 需自行实现文件日志的格式化逻辑
    def __init__(self, verbose=False, datefmt="%Y-%m-%d %H:%M:%S"):
        super().__init__(datefmt=datefmt)
        self.verbose = verbose

class CustomConsoleFormatter(CustomFileFormatter):
    # 需自行实现控制台彩色日志的格式化逻辑
    pass

class CustomLogger(logging.Logger):   
    class CustomLevels(Enum):
        PROFILE = 19
        QUERY = 21
        EMAIL = 31

    def __init__(
        self,
        name: str,
        level: int = logging.NOTSET,
        extra: dict = None,
    ) -> None:
        # 日志级别由extra中的"debug_mode"决定
        # 为True则用DEBUG级别,否则用INFO级别
        self._extra = extra or {}
        debug_mode = self._extra.get("debug_mode", False)
        level = logging.DEBUG if debug_mode else logging.INFO
        super().__init__(name, level)

        # 日志详细程度由全局配置的"verbose"项决定
        self.verbose = cfg.get("verbose", False)

        # 日期格式由全局配置的"datetime_format"项决定
        datefmt = cfg.get("datetime_format", "%Y-%m-%d %H:%M:%S")

        # 初始化文件和控制台的自定义格式化器
        # 控制台格式化器继承自文件格式化器,额外实现彩色日志
        self._file_formatter = CustomFileFormatter(verbose=self.verbose, datefmt=datefmt)
        self._console_formatter = CustomConsoleFormatter()

        # 若全局配置存在"file"项,则启用文件日志功能
        self._fileinfo = cfg.get("file", None)

        # 注册自定义日志级别
        self._addCustomLevels()

        # 设置控制台日志处理器
        self._setConsoleHandler()

        # 设置SMTP处理器用于发送告警邮件(按需启用)
        self._setCustomSMTPHandler()

        # 初始化文件日志相关配置及处理器(按需启用)
        self._setFileConfigs()
        self._setFileHandler()

    def _addCustomLevels(self) -> None:
        # 辅助函数:创建对应日志级别的记录方法
        def make_log_method(level: CustomLogger.CustomLevels):
            def log_method(self, message, *args, **kwargs):
                # 先检查级别再记录,优化日志性能
                if self.isEnabledFor(level.value):
                    self._log(level.value, message, args, **kwargs)
            return log_method

        # 遍历枚举,注册所有自定义日志级别及对应方法
        for level in CustomLogger.CustomLevels:
            logging.addLevelName(level.value, level.name)
            setattr(CustomLogger, level.name.lower(), make_log_method(level))
            # 可选:将自定义级别挂载到logging命名空间
            # setattr(logging, level.name, level.value)

    def _setConsoleHandler(self):
        # 需自行实现控制台处理器的初始化逻辑
        pass

    def _setCustomSMTPHandler(self):
        # 需自行实现SMTP邮件处理器的初始化逻辑
        pass

    def _setFileConfigs(self):
        # 需自行实现文件日志的配置逻辑
        pass

    def _setFileHandler(self):
        # 需自行实现文件日志处理器的初始化逻辑
        pass

二、未使用setLoggerClass的实例化方案

如果不需要全局设置Logger类,可直接手动创建实例,还能将其加入日志管理器字典,方便后续通过logging.getLogger获取:

# 定义自定义extra参数
extra = {"debug_mode": True}
# 直接实例化CustomLogger
logger = CustomLogger("app", extra=extra)
# 示例:手动覆盖初始化时由extra决定的日志级别
logger.setLevel(logging.DEBUG)

# 可选:将实例加入日志管理器字典,后续可通过logging.getLogger获取
logging.Logger.manager.loggerDict["app"] = logger

# 后续调用即可获取已创建的实例
logger = logging.getLogger("app")

三、使用说明

  • 基础日志级别(如logging.INFO、logging.DEBUG)需通过logging命名空间访问
  • 自定义日志级别需通过CustomLogger.CustomLevels枚举访问,例如CustomLogger.CustomLevels.QUERY、CustomLogger.CustomLevels.PROFILE

内容的提问来源于stack exchange,提问作者LucaM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 11:22:10