# 29 `logging` -- Python 用ロギング機能

バージョン 2.3 で 新たに追加 された仕様です。 このモジュールでは、アプリケーションのための柔軟なエラーログ記録 (logging) システムを実装するための関数やクラスを定義しています。

ログ記録は `Logger` クラスのインスタンス (以降 ロガー :logger) におけるメソッドを呼び出すことで行われます。各インスタンスは 名前をもち、ドット (ピリオド) を区切り文字として表記することで、 概念的には名前空間中の階層構造に配置されることになります。 例えば、"scan" と名づけられたロガーは "scan.text"、"scan.html"、 および "scan.pdf" ロガーの親ロガーとなります。ロガー名には何をつけてもよく、 ログに記録されるメッセージの生成元となるアプリケーション中の特定の 領域を示すことになります。

ログ記録されたメッセージにはまた、重要度レベル (level of importance) が関連付けられています。デフォルトのレベルとして提供されているものは `DEBUG`、`INFO`、`WARNING`、 `ERROR` および `CRITICAL` です。簡便性のために、 `Logger` の適切なメソッド群を呼ぶことで、ログに記録されたメッセージの 重要性を指定することができます。それらのメソッドとは、デフォルトの レベルを反映する形で、`debug()`、 `info()`、 `warning()`、 `error()` および `critical()` となっています。 これらのレベルを指定するにあたって制限はありません: `Logger` の より汎用的なメソッドで、明示的なレベル指定のための引数を持つ `log()` を使って自分自身でレベルを定義したり使用したりできます。

レベルもロガーに関連付けることができ、デベロッパが設定することも、 保存されたログ記録設定を読み込む際に設定することもできます。 ロガーに対してログ記録メソッドが呼び出されると、ロガーは自らの レベルとメソッド呼び出しに関連付けられたレベルを比較します。 ロガーのレベルがメソッド呼び出しのレベルよりも高い場合、実際の ログメッセージは生成されません。これはログ出力の冗長性を制御 するための基本的なメカニズムです。

ログ記録されるメッセージは `LogRecord` クラスのインスタンスとして コード化されます。ロガーがあるイベントを実際にログ出力すると決定した 場合、ログメッセージから `LogRecord` インスタンスが生成されます。

ログ記録されるメッセージは、ハンドラ (handlers) を通して、 処理機構 (dispatch mechanism) にかけられます。ハンドラは `Handler` クラスのサブクラスのインスタンスで、ログ記録された (`LogRecord` 形式の) メッセージが、そのメッセージの伝達対象となる相手 (エンドユーザ、サポートデスクのスタッフ、システム管理者、開発者) に行き着くようにする役割を持ちます。ハンドラには特定の行き先に方向付け られた `LogRecord` インスタンスが渡されます。各ロガーは ゼロ個、単一またはそれ以上のハンドラを (`Logger` の `addHandler()` メソッド) で関連付けることができます。 ロガーに直接関連付けられたハンドラに加えて、 ロガーの上位にあるロガー全てに関連付けられたハンドラ がメッセージを処理する際に呼び出されます。

ロガーと同様に、ハンドラは関連付けられたレベルを持つことができます。 ハンドラのレベルはロガーのレベルと同じ方法で、フィルタとして働きます。 ハンドラがあるイベントを実際に処理すると決定した場合、 `emit()` メソッドが使われ、メッセージを発送先に送信します。ほとんどの ユーザ定義の `Handler` のサブクラスで、この `emit()` をオーバライドする必要があるでしょう。

基底クラスとなる `Handler` クラスに加えて、多くの有用なサブクラスが 提供されています:

1. `StreamHandler` のインスタンスはストリーム (ファイル様 オブジェクト) にエラーメッセージを送信します。

2. `FileHandler` のインスタンスはディスク上のファイルに エラーメッセージを送信します。

3. `BaseRotatingHandler` はログファイルをある時点で交替させる ハンドラの基底クラスです。直接インスタンス化するためのクラスではありません。 `RotatingFileHandler` や`TimeRotatingFileHandler` を使う ようにしてください。

4. `RotatingFileHandler` のインスタンスは最大ログファイルの サイズ指定とログファイルの交替機能をサポートしながら、ディスク上のファイルに エラーメッセージを送信します。

5. `TimeRotatingFileHandler` のインスタンスは、ログファイルを 一定時間間隔ごとに交替しながら、ディスク上のファイルに エラーメッセージを送信します。

6. `SocketHandler` のインスタンスは TCP/IP ソケットにエラーメッセージを送信します。

7. `DatagramHandler` のインスタンスは UDP ソケットにエラーメッセージを送信します。

8. `SMTPHandler` のインスタンスは指定された電子メールアドレスにエラーメッセージを送信します。

9. `SysLogHandler` のインスタンスは遠隔を含むマシン上の syslog デーモンにエラーメッセージを送信します。

10. `NTEventLogHandler` のインスタンスは Windows NT/2000/XP イベントログにエラーメッセージを送信します。

11. `MemoryHandler` のインスタンスはメモリ上のバッファにエラーメッセージを送信し、指定された条件でフラッシュされるようにします。

12. `HTTPHandler` のインスタンスは "`GET`" か "`POST`"セマンティクスを使って HTTP サーバにエラーメッセージを送信します。

`StreamHandler` および `FileHandler` クラスは、中核となる ログ化機構パッケージ内で定義されています。他のハンドラはサブモジュール、 `logging.handlers` で定義されています。 (サブモジュールには もうひとつ `logging.config` があり、これは環境設定機能の ためのものです。)

ログ記録されたメッセージは `Formatter` クラスのインスタンスを 介し、表示用に書式化されます。これらのインスタンスは % 演算子と辞書を 使うのに適した書式化文字列で初期化されます。

複数のメッセージの初期化をバッチ処理するために、 `BufferingFormatter` のインスタンスを使うことができます。 書式化文字列 (バッチ処理で各メッセージに適用されます) に加えて、 ヘッダ (header) およびトレイラ (trailer) 書式化文字列が用意されて います。

ロガーレベル、ハンドラレベルの両方または片方に基づいたフィルタリング が十分でない場合、`Logger` および `Handler` インスタンスに `Filter` のインスタンスを (`addFilter()` メソッドを介して) 追加することができます。メッセージの処理を進める前に、ロガーとハンドラは ともに、全てのフィルタでメッセージの処理が許可されているか調べます。 いずれかのフィルタが偽となる値を返した場合、メッセージの処理は 行われません。

基本的な `Filter` 機能では、指定されたロガー名でフィルタを 行えるようになっています。この機能が利用された場合、名前付けされた ロガーとその下位にあるロガーに送られたメッセージがフィルタを通過 できるようになり、その他のメッセージは捨てられます。

上で述べたクラスに加えて、いくつかのモジュールレベルの関数が存在します。

`getLogger`( | [name])

  指定された名前のロガーを返します。名前が指定されていない場合、 ロガー階層のルート (root) にあるロガーを返します。 name を指定する場合には、通常は "a", "a.b", あるいは "a.b.c.d" といったようなドット区切りの階層的な 名前にします。名前の付け方はログ機能を使う開発者次第です。

  与えられた名前に対して、この関数はどの呼び出しでも同じロガーインスタンス を返します。従って、ロガーインスタンスをアプリケーションの各部 でやりとりする必要はなくなります。

`getLoggerClass`( | )

  標準の`Logger` クラスか、最後に`setLoggerClass()` に渡した クラスを返します。この関数は、新たに定義するクラス内で呼び出し、 カスタマイズした`Logger` クラスのインストールを行うときに 既に他のコードで適用したカスタマイズを取り消そうとしていないか 確かめるのに使います。例えば以下のようにします:

       class MyLogger(logging.getLoggerClass()):
           # ... override behaviour here

`debug`( | msg[, *args[, **kwargs]])

  レベル `DEBUG` のメッセージをルートロガーで記録します。 msg はメッセージの書式化文字列で、args は msg に 取り込むための引数です。キーワード文字列 kwargs からは exc_info のみが調べられ、この値の評価値が偽でない場合、 例外情報をログメッセージに追加します。(`sys.exc_info` の返す形式の) 例外情報を表すタプルが与えられていれば、それを メッセージに使います。それ以外の場合には、`sys.exc_info` を呼び出して例外情報を取得します。

`info`( | msg[, *args[, **kwargs]])

  レベル `INFO` のメッセージをルートロガーで記録します。 引数は `debug()` と同じように解釈されます。

