AP開発時に決めておくこと(1)−ログ

AP開発やシステム開発時に、予め、決めておくと後々楽になるルール/ガイドラインについて、なんとなく書いてみた。まずは、ログ関連。

ログ出力項目と出力幅(エラー系)

エラーが出力されると、運用さんに監視コンソールにログメッセージが表示され、その内容に応じてオペさん対応もしくは、ログメッセージの内容が維持部隊にメールで通知される。
そのときの動きを制御するため、ログメッセージには少なくとも以下の内容を共通的に出力しておく。

出力項目 用途
日時 言わずもがな
ログレベル 監視時のフィルタリングや、システム状況を瞬時に識別するため
ユーザ その処理の対象となるユーザ名や、処理そのものの実行契機となるユーザ
発生箇所 プロセスIDやら、機能IDやら、処理IDやら、クラス名やらメソッド名やら、発生箇所を一意に識別するためのコード
エラー種別 どのようなエラーかを一意に識別するためのコード。
ユーザ/トランザクション/データ識別子 処理対象となるユーザやデータ等を一意に識別するためのコード
性能関連情報 レスポンスタイム等の性能に関する情報

発生箇所とエラー種別の組み合わせで、障害箇所と障害時の対応を一意に決定できるようにしておくことが望ましく、維持部隊であれば、この組み合わせと対応表を常に持ち歩いておき、電話連絡があった場合でもすぐさま対応できるようにしておきたい。が、量が多くなるので、工夫は必要。
ユーザ/トランザクション/データ識別子は、調査ツールや復旧ツールを運用さんに提供するようなケースの場合に、そのツールの入力として使うデータになるものを選ぶ。
あと、忘れてはいけいないのが、3つ目のユーザや性能関連情報。全社、どちらかと言うと、セキュリティ的な面で必要となるログ出力項目に近しい。後者は、性能劣化が発生していないかを統計的に判断したり、発生していた場合、どのレイヤーで発生しているかを切り分けたりするために必要な情報。
なお、私はシステム開発におけるエラーメッセージを余り重要視していない。というのも、エラーメッセージは有れば良いものの、運用監視ツールによっては監視コンソールのメッセージ表示幅が80字に制限されるようなケースもあったりして、結局、最後まで見ることはできなかったりする。さらに、日本の会社の運用さんは、エラーメッセージの内容でその後の人間系の動作を変えるなんてことは、あんまり認めてくれない。システム開発においては、ログメッセージを見るのは特定少数の人になるため、誰でも分かりやすいというメッセージは、実はあまり重要な観点ではない。なので、可変の部分は左側、固定のメッセージは右側に寄せるなどの工夫をしたうえで、メッセージ内容の品質については、重要度を落としていたりする。
(正直、メッセージを分かりやすくするというタスクは、いつも後回しにしてたりして、いつも実施できてない。)

ログレベル

ログレベルは、運用に密接に関わってくるため、早めの段階、具体的には基本設計の段階で決めておくと良い。私は、おおむね以下の内容とすることが多い。なお、一般的なロギングライブラリでは、ログレベルが足りないため、いつも追加している。

ログレベル 用途 監視有無 運用時の基本動作
info APの正常性を確認するためのログ
warn 当該トランザクションにおいて処理継続可能だが、後から環境面や入力等について確認を行ったほうが良い状態 翌朝連絡
error 当該トランザクションにおいて処理継続不能なため、処理を中断するものの、他のトランザクションは処理継続可能と考えられるエラーが発生した場合 即連絡 or オペさん作業
fatal 当該プロセスもしくは当該ノードでの処理継続が困難だが、別ノードにおいては業務継続可能なため、システムとしては動作継続可能と思われる状態の場合 即連絡 or オペさん作業
severe fatal発生後等、別ノードでも業務が継続が不可能で、部分的にしろ全面的にしろ業務停止が発生したと思われる状態の場合 即連絡

最後のヤツについては、例えばフェイルオーバ後にAPが起動できなかった場合等が該当し、普通はインフラ側で騒ぎだすため、AP側で意識的に書き出すことはあまりない。ただ、APの種類によってはインフラ側で気付けないようなケースがあるため、念のために設計時に定義しておくようにしている。
なお、上記のレベルの考え方は、正直、ベストではない。APの処理設計だけで決定できず、インフラを含めたアーキテクト視点でログレベルを決定する必要があることと、業務の重要性や運用という観点で、切り分けが出来ないからだ。例えば、運用時の基本動作のレベル感、翌朝オペさん対応、翌朝連絡、即時オペさん対応、即時連絡&駆けつけという分け方でログレベルを決定するという考え方もある。

