如何在Python 2.6中使用logging.SysLogHandler设置ident字符串?
我配置了日志记录,使用的是 logging.fileConfig()。我有一个根日志记录器,它连接到一个处理器,这个处理器使用 SysLogHandler('/dev/log', handlers.SysLogHandler.LOG_USER)。
这一切都运行得很好,我能在 /var/log/user.log 中看到我的日志条目。
我的问题是,怎么把 syslog 的标识字符串设置成其他的,而不是默认的 python?看起来标准库中的 syslog 模块在打开日志时可以设置这个,但日志处理器并没有提供这个功能。
解决办法是创建一个 SysLogHandler 的子类,并在它的 emit 方法中使用 syslog 库吗?因为这是一个只在 Unix 系统上运行的程序,所以直接使用 syslog 不会有移植性的问题。
4 个回答
支持 RFC3164 消息的Syslog实现应该把消息的第一部分(比如示例中的 "foo:"
)识别为标签(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')
..这段代码会发送信息到syslog的套接字。
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",
}
这个方法在Python 2.6、2.7、3.4、3.5和Systemd的syslog服务器上都能用。它可能也适用于其他的syslog实现,只要它们支持RFC3164的消息。不过,当Python的SysLogHandler默认使用更新的RFC5424时,这个方法可能就不再有效了。
这段内容有点旧,但还是要把新信息记录在这里,这样大家就不需要自己写一个系统日志处理器了。
从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')
据我所知,ident字符串是syslog API的一个产物,具体可以参考这个页面。它其实就是使用了C语言中的argv[0],在这里就是“python”。
我很惊讶你在使用SysLogHandler
和域套接字时会遇到这个问题,因为通过域或TCP套接字发送给syslog守护进程的消息其实只是一个字符串,格式是优先级用<尖括号>包起来,后面跟着格式化的消息和一个NUL字节。SysLogHandler
并没有指定ident字符串,因为它并不使用syslog API(我记得某些版本的syslog API在多线程安全性方面有一些问题)。