.NETでのログとトレースのベストプラクティス


53

私はトレースとログについて多くのことを読んでおり、問題のベストプラクティスの黄金律を見つけようとしましたが、何もありません。優れたプログラマーは優れたトレースを生成すると言いますが、それはそのように言えます。それは経験からもたらされなければなりません。

また、ここやインターネットで同様の質問を読んだことがありますが、質問が詳細を欠いているためか、私が尋ねているものと同じものではなく、満足のいく答えもありません。

そのため、デバッガーをアタッチできない場合、トレースはアプリケーションのデバッグの経験をある程度再現すべきだと人々は言います。アプリケーションの各コントロールポイントでどのパスが使用されているかを確認できるように、十分なコンテキストを提供する必要があります。

さらに詳しく説明すると、「イベントログは、詳細な制御フローではなく主要な状態をキャプチャするという点でトレースとは異なる」という点で、トレースとイベントログを区別することもできます。

ここで、System.Diagnostics名前空間にある標準の.NETクラスのみを使用して、トレースとロギングを実行したいとします。TraceSourceクラスは静的Traceクラスよりもジョブに適していると考えました。トレースレベルを区別し、TraceSourceクラスを使用すると、イベントタイプを通知するパラメータを渡すことができ、Traceクラスを使用する必要があるためです。Trace.WriteLineIfその後、のようなものを確認するSourceSwitch.TraceInformationとしSourceSwitch.TraceErrors、それはさえのような性質がないTraceVerboseかをTraceStart

これらすべてを念頭に置いて、次のようにすることをお勧めします。

  • メソッドを開始するときに「開始」イベントをトレースします。これは、メソッドに渡されるパラメーター値のストリング表現とともに、単一の論理操作またはパイプラインを表す必要があります。
  • データベースにアイテムを挿入するときに「情報」イベントをトレースします。
  • 重要なif / elseステートメントで1つのパスまたは別のパスを取るときに「情報」イベントをトレースします。
  • 回復可能なエラーであるかどうかに応じて、catchブロックで「クリティカル」または「エラー」をトレースします。
  • メソッドの実行が終了したら、「停止」イベントをトレースします。

また、VerboseおよびWarningイベントタイプをトレースする最適なタイミングを明確にしてください。優れたトレース/ロギングを備えたコードの例があり、共有したい場合は、それが優れているでしょう。

注:ここでいくつかの良い情報を見つけましたが、探しているものはまだ見つかりません:http : //msdn.microsoft.com/en-us/magazine/ff714589.aspx


stackoverflowでのazureにデプロイされたネットでのロギングの優先方法も役立つかもしれません。
k3b

ロギングに適切なパターンを使用する完全なソースコードサンプルアプリケーション
キケネット

正直に言うと... .NETで作業している場合は、おそらくNew Relicのようなものをインストールして、完了と呼ぶだけでしょう。(ただし、これが投稿された時点では良い選択肢ではないかもしれません)
svidgen

回答:


17

トレースの種類の重要性は、トレースがコード内のどこにあるかではなく、トレースされたメッセージが多かれ少なかれ重要であるために選択する必要があります。例:

メソッドを開始するときに「開始」イベントをトレースします。これは、メソッドに渡されるパラメーター値の文字列表現とともに、単一の論理操作またはパイプラインを表す必要があります。

論理演算を開始するときに開始タイプを使用します。これは、開始トレースがメソッドの先頭になければならないという意味ではなく、メソッドに開始トレースがなければならないという意味でもありません。

これは、ほとんどの場合、メソッドの先頭から実際に論理演算が開始されると言われています。それ以外の場合は、コードが正しくリファクタリングされているかどうかを自問する必要があります。

パラメータのトレースも悪い考えかもしれません。何をトレースするか、ケースバイケースで考える必要があります。たとえば、メソッドのパラメータをトレースするのは本当に悪いvoid Authenticate(string userName, string plainPassword)です。

データベースにアイテムを挿入するときに「情報」イベントをトレースします。

場合によります。一部のアイテムはトレースする必要がありますが、すべてのアイテムではありません。

  • たとえば、実際にデータベースにログアイテムを挿入しているとします。ログをトレースしますか?そして、トレースを記録しますか?そして、トレースのロギングをトレースしますか?
  • 別の例:機密データを挿入しています。これには監査が必要です。挿入を監査したのに、なぜトレースするのですか?

重要なif / elseステートメントで1つのパスまたは別のパスを取るときに「情報」イベントをトレースします。

繰り返しますが、それは依存します。

天気に応じて、catchブロックで「クリティカル」または「エラー」をトレースします。これは回復可能なエラーです。

回復不能なエラーの後に実行されるアクションは、トレース以上の場合があります。たとえば、サーバー側では、さらに分析するためにデータベースに例外を保存します。また、一部の例外は他の例外ほど重要ではなく、トレースを必要としません。

メソッドの実行が終了したら、「停止」イベントをトレースします。

最初のポイントを参照してください。

VerboseおよびWarningイベントタイプをトレースする最適なタイミングを明確にしてください。

冗長:

詳細は、何かが本当にうまくいかないときにトレースする必要があるものをトレースするために使用されます。ほとんどの場合、冗長メッセージのトレースを無効にしますが、エッジケースで何かが失敗する理由を理解するために、コードの一部をデバッグする必要がある場合があります。

