syslog中的多行日志记录

发布于 2024-10-27 14:29:21 字数 1054 浏览 6 评论 0原文

因此,我已经将我的 Python 应用程序配置为使用 Python 的 SysLogHandler 记录到 syslog,并且一切正常。多行处理除外。并不是说我需要如此严重地发出多行日志记录(我做了一点),而是我需要能够读取 Python 的异常。我正在使用带有 rsyslog 4.2.0 的 Ubuntu。这就是我得到的:

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

So I've configured my Python application to log to syslog with Python's SysLogHandler, and everything works fine. Except for multi-line handling. Not that I need to emit multiline log records so badly (I do a little), but I need to be able to read Python's exceptions. I'm using Ubuntu with rsyslog 4.2.0. This is what I'm getting:

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!

Test code in case you need it:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

[旋木] 2024-11-03 14:29:22

或者,如果您想让系统日志在一行中保持完整以便解析,您可以在查看日志时替换字符。

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

Alternatively, if you want to keep your syslog intact on one line for parsing, you can just replace the characters when viewing the log.

tail -f /var/log/syslog | sed 's/#012/\n\t/g'
云淡风轻 2024-11-03 14:29:22

好吧,终于弄清楚了...

rsyslog 默认情况下会转义所有奇怪的字符(ASCII < 32),这包括换行符(以及制表符和其他字符)。

$EscapeControlCharactersOnReceive:

该指令指示 rsyslogd 在接收过程中替换控制字符
信息。目的是提供一种方法来阻止不可打印
进入整个系统日志系统的消息。如果这个选项是
打开时,所有控制字符都转换为 3 位八进制
编号并以 $ControlCharacterEscapePrefix 为前缀
字符(默认为“\”)。例如,如果 BEL 字符
(ctrl-g) 包含在消息中,它将被转换为“\007”。

您只需将其添加到 rsyslog 配置中即可将其关闭:

$EscapeControlCharactersOnReceive off

或者使用“新”高级语法:

global(parser.escapeControlCharactersOnReceive="off")

OK, figured it out finally...

rsyslog by default escapes all weird characters (ASCII < 32), and this include newlines (as well as tabs and others).

$EscapeControlCharactersOnReceive:

This directive instructs rsyslogd to replace control characters during reception of the
message. The intent is to provide a way to stop non-printable
messages from entering the syslog system as whole. If this option is
turned on, all control-characters are converted to a 3-digit octal
number and be prefixed with the $ControlCharacterEscapePrefix
character (being ‘\’ by default). For example, if the BEL character
(ctrl-g) is included in the message, it would be converted to “\007”.

You can simply add this to your rsyslog config to turn it off:

$EscapeControlCharactersOnReceive off

or, with the "new" advanced syntax:

global(parser.escapeControlCharactersOnReceive="off")
江湖正好 2024-11-03 14:29:22

另一种选择是子类化 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)

Another option would be to subclass the SysLogHandler and override emit() - you could then call the superclass emit() for each line in the text you're sent. Something like:

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文