メールでdjangoエラーレポートを使用しています。これは通常、非常に便利な機能ですが、データベースのダウンタイムが5分になり、2000通のメールが届いたことを除けば。djangoが1分間に送信できるメールの数を抑えるのに役立つミドルウェアはありますか?
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.request
ですdjango
。ロギングシステムのドキュメントを見ると、ロギングフィルタを実装することで、これをよりクリーンな(?)方法で実現できる可能性があります。
次のようにして、メールを1分あたり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)
1つのオプションは、エラー報告のためにErrorStackのようなものに切り替えることです。プロジェクトに簡単に統合できるように、djangoアプリを作成しました。
データベースのダウンタイムは意図的なものではなかったと思います。その場合、Djangoプロセスを何らかのメンテナンスモードにするか、オフラインにする必要がありますか?
それ以外の場合、通常のメールアプリはdjango-mailerです。これは、送信メールをデータベースに保存しているために失敗したために役立つ可能性があります:)
本当にレート制限が必要な場合は、MTAで行うのが最善です。これは、メールの送信を担当するMTAプロセスの一部、またはスパムと戦う手段として着信接続を抑制するためにqmailにこのパッチを使用するようなエキゾチックなものをシャットダウンする機能を意味する可能性があります
たぶん、羽ばたきに関するNagiosのページは読む価値があります