【问题标题】:How to throttle Django error emails如何限制 Django 错误邮件
【发布时间】:2011-01-04 08:50:56
【问题描述】:

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

【问题讨论】:

    标签: python django error-handling error-reporting


    【解决方案1】:

    以 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 以更简洁(?)的方式实现。

    【讨论】:

    • 不错。我喜欢这个不依赖redis连接,使用django的核心缓存框架
    • get_cache 现在已被删除(从 Django 1.9 开始)。改用from django.core.cache import cache——但跨多个线程或进程似乎存在问题......仍在处理......
    • Django 1.9 更改了默认日志配置,以便通过 django logger 和 not django.request logger 记录 Django 相关内容,如下所示。如果您要复制/粘贴@Gattster 提供的配置,请确保修复该问题。日志记录部分应如下所示:``` 'loggers': { 'django': { 'handlers': ['mail_admins'], 'level': 'ERROR', 'propagate': True, }, } ```
    • @sebhaase 随时更新答案以反映 django 的变化
    • @miha 随时更新答案以反映 django 的变化
    【解决方案2】:

    也许Nagios' page关于拍打值得一读

    【讨论】:

      【解决方案3】:

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

      settings.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,
                  },
              }
      }
      

      error_email_limiter/handlers.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)
      

      【讨论】:

        【解决方案4】:

        一种选择是切换到ErrorStack 之类的东西来报告错误。我写了一个django app 以使其集成到您的项目中变得非常简单。

        【讨论】:

        • 这听起来不错。您是否也评估了 hoptoad.com?我需要决定选择哪个服务。
        • 不,我没有详细看过hoptoad。
        【解决方案5】:

        我认为数据库停机不是故意的,在这种情况下,您可能应该将 Django 进程放入某种 maintenance mode 或使其脱机?

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

        如果您确实需要限制速率,最好在您的 MTA 中这样做。这可能意味着能够只关闭负责发送邮件的 MTA 进程部分或使用 this patch for qmail to throttle incoming connections as a means of fighting spam 等奇异的东西。

        【讨论】:

          猜你喜欢
          • 2012-12-10
          • 2015-03-29
          • 2013-03-02
          • 1970-01-01
          • 2012-11-15
          • 1970-01-01
          • 1970-01-01
          • 2014-10-25
          • 2018-04-16
          相关资源
          最近更新 更多