方針設計

2008年01月29日
仕様で規定されているものは別として、プログラムの問題分析にはどのようなログが 理想的かは経験に基づく状況判断に依存するところが大きいところです。ここでは チーム開発におけるログ出力の方針などについて説明します。

チーム開発の問題分析

一般的なシステム開発では統合テスト付近から後は開発物が開発者本人の手を離れて テストされることになります。同時に開発者は目の前で問題の発生を見られないまま 分析しなければならない状況が多くなってきます。

基本的にテスターなどからの状況説明、ログ、画面キャプチャなどから推測される プログラムの動きをソースコード上で追う事になるわけですが、問題の報告には 主観や個人の能力、勘違い、先入観などが入りやすいことも事実です。このような 中で客観性の高いログはとても重要です。

問題の報告

ソースデバッガやプロファイラは問題の詳細を調査するために大変有用なツール ですが、システム開発で使用するログとは目的が違うことに注意してください。 これらのツールに慣れてしまったプログラマはトレースやデバッグレベルのログを 省略する傾向にあります。しかしそれは単に問題分析の経験が浅いと言わざるを得ません。

数百万の損失や訴訟のリスクがあるバグを「再現待ちです」などとは誰も言えません。 障害分析とは、発生した時が最大にして最後のチャンスであることをよく肝に 銘じてください。

誰のためのログか

開発から実運用まで、ログはさまざま立場の人が問題を調査するために利用します。 開発の組織構成によってもさまざまですが、大まかには以下の 4 つに分類できます。

開発担当者

ソースコードを書いた本人、あるいはそれを引き継いだ人。問題の報告内容からすぐに 調査にかかれる (あるいは原因を即答できる) 必要があります。プログラミング言語に ついての知識を持ち、ログからソースを追って問題を分析できますが、システム全体の 設計までは知らないかもしれません。

開発チーム

開発に携わっているチームの人。プログラミングの知識を持ち、ログやソースの 分析が行え、システム設計上その動きが正しいかどうかを判断できる人たちです。 しかしソース個別で「何を意図してこう書いたか」などは担当者レベルでしか分からない 可能性があります。

開発以外の技術者

例えば製品の問題分析やパフォーマンスチューニングなどを行うために現場で 作業を行うエンジニアです。言語やシステムの知識はあっても、対象の開発物に 対する設計や諸事情までは知らないかも知れません。

エンドユーザやシステム管理者

システムを利用する人、あるいはその中でもシステム管理を行う人です。システム 全体の構築と運用を行う人たちであって、基本的にソースを追って問題を分析する 立場ではありません。「シェルを組む」「設定ファイルを記述する」「ログで見当 をつける」という知識を持ちます。また「この動きが要件的に正しいか」を判断 できます。

同じ状況を説明にするにしても見る人の立場によって適切な表現が変わってくる ことに注意してください。例えば「該当するレコードが存在しない」という メッセージは開発者がコードの動きを知る上で適切かもしれませんが、運用者から すれば「認証に失敗しました」の方が ID かパスワードを間違えただけとすぐに 分かるため適切です。

ログレベル再考

誰に宛てたログかをはっきり意識することはログを挿入する時に重要な点のひとつ です。そして、誰が見るかを想定することでそのログの出力レベルが決定します。 これは同時にそのログをどのフェーズまで出すかという事につながります。

ログを挿入するときに一番重要な点がこれです。開発時に挿入するログは開発者 本人に向けた情報になりがちですが、後で問題分析をする他人に理解できるか、 誤解を与えないか

トレース

見やすさよりも情報量優先。担当外の人間が読むことまで配慮しなくても良いが、 少なくともこのログレベルで発生した問題は速やかに原因を特定 (あるいは 切り分け) できなくてはならない。また出力抑止した時にパフォーマンスに影響の 無いよう if で囲むなどの配慮が必要。

デバッグとの使い分けに迷うかもしれないが、他人に常時見せ付けるには冗長だが いざ問題の焦点になったら参考になるようなものはトレースで。例えばリクエスト ごとのセッション内容のダンプなど。

デバッグ

