2009-03-26 9 views
8

私は自分のコードに含める必要があるログの量に悩まされています。.NETではパッシブロギングが可能ですか?

これが完了したか、誰かがより良いアイデアを出しているかどうかはわかりませんが、誰かがアプリケーションにロガーを「注入する」方法があるのだろうかと疑問に思っていました。スレッドと静かのような事をすることなく、彼らが起こるとしてのプロセスを記録します:

public void MyProcess(int a, string b, object c) 
{ 
    log(
    String.Format(
     "Entering process MyProcess with arguments: [a] = [{0}]; [b] = [{1}]; [c] = [{2}]", 
     a.ToString(), 
     b, 
     c.ToString() 
); 

    try 
    { 
    int d = DoStuff(a) 
    log(
     String.Format(
     "DoStuff({0}) returned value {1}", 
     a.ToString(), 
     d.ToString() 
    ) 
    ); 
    } 
    catch (Exception ex) 
    { 
    log(
     String.Format("An exception occurred during process DoStuff({0})\nException:\n{1}", 
     a.ToString(), 
     ex.ToString()) 
    ) 
    } 
} 
私は私のロガーに言うことができればどのような素晴らしいだろうことです

:それは、その後に行くのすべてを監視します

Monitor(MyClass.MyMethod) 

その方法の中には、wiこれらのメソッドに渡された値、例外などが発生します。

過去にこのようなものを実装した人はいますか?それでもになりますか?このような方法でログインするのはパイプの夢ですか?

私はこれを行うものを設計するのが大好きですが、どこから始めたらいいのか分かりません。もちろん、私はホイールを再発明したくないのですが、すでに完成していれば、誰かが私を正しい方向に向けることができれば素晴らしいことでしょう。

任意の提案をありがたく受け取ったことでしょう...

編集:私は、私がログに必要な詳細レベルへと照会の回答にコメントしようと思いました。重要なロギングが設定されている場合は、例外とともに特定の情報だけがログに記録されるのに対して、詳細なロギングが指定されていればすべてがログに記録されるように、構成可能なロギングレベルを設定する必要があることがよくあります。致命的なロギングが設定されていると、アプリケーションを終了させる情報だけが記録されます。このようなものは設定可能か、AOPはログレベルの数に応じて3つまたは4つの異なるビルドを必要としますか?あなたは「周り」方法をログに記録するPostSharpを使用することができます致命的、クリティカル、情報、詳細な

+0

これは実行時に設定することができますが、実行時に実行されるロガーは引き続きすべての情報を受け取り、何を記録するかを決定する必要があります。すべての情報のオーバーヘッドがロガーに渡されることを望まない場合、唯一の方法は異なるビルドを持つことです。 –

答えて

9

私は頻繁に4つのレベルを使用しています。これはまさにAOPがうまくいくものです。あなたは特にログのためのプラグインであるLog4PostSharpから始めたいと思うかもしれません。

+0

過去にPostSharpに問題がありました。チームビルドとうまく組み合わせられませんでした。実際には、コンパイラによって生成されたILを編集し、編集されたバイナリをどこに書き込むかについて混乱します。多分それは今修正されているでしょう。いずれにしても私のILを書き直しても神経質になってしまった。 –

+0

コード契約については、お買いものに間違いがありますか? –

+0

私は分かりません。それはILを書き換えますか? Microsoftが十分にテストしたシナリオを使用していますか?私はPostSharpがILを書き換える数少ないコードのうちの唯一のものであることに懸念していました。チームビルドなどで考慮しないかもしれません。 「コード契約」のURLを入力してください。 –

4

これはAspect Oriented Programmingの古典的な例です。非常に良いCLRベースのライブラリについては、PostSharpを参照してください。

4

AoPロギングの例:メソッドの前後に何かを貼り付ける場合のテキストブック(AoPはありますが、アイデアを得ているかどうかはわかりません)の1つです。

AoPのルートを調べたい場合は、PostSharpがMicrosoft Unity(IoC too)の城とともに人気のあるものの1つです。 AOPの

一つの単純な例は、あなたの代わりに実際のメソッド内のメソッド呼び出しを追加するの、メソッドの前と後のあなたのコードを追加しています。あなたはC#で質問にタグを付けたので、それをログに記録する拡張メソッドを調べるだけでよいでしょう。これは既にthis questionです。

私は実践的なアプローチを取っています:どのくらいの実際のロギングをしていますか?コードを読んでいる人を驚かせる代わりに、拡張メソッドを使うだけで逃げることができますか?ロギングbuilt into the .NET frameworkはすでにまともです。

+0

さて、私は拡張メソッドで逃げることを考えましたが、クライアントはconfigファイルで定義された可変レベルのログを必要とします。したがって、設定ファイルで指定されたログのレベルによって、ログの詳細が異なります。これを妨げるものはどれですか? – BobTheBuilder

+0

設定ファイル、情報/警告/エラー、カテゴリですべて定義できます。 –

+0

PostSharpなどのいずれの場合でも、ロギングAPIのEnterprise Libraryを参照する必要があります。ログに記録する内容、場所、形式を構成できます。 –

1

Jonが言及したロギングメソッドに加えて、プログラムフローをトレースするためのVSのもう1つの便利な機能に注目する価値があります。これは、単にメッセージを出力したりマクロを実行するブレークポイント

あなたのブレークポイントを右クリックし、When Hit ...コンテキストメニュー項目を選択します。

他の非常に便利な機能は、System.DiagnosticsのTraceオブジェクトとTrace Listnerです。

+0

私はこの機能を使用しますが、開発段階では優れていますが、クライアントが本番環境でアプリケーションを個別にデバッグするのに役立つわけではありません。 – BobTheBuilder

0

最近、IDisposableインターフェイスを使用してロギングコンテキストで領域をラップするロギングライブラリを作成しました。

using(var logger = new LogSite("methodName", new object[] { p1, p2, p3 }) 
{ 
    // code that does stuff goes here 
} 

LOGSITEの目的は、あなただけ取得するMethodBase.GetCurrentMethod()と使用リフレクションを使用できるようにMethodBaseとしてコンストラクタのための便利なオーバーロードの束を持っている:基本的に、あなたはこのように使用LOGSITE使い捨てのオブジェクトがありますメソッドとパラメータの実際の名前(ハードコードされた文字列ではなく)。

これは動作します。コンストラクタでは、ログにすべてのトレース情報を書き込んでブロックに入ったことを示します。 Disposeメソッドでは、終了エントリが書き込まれます。

廃棄中に、Marshal.GetExceptionCode()もゼロ以外の値をチェックして、使用しているコードが例外をスローしたか、正常に終了したかどうかを確認します。それはあなたに例外を与えるものではないので、catchハンドラに明示的に記録する必要がありますが、その領域の "合格/不合格"を示します。これにより、単一のメソッドでこれらのブロックをたくさん持つことができ、どれが例外を正確にスローしたのかを知ることができるので、ロギングスコープをメソッドだけよりも具体化することができます。ロガーがすでにメソッド名、パラメータ情報、およびすべてのことを知っている、とのための内部メソッドを持ってい

try { ... } 
catch (Exception ex) 
{ 
    logger.LogException(ex); 
} 

:「ロガー」オブジェクトが利用可能になりましありますので、同じように、あなたのcatchハンドラがちょうど見えます。また

、例外情報を形式化する。

この高レベルオブジェクトの下にあるアーキテクチャに入る前に、前に決定した「合否」を処理する「LogDisposition」の概念があり、「LogEntryType」の概念があります列挙型)は、渡されているログエントリの種類(エラー、トレースなど)を示します。

実際にロギングを行うのは、単なるパブリッシャー/リスナーパターンです。パブリッシャは、渡されたログエントリを取得し、マルチキャストデリゲートとよく似ています。LogListenerインスタンスのレジストリを保持しています(プログラムの開始時に設定するか、必要に応じて動的に追加する必要があります)。 。

LogListenersは、どのような種類のログエントリをフィルタリングするかをフィルタリングします。したがって、エラーのない状態でメソッドのエントリポイントと終了ポイントを使用しない場合は、ログ。これは実行時に制御することができ、ユーザは詳細なログを任意にオンまたはオフにするなどの作業を行うことができます。パブリッシャーはさまざまなログリスナーに書き込むことができるので、ファイルに書き込んだり、データベースに書き込んだり、GUIにエラー通知を表示したりすることができます。

これはかなり良いシステムですが、相対的に豊富なロギングを得るためには比較的少量のコーディングが必要です。

もしあなたが望むなら、私はあなたにコードサンプルを与えることができます...私の(ほぼ完全に非アクティブな)ブログを通して私に連絡することができます(私のアカウントのプロフィールを参照)。

希望に役立ちます。

0

すべてのプロジェクトでopensource​​を使用します。これは、ログは基本的に同じくらい簡単ですなど、あなたがデータベース、zipファイル、ローリングログファイル、RRSフィード、Telnetクライアントにログインすることができ拡張子のすべての種類の非常に単純な実装です:

'Will print stack trace after message' 
log.err(ex.message,ex) 

log.warn("warn") 
log.info("info") 
log.debug("debug") 

なロギングパラメータあなたのアプリが実行時に出力フォーマットと出力レベルをすべてリアルタイムで読み取ることができます。

関連する問題