2016-07-08 6 views
1

サーバまたはデータベースのエラーにより、サーバログファイルに何千もの同じスタックトレースが発生します。今日は1か月前とは違うエラー/スタックトレースかもしれません。しかし、ログファイルが完全に回転してしまい、以前に何が起こったのかがわかりません。 (代わりに、ディスクスペースが足りなくなってしまいます。私のコントロール外の理由から、この問題は別に解決しています)。とにかく、私は同じスタックトレースの何千ものコピーを必要としません - ちょうど十数かそれほど十分であるはずです。log4jの反復ログ出力を自動的に折りたたむ方法

私はlog4j/log4j2 /別のシステムが自動的に繰り返しエラーを崩壊させてログファイルをいっぱいにしないようにしたいと思います。たとえば、同じ場所からの10または100回の例外のしきい値によって、log4jがカウントを開始し、来るのを止めるまで待ってから、何回出現したかのカウントを出力する可能性があります。

あらかじめ作成された解決策が存在します(リンク付きの簡易アンケートが最適です)。これが自分自身を実装すべきものなら、何が良いパターンで始めるべきなのか、私は何を気にするべきですか?

ありがとうございます!

+0

ログファイルのサイズや数量を拡大しようとしましたか?また、問題の実際の解決策は、すべてのスタックトレースを引き起こしていることを修正するように見えます。 – DwB

+0

@DwB、私は元々の質問で述べたように、私はVMディスクのサイズ(多くの場合、私の手にはない決定、別々に対処されている)を支配していません。スタックトレースの原因を修正するためのあなたの提案の他の部分に:もちろん、それは与えられたものですが、私たちは理想的な世界に住んでいません。特に、システムに統合ポイントと依存関係があり、私のコントロール外に下がってしまったときに、私はすべてのことを修正したいとは思っていません。また、私が言ったように - ポイントは予期しないエラー出力があるときにログを保持することです。 –

答えて

3

BurstFilterは何をしますか?そうでない場合は、あなたのために働くアルゴリズムでJiraの問題を作成してください。そうすれば、Log4jチームはそれを考慮して喜んで行います。あなたがパッチを提供することができれば、組み込まれる可能性がさらに高くなります。

+0

これは、私が探しているものにかなり近いようですが、行番号やメソッド名でさらに制限したいと考えています(同じ原点の類似メッセージをフィルタリングするなど)。それでも、これは正しい方向への一歩です。 –

0

Log4jのBurstFilterは、ディスクをいっぱいにするのを防ぐのに役立ちます。可能な限りコードの一部として適用されるように設定するか、保持したいメッセージを除外します(つまり、アペンダ上では使用しませんが、特定のロガーに対しては使用しないでください)。あなたのコードで分離する)。

ロガーをラップし、指定された期間内にn個のメッセージに基づいてフィルタリングされたシンプルなユーティリティクラスを作成しました。私は、あなたのような問題に遭遇する機会を守るために、私の警告とエラーログの大部分でそのインスタンスを使用しました。私の状況では、さまざまな状況に迅速に適応することが容易だったため、これはかなりうまく機能しました。

何かのように:

... 

public DurationThrottledLogger(Logger logger, Duration throttleDuration, int maxMessagesInPeriod) { 
    ... 
} 

public void info(String msg) { 
    getMsgAddendumIfNotThrottled().ifPresent(addendum->logger.info(msg + addendum)); 
} 


private synchronized Optional<String> getMsgAddendumIfNotThrottled() { 
    LocalDateTime now = LocalDateTime.now(); 
    String msgAddendum; 
    if (throttleDuration.compareTo(Duration.between(lastInvocationTime, now)) <= 0) { 
     // last one was sent longer than throttleDuration ago - send it and reset everything 
     if (throttledInDurationCount == 0) { 
      msgAddendum = " [will throttle future msgs within throttle period]"; 
     } else { 
      msgAddendum = String.format(" [previously throttled %d msgs received before %s]", 
        throttledInDurationCount, lastInvocationTime.plus(throttleDuration).format(formatter)); 
     } 
     totalMessageCount++; 
     throttledInDurationCount = 0; 
     numMessagesSentInCurrentPeriod = 1; 
     lastInvocationTime = now; 
     return Optional.of(msgAddendum); 
    } else if (numMessagesSentInCurrentPeriod < maxMessagesInPeriod) { 
     msgAddendum = String.format(" [message %d of %d within throttle period]", numMessagesSentInCurrentPeriod + 1, maxMessagesInPeriod); 
     // within throttle period, but haven't sent max messages yet - send it 
     totalMessageCount++; 
     numMessagesSentInCurrentPeriod++; 
     return Optional.of(msgAddendum); 
    } else { 
     // throttle it 
     totalMessageCount++; 
     throttledInDurationCount++; 
     return emptyOptional; 
    } 
} 

私は残念ながら、コードの古いバージョンからこれを引っ張ってんだけど、要点があります。彼らは私がその1つのログメッセージのためにこれらのいずれかを作成するためのコードを一行も書いてみましょうので、私は私が主に使用される静的ファクトリメソッドの束を書いた:

} catch (IOException e) { 
    DurationThrottledLogger.error(logger, Duration.ofSeconds(1), "Received IO Exception. Exiting current reader loop iteration.", e); 
} 

これはおそらく、あなたのように重要ではありません場合;私たちのために、我々は非常に簡単に泳ぐことができる幾分弱い卒業論文を使用していました。

関連する問題