How to configure logging to syslog in Python?

Viewed 178942

I can't get my head around Python's logging module. My needs are very simple: I just want to log everything to syslog. After reading documentation I came up with this simple test script:

import logging
import logging.handlers

my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)

handler = logging.handlers.SysLogHandler()

my_logger.addHandler(handler)

my_logger.debug('this is debug')
my_logger.critical('this is critical')

But this script does not produce any log records in syslog. What's wrong?

12 Answers

I add a little extra comment just in case it helps anyone because I found this exchange useful but needed this little extra bit of info to get it all working.

To log to a specific facility using SysLogHandler you need to specify the facility value. Say for example that you have defined:

local3.* /var/log/mylog

in syslog, then you'll want to use:

handler = logging.handlers.SysLogHandler(address = ('localhost',514), facility=19)

and you also need to have syslog listening on UDP to use localhost instead of /dev/log.

Here's the yaml dictConfig way recommended for 3.2 & later.

In log cfg.yml:

version: 1
disable_existing_loggers: true

formatters:
    default:
        format: "[%(process)d] %(name)s(%(funcName)s:%(lineno)s) - %(levelname)s: %(message)s"

handlers:
    syslog:
        class: logging.handlers.SysLogHandler
        level: DEBUG
        formatter: default
        address: /dev/log
        facility: local0

    rotating_file:
        class: logging.handlers.RotatingFileHandler
        level: DEBUG
        formatter: default
        filename: rotating.log
        maxBytes: 10485760 # 10MB
        backupCount: 20
        encoding: utf8

root:
    level: DEBUG
    handlers: [syslog, rotating_file]
    propogate: yes

loggers:
    main:
        level: DEBUG
        handlers: [syslog, rotating_file]
        propogate: yes

Load the config using:

log_config = yaml.safe_load(open('cfg.yml'))
logging.config.dictConfig(log_config)

Configured both syslog & a direct file. Note that the /dev/log is OS specific.

I fix it on my notebook. The rsyslog service did not listen on socket service.

I config this line bellow in /etc/rsyslog.conf file and solved the problem:

$SystemLogSocketName /dev/log

I use JSON logging and wanted use SysLogHandler with UDP port 514. Eventually got JSON handler config working. In the handlers section, I have:

{
    "syslog": {
        "class": "logging.handlers.SysLogHandler",
        "address": ["127.0.0.1", 514],
        "facility": "local6",
        "formatter": "syslog_fmt"
}

Didn't find this anywhere else.

[Edit] To be clearer about what is going on here: this is only for python code, and using python's built in logging module. The module allows format and destination(s) of the log messages to be configured. One way to configure the log format and destination(s) is by using a JSON file that is used to configure the logging.

The above example allowed me to send log messages to a syslog daemon.

A complete example of such a file is included below.

{
    "version": 1,
    "disable_existing_loggers": "False",
    "formatters": {
        "verbose": {
            "format": "%(asctime)s:%(levelname)s:%(process)d:%(filename)s:%(funcName)s:L%(lineno)d:%(message)s"
        },
        "syslog": {
            "format": "%(levelname)s:%(process)d:%(filename)s:%(funcName)s:L%(lineno)d:%(message)s"
        }
    },
    "handlers": {
        "console": {
            "class":"logging.StreamHandler",
            "formatter": "standard"
        },
        "syslog": {
        "class": "logging.handlers.SysLogHandler",
        "address": ["127.0.0.1", 514],
        "facility": "local6",
        "formatter": "syslog_fmt"
        }
    },
    "loggers": {
        "": {
            "handlers": ["console","syslog"],
            "level": "DEBUG",
            "propagate": "True"
        }
    }
}

The example above sends python log messages to both syslog and the console. The format of messages for destinations is different (syslog already prefixes each message with a timestamp). For the syslog destination, the log uses facility LOCAL6.

Related