代码之家  ›  专栏  ›  技术社区  ›  Gattster

如何阻止Django错误电子邮件

  •  16
  • Gattster  · 技术社区  · 14 年前

    我通过电子邮件使用django错误报告。这通常是一个非常有用的功能,除了现在我们有5分钟的数据库停机时间,我收到了2000封电子邮件。是否有任何中间件可以帮助我控制Django每分钟发送的电子邮件数量?

    5 回复  |  直到 7 年前
        1
  •  12
  •   miha    7 年前

    以gattster的伟大答案为例,我编写了一个基于django内置缓存函数的简单实现。

    # -*- coding: utf-8 -*-
    
    from django.utils.log import AdminEmailHandler
    from django.core.cache import cache
    
    
    class ThrottledAdminEmailHandler(AdminEmailHandler):
    
        PERIOD_LENGTH_IN_SECONDS = 10
        MAX_EMAILS_IN_PERIOD = 1
        COUNTER_CACHE_KEY = "email_admins_counter"
    
        def increment_counter(self):
            try:
                cache.incr(self.COUNTER_CACHE_KEY)
            except ValueError:
                cache.set(self.COUNTER_CACHE_KEY, 1, self.PERIOD_LENGTH_IN_SECONDS)
            return cache.get(self.COUNTER_CACHE_KEY)
    
        def emit(self, record):
            try:
                counter = self.increment_counter()
            except Exception:
                pass
            else:
                if counter > self.MAX_EMAILS_IN_PERIOD:
                    return
            super(ThrottledAdminEmailHandler, self).emit(record)
    

    而且Django 1.9中的日志配置也发生了更改,因此为了让这个处理程序工作,您需要将日志配置为:

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': True,
        'handlers': {
            'mail_admins': {
                'level': 'ERROR',
                'class': 'fully.qualified.path.to.handler.ThrottledAdminEmailHandler'
            }
        },
        'loggers': {
            'django': {
                'handlers': ['mail_admins'],
                'level': 'ERROR',
                'propagate': True,
            },
        }
    }
    

    其中,更改仅用于更改记录器的名称 django.request django .如果您查看日志系统文档,这可能是在一个清理器(?)中实现的。通过实施 logging filter .

        2
  •  8
  •   Gattster    12 年前

    我通过以下操作将电子邮件限制为每分钟10封。这将使用我安装时独有的redis连接功能。我建议修改增量计数器功能以满足您的需要。为了安全起见,请使用直接redis或memcache连接,而不要使用任何django.cache包装器。

    设置Py

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'mail_admins': {
                'level': 'ERROR',
                'class': 'error_email_limiter.handler.MyAdminEmailHandler'
            }
        },
        'loggers': {
            'django.request': {
                'handlers': ['mail_admins'],
                'level': 'ERROR',
                'propagate': True,
                },
            }
    }
    

    错误\电子邮件\限制器/处理程序.py

    class MyAdminEmailHandler(AdminEmailHandler):
        def incr_counter(self):
            c = get_redis_connection()
            key = self._redis_key()
            res = c.incr(key)
            c.expire(key, 300)
            return res
    
        def _redis_key(self):
            return time.strftime('error_email_limiter:%Y-%m-%d_%H:%M',
                                 datetime.datetime.now().timetuple())
    
        def emit(self, record):
            try:
                ctr = self.incr_counter()
            except Exception:
                pass
            else:
                if ctr >= 10:
                    return
            super(MyAdminEmailHandler, self).emit(record)
    
        3
  •  2
  •   Carl Meyer    14 年前

    一种选择是切换到 ErrorStack 用于错误报告。我写了一篇 django app 把它简单地集成到你的项目中。

        4
  •  1
  •   Van Gale    14 年前

    我认为数据库停机不是有意的,在这种情况下,您可能应该将Django进程放入某种类型的 maintenance mode 还是离线了?

    否则,通常的邮件应用程序是 django-mailer 这可能对您有所帮助,因为它将发送邮件存储在您的数据库中,因此会失败:)

    如果你真的需要评分限制,最好在MTA中这样做。这可能意味着可以关闭负责发送邮件的MTA进程的一部分,或者使用 this patch for qmail to throttle incoming connections as a means of fighting spam

        5
  •  0
  •   j_syk    12 年前

    也许吧 Nagios' page 拍打是值得一读的。