web-dev-qa-db-ja.com

PythonログインDjango

Python Djangoに満足していることをログに記録する方法を設定する方法をまだ見つけていません。私の要件はかなり単純です。

  • さまざまなイベントのさまざまなログハンドラー-つまり、さまざまなファイルにログを記録できるようにしたい
  • モジュール内のロガーに簡単にアクセスできます。モジュールは、少しの労力でロガーを見つけることができるはずです。
  • コマンドラインモジュールに簡単に適用できる必要があります。システムの一部は、スタンドアロンのコマンドラインまたはデーモンプロセスです。ロギングはこれらのモジュールで簡単に使用できるはずです。

私の現在の設定は、logging.confファイルおよびセットアップログは、各モジュールからログに記録します。気分が悪い。

好きなロギング設定がありますか?詳細を教えてください:構成をどのようにセットアップしますか(logging.confまたはコードで設定)、ロガーを開始する場所とタイミング、およびモジュール内でロガーにアクセスする方法など。

93
Parand

私がこれまでに見つけた最良の方法は、settings.pyでロギング設定を初期化することです。他にはありません。構成ファイルを使用することも、プログラムで段階的に実行することもできます。要件に応じて異なります。重要なことは、通常、レベルと時々logging.Filtersを使用して、必要なハンドラーをルートロガーに追加することです。適切なファイル、コンソール、syslogなどに必要なイベントを取得します。もちろん、他のロガーにハンドラーを追加できますでも、私の経験ではこれは一般的に必要ありません。

各モジュールで、ロガーを定義します

_logger = logging.getLogger(__name__)
_

そして、モジュール内のイベントのロギングに使用します(さらに区別したい場合は、上記で作成したロガーの子であるロガーを使用します)。

Settings.pyへのログインを設定しないサイトでアプリを使用する可能性がある場合、次のようにNullHandlerを定義します。

_#someutils.py

class NullHandler(logging.Handler):
    def emit(self, record):
        pass

null_handler = NullHandler()
_

ロギングを使用する私のアプリのモジュールで作成されたすべてのロガーにそのインスタンスが追加されていることを確認してください。 (注:NullHandlerはすでにPython 3.1のロギングパッケージに含まれており、Python 2.7になります。)

_logger = logging.getLogger(__name__)
logger.addHandler(someutils.null_handler)
_

これは、settings.pyでログインを設定していないサイトでモジュールが適切に再生され、迷惑な「ロガーXYZのハンドラーが見つかりません」というメッセージ(潜在的に警告である)が表示されないようにするためです。誤って設定されたロギング)。

この方法で行うと、指定された要件を満たします。

  • 現在のように、イベントごとに異なるログハンドラーを設定できます。
  • モジュール内のロガーに簡単にアクセスできます-getLogger(__name__)を使用します。
  • コマンドラインモジュールに簡単に適用できます-_settings.py_もインポートします。

更新:バージョン1.3以降、Djangoには ロギングのサポート が組み込まれています。

53
Vinay Sajip

これはすでに解決済みの回答であることは知っていますが、Django> = 1.3のとおり、新しいログ設定があります。

古いものから新しいものへの移動は自動ではないため、ここに書き留めておきます。

そしてもちろん、チェックアウト Django doc もう少し。

これは、Django-admin createproject v1.3でデフォルトで作成される基本的な設定です。最新のDjangoバージョンでは燃費が変わる可能性があります。

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'class': 'Django.utils.log.AdminEmailHandler',
        }
    },
    'loggers': {
        'Django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        }
    }
}

この構造は、標準 Python logging dictConfig に基づいており、次のブロックを指示します。

  • formatters-対応する値は、各キーがフォーマッタIDであり、各値が対応するフォーマッタインスタンスの構成方法を説明する辞書である辞書です。
  • filters-対応する値は、各キーがフィルターIDであり、各値が対応するフィルターインスタンスの構成方法を説明する辞書である辞書です。
  • handlers-対応する値は、各キーがハンドラーIDであり、各値が対応するHandlerインスタンスを構成する方法を説明する辞書である辞書です。各ハンドラには次のキーがあります。

    • class(必須)。これは、ハンドラクラスの完全修飾名です。
    • level(オプション)。ハンドラーのレベル。
    • formatter(オプション)。このハンドラーのフォーマッターのID。
    • filters(オプション)。このハンドラーのフィルターのIDのリスト。