`warning`( | msg[, *args[, **kwargs]])

  レベル `WARNING` のメッセージをルートロガーで記録します。 引数は `debug()` と同じように解釈されます。

`error`( | msg[, *args[, **kwargs]])

  レベル `ERROR` のメッセージをルートロガーで記録します。 引数は `debug()` と同じように解釈されます。

`critical`( | msg[, *args[, **kwargs]])

  レベル `CRITICAL` のメッセージをルートロガーで記録します。 引数は `debug()` と同じように解釈されます。

`exception`( | msg[, *args])

  レベル `ERROR` のメッセージをルートロガーで記録します。 引数は `debug()` と同じように解釈されます。 例外情報はログメッセージに追加されます。このメソッドは 例外ハンドラからのみ呼び出されます。

`log`( | level, msg[, *args[, **kwargs]])

  レベル `level` のメッセージをルートロガーで記録します。 その他の引数は `debug()` と同じように解釈されます。

`disable`( | lvl)

  全てのロガーに対して、ロガー自体のレベルに優先するような上書きレベル lvl を与えます。アプリケーション全体にわたって一時的にログ出力の 頻度を押し下げる必要が生じた場合にはこの関数が有効です。

`addLevelName`( | lvl, levelName)

  内部辞書内でレベル lvl をテキスト levelName に関連付け ます。これは例えば `Formatter` でメッセージを書式化する 際のように、数字のレベルをテキスト表現に対応付ける際に用いられます。 この関数は自作のレベルを定義するために使うこともできます。 使われるレベル対する唯一の制限は、レベルは正の整数でなくては ならず、メッセージの深刻さが上がるに従ってレベルの数も上がらなくては ならないということです。

`getLevelName`( | lvl)

  ログ記録レベル lvl のテキスト表現を返します。レベルが定義 済みのレベル `CRITICAL`、`ERROR`、 `WARNING`、 `INFO`、あるいは `DEBUG` のいずれかである場合、対応する文字列が返されます。 `addLevelName()` を使ってレベルに名前を関連づけていた 場合、lvl に関連付けられていた名前が返されます。 定義済みのレベルに対応する数値を指定した場合、レベルに対応した 文字列表現を返します。そうでない場合、文字列 "Level %s" % lvl を 返します。

`makeLogRecord`( | attrdict)

  属性が attrdict で定義された、新たな `LogRecord` インスタンスを生成して返します。この関数は pickle 化された `LogRecord` 属性の辞書を作成し、ソケットを介して送信し、受信端で `LogRecord` インスタンスとして再構成する際に便利です。

`makeLogRecord`( | attrdict)

  attrdict で属性を定義した、新しい `LogRecord` インスタンスを 返します。この関数は、逆 pickle 化された `LogRecord` 属性辞書を socket 越しに受け取り、受信端で `LogRecord` インスタンスに再構築す る場合に有用です。

`basicConfig`( | )

  デフォルトのフォーマッタ (formatter) を持つ `StreamHandler` を生成してルートロガーに追加し、ログ記録システムの基本的な環境設定を 行います。 関数 `debug()`、`info()`、`warning()`、 `error()`、および `critical()` は、ルートロガーに ハンドラが定義されていない場合に自動的に `basicConfig()` を呼び出します。

`shutdown`( | )

  ログ記録システムに対して、バッファのフラッシュを行い、全てのハンドラを 閉じることで順次シャットダウンを行うように告知します。

`setLoggerClass`( | klass)

  ログ記録システムに対して、ロガーをインスタンス化する際にクラス klass を使うように指示します。指定するクラスは引数として 名前だけをとるようなメソッド `__init__()` を定義して いなければならず、`__init__()` では `Logger.__init__()` を呼び出さなければなりません。典型的な利用法として、この関数は自作の ロガーを必要とするようなアプリケーションにおいて、他のロガーが インスタンス化される前にインスタンス化されます。

参考:

PEP 282, A Logging System
  本機能を Python 標準ライブラリに含めるよう記述している提案書。

この `logging` パッケージのオリジナル
  オリジナルの`logging`パッケージ。このサイトにあるバー ジョンのパッケージは、標準で`logging`パッケージを含まな いPython 1.5.2 と 2.1.x、2.2.xでも使用できます