堅牢なアプリケーションを構築する上で、避けて通れないのが「例外処理」と「ロギング」の連携です。その第一歩として、すべての例外の基底クラスである System.Exception が何を持ち、何ができるのかを徹底的に調査します。
なぜここから始めるのか。それは、独自例外であってもサードパーティ製ライブラリの例外であっても、最終的に我々が確実にアクセスできる情報は Exception クラスに定義されているものだけだからです。
1. プロパティ一覧
Exception クラスのプロパティは、発生した問題の「コンテキスト」を保持しています。
| プロパティ名 | 意味 | ログにおける活用方法 |
|---|---|---|
| Data | 例外に関する追加情報を格納する辞書 (IDictionary)。 | 引数の値や状態など、型定義にない動的な情報を付加してログに流せる。 |
| HelpLink | 関連するヘルプファイルやWebサイトへのURL。 | 運用手順書や既知のトラブルシューティングへの誘導。 |
| HResult | 特定のエラーに割り当てられた数値。 | Windows OS固有のエラーや、COM相互運用時のエラー特定に使用。 |
| InnerException | 現在の例外を引き起こした直前の例外。 | 例外の連鎖(Cause)を辿るために不可欠。再スロー時に情報を落とさない。 |
| Message | エラーの内容を説明するテキスト。 | ユーザーや運用担当者が最初に目にする概要。 |
| Source | エラーを発生させたアプリケーションまたはオブジェクトの名前。 | どのコンポーネント/アセンブリが起点かを確認する。 |
| StackTrace | 例外が発生するまでのメソッド呼び出しの履歴。 | 最重要項目。 ソースコードのどこで問題が起きたかを特定する。 |
| TargetSite | 例外をスローしたメソッド。 | StackTraceから抽出可能だが、特定のメソッド名をログに明記したい場合に便利。 |
2. メソッド一覧
Exception クラスに定義されているパブリックメソッドは、例外情報のシリアル化や、デバッグ時に必要な情報の集約を担います。
| メソッド名 | 意味 | ログにおける活用方法 |
|---|---|---|
| ToString() | 現在の例外の文字列表現を作成します。 | 最頻出。 クラス名、Message、InnerException、StackTraceを統合した文字列を生成するため、簡易的なログ出力にはこれ一つで十分な情報量が得られます。 |
| GetBaseException() | 例外チェーンを遡り、最初に発生した原因(根本例外)を返します。 | 多数のラッパー例外に包まれている場合でも、ex.GetBaseException().Message を参照することで「真の原因」をログの冒頭に記録できます。 |
| GetType() | 現在のインスタンスの正確なランタイム型を取得します。 | ログの「エラーカテゴリ例外の型を簡単に残せます。 |
| GetHashCode() | 特定の型のハッシュ関数として機能します。 | ログ出力において直接利用する機会は少ないですが、短時間での同一例外の重複判定などに利用されることがあります。 |
| Equals(Object) | 指定したオブジェクトが現在のオブジェクトと等しいかどうかを判断します。 | 同上。ログの重複排除ロジックなどで利用される可能性があります。 |
| GetObjectData(...) | 例外に関するデータを使用して SerializationInfo を設定します。 |
ログ出力そのものよりは、例外情報をプロセスをまたいで転送(分散トレーシングや分散ログ)する際のシリアル化処理で使用されます。 |
ただ後方互換のために残されているだけで現在は使用が推奨されないメソッドもあるためご注意ください。
3. ロギングに向けた深い考察:なぜこれらを知る必要があるのか
すべての例外がこれらを持っているということは、システムの例外とログ設計において、統一基盤を構築することが可能ということを意味します。
根本原因の特定自動化
GetBaseException() を活用すれば、ログのサマリーに常に「真犯人」を表示させることができます。例えば例外を複数回ラップするようなコードであっても最初に発生したエラーを出力することができます。
構造化ログへの展開
Data プロパティや GetType() の結果を、単なるテキストではなく JSON などの構造化データとしてログ基盤(ELK Stack や Datadog など)に送ることで、後から「特定のメソッド(TargetSite)で発生しているエラーの統計」を即座に出すことが可能になります。
最後に
C#における例外とログの戦略を考えるうえで最も重要なExceptionクラスについて解説を行いました。
次回はException.Dataを利用した「コンテキスト付きロギング」の設計について考察していこうと思います。
この記事が皆様のコーディングライフの助けになれば幸いです。
参考資料