CodeGym /Blog Java /Random-PL /Logowanie w Javie
Autor
Jesse Haniel
Lead Software Architect at Tribunal de Justiça da Paraíba

Logowanie w Javie

Opublikowano w grupie Random-PL
Cześć! Pisząc lekcje szczególnie kładę nacisk na konkretny temat, który będzie absolutnie niezbędny w realnej pracy. SŁUCHAJCIE! Temat, którym się dzisiaj zajmiemy, z pewnością przyda się we wszystkich Twoich projektach od pierwszego dnia zatrudnienia. Będziemy rozmawiać o Java Logging. Ten temat wcale nie jest skomplikowany (powiedziałbym nawet, że łatwy). Ale będziesz miał wystarczająco dużo oczywistych rzeczy, którymi będziesz się stresować w swojej pierwszej pracy, więc lepiej już teraz dokładnie to zrozumieć :) Cóż, zaczynajmy.

Co to jest logowanie w Javie?

Rejestrowanie to akt rejestrowania danych o działaniu programu. Miejsce, w którym zapisujemy te dane, nazywa się „dziennikiem”. Od razu pojawiają się dwa pytania: jakie dane są zapisywane i gdzie? Zacznijmy od „gdzie”. Dane o działaniu programu można zapisywać w wielu różnych miejscach. Na przykład podczas studiów często korzystasz z System.out.println()do wysyłania danych do konsoli. To rzeczywiście jest logowanie, choć w najprostszej formie. Oczywiście nie jest to zbyt wygodne dla użytkowników lub zespołu wsparcia produktu: oczywiście nie będą chcieli instalować IDE i monitorować konsoli :) Istnieje bardziej zwyczajowy format zapisywania informacji: pliki tekstowe. Ludziom znacznie wygodniej jest czytać dane w tym formacie, az pewnością jest to o wiele wygodniejsze do przechowywania danych! Teraz drugie pytanie: jakie dane programu powinny być rejestrowane? To zależy wyłącznie od Ciebie! System rejestrowania w Javie jest bardzo elastyczny. Możesz skonfigurować go tak, aby rejestrował wszystko, co robi twój program. Z jednej strony to dobrze. Ale z drugiej strony wyobraźcie sobie, jak duże byłyby logi Facebooka czy Twittera, gdyby zapisali w nich wszystko. Te duże firmy prawdopodobnie mają możliwość przechowywania tak dużej ilości danych. Ale wyobraź sobie, jak trudne byłoby znalezienie informacji o jednym krytycznym błędzie w 500 gigabajtach dzienników tekstowych? To byłoby gorsze niż szukanie igły w stogu siana. W związku z tym Javę można skonfigurować tak, aby rejestrowała tylko dane o błędach. Lub nawet tylko krytyczne błędy! To powiedziawszy, mówienie o natywnym systemie rejestrowania Javy nie jest całkowicie dokładne. Faktem jest, że programiści potrzebowali logowania, zanim ta funkcjonalność została dodana do języka. Zanim Java wprowadziła własną bibliotekę rejestrowania, wszyscy korzystali już z biblioteki log4j. Historia logowania w Javie jest właściwie bardzo długa i pouczająca. Krótko mówiąc, Java ma swoją własną bibliotekę logowania, ale prawie nikt jej nie używa :) Później, kiedy pojawiło się kilka różnych bibliotek logowania i zaczęły być używane przez programistów, pojawiły się problemy z kompatybilnością. Aby powstrzymać ludzi przed wymyślaniem koła na nowo w tuzinie różnych bibliotek z różnymi interfejsami, stworzono abstrakcyjny framework SLF4J („Service Logging Facade For Java”). Nazywa się to abstrakcyjnym, ponieważ nawet jeśli używasz i wywołujesz metody klas SLF4J, w rzeczywistości używają one wszystkich wcześniejszych struktur rejestrowania: log4j, standardowego java.util.logging i innych. Jeśli w pewnym momencie będziesz potrzebować jakiejś specyficznej funkcji Log4j, której brakuje w innych bibliotekach, ale nie chcesz bezpośrednio łączyć swojego projektu z tą biblioteką, po prostu użyj SLF4J. A następnie pozwól mu wywołać metody Log4j. Jeśli zmienisz zdanie i zdecydujesz, że nie potrzebujesz już funkcji Log4j, wystarczy ponownie skonfigurować „tutaj , a biblioteka Log4j tutaj . Następnie rozpakuj archiwum i użyj IntelliJ IDEA, aby dodać pliki JAR do ścieżki klasy. Pozycje menu: Plik -> Struktura projektu -> Biblioteki Wybierz niezbędne pliki JAR i dodaj je do projektu (pobrane przez nas archiwa zawierają wiele plików JAR — spójrz na obrazki, aby zobaczyć te, których potrzebujesz) Uwaga: ta instrukcja dla tych Dlaczego potrzebujemy logowania - 2Dlaczego potrzebujemy logowania - 3uczniów którzy nie wiedzą, jak używać Mavena. Jeśli wiesz, jak korzystać z Mavena, zwykle lepiej (dużo łatwiej) jest zacząć od niego. Jeśli używasz Maven , dodaj tę zależność:

    	<dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.14.0</version>
    	</dependency>
