简体   繁体   English

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

[英]How to configure logging to syslog in Python?

I can't get my head around Python's logging module.我无法理解 Python 的logging模块。 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.但是这个脚本不会在 syslog 中产生任何日志记录。 What's wrong?怎么了?

Change the line to this: 将行更改为:

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

This works for me 这适合我

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

You should always use the local host for logging, whether to /dev/log or localhost through the TCP stack. 您应始终使用本地主机进行日志记录,无论是通过TCP堆栈还是/ dev / log或localhost。 This allows the fully RFC compliant and featureful system logging daemon to handle syslog. 这允许完全符合RFC且功能强大的系统日志记录守护程序来处理syslog。 This eliminates the need for the remote daemon to be functional and provides the enhanced capabilities of syslog daemon's such as rsyslog and syslog-ng for instance. 这消除了远程守护进程功能的需要,并提供了syslog守护进程的增强功能,例如rsyslog和syslog-ng。 The same philosophy goes for SMTP. SMTP也是如此。 Just hand it to the local SMTP software. 只需将其交给本地SMTP软件即可。 In this case use 'program mode' not the daemon, but it's the same idea. 在这种情况下使用'程序模式'而不是守护进程,但它是相同的想法。 Let the more capable software handle it. 让功能更强大的软件处理它。 Retrying, queuing, local spooling, using TCP instead of UDP for syslog and so forth become possible. 可以重试,排队,本地假脱机,使用TCP而不是UDP来进行系统日志等。 You can also [re-]configure those daemons separately from your code as it should be. 您也可以[代码]单独[重新]配置这些守护程序。

Save your coding for your application, let other software do it's job in concert. 保存您的应用程序编码,让其他软件协同工作。

I found the syslog module to make it quite easy to get the basic logging behavior you describe: 我发现syslog模块可以很容易地获得您描述的基本日志记录行为:

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

There are other things you could do, too, but even just the first two lines of that will get you what you've asked for as I understand it. 还有其他一些你可以做的事情,但即便只是前两行也会让你得到我所理解的东西。

Piecing things together from here and other places, this is what I came up with that works on unbuntu 12.04 and centOS6 从这里和其他地方拼凑起来的东西,这就是我提出的可以在unbuntu 12.04和centOS6上运行的东西

Create an file in /etc/rsyslog.d/ that ends in .conf and add the following text /etc/rsyslog.d/中创建一个以.conf结尾的文件并添加以下文本

local6.*        /var/log/my-logfile

Restart rsyslog , reloading did NOT seem to work for the new log files. 重新启动rsyslog ,重新加载似乎rsyslog用于新的日志文件。 Maybe it only reloads existing conf files? 也许它只重新加载现有的conf文件?

sudo restart rsyslog

Then you can use this test program to make sure it actually works. 然后你可以使用这个测试程序来确保它确实有效。

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

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. 要使用SysLogHandler登录到特定设施,您需要指定设施值。 Say for example that you have defined: 比如你已经定义了:

local3.* /var/log/mylog

in syslog, then you'll want to use: 在syslog中,那么你将要使用:

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. 并且您还需要在UDP上侦听syslog以使用localhost而不是/ dev / log。

Is your syslog.conf set up to handle facility=user? 您的syslog.conf是否设置为处理facility = user?

You can set the facility used by the python logger with the facility argument, something like this: 您可以使用facility参数设置python logger使用的工具,如下所示:

handler = logging.handlers.SysLogHandler(facility=SysLogHandler.LOG_DAEMON)
import syslog
syslog.openlog(ident="LOG_IDENTIFIER",logoption=syslog.LOG_PID, facility=syslog.LOG_LOCAL0)
syslog.syslog('Log processing initiated...')

the above script will log to LOCAL0 facility with our custom "LOG_IDENTIFIER"... you can use LOCAL[0-7] for local purpose. 上面的脚本将使用我们的自定义“LOG_IDENTIFIER”登录LOCAL0工具......您可以将LOCAL [0-7]用于本地目的。

From https://github.com/luismartingil/per.scripts/tree/master/python_syslog 来自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')

Here's the yaml dictConfig way recommended for 3.2 & later. 这是推荐用于3.2及更高版本的yaml dictConfig方式。

In log cfg.yml : 在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. 配置syslog和直接文件。 Note that the /dev/log is OS specific. 请注意, /dev/log是特定于操作系统的。

I use JSON logging and wanted use SysLogHandler with UDP port 514. Eventually got JSON handler config working.我使用 JSON 日志记录并希望将 SysLogHandler 与 UDP 端口 514 一起使用。最终使 JSON 处理程序配置正常工作。 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. [编辑]更清楚地了解这里发生了什么:这仅适用于 python 代码,并且使用 python 的内置日志记录模块。 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.配置日志格式和目标的一种方法是使用用于配置日志记录的 JSON 文件。

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.上面的示例将 python 日志消息发送到系统日志和控制台。 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.对于系统日志目标,日志使用设施 LOCAL6。

I fix it on my notebook. 我在笔记本上修好了。 The rsyslog service did not listen on socket service. rsyslog服务没有侦听套接字服务。

I config this line bellow in /etc/rsyslog.conf file and solved the problem: 我在/etc/rsyslog.conf文件中配置了这一行并解决了问题:

$SystemLogSocketName /dev/log

您还可以添加文件处理程序或旋转文件处理程序以将日志发送到本地文件: http//docs.python.org/2/library/logging.handlers.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM