在 Python 日志记录模块 AKA 日志压缩中抑制具有相同内容的多条消息

Posted

技术标签:

【中文标题】在 Python 日志记录模块 AKA 日志压缩中抑制具有相同内容的多条消息【英文标题】:Suppress multiple messages with same content in Python logging module AKA log compression 【发布时间】:2017-11-25 06:29:14 【问题描述】:

根据设计,我的应用程序有时会产生重复的错误,这些错误会填满日志文件并使其阅读起来很烦人。看起来是这样的:

WARNING:__main__:CRON10: clock unset or no wind update received in 60 sec -> supressed rrd update
WARNING:__main__:CRON10: clock unset or no wind update received in 60 sec -> supressed rrd update
WARNING:__main__:CRON10: clock unset or no wind update received in 60 sec -> supressed rrd update
WARNING:__main__:CRON10: clock unset or no wind update received in 60 sec -> supressed rrd update

如何使用 Python 日志记录模块来抑制重复消息并输出更多 rsyslog 样式 (http://www.rsyslog.com/doc/rsconf1_repeatedmsgreduction.html):

WARNING:__main__:CRON10: clock unset or no wind update received in 60 sec -> supressed rrd update
--- The last message repeated 3 times

有没有办法扩展日志记录,还是我必须编写一个完全自己的记录器?

我用于记录的代码是:

logging.basicConfig(format='%(asctime)s %(message)s')
logging.basicConfig(level=logging.info)
logger = logging.getLogger(__name__)
hdlr = logging.FileHandler(LOGFILE)
hdlr.setFormatter(formatter)
logger.addHandler(hdlr) 

对此有什么想法吗?

【问题讨论】:

How to avoid duplicate outputs using logging module的可能重复 @Anthon:链接的欺骗是关于注册多个处理程序的结果。这不是这里描述的问题。 【参考方案1】:

您可以创建一个logging.Filter,它将跟踪最后记录的记录并过滤掉任何重复(相似)的记录,例如:

import logging

class DuplicateFilter(logging.Filter):

    def filter(self, record):
        # add other fields if you need more granular comparison, depends on your app
        current_log = (record.module, record.levelno, record.msg)
        if current_log != getattr(self, "last_log", None):
            self.last_log = current_log
            return True
        return False

然后只需将其添加到您使用的记录器/处理程序(即hdlr.addFilter(DuplicateFilter()))或根记录器即可过滤所有默认日志。这是一个简单的测试:

import logging

logging.warn("my test")
logging.warn("my repeated test")
logging.warn("my repeated test")
logging.warn("my repeated test")
logging.warn("my other test")

logger = logging.getLogger()  # get the root logger
logger.addFilter(DuplicateFilter())  # add the filter to it

logging.warn("my test")
logging.warn("my repeated test")
logging.warn("my repeated test")
logging.warn("my repeated test")
logging.warn("my other test")

这将打印出来:

警告:root:我的测试
警告:root:我的重复测试
警告:root:我的重复测试
警告:root:我的重复测试
警告:root:我的其他测试
警告:root:我的测试
警告:root:我的重复测试
警告:root:我的其他测试

【讨论】:

CAVEAT:如果logging.*() 与格式字符串参数一起使用(例如logging.warn("some error: %s",errstr)),DuplicateFilter 会将任何此类行视为重复,因为检查了格式字符串 - 而不是打印的字符串。跨度> 这可以通过调用record.getMessage()来规避

以上是关于在 Python 日志记录模块 AKA 日志压缩中抑制具有相同内容的多条消息的主要内容,如果未能解决你的问题,请参考以下文章

在Python日志记录模块中禁止换行

python日志模块记录三_日志命名_日志轮转

Python日志—Python日志模块logging介绍

在 Python 中使用日志记录模块进行颜色记录

Python logging模块使用配置文件记录日志

python日志模块-logging