【问题标题】:How do I set the ident string when using logging.SysLogHandler in Python 2.6?在 Python 2.6 中使用 logging.SysLogHandler 时如何设置 ident 字符串?
【发布时间】:2011-05-14 18:13:18
【问题描述】:

我已经使用 logging.fileConfig() 配置了日志记录。我有一个根记录器转到使用 SysLogHandler('/dev/log', handlers.SysLogHandler.LOG_USER)

的处理程序

这一切都很好,我在 /var/log/user.log 中看到了我的日志条目

问题是如何将 syslog ident 字符串设置为 python 以外的字符串?似乎标准库中的 syslog 模块允许在打开日志时进行设置,但日志处理程序不提供此功能。

解决方案是继承 SysLogHandler 并在它的 emit 方法中使用 syslog 库吗?这是一个仅适用于 unix 的程序,因此直接使用 syslog 不会造成可移植性问题。

【问题讨论】:

    标签: python logging syslog ident


    【解决方案1】:

    这有点旧,但应该在这里记录新信息,这样人们就不会觉得有必要编写自己的 syslog 处理程序。

    从 Python 3.3 开始,SysLogHandler 具有 .ident 的类属性正是为此目的;它的默认值为 ''。

    例子:

    import logging
    from logging.handlers import SysLogHandler
    
    h = SysLogHandler(address=('some.destination.com',514), facility=SysLogHandler.LOG_LOCAL6)
    h.setFormatter(
        logging.Formatter('%(name)s %(levelname)s %(message)s')
    )
    h.ident = 'conmon'
    
    syslog = logging.getLogger('syslog')
    syslog.setLevel(logging.DEBUG)
    syslog.addHandler(h)
    
    syslog.debug('foo syslog message')
    

    【讨论】:

    • 不过这是 Python 3.3+。
    • 仅供可能遇到相同问题的其他人参考。如果您从 yaml 文件执行dictConfig,则设置ident 的方式是将ident 键放在. 键下。所以它会类似于handlers:\n\t syslog:\n\t\t .:\n\t\t\t ident: appname
    【解决方案2】:

    接受 RFC3164 消息的 Syslog 实现应将消息的第一部分(示例中为 "foo:")识别为 TAG。

    MSG 部分有两个字段,分别称为 TAG 字段和 CONTENT 场地。 TAG 字段中的值将是程序的名称或 生成消息的进程。

    Python 代码..

    import logging
    from logging.handlers import SysLogHandler
    
    h = SysLogHandler(address='/dev/log')
    h.setFormatter(logging.Formatter('foo: %(message)s'))
    logging.getLogger().addHandler(h)
    
    logging.error('bar')
    

    ..将其发送到系统日志套接字

    connect(3, {sa_family=AF_UNIX, sun_path="/dev/log"}, 10) = 0
    sendto(3, "<11>foo: bar\0", 13, 0, NULL, 0) = 13
    close(3)
    

    这反过来又在 systemd 的日志中生成。

    Dec 13 14:48:20 laptop foo[1928]: bar
    

    日志消息详情:

    {
      ..
      "PRIORITY" : "3",
      "SYSLOG_FACILITY" : "1",
      "SYSLOG_IDENTIFIER" : "foo",
      "MESSAGE" : "bar",
      "_PID" : "1928",
    }
    

    它适用于 Py2.6、2.7、3.4、3.5 和 Systemd 的 syslog 服务器。它也可以与其他 syslog 实现(如果它们接受 RFC3164)消息一起使用。当 python 的 SysLogHandler 默认为较新的 RFC5424 时,此解决方案可能会中断。

    【讨论】:

    • 这是救命稻草
    【解决方案3】:

    AFAIK,ident 字符串是 syslog API 的工件,请参阅 this page。它只是使用 C argv[0] 当然是“python”。

    我很惊讶您使用带有域套接字的SysLogHandler 得到这个,因为跨域或 TCP 套接字发送到 syslog 守护进程的消息只是一个字符串,其优先级在 后跟格式化消息和一个 NUL 字节。 SysLogHandler 没有指定 ident 字符串,因为它不使用 syslog API(在某些版本中存在一些线程安全问题,IIRC)。

    【讨论】:

    • Vinay 感谢您的详尽回答。事实证明你是对的,这主要是与我的运营团队的沟通不畅。我们正在使用一个新的格式化程序将一个假的“ident”标志作为第一个参数,而 rsyslog 再高兴不过了。
    • 这是过时的信息,我会将 FirefighterBlu3 的答案标记为正确的。
    • 没有理由拒绝投票,因为信息已经过时了。这是当时的正确答案,感谢FirefighterBlu3 提供更新。
    【解决方案4】:

    对于 Python 2.7,您可以执行以下操作:

    class MySysLogHandler(logging.handlers.SysLogHandler):
        def __init__(self):
            super(MySysLogHandler, self).__init__(address='/dev/log')
        def emit(self, record):
            priority = self.encodePriority(self.facility, self.mapPriority(record.levelname))
            record.ident = "My[" + str(priority) + "]:"
            super(MySysLogHandler, self).emit(record)
    
    handler = MySysLogHandler()
    handler.formatter = logging.Formatter(fmt="%(ident)s %(levelname)s: %(message)s")
    logging.root.addHandler(handler)
    logging.info("hello world")
    

    这将在系统日志中产生:

    Sep 3 16:28:53 hostname My[14]: INFO: hello world

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-20
      • 2022-07-19
      • 1970-01-01
      • 1970-01-01
      • 2017-04-16
      • 2010-09-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多