如何限制Django错误邮件的发送频率
我在用Django的错误报告功能,通过邮件来接收错误信息。这个功能通常很有用,但现在我们数据库出现了5分钟的故障,我收到了2000封邮件。有没有什么中间件可以帮我限制Django每分钟发送的邮件数量呢?
5 个回答
2
一个选择是换用像 ErrorStack 这样的工具来报告错误。我写了一个 django 应用,让它变得超级简单,可以轻松地集成到你的项目中。
8
我通过以下方法把每分钟发送的邮件限制在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)
17
以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
。如果你查看日志系统的文档,可能会发现通过实现一个日志过滤器,可以用更简洁的方式来实现这个功能。