Articles

jak działa Log4J2: 10 Sposobów, aby uzyskać jak najwięcej z niego

Log4j2 jest zaktualizowaną wersją popularnej i wpływowej biblioteki log4j, używanej szeroko w ekosystemie Java przez tak wiele lat. Wersja 2.x zachowuje wszystkie funkcje logowania swojego poprzednika i opiera się na tym fundamencie z pewnymi znaczącymi ulepszeniami, zwłaszcza w obszarze wydajności.

i oczywiście, biorąc pod uwagę, jak instrumentalne jest rejestrowanie dla każdej aplikacji, zarówno do celów audytu, jak i debugowania, wybór solidnej biblioteki rejestrowania jest dość ważną decyzją.

w kolejnych sekcjach przyjrzymy się, dlaczego biblioteka log4j2 jest doskonałym wyborem dla tej decyzji i jak możemy z niej korzystać w aplikacji.

podstawowa konfiguracja Log4j2

aby zacząć używać log4j2 w swoim projekcie, wystarczy dodać zależność log4j-core. Jeśli używasz Maven, możesz dodać następującą zależność do swojego pom.plik xml:

i jeśli pracujesz z Gradle, musisz dodać zależność do kompilacji.plik gradle:

dependencies { compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.8.2'}

po wyjęciu z pudełka log4j2 automatycznie zapewni prostą konfigurację, jeśli nie zdefiniujesz jej jawnie. Domyślna konfiguracja loguje się do konsoli na poziomie błędu lub wyższym.

aby rozpocząć rejestrowanie wiadomości za pomocą tej podstawowej konfiguracji, wystarczy uzyskać instancję Loggera za pomocą klasy LogManager:

private static Logger logger = LogManager.getLogger(MyService.class);

następnie można użyć obiektu logger z metodami odpowiadającymi żądanemu poziomowi dziennika:

logger.error("This is an error message");

dostosowywanie konfiguracji Log4j2

niestandardową konfigurację log4j2 można utworzyć programowo lub poprzez plik konfiguracyjny.

biblioteka obsługuje pliki konfiguracyjne napisane w XML, JSON, YAML, a także .format właściwości. Tutaj użyjemy XML do omówienia wszystkich przykładów przede wszystkim.

najpierw możesz nadpisać domyślną konfigurację, po prostu tworząc log4j2.plik xml na ścieżce classpath:

przyjrzyjmy się bliżej znacznikom używanym w tej prostej konfiguracji:

  • Configuration: główny element pliku konfiguracyjnego log4j2; atrybut status przedstawia poziom, na którym wewnętrzne zdarzenia log4j powinny być rejestrowane
  • Appenders: ten element zawiera listę appenderów; w naszym przykładzie zdefiniowany jest appender odpowiadający konsoli systemowej
  • Loggers: ten element zawiera listę instancji Loggera. Element główny jest standardowym loggerem, który wysyła wszystkie wiadomości

ważne jest, aby zrozumieć, że Logger główny jest obowiązkowy w każdej konfiguracji. Jak wspomniano, jeśli go nie podasz, zostanie on automatycznie skonfigurowany domyślnie z appenderem konsoli i poziomem dziennika błędów.

Konfigurowanie Appenderów

w architekturze log4j2 appender jest zasadniczo odpowiedzialny za wysyłanie wiadomości dziennika do określonego miejsca docelowego.

oto niektóre z najbardziej przydatnych typów appenderów, które zapewnia biblioteka:

  • ConsoleAppender – rejestruje wiadomości do konsoli systemowej
  • FileAppender – zapisuje wiadomości dziennika do pliku
  • RollingFileAppender – zapisuje wiadomości do toczącego się pliku dziennika
  • JDBCAppender – używa relacyjnej bazy danych logów
  • AsyncAppender – zawiera listę innych appenderów i określa dzienniki, które mają być zapisane w osobnym wątku

aby lepiej zrozumieć, jak działają appendery, przyjrzyjmy się przykładom konfiguracji.

RollingFileAppender

zapisywanie wszystkiego do jednego pliku nie jest oczywiście idealne. Zazwyczaj znacznie lepiej jest regularnie przewracać aktywny plik dziennika – co dokładnie robi RollingFileAppender.

Możesz również wyjść poza podstawy z tego typu appenderem i skonfigurować zarówno niestandardową politykę wyzwalania, jak i strategię rollover.

Polityka wyzwalania określa, kiedy plik dziennika jest zwijany, co oznacza, że tworzony jest nowy plik, podczas gdy strategia rolowania określa sposób zwijania pliku.

jako szybki przykład, skonfigurujmy appendera, który tworzy nowy plik dziennika oparty na 3 zasadach:

  • OnStartupTriggeringPolicy – nowy plik dziennika jest tworzony za każdym razem, gdy zaczyna się JVM
  • TimeBasedTriggeringPolicy – plik dziennika jest rozwijany na podstawie wzorca daty/czasu
  • SizeBasedTriggeringPolicy – plik jest rozwijany, gdy osiągnie określony rozmiar

konfiguracja użyje defaultloverstrategy:

Możesz zobaczyć, jak elastyczny jest ten styl konfiguracji i jak możesz dostosować dokładną semantykę strategii logowania – aż do ostatniego szczegółu.

JDBCAppender

jak sama nazwa wskazuje, ten appender używa JDBC do zapisywania logów do relacyjnej bazy danych.

dla tej konfiguracji musisz zdefiniować ConnectionSource, które może być źródłem danych JNDI lub niestandardową fabryką połączeń. Rejestrator używa Źródła ConnectionSource, aby uzyskać połączenia JDBC, dlatego ważne jest, aby użyć puli połączeń dla lepszej wydajności.

aby skonfigurować appendera w pliku konfiguracyjnym XML, możesz użyć znacznika JDBC:

jak widać, źródło danych JNDI jest po prostu określone za pomocą atrybutu Jndiname znacznika DataSource. Wraz z ConnectionSource można zdefiniować tabelę i kolumny, które będą używane do przechowywania danych dziennika.

The Failoveappender

na koniec, rzućmy okiem na Failoveappender; definiuje to główny appender i listę kopii zapasowych, które wejdą do obsługi logowania w przypadku awarii głównego.

na przykład, możesz skonfigurować podstawowy JDBCAppender, z dodatkowym The RollingFile i konsolowymi appenderami w przypadku, gdy nie można nawiązać połączenia z bazą danych:

w środowisku produkcyjnym, posiadanie strategii przełączania awaryjnego dla mechanizmu logowania jest zawsze dobrym pomysłem.

Konfigurowanie układów

podczas gdy nadawcy są odpowiedzialni za wysyłanie wiadomości dziennika do miejsca docelowego, układy są używane przez nadawców do definiowania sposobu sformatowania wiadomości dziennika.

oto krótki opis niektórych z częściej używanych układów, które oferuje log4j2:

  • PatternLayout – konfiguruje wiadomości według wzorca Łańcuchowego
  • JsonLayout – definiuje format JSON dla wiadomości dziennika
  • CsvLayout – może być używany do tworzenia wiadomości w formacie CSV

PatternLayout

pierwszym typem układu, na który będziemy patrzeć, jest PatternLayout. Jest to dość elastyczne rozwiązanie, które daje dużą kontrolę nad ostatecznym wyjściem komunikatu dziennika.

mechanizm jest przede wszystkim napędzany przez wzorzec konwersji, który zawiera specyfikatory konwersji. Każdy specyfikator zaczyna się znakiem%, a następnie modyfikatorami, które kontrolują takie rzeczy, jak szerokość i kolor wiadomości, oraz znakiem konwersji, który reprezentuje zawartość, takim jak data lub nazwa wątku.

przyjrzyjmy się przykładowi konfiguracji PatternLayout, który konfiguruje linie dziennika tak, aby pokazywały datę, wątek, poziom dziennika i komunikat dziennika o różnych kolorach dla różnych poziomów dziennika:

te specyfikatory są warte szczegółowego zrozumienia, więc przyjrzyjmy się im bliżej:

  • %d{HH:mm:ss.SSS} – wypisuje datę zdarzenia log w określonym formacie
  • %t – wypisuje nazwę wątku
  • %level – wyświetla poziom dziennika wiadomości
  • %highlight{%level} – służy do definiowania kolorów wzorca między nawiasami klamrowymi
  • %msg%N – wypisuje komunikat dziennika

wyjście wyświetli poziomy dziennika o różnych kolorach:

Więcej informacji o pełnym zestawie możliwości definiowania wzorców w dokumentacji log4j2 na patternlayout.

Jsonlayout

rejestrowanie danych za pomocą formatu JSON ma pewne istotne zalety, takie jak ułatwianie analizowania i przetwarzania dzienników przez narzędzia rejestrujące w dół linii.

aby skonfigurować JSONLayout w log4j2, możesz po prostu zdefiniować odpowiedni tag:

<JSONLayout complete="true" compact="false"/>

ustawienie complete = true spowoduje utworzenie dobrze uformowanego dokumentu JSON:

aby móc tworzyć JSON, musisz również dodać bibliotekę jackson-databind do ścieżki klasy:

Konfigurowanie filtrów

Filtry w log4j2 służą do określenia, czy wiadomość dziennika powinna zostać przetworzona, czy pominięta.

filtr można skonfigurować dla całej konfiguracji lub na poziomie loggera lub appendera.

biblioteka udostępnia kilka typów filtrów, które można wykorzystać:

  • BurstFilter – kontroluje liczbę dozwolonych zdarzeń dziennika
  • DynamicThresholdFilter – filtruje linie dziennika na podstawie określonych atrybutów
  • RegexFilter – filtruje wiadomości na podstawie tego, czy pasują do wyrażenia regularnego

można na przykład kontrolować szybkość, z jaką aplikacja może rejestrować dane.

aby to zrobić, możesz skonfigurować filtr BurstFilter i zastosować go do wiadomości informacyjnych:

<Filters> <BurstFilter level="INFO" rate="10" maxBurst="100"/></Filters>

To będzie selektywnie ignorować kontrolę ruchu wiadomości na poziomie informacji i poniżej, upewniając się, że nie tracisz żadnej z ważniejszych wiadomości powyżej informacji.

w tym przypadku, rate definiuje średnie komunikaty logów, które powinny być przetwarzane na sekundę, a maxBurst kontroluje ogólny rozmiar impulsu ruchu, zanim filtr zacznie eliminować wpisy dziennika.

Podobnie, możemy skonfigurować appender tylko tak, aby akceptował komunikaty dziennika, które pasują do określonego wyrażenia regularnego:

<Appenders> <JDBC name="JDBCAppender"> <RegexFilter regex="*jdbc*" onMatch="ACCEPT" onMismatch="DENY"/> </JDBC></Appenders>

Ogólnie rzecz biorąc, ten mechanizm filtrowania może być używany z dużą precyzją, aby upewnić się, że każdy appender w ogólnej konfiguracji logowania śledzi właściwe informacje. Możliwość rejestrowania tylko bardzo konkretnych i istotnych informacji na ogół prowadzi do bardzo szybkiej analizy przyczyn źródłowych, zwłaszcza w złożonych systemach-zwłaszcza w połączeniu z potężnym narzędziem do przeglądania dziennika.

Konfigurowanie loggerów

oprócz głównego loggera możemy również zdefiniować dodatkowe elementy Loggera z różnymi poziomami logów, aplikatorami lub filtrami. Każdy Rejestrator wymaga nazwy, która może być później użyta do odniesienia się do niego:

<Loggers> <Logger name="RollingFileLogger"> <AppenderRef ref="RollingFileAppender" /> </Logger></Loggers>

aby pisać wiadomości dziennika za pomocą tego konkretnego rejestratora, możesz uzyskać odniesienie do niego za pomocą klasy LogManager:

Logger rfLogger = LogManager.getLogger("RollingFileLogger");rfLogger.info("User info updated");

innym bardzo popularnym sposobem strukturyzowania hierarchii tych rejestratorów jest oparty na klasie Java:

Logger rfLogger = LogManager.getLogger("RollingFileLogger");rfLogger.info("User info updated");

Logger logger = LogManager.getLogger(MyServiceTest.class);

używanie lookupów

lookups reprezentuje sposób wstawiania zewnętrznych wartości do konfiguracji log4j2. Widzieliśmy już Przykład wyszukiwania daty w konfiguracji RollingFileAppender:

<RollingFile name="RollingFileAppender" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">

${date:yyy-MM} lookup wstawi bieżącą datę do nazwy pliku, podczas gdy poprzedzająca $ jest znakiem ucieczki, aby wstawić wyrażenie lookup do atrybutu filePattern.

Możesz również wstawić wartości właściwości systemu do konfiguracji log4j2 przy użyciu formatu ${sys:nazwa_właściwości}:

<File name="ApplicationLog" fileName="${sys:path}/app.log"/>

innym typem informacji, które możesz wyszukać i wstawić, są informacje o środowisku Java:

<PatternLayout header="${java:version} - ${java:os}"> <Pattern>%d %m%n</Pattern></PatternLayout>

Więcej szczegółów na temat rodzaju danych, które możesz wstawić za pomocą wyszukiwań, znajdziesz w dokumentacja log4j2.

Konfiguracja programowa

oprócz plików konfiguracyjnych, log4j2 może być również konfigurowany programowo. Można to zrobić na kilka sposobów:

  • Utwórz konfigurację niestandardowąfactory
  • Użyj klasy konfiguratora
  • zmodyfikuj konfigurację po inicjalizacji
  • połącz pliki właściwości i konfigurację programową

przyjrzyjmy się, jak skonfigurować programowo układ i appender:

następnie możesz zdefiniować logger za pomocą klasy LoggerConfig, powiązać z nim appender i aktualizacja konfiguracji:

następnie możesz zacząć używać loggera jak zwykle:

Logger pLogger = LogManager.getLogger("programmaticLogger");pLogger.info("Programmatic Logger Message");

ten styl płynnego API może prowadzić do szybszego rozwoju i iteracji w bardziej złożonych konfiguracjach logowania, ponieważ teraz korzystasz z zalet pracy bezpośrednio z kodem Java.

jednak, biorąc pod uwagę, że XML może być nadal bardziej czytelny i kompaktowy, często można rozwijać konfigurację programowo, a następnie przekonwertować ją na XML, gdy wszystko jest zrobione.

niestandardowe poziomy dziennika

wbudowane poziomy dziennika dla log4j2 to:

  • OFF
  • FATAL
  • ERROR
  • WARN
  • INFO
  • DEBUG
  • śledzenie
  • wszystkie

oprócz tych, Możesz również zdefiniować niestandardowy poziom dziennika zgodnie z potrzebami aplikacji.

na przykład, aby zdefiniować nowy poziom dziennika, możesz użyć poziomu.FORNAME () API-określenie nazwy nowego poziomu i liczby całkowitej, która reprezentuje miejsce poziomu w hierarchii poziomów dziennika:

Level myLevel = Level.forName("NEW_LEVEL", 350);

aby określić, jakiej wartości całkowitej użyć, możesz spojrzeć na wartości zdefiniowane dla innych poziomów dziennika w dokumentacji log4j2:

wartość 350 umieszcza poziom pomiędzy WARN i INFO, co oznacza, że komunikaty będą wyświetlane, gdy poziom zostanie ustawiony na INFO lub wyżej.

aby zalogować wiadomość na poziomie niestandardowym, musisz użyć metody log ():

logger.log(myLevel, "Custom Level Message");

równoważna konfiguracja XML może być:

<CustomLevels> <CustomLevel name="NEW_XML_LEVEL" intLevel="350" /></CustomLevels>

następnie można jej użyć poprzez standardowe log API:

logger.log(Level.getLevel("NEW_XML_LEVEL"),"Custom XML Level Message");

nowe niestandardowe poziomy będą wyświetlane w taki sam sposób jak standardowe:

11:28:23.558 NEW_LEVEL - Custom Level Message11:28:23.559 NEW_XML_LEVEL - Custom XML Level Message

Migracja z Log4j 1.x

Jeśli migrujesz aplikację przy użyciu 1.x wersja biblioteki do aktualnej 2.wersja x, istnieje kilka tras, którymi możesz podążać:

  • użyj log4j 1.x bridge
  • ręczna aktualizacja API i konfiguracja

Korzystanie z mostu jest trywialne. Wystarczy zastąpić zależność log4j biblioteką log4j-1.2-api:

chociaż jest to szybsza metoda, ma tę wadę, że jest ograniczona w typie konfiguracji, którą można przekonwertować.

metoda ręczna to oczywiście więcej pracy, ale ostatecznie doprowadzi do bardziej elastycznego i wydajnego rozwiązania rejestrowania.

oto niektóre z najczęstszych rodzajów zmian, które musisz zrobić:

wnioski

pliki dziennika są krytyczne w każdym środowisku produkcyjnym, a Wybór dobrego rozwiązania do rejestrowania może być różnicą między spędzeniem 5 minut a spędzeniem całego dnia, aby zrozumieć problem w produkcji.

Log4j2 to wydajne i solidne rozwiązanie do logowania dla nowoczesnych aplikacji Java, z szerokim zakresem opcji konfiguracyjnych.

pozwala na łatwą konfigurację zaawansowanych najlepszych praktyk logowania, takich jak rolling files, różne typy celów wyjściowych logowania, wsparcie dla strukturalnych formatów logowania, takich jak JSON lub XML, przy użyciu wielu rejestratorów i filtrów oraz niestandardowych poziomów dziennika.

wreszcie, gdy musisz wyjść poza ręczną analizę danych dziennika, zdecydowanie sprawdź możliwości rejestrowania zawarte w Retrace APM.