2009-10-23 8 views
12

Mam moduł rejestrowania MemoryHandler skonfigurowany do kolejkowania komunikatów debugowania i komunikatów o błędach dla celu SMTPHandler. Chcę, aby wiadomość e-mail została wysłana, gdy błędy procesu zawierają wszystkie instrukcje debugowania do tego momentu (po jednym w wierszu). Zamiast tego otrzymuję osobny adres e-mail dla każdej wiadomości debugowania.Dane wyjściowe sortowania w dzienniku Python MemoryHandler z SMTPHandler

Wygląda na to, że powinno być trywialne i częścią pakietu logowania, ale nie mogę znaleźć niczego na ten temat, żadnych przykładów, niczego w Google.

log = logging.getLogger() 
log.setLevel(logging.DEBUG) 
debug_format = logging.Formatter("%(levelname)s at %(asctime)s in %(filename)s (line %(lineno)d):: %(message)s") 

# write errors to email 
error_mail_subject = "ERROR: Script error in %s on %s" % (sys.argv[0], os.uname()[1]) 
error_mail_handler = logging.handlers.SMTPHandler(SMTP_HOST, '[email protected]'+os.uname()[1], [LOG_EMAIL], error_mail_subject) 
error_mail_handler.setLevel(logging.ERROR) 
#error_mail_handler.setLevel(logging.DEBUG) 
error_mail_handler.setFormatter(debug_format) 

# buffer debug messages so they can be sent with error emails 
memory_handler = logging.handlers.MemoryHandler(1024*10, logging.ERROR, error_mail_handler) 
memory_handler.setLevel(logging.DEBUG) 

# attach handlers 
log.addHandler(memory_handler) 
log.addHandler(error_mail_handler) 

związane z tym:

Czy muszę dodać error_mail_handler do rejestratora jednoznacznie, czy jest to cel memory_handler tak? Czy należy ustawić error_mail_handler na cel DEBUG lub ERROR? Czy potrzebuje nawet celu, gdy jest karmiony od memory_handler?

Chciałbym zobaczyć działający kod od każdego, kto rozwiązał ten problem.

Odpowiedz

17

Być może zechcesz użyć lub zmodyfikować BufferingSMTPHandler, który jest w this test script.

Ogólnie rzecz biorąc, nie trzeba dodawać programu obsługi do programu rejestrującego, jeśli jest on obiektem obsługi programu MemoryHandler, który został dodany do programu rejestrującego. Jeśli ustawisz poziom obsługi, która wpłynie na to, co program obsługi faktycznie przetworzy - nie będzie przetwarzać niczego, co jest mniej surowe niż ustawienie poziomu.

+0

Świetne rzeczy. Nie codziennie otrzymujesz odpowiedź na pytanie autora modułu! – SpliFF

+0

@VinaySajip - co myślisz o używaniu modułu smtplib do wysyłania e-maili? – codingknob

+0

@ algotr8der - Możesz zobaczyć z linku (zaktualizowanego), że skrypt faktycznie używa 'smtplib' do wysyłania wiadomości e-mail. –

0

Do tego celu używam BufferingSMTPHandler sugerowanego przez Vinay Sajip z jednym niewielkim uszczypnąć: ustawić długość bufora do czegoś naprawdę wielkiego (powiedzmy 5000 rekordy dziennika) i recznie zadzwonić do spłukiwania metodę obsługi każdy niektóre sekund i po sprawdzeniu conectivity internetu.

# init 
log_handler1 = BufferingSMTPHandler(
    'smtp.host.lala', "[email protected]", ['[email protected]'], 'Log event(s)',5000) 
... 
logger.addHandler(log_handler1) 
... 

# main code 
... 
if internet_connection_ok and seconds_since_last_flush>60: 
    log_handler1.flush() # send buffered log records (if any) 
+2

To działałoby tylko wtedy, gdy przewodnik jest nadal w zasięgu, gdy jest przepłukiwany. W przeciwnym razie będziesz musiał pobrać handler z obiektu rejestratora, aby wywołać połączenie. – DeaconDesperado

5

pisałem własne nieludzki realizację wątku bezpieczny z BufferingSMTPHandler który wysyła maile z osobnym wątku. Głównym celem jest nie blokowanie głównego wątku.

Jak napisano, używa dwóch kolejek - wydawało się to konieczne, aby zaimplementować użyteczne parametry na poziomie klasy zdefiniowane w sekcji "Parametry konfigurowalne" kodu. Chociaż możesz używać kodu tak, jak jest, prawdopodobnie lepiej będzie, jeśli przestudiujesz go i wykorzystasz do napisania własnej klasy.

Issues:

  • Niektóre parametry klasy szczebla może być może być instancja poziomu zamiast.
  • Albo threading.Timer lub moduł signal może być użyty do uniknięcia pętli, które działają wiecznie.
2

Jeśli używasz Django - tutaj jest prosta obsługi buforowania, która będzie używać standardowych metod email Django:

import logging 

from django.conf import settings 
from django.core.mail import EmailMessage 


class DjangoBufferingSMTPHandler(logging.handlers.BufferingHandler): 
    def __init__(self, capacity, toaddrs=None, subject=None): 
     logging.handlers.BufferingHandler.__init__(self, capacity) 

     if toaddrs: 
      self.toaddrs = toaddrs 
     else: 
      # Send messages to site administrators by default 
      self.toaddrs = zip(*settings.ADMINS)[-1] 

     if subject: 
      self.subject = subject 
     else: 
      self.subject = 'logging' 

    def flush(self): 
     if len(self.buffer) == 0: 
      return 

     try: 
      msg = "\r\n".join(map(self.format, self.buffer)) 
      emsg = EmailMessage(self.subject, msg, to=self.toaddrs) 
      emsg.send() 
     except Exception: 
      # handleError() will print exception info to stderr if logging.raiseExceptions is True 
      self.handleError(record=None) 
     self.buffer = [] 

w Django settings.py trzeba będzie skonfigurować e-mail i zalogowaniu tak:

EMAIL_USE_TLS = True 
EMAIL_PORT = 25 
EMAIL_HOST = '' # example: 'smtp.yandex.ru' 
EMAIL_HOST_USER = '' # example: '[email protected]' 
EMAIL_HOST_PASSWORD = '' 
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER 
SERVER_EMAIL = EMAIL_HOST_USER 

LOGGING = { 
    'handlers': { 
     ... 
     'mail_buffer': { 
      'level': 'WARN', 
      'capacity': 9999, 
      'class': 'utils.logging.DjangoBufferingSMTPHandler', 
      # optional: 
      # 'toaddrs': '[email protected]' 
      # 'subject': 'log messages' 
     } 
    }, 
    ... 
} 
Powiązane problemy