rotatingfilehandler multiple logger log example python logging syslog rsyslog

multiple - python logging to console



Registros de registro de varias lĂ­neas en syslog (3)

Alternativamente, si desea mantener su syslog intacto en una línea para el análisis, puede simplemente reemplazar los caracteres al visualizar el registro.

tail -f /var/log/syslog | sed ''s/#012//n/t/g''

Así que configuré mi aplicación Python para iniciar sesión en syslog con SysLogHandler de Python, y todo funciona bien. Excepto por el manejo de múltiples líneas. No es que necesite emitir registros de registro de líneas múltiples tan mal (hago un poco), pero necesito poder leer las excepciones de Python. Estoy usando Ubuntu con rsyslog 4.2.0. Esto es lo que obtendré:

Mar 28 20:11:59 telemachos root: ERROR ''EXCEPTION''#012Traceback (most recent call last):#012 File "./test.py", line 22, in <module>#012 foo()#012 File "./test.py", line 13, in foo#012 bar()#012 File "./test.py", line 16, in bar#012 bla()#012 File "./test.py", line 19, in bla#012 raise Exception("EXCEPTION!")#012Exception: EXCEPTION!

Código de prueba en caso de que lo necesites:

import logging from logging.handlers import SysLogHandler logger = logging.getLogger() logger.setLevel(logging.INFO) syslog = SysLogHandler(address=''/dev/log'', facility=''local0'') formatter = logging.Formatter(''%(name)s: %(levelname)s %(message)r'') syslog.setFormatter(formatter) logger.addHandler(syslog) def foo(): bar() def bar(): bla() def bla(): raise Exception("EXCEPTION!") try: foo() except: logger.exception("EXCEPTION")


OK, finalmente lo descubrí ...

rsyslog por defecto escapa de todos los caracteres extraños (ASCII <32), y esto incluye nuevas líneas (así como también pestañas y otras). Simplemente agregue esto a su configuración rsyslog para desactivarlo:

$EscapeControlCharactersOnReceive off


Otra opción sería crear una subclase de SysLogHandler y anular emit emit() - entonces podría llamar a la superclase emit() para cada línea en el texto que le envían. Algo como:

from logging import LogRecord from logging.handlers import SysLogHandler class MultilineSysLogHandler(SysLogHandler): def emit(self, record): if ''/n'' in record.msg: record_args = [record.args] if isinstance(record.args, dict) else record.args for single_line in record.msg.split(''/n''): single_line_record = LogRecord( name=record.name, level=record.levelno, pathname=record.pathname, msg=single_line, args=record_args, exc_info=record.exc_info, func=record.funcName ) super(MultilineSysLogHandler, self).emit(single_line_record) else: super(MultilineSysLogHandler, self).emit(record)