ログレベル利用規則(log4net)

C#+log4netを利用してログ出力する場合にログレベルをどうやって決定するかの基準を決定しました。Java+log4jなど、ほかの組み合わせにも通用するルールだと思います。

ログレベルは以下の用途で利用します。

Level 用途
Debug デバッグ作業にプログラマが必要な情報を好きなだけ出力してください。
Information 他システムとの連携のために必要な情報を出力してください。
Warning 継続可能な問題が起きたときに問題の内容を説明するのに必要な情報を出力してください。
Error 継続不可能な問題が起きたときに問題の内容を説明するのに必要な情報を出力してください。
Fatal OSのプロセスを直ちに終了する必要がある致命的な問題が起きたときに問題の内容を説明するのに必要な情報を出力してください。

システムリリース時のログレベルはInformationレベルを想定しています。 Informationレベルよりも重大なログレベルでログ出力する場合は、実運用時にもログ出力されることを考慮(多言語化対応など)して出力内容を決めてください。 具体的にはString.Formatを使って文字列を組み立てるようにするのがよいでしょう。

これは、後々多言語化対応などを考慮したテクニックです。
LOG.Warn(String.Format("処理中のジョブ(={0})で例外が発生しました。", tJob), e);
このように書いておけば、以下のようにメッセージリソースを用意することで簡単に多言語化対応できます。
LOG.Warn(String.Format(Messages.XXXXXXX, tJob), e);

log4netにはILog#WarnFormatやILog#InfoFormatといったフォーマットを同時に行ってくれるメソッドも用意されています。 ただし、このフォーマットつきメソッドにはExceptionを引数で渡すことができません。

LOG.WarnFormat(Messages.XXXXXXX, tJob, e); // これではダメ

String#Formatを事前に呼び出して、フォーマットなしメソッドを呼び出す必要があります。

LOG.Warn(String.Format(Messages.XXXXXXX, tJob), e); // これはOK

もし、すべての関数の処理開始・終了を記録したいなど、ログ出力コードが広範囲に散らばるような場合はAOPを含めたメタ的なコード挿入を検討してください。

以下、各ログレベルごとの詳細を説明します。

Debugレベル

Debugレベルのログはプログラマの判断で好きなだけ出力してよいです。 ただし、ログを出力するコードは必ずILog#IsDebugEnabledプロパティの判定を行った後のブロックに記述してください。

これは、ログ出力処理による速度劣化を起こさないためのテクニックです。
if(LOG.IsDebugEnabled)
{
  long tStart = DateTime.Now.Ticks;
  LOG.Debug("ゆっくりしていってね!");
 
  string tText1 = "文字列を連結するような";
  string tText2 = "場合はログ出力処理が致命的な速度劣化を起こすことがあります。";
  LOG.Debug(tText1 + tText2);
 
  for(int i = 0; i < 10000; i++)
  {
    LOG.Debug("ループ処理を行う" + tText2);
  }
 
  LOG.Debug("ゆっくりした結果がこれだよ!" + (DateTime.Now.Ticks - tStart));
}
想定される用途
トレースログ, 引数の内容一覧, あるコードポイントでの変数一覧

Informationレベル

Informationレベルには他システムとの連動のために必要な情報を出力してください。 具体的には、ある処理を始めた時刻や通信電文の内容などの他システムと連携した動作の証拠や、システム間の問題の切り分けに必要な情報を出力します。 また、クラスライブラリの境界などでもこのログレベルを利用します。

想定される用途
通信電文, 処理開始終了時刻, 初期化処理に利用した設定値

Warningレベル

Warningレベルには続行可能な問題が起きたときにそのことをログを監視するシステム運用者などに伝えるための情報を出力してください。 具体的には、無視しても良いような例外を下位のライブラリから受け取った場合や、問題ではあるが自動復旧手順が決定している場合にこのログレベルで出力します。 このレベルのログを発見した監視者は、しばしば最終的に目的とする処理が完了しているのか処理をあきらめたのかに興味があります。 そこで、処理が完了しているのかがわかるように以下の文字列をログに出力するようにしてください。

  • 目的とする処理を完了できた場合は “[Recover]” という文字列をログの先頭に書き出すようにします。
  • 目的とする処理をあきらめた場合は “[Skip]” という文字列をログの先頭に書き出すようにします。
想定される用途
無視しても良い例外, 自動復旧した問題

Errorレベル

Errorレベルには続行不可能な問題が起きたときにそのことをログを監視するシステム運用者などに伝えるための情報を出力してください。 具体的には、無視できない例外を下位のライブラリから受け取った場合や、復旧手順が不明な問題が起きた場合にこのログレベルで出力します。 ただし、問題を例外として外部に報告する場合はログを出力する必要はありません。なぜならば、起きている問題の復旧手順が外部で決定されている可能性があるからです。外部が例外を適切に処理できるように、できるだけ詳細な情報を例外にセットするように心がけましょう。

想定される用途
復旧できない例外, 復旧手順が確定されていない問題

Fatalレベル

Fatalレベルのログは致命的な問題が起きたときにそのことをログを監視するシステム運用者などに伝えるための情報を出力してください。 具体的には、メモリやハードディスクが破損したことを検出したなど、対処方法が無くシステムをこのまま実行し続けると問題が拡大する場合にこのログレベルで出力します。 デバイスドライバなどを実装するなどしない限り、このログレベルを利用することはありません。

また、ハードディスクが破損しているなどの場合はログ出力自体が失敗することがありえます。

想定される用途
メモリが破損した, CPUが破損した

コメントをどうぞ