運用・保守担当者は、表2のケース1をほぼ間違いなく、経験しているのではないでしょうか。
時間をかけて調べてみると、テスト環境と本番環境のわずかな差異が原因だったり、「0.01秒間にXとYの処理を実行すると、エラーが発生する」といった、故意に起こすのが難しい原因だったりと、理由は様々です。
ただ理由は何であれ、早急に原因を究明し、何からの暫定対応を行わなければいけません。そのためには、原因を究明する材料、つまり障害発生時の状況をログとして出力する必要があります。Webアプリケーションを例に、原因究明に必要な内容をあげます。
- 障害が起こる直前はどのような状態か?
-
- どの操作をして、Bという画面を表示したのか?
- どのようなセッション情報を保持しているのか?
- 更新しようとしたデータはどのような値か?
- どのような操作をしたのか?
-
- Bという画面で、入力した値は何か?
- どのボタンを押したのか?
- どのような値にデータを更新したのか?
- 操作した後、どのような画面が表示されたのか?
表3:障害の原因究明に必要な内容(Webアプリケーションを例にしたもの)
そこで、再現の可能性を高めるためにも、障害が発生したときに実行することが多い、例外処理(try〜catch文)についてログ出力の記述ルールを策定する必要があります。以下は例です。
リスト1:例外処理の記述例
try{
// 帳票設定ファイルを読み込み、PDFとして出力する。
}catch(FileNotFoundException fnfe){
//障害発生。ログに状況を出力
System.out.println(“画面ID:” + SCREEN_ID);
System.out.println(“処理ID:” + EXECUTE_ID);
System.out.println(“セッション情報:” + “パラメータX・・・” + session.getAttribute(“X”) );
System.out.println(“リクエスト情報:” + “パラメータY・・・” + request.getAttribute(“Y”) );
fnfe.printStackTrace();
}
上記の例ではSystemクラスを使用しておりますが、現在は、logging APIやLog4Jといったログ出力ツールが充実しておりますので、通常はこれらのログ出力ツールを使って開発すると思います(各ツールによって記述方法が異なりますので、詳細は各ツールのマニュアルをご覧ください)。
また、ログ出力ツールについても、出力ルールを定めておくのが良いでしょう。以下はLog4Jを使った場合の、ログ出力のルール例です。
ログレベル |
ルール |
fatal |
ハードウェア障害など、システムがこれ以上動作できない場合に記述する(注1)。 |
error |
SQLの実行エラー、HTTPプロトコルエラーなど、正しく処理が出来なかった場合に記述する。 |
warn |
「1度は正しく処理ができなかったが、再度処理したら完了した」というように、問題は発生したが、処理として影響がなかった場合に記述する。 |
info |
システム開始/停止時といった、システム状態が変わるときに記述する。 また、「○○登録」「○○変更」「○○削除」といった程度の現在の処理状況を記述する。 |
debug |
障害の原因究明用。どのメソッドをどんな引数で実行し、どんな出力をしたかまで把握できるように記述する。 |
表4:ログ出力ルール例(Log4Jの場合)
※注1:
実は筆者はこのレベルをソースに記述したことがありません。このような障害は、OSのログなど、別のログでも出力されるので、そちらのほうがより詳細の内容がわかるためです。
この出力ルールに従うと、リスト1は以下のように修正できます。
リスト2:Log4Jを使った例外処理の記述例
try{
// 帳票設定ファイルを読み込み、PDFとして出力する。
}catch(FileNotFoundException fnfe){
//障害発生。ログに状況を出力
log.error(“画面ID:” + SCREEN_ID);
log.error(“処理ID:” + EXECUTE_ID);
log.error(“セッション情報:” + “パラメータX・・・” + session.getAttribute(“X”) );
log.error(“リクエスト情報:” + “パラメータY・・・” + request.getAttribute(“Y”) );
log.error(“帳票ファイルが読めませんでした。”, fnfe);
|