私は通常、少なくともこれを行います:

  • .logファイルを追加する
  • このログに書き込むようにアプリを構成する

次のように変換されます:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    },
    'filters': {
        'require_debug_false': {
            '()': 'Django.utils.log.RequireDebugFalse'
        }
    },
    'handlers': {
        'null': {
            'level':'DEBUG',
            'class':'Django.utils.log.NullHandler',
        },
        'console':{
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        # I always add this handler to facilitate separating loggings
        'log_file':{
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(VAR_ROOT, 'logs/Django.log'),
            'maxBytes': '16777216', # 16megabytes
            'formatter': 'verbose'
        },
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'Django.utils.log.AdminEmailHandler',
            'include_html': True,
        }
    },
    'loggers': {
        'Django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
        'apps': { # I keep all my of apps under 'apps' folder, but you can also add them one by one, and this depends on how your virtualenv/paths are set
            'handlers': ['log_file'],
            'level': 'INFO',
            'propagate': True,
        },
    },
    # you can also shortcut 'loggers' and just configure logging for EVERYTHING at once
    'root': {
        'handlers': ['console', 'mail_admins'],
        'level': 'INFO'
    },
}

編集

リクエストの例外は常にログに記録される および チケット#16288 を参照してください。

上記のサンプルconfを更新して、mail_adminsの正しいフィルターを明示的に含めて、デフォルトでは、デバッグがTrueの場合に電子メールが送信されないようにしました。

フィルターを追加する必要があります。

'filters': {
    'require_debug_false': {
        '()': 'Django.utils.log.RequireDebugFalse'
    }
},

それをmail_adminsハンドラーに適用します。

    'mail_admins': {
        'level': 'ERROR',
        'filters': ['require_debug_false'],
        'class': 'Django.utils.log.AdminEmailHandler',
        'include_html': True,
    }

それ以外の場合、settings.DEBUGがTrueの場合、Django.core.handers.base.handle_uncaught_exceptionは 'Django.request'ロガーにエラーを渡しません。

Django 1.5でこれを行わないと、

DeprecationWarning: 'mail_admins'ロギングハンドラーにフィルターが定義されていません:暗黙的なdebug-false-onlyフィルターを追加します

しかし、Django 1.4とDjango 1.5の両方で物事はまだ正しく動作します。

**編集の終了**

このconfは、Django docのサンプルconfに強く影響を受けていますが、ログファイルの部分を追加しています。

私は次のこともよくします:

LOG_LEVEL = 'DEBUG' if DEBUG else 'INFO'

...
    'level': LOG_LEVEL
...

その後、ロギングconfがまったく定義されていない場合に備えて、pythonコードで常にNullHandlerを追加します。これにより、ハンドラが指定されていない場合の警告が回避されます。 Django( ref )でのみ呼び出されるとは限らないライブラリに特に便利です。

import logging
# Get an instance of a logger
logger = logging.getLogger(__name__)
class NullHandler(logging.Handler): #exists in python 3.1
    def emit(self, record):
        pass
nullhandler = logger.addHandler(NullHandler())

# here you can also add some local logger should you want: to stdout with streamhandler, or to a local file...

[...]

logger.warning('etc.etc.')

お役に立てれば!

121
Stefano

urls.pyファイルを使用して、最上位のlogging.iniでロギングを初期化します。

logging.iniの場所はsettings.pyで提供されますが、それだけです。

その後、各モジュールは

logger = logging.getLogger(__name__)

テスト、開発、および実稼働インスタンスを区別するために、異なるlogging.iniファイルがあります。ほとんどの場合、エラーのみでstderrに送信される「コンソールログ」があります。ログディレクトリに移動する通常のローリングログファイルを使用する「アプリケーションログ」があります。

8
S.Lott

現在、自分で作成したロギングシステムを使用しています。ロギングにはCSV形式を使用します。

Django-csvlog

このプロジェクトにはまだ完全なドキュメントがありませんが、私はそれに取り組んでいます。

6
Oduvan