2010-01-12 19 views
12

Używam raportowania błędów django przez e-mail. Zwykle jest to bardzo przydatna funkcja, z tym że teraz mamy 5 minut przestoju bazy danych i mam 2000 e-maili. Czy istnieje oprogramowanie pośrednie, które pomoże mi zmniejszyć liczbę wiadomości e-mail, które django może wysłać na minutę?Jak blokować komunikaty o błędach Django

Odpowiedz

9

Korzystanie wielką odpowiedź Gattster jako przykład, napisałem prostą implementację w oparciu o Django funkcji wbudowanych skrytek.

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

a konfiguracja rejestrowania została zmieniona w Django 1.9, tak więc, aby do tego uchwytu do pracy, trzeba skonfigurować rejestrowanie jako:

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

gdzie zmiana jest tylko do zmiany nazwa rejestratora od django.request do django. Jeśli zajrzysz do dokumentacji systemu rejestrowania, można to prawdopodobnie osiągnąć w sposób czystszy (?) Poprzez implementację logging filter.

+1

Nice. Podoba mi się, że to nie zależy od połączenia redis i używa podstawowego szkieletu pamięci podręcznej django: – Gattster

+1

'get_cache' jest teraz usuwany (od Django 1.9). zamiast tego używają 'od django.core.cache import cache', ale wydaje się, że istnieje problem w wielu wątkach lub procesach ... nadal działa w ... – sebhaase

+1

Django 1.9 zmienił domyślną konfigurację rejestrowania, tak aby zawartość związana z Django była rejestrowane przez 'django' logger i ** not **' django.request' logger, jak widać poniżej. Upewnij się, że to naprawisz, jeśli zamierzasz skopiować/wkleić dostarczony config @Gattster. Sekcja rejestrowanie powinna wyglądać następująco: '' ' 'rejestratory': { " Django: { 'koparki': [ 'mail_admins'], 'poziomu': 'Błąd', 'propagować': True , }, } } '' ' – miha

1

Przypuszczam przestój w bazie nie było zamierzone, w tym przypadku prawdopodobnie powinien umieścić swój proces Django w jakiś maintenance mode lub podjęte w trybie offline?

Inaczej, zwykle aplikacja poczty elektronicznej jest django-mailer które mogą ci pomóc tylko dlatego, że przechowuje pocztę wychodzącą w bazie danych, a zatem nie udało :)

Jeśli naprawdę potrzebujesz, aby ocenić ograniczyć najlepiej byłoby zrobić więc w twoim MTA. Może to oznaczać możliwość tylko wyłączenie część procesu MTA odpowiedzialnego za wysyłanie poczty lub coś egzotycznego jak przy użyciu this patch for qmail to throttle incoming connections as a means of fighting spam

2

Jedną z opcji jest, aby przełączyć się do czegoś jak ErrorStack dla zgłaszanie błędów. Napisałem numer django app, aby uczynić go głupim - łatwo zintegrować się z projektem.

+0

To brzmi jak dobre podejście. Czy oceniłeś również hoptoad.com? Muszę zdecydować, którą usługę wybrać. – Gattster

+0

Nie, nie przyjrzałem się szczegółowo tej opcji. –

7

Ograniczam wiadomości e-mail do 10 na minutę, wykonując następujące czynności. Wykorzystuje to funkcję połączenia redis, unikalną dla mojej instalacji. Sugeruję modyfikację funkcji incr_counter, aby pasowała do twoich potrzeb. Aby być bezpiecznym, użyj bezpośredniego połączenia redis lub memcache, a nie żadnych wrapperów 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) 
Powiązane problemy