Многострочные записи журнала в системном журнале - PullRequest
35 голосов
/ 28 марта 2011

Итак, я настроил свое приложение Python для входа в системный журнал с помощью Python SysLogHandler, и все работает отлично. За исключением многострочной обработки. Не то чтобы мне нужно было так сильно создавать многострочные записи в журнале (я делаю немного), но мне нужно уметь читать исключения Python. Я использую Ubuntu с rsyslog 4.2.0. Вот что я получаю:

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!

Тестовый код, если он вам нужен:

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")

Ответы [ 3 ]

35 голосов
/ 26 апреля 2012

В качестве альтернативы, если вы хотите сохранить системный журнал без изменений в одной строке для разбора, вы можете просто заменить символы при просмотре журнала.

tail -f /var/log/syslog | sed 's/#012/\n\t/g'
31 голосов
/ 05 апреля 2011

ОК, наконец-то разобрался ...

rsyslog по умолчанию экранирует все странные символы (ASCII <32), включая новые строки (а также вкладки и другие). Просто добавьте это в конфигурацию rsyslog, чтобы отключить: </p>

$EscapeControlCharactersOnReceive off
3 голосов
/ 02 июня 2016

Другим вариантом будет создание подкласса SysLogHandler и переопределение emit() - тогда вы можете вызвать суперкласс emit() для каждой строки в отправляемом тексте.Что-то вроде:

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)
...