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
syslogメッセージをどこで確認していますか?SysLogHandler()は、これらのメッセージをローカルホストのポート514のudpソケットに送信します。
スザンシャキャ

あなたは絶対的に正しいです。そして私は「localhostの-514」ドキュメントのことを見てきたけど...ため息...の/ dev /ログは、デフォルトで使用されるべきであることを考えていない
トール

回答:


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


3
どうすればこれらのログをsyslogで識別できますか?アプリケーション名や、syslogtag = djangoのようなタグを付けることができますか?
Luv33preet 2017年

/etc/syslog.d/confファイルの構成を覚えて、syslog / rsyslogサービスを再起動します
linrongbin

5
@ Luv33preet私は、のようなフォーマッターを使用して(そうではなくなく)、動作のlogging.Formatter(fmt='myscriptname[%(process)d]: %(levelname)s: %(message)s', ...)ようなrsyslog条件 をテストしました$programname == 'myscriptname'
ピーター

26

TCPスタックを介した/ dev / logまたはlocalhostのいずれであっても、ログには常にローカルホストを使用する必要があります。これにより、完全にRFCに準拠した機能的なシステムロギングデーモンがsyslogを処理できるようになります。これにより、リモートデーモンが機能する必要がなくなり、rsyslogやsyslog-ngなどのsyslogデーモンの拡張機能が提供されます。同じ哲学がSMTPにも当てはまります。ローカルのSMTPソフトウェアに渡すだけです。この場合、デーモンではなく「プログラムモード」を使用しますが、同じ考え方です。より有能なソフトウェアで処理してください。再試行、キューイング、ローカルスプーリング、syslogのUDPではなくTCPの使用などが可能になります。また、必要に応じて、これらのデーモンをコードとは別に[再]構成することもできます。

アプリケーションのコーディングを保存し、他のソフトウェアが協調してそれを実行できるようにします。


2
あなたは公正なポイントを上げます。さまざまなロギングデーモンが使用する共通のアドレスとポートを指定できますか?デーモンがtcpソケットにバインドされているかどうかを判断する標準の検出メカニズムはありますか?
init_js 2018

完全にあなたと同意します。
DAKS

20

私が見つかりましたsyslogのモジュールを使用すると、記述し、基本的なロギング動作を得るために非常に簡単にそれを作るために:

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

他にもできることはありますが、最初の2行だけでも、私が理解しているとおりに、求められていることがわかります。


すべてのステートメントに影響を与えることなくロガー設定を変更できるため、ロギングモジュールを保持しています。同時にさまざまなタイプのロギングが必要な場合に動作を変更することもできます
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)

また、/ dev / logの代わりにlocalhostを使用するには、syslogでUDPをリッスンする必要があります。


3
syslogをUDPでリッスンする必要はありません。あなたの例は、address = '/ dev / log'でも完全に機能します。
2012年

5
はい、確かですが、address =( 'localhost'、514)で、ログサーバーがある日、localhostをサーバーのアドレスに置き換え、リモートログを取得します;-)
Oliver Henriot

5
facility = 19はどこから来たのですか?なぜそれがfacility = "local3"ではないのですか
boatcoder 2013年

4
@ Mark0978 19は、RFC3146(およびその後RFC5424)で定義されたlocal3の数値表現です
Andrew Sledge

3
私もこれについて不思議に思い、ファシリティコードがPythonのSysLogHandlerの
clebio

11

syslog.confはfacility = userを処理するように設定されていますか?

Pythonロガーが使用する機能は、次のようにfacility引数で設定できます。

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

パラメータのLOG_DAEMON値として提供するものを指定する必要がありfacilityます。
tzot

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
あなたのコメントは、元の要求とは何の関係もありません
トール

@thor私はこれが関連していることに同意します。syslogパッケージは純粋なPython実装よりも少し効率的だと思いますか?(柔軟性が低い場合)
Daniel Santos

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)では機能しません:トレースバック(最後の最後の呼び出し):ファイル "syslog_bridge.py"、68行目、<module> handlers.append(SysLogLibHandler(logFacilityLocalN ))ファイル "syslog_bridge.py"、29行目、init syslog.openlog(syslog.LOG_PID、self.FACILITY [n])TypeError:ident string [、logoption [、facility]]
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)

syslogと直接ファイルの両方を構成しました。/dev/logはOS固有であることに注意してください。


1

ノートブックで修正します。rsyslogサービスはソケットサービスをリッスンしませんでした。

私はこの行を/etc/rsyslog.confファイルに以下のように設定し 、問題を解決しました:

$SystemLogSocketName /dev/log


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.