我使用logging模块来警告某些例程的问题。这些例程可以在返回到正常操作之前运行若干次(例如,对失败但最终经历的API的重复查询)。每个失败的呼叫都会触发一个日志条目。
有没有办法限制相同日志消息的数量?
我希望在输出ddl.SelectedValue == ""
个相同的消息后触发此限制,然后可能会通知生成n
更多(因此不会使日志文件混乱)并在收到恢复日志后重置。这是理想的情况 - 我正在研究如何解决问题。
我找到的最接近的是conditional release of logs,但我不知道这如何适应我的情况
另一种可能性是将限制放在系统日志级别(n
或rsyslog
),但这是一个“每个进程”设置,所以我可能会丢失有用的日志(那些将介于两者之间)循环生成的)
答案 0 :(得分:2)
使用logging.Filter
!
DuplicateFilter
采用两个正则表达式模式或一个字符串(要编译成一个),一个应该与要过滤掉的字符串匹配,另一个要重置过滤器。
import logging
import os
import re
import sys
from sre_parse import Pattern
class DuplicateFilter(logging.Filter):
def __init__(self, match_against, reset_at_message, hide_at_count=5, name=''):
super(DuplicateFilter, self).__init__(name)
if isinstance(match_against, Pattern):
self.match_against = match_against
else:
self.match_against = re.compile(match_against)
if isinstance(reset_at_message, Pattern):
self.reset_at_message = reset_at_message
else:
self.reset_at_message = re.compile(reset_at_message)
self.hide_at_count = hide_at_count
self.count = 0
def filter(self, record: logging.LogRecord):
_ = super(DuplicateFilter, self).filter(record)
if not _:
return _
msg = record.getMessage()
if self.match_against.match(msg):
self.count += 1
if self.count >= self.hide_at_count:
return False
elif self.reset_at_message.match(msg):
record.msg = os.linesep.join([
'{:d} more generated'.format(self.count - self.hide_at_count),
record.msg
])
self.count = 0
return True
handler = logging.StreamHandler(sys.stdout)
handler.addFilter(DuplicateFilter('Filter me!', 'Reset at me'))
logging.basicConfig(level='INFO', handlers=[handler, ])
log = logging.getLogger()
for _ in range(10):
log.info('Filter me!')
log.info('Reset at me')
for _ in range(3):
log.info('Filter me!')
这是生成的日志:
INFO:root:Filter me!
INFO:root:Filter me!
INFO:root:Filter me!
INFO:root:Filter me!
INFO:root:5 more generated
Reset at me
INFO:root:Filter me!
INFO:root:Filter me!
INFO:root:Filter me!
只是预先等待" 5更多生成"消息可能不是你想要的,但希望这是一个很好的起点。