2009-07-30 7 views
7

私は、常にデバイスから値を読み取るコンポーネントを持っています。現在、それは{n}秒ごとに更新され、その値を持つデバッグメッセージをILogのインスタンスに記録します。log4net - N番目のメッセージのみを記録するフィルタ?

1秒ごとに私はあまりにも頻繁に、私は気にしないと、それはあまりにも多くのログスペースを食べる。しかし、私は確かにそのコンポーネントから10番目または30番目のメッセージをすべてキャプチャすることに興味があるので、そのコンポーネントの一般的な要点を得ることができます。

私は自分自身のILogの実装に慣れていないこの方法を知っている人はいませんか?

答えて

11

これはおそらく手遅れですが、フィルタを実装できます。 http://www.mail-archive.com/log4net-user%40logging.apache.org/msg02517.htmlは、例外が記録される頻度を制限するフィルタを実装する方法を示しています(例外の種類が最後の例外の種類と同じで、指定された時間が経過していない場合)。ここで

は、そのリンクから実際のフィルタのソースコードです:

public class ExceptionThrottleFilter : FilterSkeleton 
{ 
    private DateTime lastException = DateTime.MinValue; 
    private Type exceptionType = typeof(Exception); 
    private int threshold = 5; // seconds 

    public override void ActivateOptions() 
    { 
    base.ActivateOptions(); 
    } 

    public override FilterDecision Decide(LoggingEvent loggingEvent) 
    { 
    if (loggingEvent.ExceptionObject != null && loggingEvent.ExceptionObject.GetType) == exceptionType) 
    { 
     if (loggingEvent.TimeStamp.Subtract(lastException).TotalSeconds > threshold) 
     { 
     lastException = loggingEvent.TimeStamp; 
     return FilterDecision.Accept; 
     } 
     else 
     { 
     return FilterDecision.Deny; 
     } 
    } 
    else 
    { 
     return FilterDecision.Neutral; 
    } 
    } 

    public Type ExceptionType 
    { 
    get { return exceptionType; } 
    set { exceptionType = value; } 
    } 

    public int Threshold 
    { 
    get { return threshold; } 
    set { threshold = value; } 
    } 
} 

それはこのように構成されます:スロットル」にそれを修正する非常に簡単になるように

<filter type="Company.Project.Logging.ExceptionThrottleFilter"> 
    <threshold value="2" /> 
    <exceptionType value="System.ApplicationException" /> 
</filter> 

に思えます"繰り返すメッセージ。このようなたぶん何か(未テスト):

public class DuplicateMessageThrottleFilter : FilterSkeleton 
{ 
    private string lastMessage; 

    public override void ActivateOptions() 
    { 
    base.ActivateOptions(); 
    } 

    public override FilterDecision Decide(LoggingEvent loggingEvent) 
    { 
    string newMessage; 
    if (loggingEvent.MessageObject != null) 
    { 
     newMessage = loggingEvent.MessageObject.ToString(); 
    } 

    if (newMessage.Equals(lastMessage)) 
    { 
     return FilterDecision.Deny; 
    } 

    lastMessage = newMessage; 
    return FilterDecision.Accept; 
    } 
} 

どのようにそれを行うには、それが繰り返された回数と記録されたメッセージに注釈を付けるのはいいことかもしれませんが、私には明らかにされていません。

Some message. 
Some message. 
Some message. 
Look, a new message. 
Some message. 
Some message. 
Look, a new message. 

Some message. (3 times) 
Look, a new message. 
Some message. (2 times) 
Look, a new message. 

ForwardingAppenderまたはBufferingForwardingAppenderのおそらくいくつかの種類:このような何かを生成することができます。それは常に1つのメッセージの背後にあるでしょう。メッセージが入ります。「RepeatedMessageAppender」はそのメッセージを保持します。最後のメッセージと異なる場合は、最後のメッセージを「本当の」アペンダーに転送します(「繰り返しカウント」が0より大きい場合は、転送前に最後のメッセージに番号を追加します - これは私の一部です)。 Appenderに渡されるLoggingEventを変更するのは簡単ではないと思うからです)。最後のメッセージと同じ場合は、カウンタをインクリメントして転送しないでください。 "RepeatedMessageAppender"は1つ遅れているため、おそらくBufferingForwardingAppenderでなければならず、Flushを実装する必要があります。

多分、あなた(または他の誰か)がこの情報を役立つでしょう。

+0

確かに非常に便利です。 「何回」タグ付けするには、回数を格納するプロパティを使用し、value = "%message(%property {numberOfSimilar} times)"のようにPatternLayoutで表示することをお勧めします。このプロパティはGlobalContext.Properties [Decision(LoggingEvent)]で設定できます["numberOfSimilar"] ++; – PPC

+0

これは決して遅すぎることはありません... – KornMuffin

1

あなたが記録しているものによって異なります。 1秒ごとに何かが記録されている場合、おそらくあなたは記録しているものを再訪するべきです。

シンプルなメッセージをハッシュしてしばらくしてから印刷することができます。

+0

私はそれをログに記録していません、私はそのコンポーネントのデバッグレベルのロギングを無効にしますが、アプリケーションが現在デバイス上にあると思う値をログに記録したい場合はオプションとして保持します。ハッシングは良い解決策のように聞こえますが、簡単な方法で設定するのですか? –

+0

私は「ハッシュ類似して印刷を待つ」に同意しません。これはロギングメカニズムの責任であり、何を印刷すべきか疑問に思うのはビジネスコードの責任ではありません。あなたのマシンは1秒に1回「私は立ち上がっています」と言っています。これは、マシン自体ではなく、特に2つの異なるログが必要な場合に、これを「13:44以降」に変換するロギングロジックです。機構。 – PPC