Świetnie! Ustaliliśmy ustawienia :) Zobaczmy, jak działa SLF4J. Jak upewnić się, że praca programu jest gdzieś rejestrowana? Aby to zrobić potrzebujemy dwóch rzeczy: loggera i appendera. Zacznijmy od pierwszego. Rejestrator to obiekt, który zapewnia pełną kontrolę nad logowaniem. Tworzenie loggera jest bardzo proste: robimy to za pomocą statycznych metod LoggerFactory.getLogger() . Parametr metody to klasa, której działanie zostanie zarejestrowane. Uruchommy nasz kod:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyTestClass {

   public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);

   public static void main(String[] args) {

       LOGGER.info("Test log entry!!!");
       LOGGER.error("An error occurred!");
   }
}
Wyjście konsoli:

ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2 15:49:08.907 [main] ERROR MyTestClass - An error occurred!
Co tu widzimy? Najpierw widzimy komunikat o błędzie. Wynika to z faktu, że obecnie brakuje nam niezbędnych ustawień. W związku z tym nasz rejestrator jest obecnie w stanie wysyłać tylko komunikaty o błędach (ERROR) i tylko do konsoli. Metoda logger.info() nie zadziałała. Ale logger.error() zrobił! Na konsoli widzimy aktualną datę, metodę, w której wystąpił błąd ( main), słowo „BŁĄD” i nasza wiadomość! BŁĄD to poziom rejestrowania. Ogólnie rzecz biorąc, jeśli wpis dziennika jest oznaczony słowem „BŁĄD”, oznacza to, że w tym momencie w programie wystąpił błąd. Jeżeli wpis jest oznaczony słowem „INFO”, to komunikat przedstawia po prostu aktualne informacje dotyczące normalnego działania programu. Biblioteka SLF4J ma wiele różnych poziomów rejestrowania, które pozwalają elastycznie konfigurować rejestrowanie. Zarządzanie tym wszystkim jest bardzo łatwe: cała niezbędna logika jest już zawarta w klasie Java Logger . Wystarczy wywołać odpowiednie metody. Jeśli chcesz zarejestrować rutynową wiadomość, wywołaj metodę logger.info() . W przypadku komunikatu o błędzie użyj funkcji logger.error() . Aby uzyskać ostrzeżenie, użyj logger.warn()

Porozmawiajmy teraz o appenderze

Aplikator to miejsce, do którego trafiają Twoje dane. W pewnym sensie przeciwieństwo źródła danych, czyli „punkt B”. Domyślnie dane są wysyłane do konsoli. Zauważ, że w poprzednim przykładzie nie musieliśmy niczego konfigurować: tekst pojawił się w konsoli, a logger biblioteki Log4j może wysyłać do konsoli tylko komunikaty na poziomie ERROR. Oczywiście ludziom wygodniej jest czytać i zapisywać dzienniki w pliku tekstowym. Aby zmienić domyślne zachowanie rejestratora, musimy skonfigurować nasz program dołączający pliki. Aby rozpocząć, musisz utworzyć plik log4j.xml bezpośrednio w folderze src. Format XML już znasz: ostatnio mieliśmy o nim lekcję :) Oto zawartość pliku:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
   <Appenders>
       <File name="MyFileAppender" fileName="C:\Users\Username\Desktop\testlog.txt" immediateFlush="false" append="false">
           <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
       </File>
   </Appenders>
   <Loggers>
       <Root level="INFO">
           <AppenderRef ref="MyFileAppender"/>
       </Root>
   </Loggers>
