簡體   English   中英

如何在 Python 中配置日志記錄到 syslog?

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

我無法理解 Python 的logging模塊。 我的需求非常簡單:我只想將所有內容記錄到系統日志中。 閱讀文檔后,我想出了這個簡單的測試腳本:

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 中產生任何日志記錄。 怎么了?

將行更改為:

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

您應始終使用本地主機進行日志記錄,無論是通過TCP堆棧還是/ dev / log或localhost。 這允許完全符合RFC且功能強大的系統日志記錄守護程序來處理syslog。 這消除了遠程守護進程功能的需要,並提供了syslog守護進程的增強功能,例如rsyslog和syslog-ng。 SMTP也是如此。 只需將其交給本地SMTP軟件即可。 在這種情況下使用'程序模式'而不是守護進程,但它是相同的想法。 讓功能更強大的軟件處理它。 可以重試,排隊,本地假脫機,使用TCP而不是UDP來進行系統日志等。 您也可以[代碼]單獨[重新]配置這些守護程序。

保存您的應用程序編碼,讓其他軟件協同工作。

我發現syslog模塊可以很容易地獲得您描述的基本日志記錄行為:

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

還有其他一些你可以做的事情,但即便只是前兩行也會讓你得到我所理解的東西。

從這里和其他地方拼湊起來的東西,這就是我提出的可以在unbuntu 12.04和centOS6上運行的東西

/etc/rsyslog.d/中創建一個以.conf結尾的文件並添加以下文本

local6.*        /var/log/my-logfile

重新啟動rsyslog ,重新加載似乎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")

我添加了一些額外的評論以防萬一它可以幫助任何人,因為我發現這個交換有用,但需要這些額外的信息來使它全部工作。

要使用SysLogHandler登錄到特定設施,您需要指定設施值。 比如你已經定義了:

local3.* /var/log/mylog

在syslog中,那么你將要使用:

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

並且您還需要在UDP上偵聽syslog以使用localhost而不是/ dev / log。

您的syslog.conf是否設置為處理facility = user?

您可以使用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...')

上面的腳本將使用我們的自定義“LOG_IDENTIFIER”登錄LOCAL0工具......您可以將LOCAL [0-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')

這是推薦用於3.2及更高版本的yaml dictConfig方式。

在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

使用以下命令加載配置

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

配置syslog和直接文件。 請注意, /dev/log是特定於操作系統的。

我使用 JSON 日志記錄並希望將 SysLogHandler 與 UDP 端口 514 一起使用。最終使 JSON 處理程序配置正常工作。 在處理程序部分,我有:

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

沒有在其他任何地方找到這個。

[編輯]更清楚地了解這里發生了什么:這僅適用於 python 代碼,並且使用 python 的內置日志記錄模塊。 該模塊允許配置日志消息的格式和目的地。 配置日志格式和目標的一種方法是使用用於配置日志記錄的 JSON 文件。

上面的示例允許我將日志消息發送到系統日志守護進程。

下面包含此類文件的完整示例。

{
    "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"
        }
    }
}

上面的示例將 python 日志消息發送到系統日志和控制台。 目的地的消息格式不同(系統日志已經為每條消息加上時間戳作為前綴)。 對於系統日志目標,日志使用設施 LOCAL6。

我在筆記本上修好了。 rsyslog服務沒有偵聽套接字服務。

我在/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