ロギング
クイックロギング入門書
Djangoは、Pythonの組み込みlogging
モジュールを使用してシステムロギングを実行します。 このモジュールの使用法については、Python独自のドキュメントで詳しく説明されています。 ただし、Pythonのロギングフレームワークを使用したことがない場合(または使用している場合でも)、ここに簡単な入門書があります。
選手のキャスト
Pythonロギング構成は、次の4つの部分で構成されています。
ロガー
ロガーは、ロギングシステムへのエントリポイントです。 各ロガーは、処理のためにメッセージを書き込むことができる名前付きバケットです。
ロガーは、ログレベルを持つように構成されています。 このログレベルは、ロガーが処理するメッセージの重大度を示します。 Pythonは、次のログレベルを定義しています。
DEBUG
:デバッグ用の低レベルのシステム情報INFO
:一般的なシステム情報WARNING
:発生した軽微な問題を説明する情報。ERROR
:発生した主要な問題を説明する情報。CRITICAL
:発生した重大な問題を説明する情報。
ロガーに書き込まれる各メッセージは、ログレコードです。 各ログレコードには、その特定のメッセージの重大度を示すログレベルもあります。 ログレコードには、ログに記録されているイベントを説明する有用なメタデータを含めることもできます。 これには、スタックトレースやエラーコードなどの詳細が含まれる場合があります。
メッセージがロガーに渡されると、メッセージのログレベルがロガーのログレベルと比較されます。 メッセージのログレベルがロガー自体のログレベル以上の場合、メッセージはさらに処理されます。 そうでない場合、メッセージは無視されます。
ロガーがメッセージを処理する必要があると判断すると、そのメッセージはハンドラーに渡されます。
ハンドラー
ハンドラーは、ロガー内の各メッセージに何が起こるかを決定するエンジンです。 画面、ファイル、またはネットワークソケットへのメッセージの書き込みなど、特定のロギング動作について説明します。
ロガーと同様に、ハンドラーにもログレベルがあります。 ログレコードのログレベルがハンドラーのレベルを満たしていないか超えていない場合、ハンドラーはメッセージを無視します。
ロガーは複数のハンドラーを持つことができ、各ハンドラーは異なるログレベルを持つことができます。 このようにして、メッセージの重要性に応じてさまざまな形式の通知を提供することができます。 たとえば、ERROR
およびCRITICAL
メッセージをページングサービスに転送する1つのハンドラーをインストールし、2番目のハンドラーがすべてのメッセージ(ERROR
および [X181Xを含む)をログに記録することができます。 ]メッセージ)後で分析するためにファイルに。
フィルタ
フィルタは、どのログレコードがロガーからハンドラーに渡されるかをさらに制御するために使用されます。
デフォルトでは、ログレベルの要件を満たすすべてのログメッセージが処理されます。 ただし、フィルターをインストールすることにより、ロギングプロセスに追加の基準を設定できます。 たとえば、特定のソースからのERROR
メッセージのみを送信できるようにするフィルターをインストールできます。
フィルタを使用して、発行される前にログレコードを変更することもできます。 たとえば、特定の基準セットが満たされた場合に、ERROR
ログレコードをWARNING
レコードにダウングレードするフィルターを作成できます。
フィルタはロガーまたはハンドラーにインストールできます。 複数のフィルターをチェーンで使用して、複数のフィルタリングアクションを実行できます。
フォーマッター
最終的に、ログレコードはテキストとしてレンダリングする必要があります。 フォーマッターは、そのテキストの正確なフォーマットを記述します。 フォーマッターは通常、 LogRecord属性を含むPythonフォーマット文字列で構成されます。 ただし、特定のフォーマット動作を実装するカスタムフォーマッターを作成することもできます。
ロギングの使用
ロガー、ハンドラー、フィルター、フォーマッターを構成したら、コードにロギング呼び出しを行う必要があります。 ロギングフレームワークの使用は次のように機能します。
# import the logging library
import logging
# Get an instance of a logger
logger = logging.getLogger(__name__)
def my_view(request, arg1, arg):
...
if bad_mojo:
# Log an error message
logger.error('Something went wrong!')
以上です! bad_mojo
条件がアクティブになるたびに、エラーログレコードが書き込まれます。
ロガーの命名
logging.getLogger()
を呼び出すと、ロガーのインスタンスが取得されます(必要に応じて作成されます)。 ロガーインスタンスは名前で識別されます。 この名前は、構成の目的でロガーを識別するために使用されます。
慣例により、ロガー名は通常__name__
であり、ロガーを含むPythonモジュールの名前です。 これにより、モジュールごとにロギング呼び出しをフィルタリングおよび処理できます。 ただし、ロギングメッセージを整理する他の方法がある場合は、ロガーを識別するためにドットで区切った名前を指定できます。
# Get an instance of a specific named logger
logger = logging.getLogger('project.interesting.stuff')
ロガー名の点線のパスは階層を定義します。 project.interesting
ロガーは、project.interesting.stuff
ロガーの親と見なされます。 project
ロガーはproject.interesting
ロガーの親です。
階層が重要なのはなぜですか? ロガーは、親へのロギング呼び出しを伝搬に設定できるためです。 このようにして、ロガーツリーのルートでハンドラーの単一のセットを定義し、ロガーのサブツリー内のすべてのロギング呼び出しをキャプチャできます。 project
名前空間で定義されたロガーは、project.interesting
およびproject.interesting.stuff
ロガーで発行されたすべてのログメッセージをキャッチします。
この伝播は、ロガーごとに制御できます。 特定のロガーをその親に伝播させたくない場合は、この動作をオフにすることができます。
ロギングコールを行う
ロガーインスタンスには、デフォルトのログレベルごとのエントリメソッドが含まれています。
logger.debug()
logger.info()
logger.warning()
logger.error()
logger.critical()
利用可能な他の2つのロギング呼び出しがあります。
logger.log()
:特定のログレベルのログメッセージを手動で送信します。logger.exception()
:現在の例外スタックフレームをラップするERROR
レベルのログメッセージを作成します。
ロギングの構成
ロギング呼び出しをコードに入れるだけでは十分ではありません。 また、ロギング出力を使用できるように、ロガー、ハンドラー、フィルター、およびフォーマッターを構成する必要があります。
Pythonのロギングライブラリは、プログラムインターフェイスから構成ファイルに至るまで、ロギングを構成するためのいくつかの手法を提供します。 デフォルトでは、Djangoは dictConfigフォーマットを使用します。
ロギングを構成するには、:setting: `LOGGING` を使用してロギング設定の辞書を定義します。 これらの設定は、ログ設定に必要なロガー、ハンドラー、フィルター、フォーマッター、およびこれらのコンポーネントに必要なログレベルとその他のプロパティを記述します。
デフォルトでは、:setting: `LOGGING` 設定は、次のスキームを使用して Djangoのデフォルトのロギング構成とマージされます。
:setting: `LOGGING` dictConfigのdisable_existing_loggers
キーがTrue
に設定されている場合(キーがない場合はdictConfig
のデフォルトです)その後、デフォルト構成のすべてのロガーが無効になります。 無効にされたロガーは、削除されたものと同じではありません。 ロガーは引き続き存在しますが、ログに記録されたものはすべてサイレントに破棄され、親ロガーにエントリを伝播することさえありません。 したがって、'disable_existing_loggers': True
の使用には十分注意する必要があります。 それはおそらくあなたが望むものではありません。 代わりに、disable_existing_loggers
をFalse
に設定して、デフォルトのロガーの一部またはすべてを再定義できます。 または、:setting: `LOGGING_CONFIG` をNone
に設定し、ログ設定を自分で処理することができます。
ロギングは、一般的なDjango setup()
機能の一部として構成されます。 したがって、ロガーは常にプロジェクトコードで使用する準備ができていると確信できます。
例
dictConfig形式の完全なドキュメントは、構成辞書のロギングに関する最良の情報源です。 ただし、可能なことを味わうために、いくつかの例を示します。
まず、すべてのログメッセージをコンソールに出力できるようにする小さな構成を次に示します。
import os
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'root': {
'handlers': ['console'],
'level': 'WARNING',
},
}
これにより、親root
ロガーが、WARNING
レベル以上のメッセージをコンソールハンドラーに送信するように構成されます。 レベルをINFO
またはDEBUG
に調整すると、より多くのメッセージを表示できます。 これは、開発中に役立つ場合があります。
次に、よりきめ細かいロギングを追加できます。 これは、ロギングシステムに django という名前のロガーからより多くのメッセージを出力させる方法の例です。
import os
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'root': {
'handlers': ['console'],
'level': 'WARNING',
},
'loggers': {
'django': {
'handlers': ['console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
'propagate': False,
},
},
}
デフォルトでは、この設定はレベルINFO
以上のdjango
ロガーからコンソールにメッセージを送信します。 これは、Djangoのデフォルトのログ設定と同じレベルですが、デフォルトの設定では、DEBUG=True
の場合にのみログレコードが表示されます。 Djangoは、そのようなINFO
レベルのメッセージをあまりログに記録しません。 ただし、この構成では、環境変数DJANGO_LOG_LEVEL=DEBUG
を設定して、すべてのデータベースクエリが含まれているため非常に冗長なDjangoのすべてのデバッグログを表示することもできます。
コンソールにログインする必要はありません。 django という名前のロガーからのすべてのログをローカルファイルに書き込む構成は次のとおりです。
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': '/path/to/django/debug.log',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'DEBUG',
'propagate': True,
},
},
}
この例を使用する場合は、'filename'
パスを、Djangoアプリケーションを実行しているユーザーが書き込み可能な場所に変更してください。
最後に、かなり複雑なログ設定の例を次に示します。
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
'simple': {
'format': '{levelname} {message}',
'style': '{',
},
},
'filters': {
'special': {
'()': 'project.logging.SpecialFilter',
'foo': 'bar',
},
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'handlers': {
'console': {
'level': 'INFO',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'filters': ['special']
}
},
'loggers': {
'django': {
'handlers': ['console'],
'propagate': True,
},
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': False,
},
'myproject.custom': {
'handlers': ['console', 'mail_admins'],
'level': 'INFO',
'filters': ['special']
}
}
}
このログ構成は、次のことを行います。
構成が「dictConfigバージョン1」形式であることを識別します。 現在、これは唯一のdictConfig形式のバージョンです。
2つのフォーマッタを定義します。
simple
、ログレベル名(例:DEBUG
)とログメッセージを出力します。format
文字列は、各ロギング行に出力される詳細を説明する通常のPythonフォーマット文字列です。 出力できる詳細の完全なリストは、 formatter-objects にあります。verbose
は、ログレベル名、ログメッセージに加えて、ログメッセージを生成する時間、プロセス、スレッド、およびモジュールを出力します。
2つのフィルターを定義します。
project.logging.SpecialFilter
、エイリアスspecial
を使用。 このフィルターに追加の引数が必要な場合は、フィルター構成ディクショナリで追加のキーとして提供できます。 この場合、SpecialFilter
をインスタンス化するときに、引数foo
にはbar
の値が与えられます。django.utils.log.RequireDebugTrue
。:setting: `DEBUG` がTrue
の場合にレコードを渡します。
2つのハンドラーを定義します。
console
、StreamHandler
、INFO
(またはそれ以上)のメッセージをsys.stderr
に出力します。 このハンドラーは、simple
出力形式を使用します。mail_admins
、 AdminEmailHandler 、ERROR
(またはそれ以降)のメッセージをサイト:setting: `ADMINS` に電子メールで送信します。 このハンドラーはspecial
フィルターを使用します。
3つのロガーを構成します。
django
は、すべてのメッセージをconsole
ハンドラーに渡します。django.request
。すべてのERROR
メッセージをmail_admins
ハンドラーに渡します。 さらに、このロガーはメッセージを伝播しないようにマークされています。 これは、django.request
に書き込まれたログメッセージがdjango
ロガーによって処理されないことを意味します。myproject.custom
は、INFO
以上のすべてのメッセージを渡し、special
フィルターもconsole
とmail_admins
の2つのハンドラーに渡します。 。 これは、すべてのINFO
レベルのメッセージ(またはそれ以上)がコンソールに出力されることを意味します。ERROR
およびCRITICAL
メッセージも電子メールで出力されます。
カスタムログ構成
PythonのdictConfig形式を使用してロガーを構成したくない場合は、独自の構成スキームを指定できます。
:setting: `LOGGING_CONFIG` 設定は、Djangoのロガーを構成するために使用される呼び出し可能オブジェクトを定義します。 デフォルトでは、Pythonのlogging.config.dictConfig()
関数を指します。 ただし、別の構成プロセスを使用する場合は、単一の引数を取る他の呼び出し可能オブジェクトを使用できます。 :setting: `LOGGING` の内容は、ロギングが構成されているときにその引数の値として提供されます。
ロギング構成の無効化
ロギングをまったく構成したくない場合(または独自のアプローチを使用して手動でロギングを構成したい場合)、:setting: `LOGGING_CONFIG` をNone
に設定できます。 これにより、 Djangoのデフォルトのログの構成プロセスが無効になります。
:setting: `LOGGING_CONFIG` をNone
に設定すると、自動構成プロセスが無効になり、ログ自体は無効になります。 構成プロセスを無効にしても、Djangoは引き続きロギング呼び出しを行い、定義されているデフォルトのロギング動作にフォールバックします。
Djangoのロギング構成を無効にしてから、手動でロギングを構成する例を次に示します。
LOGGING_CONFIG = None
import logging.config
logging.config.dictConfig(...)
デフォルトの構成プロセスでは、設定が完全にロードされた後にのみ:setting: `LOGGING_CONFIG` が呼び出されることに注意してください。 対照的に、設定ファイルでログを手動で構成すると、ログ構成がすぐに読み込まれます。 そのため、ログ設定は、依存するすべての設定の後に表示される必要があります。
Djangoのロギング拡張機能
Djangoは、Webサーバー環境でのロギングの固有の要件を処理するための多数のユーティリティを提供します。
ロガー
Djangoにはいくつかの組み込みロガーが用意されています。
django
django
階層内のメッセージのキャッチオールロガー。 この名前を使用してメッセージは投稿されませんが、代わりに以下のロガーの1つを使用して投稿されます。
django.request
リクエストの処理に関連するメッセージをログに記録します。 5XX応答は、ERROR
メッセージとして発生します。 4XX応答は、WARNING
メッセージとして発生します。 django.security
ロガーに記録された要求は、django.request
に記録されません。
このロガーへのメッセージには、次の追加のコンテキストがあります。
status_code
:リクエストに関連付けられたHTTP応答コード。request
:ロギングメッセージを生成したリクエストオブジェクト。
django.server
:djadmin: `runserver` コマンドによって呼び出されたサーバーが受信した要求の処理に関連するメッセージをログに記録します。 HTTP5XX応答はERROR
メッセージとしてログに記録され、4XX応答はWARNING
メッセージとしてログに記録され、その他はすべてINFO
としてログに記録されます。
このロガーへのメッセージには、次の追加のコンテキストがあります。
status_code
:リクエストに関連付けられたHTTP応答コード。request
:ロギングメッセージを生成したリクエストオブジェクト。
django.template
テンプレートのレンダリングに関連するログメッセージ。
- 欠落しているコンテキスト変数は、
DEBUG
メッセージとしてログに記録されます。
django.db.backends
コードとデータベースの相互作用に関連するメッセージ。 たとえば、リクエストによって実行されるすべてのアプリケーションレベルのSQLステートメントは、DEBUG
レベルでこのロガーに記録されます。
このロガーへのメッセージには、次の追加のコンテキストがあります。
duration
:SQLステートメントの実行にかかった時間。sql
:実行されたSQLステートメント。params
:SQL呼び出しで使用されたパラメーター。
パフォーマンス上の理由から、SQLロギングは、インストールされているロギングレベルやハンドラーに関係なく、settings.DEBUG
がTrue
に設定されている場合にのみ有効になります。
このロギングには、フレームワークレベルの初期化は含まれていません(例: SET TIMEZONE
)またはトランザクション管理クエリ(例: BEGIN
、COMMIT
、およびROLLBACK
)。 すべてのデータベースクエリを表示する場合は、データベースでクエリログをオンにします。
django.security.*
セキュリティロガーは、 SuspiciousOperation およびその他のセキュリティ関連のエラーが発生したときにメッセージを受信します。 すべてのSuspiciousOperation
を含む、セキュリティエラーのサブタイプごとにサブロガーがあります。 ログイベントのレベルは、例外が処理される場所によって異なります。 ほとんどの発生は警告としてログに記録されますが、WSGIハンドラーに到達したSuspiciousOperation
はエラーとしてログに記録されます。 たとえば、HTTP Host
ヘッダーが:setting: `ALLOWED_HOSTS` と一致しないクライアントからのリクエストに含まれている場合、Djangoは400レスポンスを返し、エラーメッセージはdjango.security.DisallowedHost
ロガーに記録されます。
これらのログイベントは、デフォルトでdjango
ロガーに到達し、DEBUG=False
のときにエラーイベントを管理者にメールで送信します。 SuspiciousOperation
が原因で400応答になるリクエストは、django.request
ロガーには記録されず、django.security
ロガーにのみ記録されます。
特定のタイプのSuspiciousOperation
を消音するには、次の例に従って、その特定のロガーをオーバーライドできます。
'handlers': {
'null': {
'class': 'logging.NullHandler',
},
},
'loggers': {
'django.security.DisallowedHost': {
'handlers': ['null'],
'propagate': False,
},
},
SuspiciousOperation
に基づかないその他のdjango.security
ロガーは次のとおりです。
django.security.csrf
: CSRF障害の場合。
django.db.backends.schema
移行フレームワークによるデータベースへのスキーマ変更中に実行されたSQLクエリをログに記録します。 RunPython によって実行されたクエリはログに記録されないことに注意してください。 このロガーへのメッセージには、追加のコンテキストにparams
とsql
があります(ただし、django.db.backends
とは異なり、継続時間ではありません)。 値は、 django.db.backends で説明されているのと同じ意味を持ちます。
ハンドラー
Djangoは、Pythonロギングモジュールによって提供されるものに加えて、1つのログハンドラーを提供します。
- class AdminEmailHandler(include_html=False, email_backend=None, reporter_class=None)
このハンドラーは、受信したログメッセージごとにサイト:setting: `ADMINS` に電子メールを送信します。
ログレコードに
request
属性が含まれている場合、リクエストの完全な詳細が電子メールに含まれます。 クライアントのIPアドレスが:setting: `INTERNAL_IPS` 設定にある場合、電子メールの件名には「内部IP」というフレーズが含まれます。 そうでない場合は、「EXTERNALIP」が含まれます。ログレコードにスタックトレース情報が含まれている場合、そのスタックトレースは電子メールに含まれます。
AdminEmailHandler
のinclude_html
引数は、:setting: `DEBUGの場合に生成されるデバッグWebページの全コンテンツを含むHTML添付ファイルをトレースバック電子メールに含めるかどうかを制御するために使用されます。 `はTrue
でした。 構成でこの値を設定するには、次のようにdjango.utils.log.AdminEmailHandler
のハンドラー定義にこの値を含めます。'handlers': { 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', 'include_html': True, } },
このHTMLバージョンの電子メールには、スタックの各レベルのローカル変数の名前と値、およびDjango設定の値を含む完全なトレースバックが含まれていることに注意してください。 この情報は非常に機密性が高い可能性があるため、電子メールで送信したくない場合があります。 Sentry などを使用して、両方の世界を最大限に活用することを検討してください。完全なトレースバックの豊富な情報に加えて、電子メールで情報を送信しないのセキュリティです。 エラーレポートから除外する特定の機密情報を明示的に指定することもできます。詳細については、エラーレポートのフィルタリングを参照してください。
AdminEmailHandler
のemail_backend
引数を設定することにより、ハンドラーによって使用されているメールバックエンドを次のようにオーバーライドできます。'handlers': { 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', 'email_backend': 'django.core.mail.backends.filebased.EmailBackend', } },
デフォルトでは、:setting: `EMAIL_BACKEND` で指定されたメールバックエンドのインスタンスが使用されます。
AdminEmailHandler
のreporter_class
引数を使用すると、django.views.debug.ExceptionReporter
サブクラスを提供して、電子メール本文で送信されるトレースバックテキストをカスタマイズできます。 次のように、使用するクラスへの文字列インポートパスを指定します。'handlers': { 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', 'include_html': True, 'reporter_class': 'somepackage.error_reporter.CustomErrorReporter' } },
- send_mail(subject, message, *args, **kwargs)
管理者ユーザーにメールを送信します。 この動作をカスタマイズするには、 AdminEmailHandler クラスをサブクラス化し、このメソッドをオーバーライドします。
フィルタ
Djangoは、Pythonロギングモジュールによって提供されるものに加えて、いくつかのログフィルターを提供します。
- class CallbackFilter(callback)
このフィルターは、コールバック関数(単一の引数、ログに記録されるレコードを受け入れる必要があります)を受け入れ、フィルターを通過するレコードごとに呼び出します。 コールバックがFalseを返した場合、そのレコードの処理は続行されません。
たとえば、管理者の電子メールから Un読み取り可能PostError (ユーザーがアップロードをキャンセルしたときに発生)をフィルターで除外するには、フィルター関数を作成します。
from django.http import UnreadablePostError def skip_unreadable_post(record): if record.exc_info: exc_type, exc_value = record.exc_info[:2] if isinstance(exc_value, UnreadablePostError): return False return True
次に、それをロギング構成に追加します。
'filters': { 'skip_unreadable_posts': { '()': 'django.utils.log.CallbackFilter', 'callback': skip_unreadable_post, } }, 'handlers': { 'mail_admins': { 'level': 'ERROR', 'filters': ['skip_unreadable_posts'], 'class': 'django.utils.log.AdminEmailHandler' } },
- class RequireDebugFalse
このフィルターは、settings.DEBUGがFalseの場合にのみレコードを渡します。
このフィルターは、デフォルトの:setting: `LOGGING` 構成で次のように使用され、 AdminEmailHandler が:setting:` DEBUG` [の場合にのみエラーメールを管理者に送信するようにします。 X193X]は
False
です:'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse', } }, 'handlers': { 'mail_admins': { 'level': 'ERROR', 'filters': ['require_debug_false'], 'class': 'django.utils.log.AdminEmailHandler' } },
- class RequireDebugTrue
- このフィルターは RequireDebugFalse に似ていますが、:setting: `DEBUG` が
True
の場合にのみレコードが渡される点が異なります。
Djangoのデフォルトのロギング構成
デフォルトでは、Djangoは次のロギングを構成します。
:setting: `DEBUG` がTrue
の場合:
django
ロガーは、django
階層(django.server
を除く)のINFO
レベル以上のメッセージをコンソールに送信します。
:setting: `DEBUG` がFalse
の場合:
django
ロガーは、django
階層(django.server
を除く)のメッセージをERROR
またはCRITICAL
レベルで AdminEmailHandler に送信します。 ]。
:setting: `DEBUG` の値に依存しません:
- django.server ロガーは、
INFO
レベル以上のメッセージをコンソールに送信します。
django.server を除くすべてのロガーは、ルートdjango
ロガーまで、ログを親に伝播します。 console
およびmail_admins
ハンドラーは、上記の動作を提供するためにルートロガーに接続されています。
:source: `django / utils / log.py` で定義されているこのデフォルトのロギング構成を補完または置換する方法については、ロギングの構成も参照してください。