开发者

How do I set the ident string when using logging.SysLogHandler in Python 2.6?

I have logging configured using logging.fileConfig(). I have a the root logger going to a handler that uses SysLogHandler('/dev/log', handlers.SysLogHandler.LOG_USER)

This all works perfectly well, and I see my log entries in /var/log/user.log

The question is how can I set the syslog ident string to something other than python? It appears the syslog module in the standard lib allows setting this when opening a log, but the logging handler doesn't offer this feature.

Would the solution be to subclass SysLogHandler and use the syslog library inside it's emit method? This开发者_运维百科 is a unix only program, so using syslog directly doesn't pose a portability problem.


This is a bit old but new information should be recorded here so people don't feel the need to write their own syslog handler.

Since Python 3.3, the SysLogHandler has a class attribute of .ident precisely for this purpose; the default for it is ''.

Example:

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


Syslog implementations accepting RFC3164 messages should recognize first part of the message ("foo:" in the example) as TAG.

The MSG part has two fields known as the TAG field and the CONTENT field. The value in the TAG field will be the name of the program or process that generated the message.

Python code..

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

..will send this into syslog socket

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)

Which in turn, produces this in systemd's journal.

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

Journal message details:

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

It works with Py2.6, 2.7, 3.4, 3.5 and Systemd's syslog server. It may work with other syslog implementations as well (if they accept RFC3164) messages. This solution will probably break when python's SysLogHandler will default to newer RFC5424.


AFAIK, the ident string is an artifact of the syslog API, see this page. It's just using the C argv[0] which would of course be "python".

I'm surprised that you're getting this using SysLogHandler with a domain socket, as the message sent to syslog daemons across domain or TCP sockets is just a string with the priority in <angle brackets> followed by the formatted message and a NUL byte. There's no ident string specified by SysLogHandler, as it doesn't use the syslog API (which has some thread-safety issues in some versions, IIRC).


For Python 2.7, you could do something like this:

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

This will produce in the syslog:

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