Python 的 logging.Logger:覆盖 makeRecord 方法

3

我有一个格式化程序,它期望记录中有一个特殊的属性“user_id”,但并不总是存在(有时我使用特殊的logging.Filter将其添加到记录中)。 我尝试重写logging.Logger的makeRecord方法,如下所示:

import logging

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)-15s user_id=%(user_id)s %(filename)s:%(lineno)-15s: %(message)s')


class OneTestLogger(logging.Logger):
    def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None):
        rv = logging.Logger.makeRecord(self, name, level, fn, lno,
                                       msg, args, exc_info,
                                       func, extra)
        rv.__dict__.setdefault('user_id', 'master')
        return rv


if __name__ == '__main__':

    logger = OneTestLogger('main')
    print logger
    logger.info('Starting test')

但似乎这不起作用,我一直得到以下错误:

<main.MyLogger instance at 0x7f31a6a5b638>

找不到记录器“main”的处理程序。

我做错了什么? 谢谢。

1个回答

0

按照Logging Cookbook提供的指南进行操作。只实现了第一部分,没有实现过滤器(在下面的引用中也没有出现)。

这通常意味着,如果您需要对LogRecord执行任何特殊操作,则必须执行以下操作之一。

  1. 创建自己的Logger子类,覆盖Logger.makeRecord(),并在实例化任何您关心的记录器之前使用setLoggerClass()设置它。

我简化了您的示例,只添加了“主机名”:

import logging
from socket import gethostname

logging.basicConfig(level=logging.DEBUG,
                            format='%(asctime)s - %(hostname)s - %(message)s')

class NewLogger(logging.Logger):
    def makeRecord(self, *args, **kwargs):
        rv = super(NewLogger, self).makeRecord(*args, **kwargs)
        # updating the rv value of the original makeRecord
        # my idea is to use the same logic than a decorator by
        # intercepting the value return by the original makeRecord
        # and expanded with what I need
        rv.__dict__['hostname'] = gethostname()
        # by curiosity I am checking what is in this dictionary
        # print(rv.__dict__)
        return rv

logging.setLoggerClass(NewLogger)

logger = logging.getLogger(__name__)
logger.info('Hello World!')

请注意,此代码适用于Python 2.7。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接