我通过电子邮件使用django错误报告.它通常是一个非常有用的功能,除了现在我们有5分钟的数据库停机时间,我收到了2000封电子邮件.是否有任何中间件可以帮助我限制django每分钟发送的电子邮件数量?
以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
.如果您查看日志记录系统文档,可以通过实现日志记录筛选器以更清晰(?)的方式实现.
通过执行以下操作,我将电子邮件限制为每分钟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)