Вывод данных для сборки в Python-протоколировании MemoryHandler с SMTPHandler
У меня есть модуль протоколирования MemoryHandler, настроенный для отладки очереди и сообщений об ошибках для целевой SMTPHandler. Я хочу, чтобы электронное письмо отправлялось при ошибках процесса, содержащих все операторы отладки до этой точки (по одной в строке). Вместо этого я получаю отдельное письмо для каждого отладочного сообщения.
Кажется, что это должно быть тривиальным и частью пакета протоколирования, но я ничего не могу найти об этом, никаких примеров, ничего в 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)
В связи с этим:
Нужно ли добавлять тег error_mail_handler
в журнал, если это цель memory_handler
?
Должно ли error_mail_handler
быть установлено значение DEBUG или ERROR? Нужна ли даже цель, когда она подается от memory_handler
?
Хотелось бы увидеть какой-нибудь рабочий код от тех, кто решил эту проблему.
Ответы
Ответ 1
Вы можете использовать или адаптировать BufferingSMTPHandler
, который находится в этот тест script.
В общем случае вам не нужно добавлять обработчик в регистратор, если он является объектом обработчика MemoryHandler, который был добавлен в регистратор. Если вы установите уровень обработчика, это повлияет на то, что обработчик фактически обрабатывает, - он не будет обрабатывать что-либо менее серьезное, чем его уровень.
Ответ 2
Я написал свою собственную реалистичную реалистичную реализацию BufferingSMTPHandler
, которая отправляет электронные письма из отдельного потока. Основная цель - не блокировать основной поток.
Как написано, он использует две очереди - это казалось необходимым для реализации некоторых полезных параметров уровня класса, определенных в разделе "Конфигурируемые параметры" кода. Хотя вы можете использовать код как есть, вероятно, лучше, если вы изучите и используете его для написания своего собственного класса.
Вопросы:
- Некоторые параметры уровня класса могут быть, возможно, на уровне экземпляра.
- Либо
threading.Timer
, либо модуль signal
можно было бы использовать, чтобы избежать циклов, которые выполняются вечно.
Ответ 3
Если вы используете django - здесь используется простой буферизатор, который будет использовать стандартные методы электронной почты 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 = []
В django settings.py вам необходимо настроить электронную почту и выполнить регистрацию следующим образом:
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'
}
},
...
}
Ответ 4
Для этой цели я использую BufferingSMTPHandler, предложенный Винаем Саджипом, с одной незначительной настройкой: я установил длину буфера на что-то действительно большое (скажем, на 5000 записей журнала) и вручную называет метод flush обработчика каждые несколько секунд и после проверки интернет-совместимость.
# 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)