通常、アプリケーションフローを非常によく理解できる詳細なメッセージがたくさんあります。また、これらのメッセージは次の理由でほとんど無効にする必要があることを意味します。

  • そうしないと、ログが非常に速く成長し、
  • ほとんどの場合、それらは必要ありません。
  • アプリケーションフローに関する機密データが含まれている場合があります。

デバッガーにアクセスできない場合に使用する必要があるツールとして、verboseを考えてください。

警告:

警告タイプのトレースは、何か間違った重要なことが発生したときに使用されますが、エラーとして扱われるほど重要ではありません。たとえば、RAMが少ないと警告が発せられることがありますが、通常よりも遅くなる場合でもアプリケーションを続行できるため、エラーをトレースする理由はありません。

例:

  • 例1:アプリケーションは、ユーザーが開くことを要求したファイルを開けませんでした。ファイルは存在し、使用されていません。アクセス許可は正しく設定されていますが、ファイルを開くことがブロックされています。この場合、アプリケーションはこのケースを管理できず、ユーザーの期待どおりに動作し続ける(つまり、実際にファイルを読み取る)ため、エラーをトレースします

  • 例2:最初の例でエラーを調べた後、ファイルパスが259文字より長いという事実がエラーの原因であることがわかります。したがって、キャッチするコードをリファクタリングしますPathTooLongException。次回、ユーザーが同じファイルを開こうとすると、アプリケーションの新しいバージョンは、ファイルが長すぎるため、このファイルを開くためにフルパスを短くするために別のフォルダーに移動する必要があることを説明するメッセージを表示しますこのアプリケーション。また、メッセージをトレースします

  • 例3:アプリケーションが小さなファイルを開いて解析するのに20秒かかりましたが、ほとんどのファイルは開いて解析するのに10〜100ミリ秒かかります。関連情報を含む警告をトレースします。ファイルが実際にあるディスクのタイプ、ファイルシステム、ファイルのサイズ、費やした正確な時間、コンピューターの電源を入れていた時間などです。ファイルを開くのに数秒かかると、何が起こるかを見つけるためにトレースを行います。たとえば、コンピュータが起動したばかりのときにネットワーク共有からファイルをロードするのに非常に時間がかかることがわかります。遅延はネットワークによるものであり、アプリケーションとは関係がないことをユーザーに説明します。

  • 例4:開いたファイルが正しく表示されません。詳細なトレースを有効にすると、データがファイルからどのようにロードされ、次にどのように解析されるかを実際に確認できます。


私が働いている場所で使用しているパターンの1つは、「KnownErrors」を警告として記録し、「UnknownErrors」をエラーとして記録することです。インフラストラクチャと警告の処理方法によっては適切でない場合がありますが、私たちにとってはうまく機能します。
アンドリューピリザー

5
 > say I want to do my tracing and logging using only the standard .NET classes

System.Diagnostics どのトレース情報がどこに行くべきかを設定できるので素晴らしいです(ファイル、イベントログ、データベース、...)

残念ながら、使用したい場合はSystem.Diagnostics、事前に(設計時に)どのトレースストリームを追跡できるかを事前に知る必要があります。(サンプル記事では、これらはTransfer、Resume、Suspend、...)です。これらは、無効、デバッグレベルまたはエラーレベルに設定できます。

実行時にclasslevel / namespacelevelでロギングの詳細度を決定できるロギングシステムが必要です。たとえば、すべてのDebug以降はfromですMyNamespace.Business.*が、ではありませんMyNamespace.Business.Calculations

log4net(またはCommon.logging)を使用している場合、すべてのクラスが独自のロガーを取得するため、どのクラスがどのレベルで記録されるかを簡単に決定できます。

データベース操作は別のクラスにあるため、個別のルールはもう必要ありません

Trace an "Information" event when inserting an item into the database.

代わりに、私はこれらのガイドラインを持つことを好む:

  • Tracelevelは基本的なワークフローを表示する必要があります
  • Debuglevelは、詳細なデータとワークフロー内の処理を表示する必要があります。これには、プログラムフローの決定(理由がある場合)(アイテムがDBに存在しなかったため新しいアイテムを作成する)
  • サービスを開始/停止するためのインフォレベルと、開始されたワークフロー/ GUIアクションごとに1つのエントリ

いい情報だと思います、ありがとう!それでも、元の質問で尋ねたように、VerboseおよびWarningイベントタイプの使用方法を明確にしてください。また、私は他の人々に彼らの視点で貢献するようお願いします。なぜなら、このトピックは私がインターネットで見たよりも深い探究に値するからです。
レヴィダード

4

Storyフレームワークを試すことができます。これは、すべてのログをコンテキストに書き込む(および他の関連情報を追加する)ので、ログを記録する独自のアプローチがあります。

ストーリーの開始および終了として、「開始」および「停止」の概念が自動的に追加されます。

また、ルールベースのシステムを使用すると、各ストーリー(コンテキスト)の処理内容を情報に基づいて制御できます。たとえば、エラーのあるストーリーや「admin」ユーザーからのストーリーをすべて印刷できます。

詳細は、このブログ記事



1
より多くの情報を含む回答を更新
Amit Apple
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.