Python(パイソン)でログ出力
Pythonでログ出力といえば、標準モジュールの logging を利用する方法が一般的。
<ログレコードを生成するのはロガーの仕事、出力するのはハンドラーの仕事>
■ログレコード(logging.LogRecord)
ログ出力されるメッセージそのものの情報を持つ。
ロガー間でやり取りされるのはこのログレコードである。
ログのメッセージ本文はもちろんのこと、下記の情報を持っている。
・ログレコードの生成時刻
・ログレコードに設定されたログレベル
・呼び出されたソースのファイル名
・呼び出されたソース中の行番号
・スタックトレース
■ロガー(logging.Logger)
ログレコードを生成したり、ほかのロガーに受け渡す。
受け取ったログレコードをハンドラに渡す。
ロガーは各開発者が自分で定義・生成することができる。
ロガーはそれぞれ名前(Logger.name)を持ち、各開発者がロガーを生成するときに、
そのモジュール名を名前に設定することが一般的。
〇ロガーの階層構造
アプリケーションのなかで、ロガーは階層構造を持つ。
階層構造は名前を元に作成され、その表現方法はPythonのモジュールの階層表現と同じ。
(文字列とドット(.)を使って表現され、ドットを挟むと階層が1段深くなる。)
下位層のロガーで生成されたレコードは、その親ロガーに伝播していく。
(設定によっては伝播させないことも可能)そして、最後にルートロガーに到達。
ルートロガーは、常に階層構造の最上位に位置するロガー。
ルートロガーは開発者自ら生成する必要はなく、loggingモジュールが定義する。
■ハンドラ(logging.Handler)
ロガーに紐づけられ、受け取ったログレコードを出力する。
出力先はコンソール、ファイルなど多岐にわたり、それぞれの出力先ごとに専用の
ハンドラーがあらかじめ定義されている。
メール送信やHTTPリクエスト送信するためのハンドラーも用意されている。
■フォーマッタ(logging.Formatter)
ハンドラに紐づけられ、設定に従い受け取ったレコードの書式を整形する。
フォーマッタのコンストラクタにフォーマット文字列を渡すことで、ログレコードに
含まれる時刻とメッセージの書式設定を変更することが可能。
また、デフォルトのフォーマッタはテキスト形式の出力を想定したものですが、
logging.Formatterクラスを継承して独自のフォーマッタを作成し、JSON形式で
ログ出力をすることなども可能
■フィルタ(logging.Filter)
ロガーやハンドラに紐づけられ、受け取ったレコードを処理するかしないかを決定する。
定義したフィルタは、ロガーやハンドラに紐づけて使用する。
フィルタオブジェクトは、これまで挙げたloggingモジュールのオブジェクトとは異なり、
デフォルトの状態では使われることはない。
ログレベルだけではコントロールし切れないような、任意の条件でログのフィルタリングを
行いたい場合に開発者が定義して使用することができる。
●ログが出力されるまでのフロー
出力されたログレコードは、ロガーの階層構造を子ロガーから親ロガーへと伝播していくが、
実際にログレコードがどのタイミングで出力されるかは、それぞれのロガーやハンドラに
設定されたログレベルや、フィルタの設定による。
●ログレベル
ログレコード、ロガー、ハンドラにはそれぞれログレベルを設定することができる。
ログレコードに設定したログレベルが、ロガーやハンドラに設定したログレベルと
同等かそれ以上の場合のみ、実際にログレコードが処理される。
ログレベルは、CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET の順で高くなる。