如何在Python中将日志记录配置为syslog?


121

我无法理解Python的logging模块。我的需求非常简单:我只想将所有内容记录到syslog中。阅读文档后,我想到了这个简单的测试脚本:

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

但是此脚本不会在syslog中产生任何日志记录。怎么了?


3
您在哪里查看系统日志消息?SysLogHandler()将这些消息发送到本地主机端口514中的udp套接字。
suzanshakya 2010年

你是绝对正确的。我已经看到了“本地主机-514”的文档,但没有想到的/ dev /日志默认情况下应使用..唉..
托尔

Answers:


140

将行更改为此:

handler = SysLogHandler(address='/dev/log')

这对我有用

import logging
import logging.handlers

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

handler = logging.handlers.SysLogHandler(address = '/dev/log')

my_logger.addHandler(handler)

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

12
需要注意的是,由于美国商务部说,'/var/run/syslog'是正确的事在OS X
offby1

救生员答案+1
chachan

3
我们如何在syslog中识别这些日志?像我们可以给任何应用程序名称或syslogtag = django这样的标签吗?
Luv33preet

并记住配置/etc/syslog.d/conf文件,然后重新启动syslog /
rsyslog

5
@ Luv33preet我已经使用(但并非没有)格式器(如logging.Formatter(fmt='myscriptname[%(process)d]: %(levelname)s: %(message)s', ...)rsyslog条件 )进行了测试$programname == 'myscriptname'
彼得

26

无论是通过TCP堆栈登录到/ dev / log还是localhost,都应始终使用本地主机进行日志记录。这允许完全符合RFC且功能强大的系统日志记录守护程序来处理syslog。这消除了远程守护程序起作用的需要,并提供了syslog守护程序的增强功能,例如rsyslog和syslog-ng。SMTP也遵循相同的原则。只需将其交给本地SMTP软件即可。在这种情况下,请使用“程序模式”而不是守护程序,但这是相同的想法。让功能更强大的软件来处理它。使用TCP代替UDP进行syslog重试,排队,本地后台处理成为可能。您也可以按原样与代码分开[重新]配置这些守护程序。

为您的应用程序保存代码,让其他软件协同工作。


2
你提出一个公平的观点。您能否指出各种日志记录守护程序使用的公共地址和端口?是否有标准的发现机制来确定守护程序是否绑定到tcp套接字?
init_js '18

我完全同意你的看法。
daks

20

我发现syslog模块可以很容易地获得您描述的基本日志记录行为:

import syslog
syslog.syslog("This is a test message")
syslog.syslog(syslog.LOG_INFO, "Test message at INFO priority")

您还可以做其他事情,但是就我所知,即使只是前两行也可以满足您的要求。


我保留了日志记录模块,因为它允许更改记录器设置而不影响所有语句。如果您想同时拥有不同类型的日志记录,还可以更改行为
chachan

14

从这里和其他地方将东西拼凑在一起,这就是我想出的在unbuntu 12.04和centOS6上运行的结果

创建一个/etc/rsyslog.d/以.conf结尾的文件,并添加以下文本

local6.*        /var/log/my-logfile

重新启动rsyslog,重新加载似乎不适用于新的日志文件。也许它只重新加载现有的conf文件?

sudo restart rsyslog

然后,您可以使用此测试程序来确保它确实有效。

import logging, sys
from logging import config

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(module)s P%(process)d T%(thread)d %(message)s'
            },
        },
    'handlers': {
        'stdout': {
            'class': 'logging.StreamHandler',
            'stream': sys.stdout,
            'formatter': 'verbose',
            },
        'sys-logger6': {
            'class': 'logging.handlers.SysLogHandler',
            'address': '/dev/log',
            'facility': "local6",
            'formatter': 'verbose',
            },
        },
    'loggers': {
        'my-logger': {
            'handlers': ['sys-logger6','stdout'],
            'level': logging.DEBUG,
            'propagate': True,
            },
        }
    }

config.dictConfig(LOGGING)


logger = logging.getLogger("my-logger")

logger.debug("Debug")
logger.info("Info")
logger.warn("Warn")
logger.error("Error")
logger.critical("Critical")

1
要在centOS7上重新启动rsyslog,sudo service rsyslog restart
radtek

12

我添加了一些额外的注释,以防万一,它对任何人都有帮助,因为我发现此交换很有用,但需要一些额外的信息才能使其正常工作。

要使用SysLogHandler登录到特定工具,您需要指定工具值。例如,您已定义:

local3.* /var/log/mylog

在syslog中,那么您将要使用:

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

并且还需要让syslog侦听UDP以使用localhost而不是/ dev / log。


3
不需要“系统日志”监听UDP。您的示例也可以完美地与address ='/ dev / log'一起使用。
2012年

