更新: System.Diagnostics の拡張機能については、欠落しているリスナーの一部を提供するために、CodePlex の Essential.Diagnostics ( http://essentialdiagnostics.codeplex.com/ )を参照してください。
フレームワーク
Q: どのようなフレームワークを使用していますか?
A: .NET 2.0 に組み込まれている System.Diagnostics.TraceSource。
アプリケーションに強力で柔軟な高パフォーマンスのロギングを提供しますが、多くの開発者はその機能を認識しておらず、十分に活用していません。
追加機能が役立つ領域や、機能は存在するが十分に文書化されていない領域がありますが、これは、ロギング フレームワーク全体 (拡張可能に設計されている) を捨てて、いくつかの一般的な代替手段のように完全に置き換える必要があることを意味するものではありません。 (NLog、log4net、Common.Logging、さらには EntLib Logging)。
アプリケーションにログ ステートメントを追加する方法を変更して車輪を再発明するのではなく、必要な数か所で System.Diagnostics フレームワークを拡張するだけです。
他のフレームワークは、EntLib でさえも、Not Invented Here 症候群に苦しんでいるように思えます。System.Diagnostics で既に完全に機能している基本 (ログ ステートメントの書き方など) を再発明するのに時間を無駄にしていると思います。存在するいくつかのギャップを埋めるのではなく。要するに、それらを使用しないでください。それらは必要ありません。
あなたが知らなかったかもしれない機能:
- Filter.ShouldTrace() が成功するまでパラメーターは個別の参照として保持されるため、フォーマット文字列と引数を取る TraceEvent オーバーロードを使用すると、パフォーマンスが向上します。これは、システムがメッセージが実際にログに記録されることを確認するまで、パラメーター値で ToString() への高価な呼び出しを行わないことを意味します。
- Trace.CorrelationManager を使用すると、同じ論理操作に関するログ ステートメントを関連付けることができます (以下を参照)。
- VisualBasic.Logging.FileLogTraceListener は、ログ ファイルへの書き込みに適しており、ファイル ローテーションをサポートしています。VisualBasic 名前空間ではありますが、DLL を含めるだけで、C# (または他の言語) プロジェクトでも同じように簡単に使用できます。
- EventLogTraceListener を使用して、複数の引数と空または null のフォーマット文字列を指定して TraceEvent を呼び出した場合、ローカライズされたメッセージ リソースを使用している場合、引数は EventLog.WriteEntry() に直接渡されます。
- Service Trace Viewer ツール (WCF から) は、(WCF を使用していない場合でも) アクティビティに関連するログ ファイルのグラフを表示するのに役立ちます。これは、複数のスレッド/アクティビティが関係する複雑な問題のデバッグに非常に役立ちます。
- すべてのリスナーをクリアする (または Default を削除する) ことで、オーバーヘッドを回避します。それ以外の場合、Default はすべてをトレース システムに渡します (そして、すべての ToString() オーバーヘッドが発生します)。
拡張を検討したい領域 (必要な場合):
- データベース トレース リスナー
- 色付きのコンソール トレース リスナー
- MSMQ / 電子メール / WMI トレース リスナー (必要な場合)
- 動的な構成変更のために Trace.Refresh を呼び出す FileSystemWatcher を実装する
その他の推奨事項:
構造化されたイベント ID を使用し、参照リストを保持します (たとえば、それらを列挙型で文書化します)。
システム内の (重要な) イベントごとに一意のイベント ID を持つことは、特定の問題を関連付けて見つけるのに非常に役立ちます。イベント ID を記録/使用する特定のコードを追跡するのは簡単で、一般的なエラーのガイダンスを簡単に提供できます。たとえば、エラー 5178 はデータベース接続文字列が間違っていることを意味します。
イベント ID は、特定のコードを知らなくてもカテゴリ別に扱うことができる、ある種の構造 (電子メールや HTTP で使用される応答コードの理論と同様) に従う必要があります。
たとえば、最初の桁は一般的なクラスを詳述できます。1xxx は「開始」操作、2xxx は通常の動作、3xxx はアクティビティ トレース、4xxx は警告、5xxx はエラー、8xxx は「停止」操作、9xxx は致命的なエラー、等
2 桁目は領域の詳細を示すことができます。たとえば、21xx はデータベース情報 (41xx はデータベース警告、51xx はデータベース エラー)、22xx は計算モード (42xx は計算警告など)、23xx は別のモジュールなどです。
割り当てられた構造化されたイベント ID をフィルターで使用することもできます。
Q: トレースを使用する場合、Trace.Correlation.StartLogicalOperation を使用しますか?
A: Trace.CorrelationManager は、あらゆる種類のマルチスレッド環境 (最近ではほぼすべての環境) でログ ステートメントを関連付けるのに非常に役立ちます。
相互に関連付けるために、論理操作ごとに少なくとも 1 回、ActivityId を設定する必要があります。
Start/Stop と LogicalOperationStack は、単純なスタックベースのコンテキストに使用できます。より複雑なコンテキスト (非同期操作など) の場合、TraceTransfer を新しい ActivityId に (変更する前に) 使用すると、関連付けが可能になります。
Service Trace Viewer ツールは、(WCF を使用していない場合でも) アクティビティ グラフを表示するのに役立ちます。
Q: このコードは手動で作成しますか? それとも、なんらかのアスペクト指向プログラミングを使用しますか? コード スニペットを共有しますか?
A: LogicalOperationScope など、(a) 作成時にコンテキストを設定し、(b) 破棄時にコンテキストをリセットするスコープ クラスを作成するとよいでしょう。
これにより、次のようなコードを記述して、操作を自動的にラップできます。
using( LogicalOperationScope operation = new LogicalOperationScope("Operation") )
{
// .. do work here
}
スコープの作成時に、必要に応じて最初に ActivityId を設定し、StartLogicalOperation を呼び出してから、TraceEventType.Start メッセージをログに記録できます。Dispose では、Stop メッセージをログに記録し、StopLogicalOperation を呼び出すことができます。
Q: トレース ソースに対して何らかの形式の粒度を提供していますか? たとえば、WPF TraceSource を使用すると、さまざまなレベルで構成できます。
A: はい。システムが大きくなるにつれて、複数のトレース ソースが有用/重要になります。
警告と上記のすべてのメッセージ、または情報と上記のすべてのメッセージを一貫してログに記録したい場合がありますが、適度なサイズのシステムでは、アクティビティ トレース (開始、停止など) と詳細ログの量が多すぎます。
すべてをオンまたはオフにするスイッチを 1 つだけ持つのではなく、一度にシステムの 1 つのセクションに対してこの情報をオンにできると便利です。
このようにして、通常のログ (すべての警告、エラーなど) から重大な問題を特定し、必要なセクションに「ズームイン」して、それらをアクティビティ トレースまたはデバッグ レベルに設定することができます。
必要なトレース ソースの数は、アプリケーションによって異なります。たとえば、アセンブリごと、またはアプリケーションの主要セクションごとに 1 つのトレース ソースが必要な場合があります。
さらに細かく制御する必要がある場合は、個別のブール スイッチを追加して、生のメッセージ ダンプなどの特定の大容量トレースをオン/オフにします。(または、WCF/WPF と同様に、別のトレース ソースを使用することもできます)。
また、アクティビティ トレースと一般的な (その他の) ログのトレース ソースを別々にすることを検討することもできます。これにより、フィルターを希望どおりに正確に構成することが少し簡単になる可能性があります。
異なるソースが使用されている場合でも、ActivityId を介してメッセージを関連付けることができることに注意してください。そのため、必要な数だけ使用してください。
リスナー
Q: どのログ出力を使用していますか?
これは、作成しているアプリケーションの種類と、ログに記録される内容によって異なります。通常、異なるものは異なる場所に配置されます (つまり、複数の出力)。
私は通常、出力を次の 3 つのグループに分類します。
(1) イベント - Windows イベント ログ (およびトレース ファイル)
たとえば、サーバー/サービスを作成する場合、Windows でのベスト プラクティスは、Windows イベント ログを使用することです (レポートする UI がありません)。
この場合、致命的、エラー、警告、および (サービス レベルの) 情報イベントはすべて、Windows イベント ログに記録されます。情報レベルは、これらのタイプの高レベル イベント、イベント ログに記録したいイベント (「サービス開始」、「サービス停止」、「Xyz への接続」、場合によっては「スケジュール開始」など) 用に予約する必要があります。 、「ユーザーがログオンしました」など。
場合によっては、イベント ログへの書き込みを、トレース システム経由ではなく、アプリケーションの組み込み部分にしたい場合があります (つまり、イベント ログ エントリを直接書き込みます)。これは、誤ってオフにできないことを意味します。(相関できるように、トレース システムで同じイベントを記録する必要があることに注意してください)。
対照的に、Windows GUI アプリケーションは通常、これらをユーザーに報告します (ただし、Windows イベント ログにも記録される場合があります)。
イベントには、関連するパフォーマンス カウンター (エラー数/秒など) がある場合もあります。イベント ログへの直接書き込み、パフォーマンス カウンター、トレース システムへの書き込み、およびユーザーへのレポートを調整して、イベントが発生するようにすることが重要です。同時に。
つまり、ユーザーが特定の時間にエラー メッセージを表示した場合、Windows イベント ログで同じエラー メッセージを見つけ、トレース ログで同じタイムスタンプを持つ同じイベントを (その他のトレースの詳細と共に) 見つけることができるはずです。
(2) アクティビティ - アプリケーション ログ ファイルまたはデータベース テーブル (およびトレース ファイル)
これは、システムが実行する通常のアクティビティです。たとえば、Web ページの提供、株式市場での取引の登録、注文の実行、計算の実行などです。
アクティビティ トレース (開始、停止など) は、ここで (適切な粒度で) 役立ちます。
また、特定のアプリケーション ログ (監査ログと呼ばれることもあります) を使用することも非常に一般的です。通常、これはデータベース テーブルまたはアプリケーション ログ ファイルであり、構造化データ (つまり、一連のフィールド) が含まれています。
アプリケーションによっては、ここで少しぼやけることがあります。良い例は、各リクエストを Web ログに書き込む Web サーバーです。同様の例として、各操作がアプリケーション固有の詳細とともにログに記録されるメッセージング システムまたは計算システムが考えられます。
あまり良くない例としては、株式市場の取引や販売注文システムがあります。これらのシステムでは、重要なビジネス価値があるため、おそらくすでにアクティビティをログに記録していますが、それらを他のアクションに関連付けるという原則は依然として重要です。
カスタム アプリケーション ログだけでなく、多くの場合、アクティビティには関連するパフォーマンス カウンター (1 秒あたりのトランザクション数など) もあります。
一般に、さまざまなシステム間でアクティビティのログを調整する必要があります。つまり、パフォーマンス カウンターを増やしてトレース システムにログを記録すると同時に、アプリケーション ログに書き込みます。すべてを同時に (またはコード内で連続して) 実行すると、問題のデバッグが容易になります (コード内の異なる時間/場所ですべてが発生する場合よりも)。
(3) デバッグ トレース - テキスト ファイル、または XML またはデータベース。
これは、Verbose レベル以下の情報です (生データ ダンプのオン/オフを切り替えるカスタム ブール スイッチなど)。これにより、システムがサブアクティビティ レベルで行っていることの内臓または詳細が提供されます。
これは、アプリケーションの個々のセクション (したがって複数のソース) に対してオン/オフできるようにするレベルです。このようなものが Windows イベント ログを乱雑にするのは望ましくありません。データベースが使用されることもありますが、一定時間後にパージされるローリング ログ ファイルである可能性が高くなります。
この情報とアプリケーション ログ ファイルの大きな違いは、構造化されていないことです。アプリケーション ログには、To、From、Amount などのフィールドが含まれる場合がありますが、詳細なデバッグ トレースは、プログラマーが入力したもの、たとえば「値 X={value}、Y=false のチェック」、または「やった、やり直そう」。
重要なプラクティスの 1 つは、アプリケーション ログ ファイルまたは Windows イベント ログに入力した内容も、同じ詳細 (タイムスタンプなど) でトレース システムに記録されるようにすることです。これにより、調査時にさまざまなログを関連付けることができます。
複雑な相関があるために特定のログ ビューア (サービス トレース ビューアなど) を使用する場合は、XML などの適切な形式を使用する必要があります。それ以外の場合は、通常は単純なテキスト ファイルで十分です。下位レベルでは情報の大部分が構造化されていないため、配列のダンプ、スタック ダンプなどを見つけることができます。上位レベルでより構造化されたログに関連付けることができれば、物事は次のようになります。大丈夫。
Q: ファイルを使用する場合、ローリング ログを使用しますか、それとも単一のファイルのみを使用しますか? 人々がログを利用できるようにするにはどうすればよいですか?
A: ファイルの場合、通常、管理の容易性の観点からローリング ログ ファイルが必要です (System.Diagnostics では、VisualBasic.Logging.FileLogTraceListener を使用するだけです)。
可用性は、システムによって異なります。ファイルについてのみ話している場合、サーバー/サービスの場合、必要に応じてローリングファイルにアクセスできます。(Windows イベント ログまたはデータベース アプリケーション ログには、独自のアクセス メカニズムがあります)。
ファイル システムに簡単にアクセスできない場合は、データベースへのデバッグ トレースの方が簡単な場合があります。[つまり、データベースの TraceListener を実装する]。
私が Windows GUI アプリケーションで見た興味深い解決策の 1 つは、実行中に非常に詳細なトレース情報を「フライト レコーダー」に記録し、問題がなければシャットダウンすると、単にファイルを削除するというものでした。
ただし、クラッシュまたは問題が発生した場合、ファイルは削除されませんでした。エラーを検出した場合、または次回の実行時にファイルに気付き、圧縮 (7zip など) して電子メールで送信するなどのアクションを実行できます。
最近の多くのシステムには、中央サーバーへの障害の自動レポートが組み込まれています (プライバシー上の理由などでユーザーに確認した後)。
閲覧中
Q: ログを表示するためにどのツールを使用しますか?
A: さまざまな理由で複数のログがある場合は、複数のビューアーを使用します。
Notepad/vi/Notepad++ またはその他のテキスト エディタは、プレーン テキスト ログの基本です。
転送を伴うアクティビティなどの複雑な操作がある場合は、明らかに、Service Trace Viewer などの専用ツールを使用します。(ただし、必要ない場合は、テキスト エディターの方が簡単です)。
私は通常、高レベルの情報を Windows イベント ログに記録するので、構造化された方法で概要をすばやく把握できます (きれいなエラー/警告アイコンを探してください)。ログに十分な量がない場合にのみ、テキスト ファイルの検索を開始する必要がありますが、少なくともログは出発点となります。(この時点で、ログ全体が調整されていることを確認すると便利です)。
一般に、Windows イベント ログは、MOM や OpenView などの監視ツールでこれらの重要なイベントを利用できるようにもします。
その他 --
データベースにログインすると、情報を簡単にフィルタリングおよびソートできます (たとえば、特定のアクティビティ ID を拡大します。(テキスト ファイルでは、Grep/PowerShell などを使用して、必要な特定の GUID をフィルタリングできます)。
MS Excel (または別のスプレッドシート プログラム)。これは、異なる値が異なる列に入るように適切な区切り文字を使用してインポートできる場合、構造化または半構造化された情報を分析するのに役立ちます。
デバッグ/テストでサービスを実行するときは、簡単にするために通常はコンソール アプリケーションでホストします。色付きのコンソール ロガーが便利だと思います (たとえば、エラーは赤、警告は黄色など)。カスタム トレース リスナーを実装する必要があります。
フレームワークにはカラー コンソール ロガーやデータベース ロガーが含まれていないため、現時点では必要に応じてこれらを作成する必要があります (それほど難しくありません)。
いくつかのフレームワーク (log4net、EntLib など) が車輪の再発明に時間を浪費し、基本的なロギング、フィルタリング、およびテキスト ファイルへのロギング、Windows イベント ログ、および XML ファイルをそれぞれ独自に再実装したことは、本当に腹立たしいことです。異なる方法 (ログステートメントはそれぞれ異なります)。その後、データベース ロガーなどの独自のバージョンを実装しましたが、そのほとんどは既に存在しており、必要なのは System.Diagnostics 用のトレース リスナーを 2 つ追加するだけでした。重複した努力の大きな無駄について話してください。
Q: ASP.NET ソリューションを構築している場合、ASP.NET ヘルス モニタリングも使用しますか? ヘルス モニター イベントにトレース出力を含めますか? Trace.axd はどうですか?
これらは必要に応じてオン/オフできます。サーバーが特定のものにどのように応答するかをデバッグするには、Trace.axd が非常に便利だと思いますが、使用頻度の高い環境や長期間のトレースでは一般的には役に立ちません。
Q: カスタム パフォーマンス カウンターはどうですか?
プロフェッショナルなアプリケーション、特にサーバー/サービスの場合、パフォーマンス モニター カウンターと Windows イベント ログへのログ記録の両方が完全に装備されていることを期待しています。これらは Windows の標準ツールであり、使用する必要があります。
使用するパフォーマンス カウンターとイベント ログのインストーラーが含まれていることを確認する必要があります。これらはインストール時に作成する必要があります (管理者としてインストールする場合)。アプリケーションが正常に実行されている場合、管理者権限は必要ありません (したがって、不足しているログを作成することはできません)。
これは、非管理者として開発を練習する正当な理由です (サービスをインストールする必要がある場合などに備えて、別の管理者アカウントを用意してください)。イベント ログに書き込む場合、.NET は、最初に書き込むときに不足しているログを自動的に作成します。非管理者として開発している場合は、これを早期に見つけて、顧客がシステムをインストールした後、管理者として実行していないために使用できないという厄介な驚きを回避できます。