节流Python smtphandler电子邮件

时间:2014-12-02 01:06:26

标签: python logging smtp postfix-mta

我想使用Python的logger smtphandler来发送错误等等的电子邮件。我也不想让我的收件箱充斥着成千上万的电子邮件来处理同样的错误。

有没有办法限制发送的电子邮件数量?理想情况下,如果它继续捕获相同的异常,请逐渐减少发送的电子邮件数量。

2 个答案:

答案 0 :(得分:1)

我最终将自己的包装器发送到SMTPHandler。初稿如此不完美。处理程序的多个实例将分别限制dupe。可以在redis中存储self.logged以使其成为共享资源。

需要设置的唯一额外参数是interval,它是一个分钟列表(int)。假设[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)

答案 1 :(得分:1)

您可以查看mailinglogger包,它看起来就像您需要的那样。 This part of documentation解释了设置限制以防止洪水泛滥。即使没有设置任何内容,它每小时也有合理的默认10封电子邮件:)