2015-11-12 40 views
5

Jestem całkiem nowy w Javie i log4j2, więc przepraszam za może dziwne pytanie. Mój problem jest następujący. Napisałem aplikację, która używa log4j2 do logowania. Program analizuje dane i zapisuje ostrzeżenie w przypadku, gdy dany ciąg nie może zostać przeanalizowany zgodnie z oczekiwaniami. Czasami program dostaje wiele nieoczekiwanych ciągów i dlatego loguje cały czas ten sam komunikat o błędzie. Pytanie brzmi: jak uniknąć wielokrotnego rejestrowania tego samego komunikatu o błędzie. Zamiast na przykład, aby zobaczyć ten sam komunikat o błędzie 2000 razy w pliku dziennika, chciałbym mieć wskazówkę w pliku logu, że ten komunikat o błędzie został napisany x-razy. Mój obecny wygląd log4j2 plik config w następujący sposób:Jak tłumić zduplikowane wiadomości w log4j2

<?xml version="1.0" encoding="UTF-8"?> 
<Configuration> 
    <Properties> 
     <Property name="pattern">%d{DEFAULT} %-5p %-18.18c %4.4L [%-15.15t] %m%n</Property> 
    </Properties> 

    <Appenders> 
     <Console name="STDERR" target="SYSTEM_ERR"> 
      <PatternLayout pattern="${pattern}" /> 
     </Console> 
    </Appenders> 
    <Loggers> 
     <Root level="warn"> 
      <AppenderRef ref="STDERR" /> 
     </Root> 
    </Loggers> 
</Configuration> 

Odpowiedz

0

ja niestety nie mam kodu na mnie aktualnie, ale jest to w jaki sposób można rozwiązać ten problem (i nie może być bardzo dobrze rozwiązanie tam już).

Możesz utworzyć nowego aplikanta, który loguje się asynchronicznie do pliku/konsoli, niezależnie od tego.

W aplikatorze możesz samodzielnie zaimplementować agregację. Za każdym razem, gdy pojawia się logevent, zamiast natychmiast go wypisać, sprawdź, czy wcześniej widziałaś tę wiadomość. Jeśli tak, zamiast go rejestrować, zwiększ swój licznik.

Ostatecznie, przekształć te zagregowane zdarzenia dziennika w zagregowaną wiadomość i przetwórz ją zamiast tysiąca zdarzeń w dzienniku.

Może to zostać rozwiązane (na przykład) przez drugiego pracownika w asynchronicznej bazie nadawców. Zwykle (szukam sprzężenia zwrotnego, ale zakładam, że będzie on dla ciebie dość podobny), asynchroniczni aplikanci kończą dodawanie zdarzeń do kolejki, która będzie przetwarzana przez inny wątek, który działa z tej kolejki.

Możesz mieć inną kolejkę dla zagregowanych wiadomości, a uruchamiający się pracownik mówi co 5 sekund. Jeśli w ciągu tych 5 sekund ta sama wiadomość zostanie wyświetlona wiele razy, pracownik może zebrać tę wiadomość i umieścić ją w kolejce do przetworzenia, aby ostatecznie znalazła się w dziennikach.

Mam nadzieję, że pomaga,

Artur

P.S .: W odniesieniu do swojej konfiguracji, wystarczy wymienić konsolę appender z niestandardowego agregowania appender. Jeśli chcesz konsoli, po prostu rozszerz ją i spraw, aby działała tak, jak chcesz :)

+0

Właściwie to może mieć sens raczej ogólny AppenderWrapper delegowania aktualnej appender. Łatwo więc możesz łatwo zmienić aplikantów, jeśli nie lubisz już aplikacji Console. – philnate

+0

Możesz osiągnąć to samo, używając filtra. Filtr może być dostarczony z wieloma wzorami, aby dopasować się do wydarzeń. Jeśli filtr pasuje do wzorca, przesyła go do pamięci wewnętrznej i zatrzymuje propagację zdarzenia. Komponent bean przechowujący pamięć w pamięci może następnie mieć pracownika, który po prostu używa zwykłego starego dziennika do rejestrowania agregacji (pamiętaj, aby napisać shit podczas zamykania).W ten sposób możesz po prostu ponownie wykorzystać wszystkie swoje agregatory i mieć filtr dot pracy. – pandaadb

0

Możliwe jest oczywiście utworzenie wtyczki log4j2, która to robi, ale uważam, że biblioteka logowania nie jest najlepsza miejsce, aby rozwiązać ten problem.

Wydaje mi się, że skończy się to znacznie prostszym kodem, jeśli w aplikacji będziesz śledzić poprzednią wiadomość, którą zalogowałeś. Jeśli następna wiadomość będzie taka sama, nie rejestruj, ale zwiększ licznik. Po naciśnięciu innej wiadomości rejestrujesz wartość licznika.

(To może być bardziej ogólnie z rozkolejkowania śledzić wiele wiadomości.)