プログラムの知識のある第三者が問題の原因分析のために読む事を想定する。 読む人間が多数のソースに渡って調査していることが予想されるため、ログのみで ある程度の動作状況が分からなければならない。従って少なすぎるのはもちろんの 事、冗長すぎてもいけない。

入出力値や条件分岐に使用した値などは最低限出したいところだが、例えばデータ ファイルを 1 文字ずつ解析する処理はトレースレベルにすべきである。また実動作 にあまり関係のない部分のログは、問題発生時にソースコードと付き合わせて論理的に フローや状態が判断できるなら省略してもかまわない。

出力している値が何であるか分かる程度のテキストが必要である。また状態を知る 上で注目すべきメッセージには●や【】などで特徴付ける工夫も有用である。

エラーを検知した時、特に例外を throw する時のログは冗長になってもかまわない。 これから throw する例外がなぜ起きたのか、それを見た分析者がどこから調べれば 良いのかを、実際に該当ソースを読まなくても推測できる程度の説明でなければ ならない。

トレースと同様に、ソースと付き合わせて原因の切り分けができなければならないし、 実運用時のパフォーマンスに影響を与えてもいけない。

情報・警告・エラー

これらのレベルは、見ている人がプログラムの知識を持っていない可能性があると いう事も配慮する。ログを見た運用者が、自分たち宛てのメッセージなのか開発側 に回さなければいけないメッセージなのかを的確に判断できなければならない。

システム環境や配備、設定に関連する問題 ─ つまり運用者だけで解決できる問題に 関しては適切な情報を与えて解決を促す必要がある。例えば、どの設定ファイルの何の 値がどうおかしいのかを知らせれば運用者だけですぐにリカバリできるが (それが 本来の姿だが)、例外のスタックトレースしか出なければ開発側に回され問題解決までに 無駄な時間を費やすことになるだろう。

運用に絡む問題については、検知した箇所で適切な情報を漏れ無く出せるよう フレームワークがきちんと設計されていることも重要である。通常、アプリケーション からでは設定ファイルの物理的な配置や通信先のサーバがどれなのか知る由も無い。 すべては無理であるとしても、運用絡みの問題はフレームワークで検知し、報告する 事を基本として設計されているべきである。

逆に開発側に向けたメッセージは、運用者が一目見て手に負えないと分かるもの でなければならない。特にエラーのログは表現ひとつ誤るだけで分析者に誤解を 与えて何日も遠回りをさせたり、ありもしない疑いをかけられたり、最悪原因不明 に陥る可能性がある。

実運用環境 (本番) ではディスク容量の見積もりなども関係してくるため、開発者が 特定以上のレベルで好き勝手に出さないようルールを設けているのが一般的です。 またそういったログはどこでどう出すかが要件定義書や設計書に盛り込まれている 必要があり、実装面でもフレームワークで規定される必要があります (例えば フレームワークまで catch されなかった例外はすべて出す、ユーザ認証ログはこの クラスを使う、など)。

まとめ

システム文化や運用などの要因も絡んで来るため明確な指針というのは存在しません ので、状況にあわせて適切に当てはめてください。

トレース デバッグ 情報 警告 エラー
対象者
開発担当者
開発チーム
開発以外の技術者
システム管理者
開発フェーズ*1
コーディング
単体テスト
統合テスト
システムテスト
実運用
何を出すか・どう出すか
  • 処理の流れはデータに依存する。どこを通ったかでなく、なぜ通ったかを客観 的に説明すること。
  • 迅速な問題対応のためにもソースを読まなくてもある程度の切り分けができる 状態にしておく。
  • 特にレアケースのエラーを扱う時は一発で原因を特定できるだけの情報を出す こと。
見る人間に対して徹底的に配慮する
  • 対象者を想定する。自分か他人か、ソースコードやデータベースを追って原因を 調査できる人間か。
  • このメッセージで原因を推測できるか。あるいは誰の担当なのかすぐ判断できる か。
  • 見た人が次に何をすべきかが明確であること。
  • 問題特定の遠回りになるような誤解を与えてはいけない。
*1 テスト環境ならスポット的な問題分析などで出力も可
CVS 2008/01/30