【发布时间】:2015-01-30 03:44:29
【问题描述】:
我想使用 Python 的记录器 smtphandler 发送电子邮件以查找错误等。我也不想让我的收件箱因为同一个错误而充斥着数千封电子邮件。
有没有办法限制发送的电子邮件数量?理想情况下,如果它不断捕获相同的异常,则减少发送的电子邮件数量。
【问题讨论】:
标签: python logging smtp postfix-mta
我想使用 Python 的记录器 smtphandler 发送电子邮件以查找错误等。我也不想让我的收件箱因为同一个错误而充斥着数千封电子邮件。
有没有办法限制发送的电子邮件数量?理想情况下,如果它不断捕获相同的异常,则减少发送的电子邮件数量。
【问题讨论】:
标签: python logging smtp postfix-mta
我最终为 SMTPHandler 制作了自己的包装器。初稿并不完美。处理程序的多个实例将分别限制欺骗。可以将self.logged存储在redis中,使其成为共享资源。
唯一需要设置的额外参数是间隔,它是分钟列表(整数)。假设 [0 10 30] 被传递给区间。它会说现在发送电子邮件。随后的欺骗将被忽略,直到 10 分钟过去。然后后续的欺骗将被忽略,直到 30 分钟之后。之后它不会发送任何电子邮件。
如果您想更改被视为重复日志的内容,请根据您的要求修改 _record_type。
import logging.handlers
import datetime
class SMTPHandler(logging.handlers.SMTPHandler):
"""
Custom SMTPHandler for the logger.
You specify the intervals to which emails will be sent. At most the number
of emails that will be sent will be equal to the number of intervals set.
"""
def __init__(self, mailhost, fromaddr, toaddrs, subject, intervals,
credentials=None, secure=None, timeout=5.0):
super(SMTPHandler, self).__init__(mailhost, fromaddr, toaddrs, subject,
credentials, secure, timeout)
self.logged = {}
self.init_date = datetime.datetime.now()
self.intervals = self._make_intervals(intervals)
def _make_intervals(self, intervals):
return [datetime.timedelta(minutes=i) for i in intervals]
def _record_type(self, record):
"""Make key from LogRecord"""
type = record.levelname + record.pathname
if record.exc_info:
type = type + str(record.exc_info[0])
return type
def update(self, record):
"""Check if a similar log has been emitted, if so how many times and has specified interval passed"""
record_type = self._record_type(record)
last = self.logged.get(record_type)
# log if hasn't been logged at all
if last is None:
self.logged[record_type] = (1, datetime.datetime.now())
return True
# log if last log was more than a specified interval before
else:
count, last_date = last
if count <= len(self.intervals):
if (last_date - self.init_date) > self.intervals[count]:
self.logged[record_type] = (count+1, datetime.datetime.now())
return True
else:
return False
else:
return False
def emit(self, record):
emittable = self.update(record)
if emittable is True:
super(SMTPHandler, self).emit(record)
【讨论】:
您可以查看mailinglogger 包,它看起来像您需要的。 This part of documentation 解释了设置限制以防止洪水泛滥。即使没有设置任何东西,它也有合理的默认每小时 10 封电子邮件:)
【讨论】: