Roland's homepage

My random knot in the Web

Have Python log to syslog

This article documents how I set up Python and the syslog daemon so that Python programs can log to syslogd.

Introduction

UNIX-like systems generally have a syslogd daemon running so that the kernel and other programs can log important events.

By default, the Python logging module writes output to the console. This is not handy when you have a program that is not started from the console. So you might want to log to a file instead. This is what I originally did for my statusline-i3 script. Over time this generates a lot of log files that I had to clean up manually.

So I decided to switch to the built-in syslogd service. This writes logfiles in one place, and rotates them if desired.

Configuring the syslogd service

The syslogd service is pretty sophisticated. It can be configured to route messages from different facilities and different levels to different files and even to different hosts. Python uses the LOG_USER facility by default. On FreeBSD this is the default facility.

On FreeBSD, LOG_USER is generally not configured to be saved to a file. Since a lot of programs use it for low-priority messages, there is a lot of traffic to this facility.

So I decided to use the LOG_LOCAL3 facility, and route that to a special file.

Note

The following is geared toward the BSD family of operating systems. On Linux e.g. /etc/syslog-ng.conf or /etc/rsyslog.conf might be used instead of /etc/syslog.conf. Some older UNIX systems only accept tab characters between the selector and action fields. The proper way to restart the syslog daemon also differs between systems.

To that end, I added the following to my /etc/syslog.conf file:

local3.*                                            /var/log/user.log

Since /var/log/messages gets all messages of level notice or higher by default, I changed that to exclude messages to local3:

*.notice;local3.none;mail.none;authpriv.none      /var/log/messages

Next I created the logfile with permissions for all to read it, and restarted the syslog daemon.

# touch /var/log/user.log
# chmod 644 /var/log/user.log
# service syslogd restart

For now, I have not configured logfile rotation.

Configure Python for logging to syslogd

Note that I’m re-configuring the root logger here, so that all log messages go to syslogd.

import os
import logging
from logging.handlers import SysLogHandler

syslog = SysLogHandler(address='/var/run/log', facility=SysLogHandler.LOG_LOCAL3)
pid = os.getpid()
syslog.ident = f'progname[{pid}]: '
logging.basicConfig(
    level='INFO',
    format='%(levelname)s: %(message)s',
    handlers=(syslog,)
)

The essential bits are;

  • to create a SysLogHandler configured for the right address and facility,
  • setting the ident of the SysLogHandler class to the name and PID of the program and
  • using said handler in the basic configuration of the logging module.

The level and format configuration parameters above are a personal preference.

Note

Both FreeBSD and macOS require that you use /var/run/log as the UNIX domain socket address.


Related articles


←  Command-line versus GUI program On the nature of GUI programs  →