如何限制 Django 错误电子邮件

How to throttle Django error emails

提问人:Gattster 提问时间:1/13/2010 更新时间:2/28/2017 访问量:3505

问:

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

python django 处理错误 报告

评论


答:

1赞 Van Gale 1/13/2010 #1

我认为数据库停机不是故意的,在这种情况下,您可能应该将 Django 进程置于某种维护模式或使其脱机?

否则,通常的邮件应用程序是 django-mailer,它可能只是因为它将传出邮件存储在您的数据库中,因此会失败:)

如果您确实需要速率限制,最好在 MTA 中进行。这可能意味着能够关闭MTA进程中负责发送邮件的部分,或者一些奇特的东西,比如使用这个补丁来限制传入的连接,作为对抗垃圾邮件的手段

0赞 thanos 1/13/2010 #2

也许 Nagios 关于拍打的页面值得一读

2赞 Carl Meyer 1/13/2010 #3

一种选择是切换到类似 ErrorStack 的东西来报告错误。我编写了一个 django 应用程序,让它变得愚蠢而简单地集成到您的项目中。

评论

0赞 Gattster 1/13/2010
这听起来是个好方法。您是否也评估过 hoptoad.com?我需要决定选择哪种服务。
0赞 Carl Meyer 1/14/2010
不,我没有详细看过 hoptoad。
8赞 Gattster 1/25/2012 #4

通过执行以下操作,我将电子邮件限制为每分钟 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)
16赞 Dennis Golomazov 9/17/2014 #5

以 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.requestdjango

评论

2赞 Gattster 11/16/2014
好。我喜欢它不依赖于 redis 连接并使用 django 的核心缓存框架
1赞 sebhaase 1/27/2017
get_cache现在被删除了(从 Django 1.9 开始)。改用 - 但似乎跨多个线程或进程存在问题......仍在努力......from django.core.cache import cache
1赞 miha 2/25/2017
Django 1.9 更改了默认的日志记录配置,以便通过记录器而不是记录器记录与 Django 相关的东西,如下所示。如果您要复制/粘贴@Gattster提供的配置,请确保修复该问题。日志记录部分应如下所示: ''' 'loggers': { 'django': { 'handlers': ['mail_admins'], 'level': 'ERROR', 'propagate': True, }, } '''djangodjango.request
0赞 Dennis Golomazov 2/28/2017
@sebhaase随时更新答案以反映 django 中的变化
0赞 Dennis Golomazov 2/28/2017
@miha随时更新答案以反映 django 中的变化