5
是的,当然可以,但是使用地址=('localhost',514),即拥有日志服务器的那一天,将localhost替换为服务器的地址,便可以进行远程日志记录;-)
Oliver Henriot 2012年

5
设施= 19来自哪里?为什么它不是africation =“ local3”
boatcoder,2013年

4
@ Mark0978 19是由RFC3146(及随后的RFC5424)定义的local3的数字表示形式
Andrew Sledge

3
我也对此感到疑惑,发现设施代码在Python的SysLogHandler
clebio 2014年

11

是否已将syslog.conf设置为处理工具=用户?

您可以使用工具参数设置python记录器使用的工具,如下所示:

handler = logging.handlers.SysLogHandler(facility=SysLogHandler.LOG_DAEMON)

您需要指定LOG_DAEMON作为facility参数值提供的内容。
tzot 2010年

4
那会是SysLogHandler.LOG_DAEMON
Craig Trader

7
import syslog
syslog.openlog(ident="LOG_IDENTIFIER",logoption=syslog.LOG_PID, facility=syslog.LOG_LOCAL0)
syslog.syslog('Log processing initiated...')

上面的脚本将使用我们的自定义“ LOG_IDENTIFIER”登录到LOCAL0工具...您可以将LOCAL [0-7]用于本地目的。


1
您的评论与原始请求无关
2012年

@thor我同意这是相关的。我猜想 syslog软件包要比纯Python实现的效率高一点?(如果不太灵活)
丹尼尔·桑托斯

7

来自https://github.com/luismartingil/per.scripts/tree/master/python_syslog

#!/usr/bin/python
# -*- coding: utf-8 -*-

'''
Implements a new handler for the logging module which uses the pure syslog python module.

@author:  Luis Martin Gil
@year: 2013
'''
import logging
import syslog

class SysLogLibHandler(logging.Handler):
    """A logging handler that emits messages to syslog.syslog."""
    FACILITY = [syslog.LOG_LOCAL0,
                syslog.LOG_LOCAL1,
                syslog.LOG_LOCAL2,
                syslog.LOG_LOCAL3,
                syslog.LOG_LOCAL4,
                syslog.LOG_LOCAL5,
                syslog.LOG_LOCAL6,
                syslog.LOG_LOCAL7]
    def __init__(self, n):
        """ Pre. (0 <= n <= 7) """
        try:
            syslog.openlog(logoption=syslog.LOG_PID, facility=self.FACILITY[n])
        except Exception , err:
            try:
                syslog.openlog(syslog.LOG_PID, self.FACILITY[n])
            except Exception, err:
                try:
                    syslog.openlog('my_ident', syslog.LOG_PID, self.FACILITY[n])
                except:
                    raise
        # We got it
        logging.Handler.__init__(self)

    def emit(self, record):
        syslog.syslog(self.format(record))

if __name__ == '__main__':
    """ Lets play with the log class. """
    # Some variables we need
    _id = 'myproj_v2.0'
    logStr = 'debug'
    logFacilityLocalN = 1

    # Defines a logging level and logging format based on a given string key.
    LOG_ATTR = {'debug': (logging.DEBUG,
                          _id + ' %(levelname)-9s %(name)-15s %(threadName)-14s +%(lineno)-4d %(message)s'),
                'info': (logging.INFO,
                         _id + ' %(levelname)-9s %(message)s'),
                'warning': (logging.WARNING,
                            _id + ' %(levelname)-9s %(message)s'),
                'error': (logging.ERROR,
                          _id + ' %(levelname)-9s %(message)s'),
                'critical': (logging.CRITICAL,
                             _id + ' %(levelname)-9s %(message)s')}
    loglevel, logformat = LOG_ATTR[logStr]

    # Configuring the logger
    logger = logging.getLogger()
    logger.setLevel(loglevel)

    # Clearing previous logs
    logger.handlers = []

    # Setting formaters and adding handlers.
    formatter = logging.Formatter(logformat)
    handlers = []
    handlers.append(SysLogLibHandler(logFacilityLocalN))
    for h in handlers:
        h.setFormatter(formatter)
        logger.addHandler(h)

    # Yep!
    logging.debug('test debug')
    logging.info('test info')
    logging.warning('test warning')
    logging.error('test error')
    logging.critical('test critical')

这非常有趣,但是在python 2.6.6(RHEL 6.4)上不起作用:追溯(最近一次调用为最后一次):<模块> handlers.append(SysLogLibHandler(logFacilityLocalN)中的文件“ syslog_bridge.py”,第68行))文件“ syslog_bridge.py”,init syslog.openlog(syslog.LOG_PID,self.FACILITY [n])中的第29行,TypeError:ident字符串[,logoption [,工具]]
Steve Cohen


3

这是推荐用于3.2及更高版本的yaml dictConfig方式。

在日志中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

使用以下命令加载配置:

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

配置了系统日志和直接文件。请注意,/dev/log是特定于操作系统的。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.