2010-01-12 4 views
12

Ich benutze Django Fehlerberichte per E-Mail. Es ist normalerweise eine sehr hilfreiche Funktion, außer dass wir nun 5 Minuten Datenbankausfallzeit haben und 2000 E-Mails bekommen habe. Gibt es irgendeine Middleware, die mir hilft, die Anzahl der E-Mails zu drosseln, die Django pro Minute versenden kann?Wie drücke ich Django Fehler E-Mails

Antwort

9

Gattster die große Antwort als Beispiel schrieb ich eine einfache Implementierung auf Basis von Djangos integrierten Cache-Funktionen.

# -*- 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) 

Und die Logging-Konfiguration wird in Django 1.9 als auch, so um diese Handler zu arbeiten, müssen Sie die Protokollierung konfigurieren geändert wie:

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

, wo die Änderung nur auf Veränderung der Name des Loggers von django.request bis django. Wenn Sie in der Dokumentation des Protokollierungssystems nachsehen, könnte dies möglicherweise auf eine sauberere (?) Weise erreicht werden, indem ein logging filter implementiert wird.

+1

Schön. Ich mag, dass dies nicht von einer Redis-Verbindung abhängig ist und verwendet djangos Kern-Cache-Framework – Gattster

+1

'get_cache' ist jetzt entfernt (ab Django 1.9). Verwendung von 'von django.core.cache importieren Cache '- aber es scheint ein Problem über mehrere Threads oder Prozesse zu sein ... immer noch an arbeiten in ... – sebhaase

+1

Django 1.9 geändert Standard-Logging-Konfiguration, so dass Django verwandte Sachen ist protokolliert über 'django' logger und ** not **' django.request' Logger, wie unten zu sehen. Stellen Sie sicher, dass Sie das beheben, wenn Sie die mitgelieferte config @ Gattster kopieren/einfügen. Der Logging-Abschnitt soll wie folgt aussehen: '' ' 'Logger': { 'django': { 'Handler': [ 'mail_admins'], 'Niveau': 'ERROR', 'verbreiten' True , }, } '' ' – miha

1

Ich nehme an waren die Datenbank Ausfallzeiten nicht beabsichtigt, werden Sie wahrscheinlich in diesem Fall setzen Sie Ihren Django Prozess in eine Art maintenance mode oder offline genommen haben sollten?

Ansonsten die üblichen Mail-App ist django-mailer, die Sie einfach geholfen haben könnte, weil es ausgehende Mail in Ihrer Datenbank gespeichert werden und somit versagt hätte :)

Wenn Sie wirklich es am besten wäre begrenzen müssen, um bewerten zu tun also in deiner MTA. Dies könnte die Fähigkeit bedeutet, nur den Teil des Prozesses verantwortlich MTA heruntergefahren für wie exotische Mail oder etwas zu senden this patch for qmail to throttle incoming connections as a means of fighting spam

2

Eine Möglichkeit ist, um so etwas wie ErrorStack zu wechseln Fehler melden. Ich schrieb eine django app, um es dumm zu machen - einfach in Ihr Projekt zu integrieren.

+0

Das klingt nach einem guten Ansatz. Hast du auch hoptoad.com bewertet? Ich muss entscheiden, welchen Service ich wählen soll. – Gattster

+0

Nein, ich habe Hoptoad nicht im Detail angeschaut. –

7

Ich begrenzte E-Mails auf 10 pro Minute, indem Sie Folgendes tun. Dies verwendet eine Redis-Verbindungsfunktion, die für meine Installation einzigartig ist. Ich schlage vor, die Funktion incr_counter an Ihre Bedürfnisse anzupassen. Um sicher zu sein, verwenden Sie eine direkte redis oder memcache Verbindung für dieses und nicht irgendwelche django.cache Wrapper.

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) 
Verwandte Themen