web-dev-qa-db-ja.com

Djangoデフォルトのロギングのセットアップ

私のDjangoインストールのために「デフォルト」ロガーをセットアップする方法を理解できないようです。私はDjango 1.3の新しいLOGGINGsettings.pyの設定。

Django Logging Docの例 を見ましたが、特定のロガーのロギングを行うハンドラーのみをセットアップしているように見えます。それらの例の場合、「Django」、「Django.request」、および「myproject.custom」という名前のロガーのハンドラーをセットアップします。

私がしたいことは、デフォルトですべてのロガーを処理するデフォルトのlogging.handlers.RotatingFileHandlerをセットアップすることだけです。つまり、プロジェクトのどこかに新しいモジュールを作成し、それがmy_app_name.my_new_moduleのようなもので示されている場合、これを行うことができ、すべてのログを回転ファイルログに移動する必要があります。

# In file './my_app_name/my_new_module.py'
import logging
logger = logging.getLogger('my_app_name.my_new_module')
logger.debug('Hello logs!') # <-- This should get logged to my RotatingFileHandler that I setup in `settings.py`!
93
Chris W.

理解した...

'catch all'ロガーを設定するには、空の文字列''で参照します。

例として、次の設定では、logs/mylog.logに保存されるDjango.requestログイベントを除き、すべてのログイベントがlogs/Django_request.logに保存されます。 'propagate'Django.requestロガーのFalseに設定されているため、ログイベントは「すべてをキャッチ」ロガーに到達しません。

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': {
        'default': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/mylog.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },  
        'request_handler': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/Django_request.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },
    },
    'loggers': {
        '': {
            'handlers': ['default'],
            'level': 'DEBUG',
            'propagate': True
        },
        'Django.request': {
            'handlers': ['request_handler'],
            'level': 'DEBUG',
            'propagate': False
        },
    }
}
147
Chris W.

答え で述べたように、クリス、デフォルトのロガーを定義する1つのオプションは、空の文字列をキーとして使用することです。

しかし、意図した方法は、ロギング構成辞書のrootキーの下に特別なロガーを定義することだと思います。これは Pythonドキュメント で見つけました。

root-これはルートロガーの設定になります。構成の処理は、propagate設定が適用されないことを除いて、他のロガーと同じです。

rootキーを使用するように変更された回答の構成は次のとおりです。

_LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': {
        'default': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/mylog.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },  
        'request_handler': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/Django_request.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },
    },
    'root': {
        'handlers': ['default'],
        'level': 'DEBUG'
    },
    'loggers': {
        'Django.request': {
            'handlers': ['request_handler'],
            'level': 'DEBUG',
            'propagate': False
        },
    }
}
_

公平を期すために、2つの構成の動作に違いはありません。 logging.getLogger('') がルートロガーを返すため、空の文字列キーでロガーを定義するとルートロガーが変更されるようです。

私が_'root'_よりも_''_を好む唯一の理由は、ルートロガーの変更について明示的であるということです。好奇心が強い場合、両方を定義すると、ルートエントリが最後に処理されるという理由だけで_'root'_が_''_をオーバーライドします。

22
Don Kirkby
import logging
logger = logging.getLogger(__name__)

追加後:

logging.basicConfig(
    level = logging.DEBUG,
    format = '%(name)s %(levelname)s %(message)s',
)

形式を次のように変更する場合があります。

format = '"%(levelname)s:%(name)s:%(message)s"  ',

または

format = '%(name)s %(asctime)s %(levelname)s %(message)s',
0
Sérgio

rootキーと空の''ロガーの両方がconfig dictで参照されている場合に使用される構成を確認する簡単なサンプルを作成しました。

import logging.config

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'fmt1': {
            'format': '[FMT1] %(asctime)-15s %(message)s',
        },
        'fmt2': {
            'format': '[FMT2] %(asctime)-15s %(message)s',
        }
    },
    'handlers': {
        'console1': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'fmt1',
        },
        'console2': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'fmt2',
        },
    },
    # First config for root logger: console1 -> fmt1
    'root': {
        'handlers': ['console1'],
        'level': 'DEBUG',
        'propagate': True,
    },
    'loggers': {
        # Second config for root logger: console2 -> fmt2
        '': {
            'handlers': ['console2'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

logging.config.dictConfig(LOGGING)

l1 = logging.getLogger()
l2 = logging.getLogger('')
root = logging.root

l1.info("l1")
l2.info("l2")
root.info("root logger")

次の結果を出力します。

[FMT1] 2018-12-18 17:24:47,691 l1
[FMT1] 2018-12-18 17:24:47,691 l2
[FMT1] 2018-12-18 17:24:47,691 root logger

rootキーの下の構成の優先度が最も高いことを示します。ブロックが削除されると、結果は次のようになります。

[FMT2] 2018-12-18 17:25:43,757 l1
[FMT2] 2018-12-18 17:25:43,757 l2
[FMT2] 2018-12-18 17:25:43,757 root logger

どちらの場合でも、3つのすべてのロガー(l1l2、およびroot)が同じロガーインスタンスであるルートロガーを参照していることをデバッグおよび判断できました。

私のように、ルートロガーを設定する2つの異なる方法に混乱していた他の人の助けになることを願っています。

0
Antwane