ログ出力先

APサーバ(WLSやWAS、TomcatJBoss等)の上でAPを動かすのであれば、あまり気にしないものの、多数のバッチや作り込みの常駐プロセスが居る場合、複数のプロセスから同一のログファイルに直接ログを吐き出すのは、将来、色々な厄介事を抱え込む可能性があるため、syslogやログ用サーバを別途立てておき、そこ経由でファイルに出力した方が良い。個別にログ監視をしようとすると、監視対象ファイルが多くなり、パフォーマンス的にも、管理的にもよろしくない。

通信ログ/電文ログ

他システム連携を行う場合、送受信データは可能な限り数日間保存しておく方が良い。というのも、トラぶった時に、何を受け取ったのか、何を送信したのかは、システム間で喧嘩の元になる。一番恥ずかしいのは、トラぶった時に、相手先システムに対して、「うちの送信データを送ってもらえませんか?」となってしまうケースである。ぶっちゃけ、陰で笑われる。
なお、電文の中身を全て記録するようなログは、PCI−DSS等、セキュリティ面で引っかかる可能性があるため、必ず、お客様と握っておくことと、アクセス制御をしっかりしたり、暗号化等のセキュリティ対策を行っておく必要がある。

シェルログ

忘れてはいけないのが、シェルに関するログ。とりあえず、syslogに書いておけば良いが、Javaばかり書いていると、シェルログの品質を見落とす。シェルのログだからと言って手を抜かず、基本は、他のログと同程度の情報を出力するように設計する。(インフラ屋さんが手を抜いて、後々苦労しているのを、良く見る。)

埋め込み情報の評価順

特にデバッグログ等では意識しないといけないが、ログメッセージ内に埋め込む値の評価について、性能面で気にする必要がある。基本は、ログ出力の決定後に埋め込む値を評価するという順序が望ましいため、それが出来るロギングライブラリを利用するか、もしくは独自にログ出力のラッパー処理を用意することが望ましい。

ログファイル名とログ監視とログローテ

ログ監視ソフトによっては、ファイル名は一律同じでないと監視できないケースがある。ログローテのことを考えると、日付付きログを監視したいものの、日付付きログでは監視できない可能性があるため、必ず、利用するログ監視ソフトの仕様を確認すること。

ちょっと疲れたので、あとは観点だけ。

  • ログローテのタイミングと方法(ローテのための作り込みとか必要。あと、ローテを何時にするかも重要。)
  • 標準エラー出力(対策しないと、エラー内容がなくなっちゃうよ)
  • ログ出力先(できればローカル。ネットワーク越し出力は、ログ消失のリスクを考えて。)
  • ログの種類(エラーログ、アクセスログ、トレースログ、トランザクションログ等、ログサイズや解析のことを考えて、分けておこう。)
  • 保管日数(ログローテに付きまとうのが、過去ログの保管日数。容量の問題もあるけど、まずはルールを調べよう。1年保管が義務とかあるし。容量の問題が気になるなら、1週間過ぎたらzipにでも固めておけば良い。ただ、直近のログはすぐに参照できるように。)
  • ログ回収と保管方法(たいてい、日時で回収される機構が存在する。回収しやすいように、保管方法やら名前やら決めると良い。)
  • セキュリティ(やっぱり、個人情報はログに出しちゃいかんので、せめて暗号化とも思うが、そうすると性能がというジレンマがある。なるべく、システム的には意味が有りつつ、人間的には意味のない何かにすることで、性能とセキュリティの双方を両立しよう。)

かなり疲れたので、最後の一言。
ログ設計は、プロジェクトの余裕度を測るバロメータです。忙しいPJほど、ログ設計を疎かにしてしまう傾向がありますが、それでも、経験豊富なメンバを抱えているPJは、ログ設計をしっかりやってます。逆に、余裕が有りそうに見えるPJでも、ログ設計がしっかりしてなければ、メンバのスキル不足を疑う必要があります。なので、ログ設計を見れば、たいてい、PJの状況(全体的な品質)は判断できると言っても大丈夫です。