</Configuration>
Nie ma tu nic szczególnie specjalnego ani trudnego :) Ale mimo wszystko przejdźmy do treści.
<Configuration status="INFO">
Jest to tak zwany StatusLogger. Nie jest powiązany z naszym rejestratorem i jest używany w wewnętrznych procesach Log4j. Jeśli ustawisz status="TRACE" zamiast status="INFO", wszystkie informacje o wewnętrznej pracy Log4j będą wyświetlane na konsoli (StatusLogger wyświetla dane na konsoli, nawet jeśli naszym appenderem jest plik). Nie potrzebujemy go teraz, więc zostawmy go tak, jak jest.

<Appenders>
   <File name="MyFileAppender" fileName="C:\Users\Evgeny\Desktop\testlog.txt" append="true">
       <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
   </File>
</Appenders>
Tutaj tworzymy nasz appender. Znacznik <File> wskazuje, że będzie to plik dołączający. name="MyFileAppender" ustawia nazwę programu dołączającego. fileName="C:\Users\Username\Desktop\testlog.txt" wskazuje ścieżkę do pliku dziennika, w którym zostaną zapisane wszystkie dane. append="true" wskazuje, czy dane powinny być zapisywane na końcu pliku. W naszym przypadku właśnie to zrobimy. Jeśli ustawisz wartość false, stara zawartość pliku dziennika będzie usuwana przy każdym uruchomieniu programu. <PatternLayout pattern="%d{rrrr-MM-dd HH:mm:ss.SSS} [%t] %-5poziom %logger{36} - %msg%n"/>wskazuje ustawienia formatowania. Tutaj możemy użyć wyrażeń regularnych, aby dostosować sposób formatowania tekstu w naszym dzienniku.

<Loggers>
       <Root level="INFO">
           <AppenderRef ref="MyFileAppender"/>
       </Root>
</Loggers>
Tutaj wskazujemy poziom główny. Ustawiliśmy poziom "INFO", co oznacza, że ​​wszystkie wiadomości, których poziom jest wyższy niż INFO (zgodnie z tabelą, którą przeglądaliśmy powyżej) nie będą logowane. Nasz program będzie miał 3 komunikaty: jeden INFO, jeden OSTRZEŻENIE i jeden BŁĄD. Przy obecnej konfiguracji wszystkie 3 komunikaty będą rejestrowane. Jeśli zmienisz poziom główny na ERROR, w dzienniku znajdzie się tylko ostatni komunikat z wywołania metody LOGGER.error(). Ponadto tutaj znajduje się również odniesienie do programu dołączającego. Aby utworzyć taką referencję, należy utworzyć znacznik <ApprenderRef> wewnątrz znacznika <Root> i dodać do niego atrybut ref='your appender's name' . Jeśli zapomniałeś, tutaj ustawiamy nazwę dołączającego: <. A oto nasz kod!

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyTestClass {

   public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);

   public static void main(String[] args) {

       LOGGER.info("The program is starting!!!");

       try {
           LOGGER.warn("Attention! The program is trying to divide a number by another.
           System.out.println(12/0);
       } catch (ArithmeticException x) {

           LOGGER.error("Error! Division by zero!");
       }
   }
}
Oczywiście jest to trochę szalone (łapanie wyjątku RuntimeException to wątpliwy pomysł), ale jest idealne do naszych celów :) Uruchommy naszą metodę main() 4 razy z rzędu i spójrzmy na nasz plik testlog.txt. Nie musisz go wcześniej tworzyć: biblioteka zrobi to automatycznie. Wszystko działało! :) Teraz masz skonfigurowany rejestrator. Możesz bawić się niektórymi ze swoich starych programów, dodając wywołania rejestratora do każdej metody. Następnie spójrz na wynikowy dziennik :) Rozważa on dogłębnie temat logowania. Trudno byłoby przeczytać to wszystko za jednym razem. To powiedziawszy, zawiera wiele dodatkowych przydatnych informacji. Dowiesz się na przykład, jak skonfigurować loggera, aby tworzył nowy plik tekstowy, jeśli nasz plik testlog.txt osiągnie określony rozmiar :) I na tym kończymy nasze zajęcia! Dzisiaj zapoznałeś się z bardzo ważnym tematem, a ta wiedza z pewnością przyda Ci się w przyszłej pracy. Do następnego razu! :)
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION