2.1 Pierwszy logger - log4j

Jak już wiesz, historia logów zaczęła się od System.err.println()wyjścia rekordu na konsolę. Nadal jest aktywnie używany do debugowania, na przykład Intellij IDEA używa go do wyświetlania komunikatów o błędach na konsoli. Ale ta opcja nie ma żadnych ustawień, więc przejdźmy dalej.

Pierwszy i najpopularniejszy rejestrator nazywał się Log4j. To było dobre i wysoce konfigurowalne rozwiązanie. Z różnych powodów decyzja ta nigdy nie trafiła do JDK, co bardzo zdenerwowało całą społeczność.

Ten logger nie tylko potrafił logować, został stworzony przez programistów dla programistów i pozwalał im rozwiązywać problemy, które ciągle pojawiały się w związku z logowaniem.

Jak już wiesz, logi są w końcu zapisywane po to, żeby ktoś je przeczytał i spróbował zrozumieć, co się stało podczas działania programu - co i kiedy poszło nie tak, jak trzeba.

Były log4jna to trzy rzeczy:

  • rejestrowanie podpakietów;
  • zestaw dołączaczy (wyniki);
  • ustawienia przeładowania na gorąco.

Po pierwsze, ustawienia log4jmożna by napisać tak, aby w jednym pakiecie umożliwić logowanie, aw innym wyłączyć. Na przykład można było włączyć logowanie w com.codegym.server, ale wyłączyć je w com.codegym.server.payment. Umożliwiło to szybkie usunięcie z dziennika niepotrzebnych informacji.

Po drugie, log4jumożliwiało zapisywanie wyników logowania do kilku plików dziennika jednocześnie. A wyjście do każdego można było skonfigurować indywidualnie. Np. w jednym pliku można było zapisać tylko informacje o poważnych błędach, w innym logi z konkretnego modułu, a w trzecim logi z określonego czasu.

W ten sposób każdy plik dziennika został dostosowany do określonego rodzaju oczekiwanego problemu. To znacznie upraszcza życie programistom, którzy nie lubią ręcznie przeglądać gigabajtowych plików dziennika.

I wreszcie, po trzecie, log4jumożliwiało zmianę ustawień dziennika bezpośrednio podczas działania programu, bez konieczności jego restartowania. Było to bardzo przydatne, gdy trzeba było skorygować działanie logów w celu znalezienia dodatkowych informacji o konkretnym błędzie.

Ważny! Istnieją dwie wersje dziennika log4j: 1.2.x i 2.xx , które są ze sobą niezgodne .

Możesz podłączyć rejestrator do projektu za pomocą kodu:

<dependencies>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.2</version>
  </dependency>

  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.2</version>
  </dependency>
</dependencies>

2.2 Pierwszy oficjalny rejestrator - JUL: java.util.logging

Po pojawieniu się zoo loggerów w społeczności Java, programiści JDKpostanowili stworzyć jeden standardowy logger, z którego będą korzystać wszyscy. Tak wyglądał logger JUL: package java.util.logging.

Jednak podczas jego opracowywania twórcy loggera przyjęli za podstawę nie log4j, ale wariant loggera firmy IBM, co wpłynęło na jego rozwój. Dobrą wiadomością jest to, że rejestrator JULjest dołączony JDK, zła wiadomość jest taka, że ​​​​niewiele osób z niego korzysta.

LIPIEC

Twórcy nie tylko JULstworzyli „kolejny uniwersalny standard” , ale także stworzyli dla niego własne poziomy logowania, które różniły się od akceptowanych wówczas przez popularne loggery.

I to był duży problem. W końcu produkty są Javaczęsto zbierane z dużej liczby bibliotek, a każda taka biblioteka miała swój własny rejestrator. Konieczne było więc skonfigurowanie wszystkich loggerów, które znajdują się w aplikacji.

Chociaż sam rejestrator jest całkiem niezły. Tworzenie rejestratora jest mniej więcej takie samo. Aby to zrobić, musisz zaimportować:


java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggingJul.class.getName());

Nazwa klasy jest specjalnie przekazywana, aby wiedzieć, skąd pochodzi logowanie.

Dopiero wraz z wydaniem programiści rozwiązali ważne problemy, po których JULkorzystanie z niego jest naprawdę wygodne. Wcześniej był to jakiś drugorzędny rejestrator.

Ten rejestrator obsługuje również wyrażenia lambda i leniwą ocenę. Zaczynając od Java 8, możesz spasować Supplier<String>. Pomaga to czytać i tworzyć ciąg tylko w momencie, gdy jest to naprawdę potrzebne, a nie za każdym razem, jak było wcześniej.

Metody z argumentem Supplier<String> msgSupplierwyglądają tak:

public void info(Supplier msgSupplier) {
   log(Level.INFO, msgSupplier);
}

2.3 Pierwsze opakowanie programu rejestrującego — JCL: jakarta commons logging

Przez długi czas wśród loggerów nie było jednego standardu, JULpowinien nim być, ale było gorzej log4j, więc jeden standard nigdy się nie pojawił. Ale pojawiło się całe zoo drwali, z których każdy chciał stać się taki sam.

JCL

Jednak zwykłym programistom Java nie podobało się, że prawie każda biblioteka ma swój własny rejestrator i musi być jakoś skonfigurowana w specjalny sposób. W związku z tym społeczność postanowiła stworzyć specjalny wrapper nad innymi loggerami – oto jakJCL: jakarta commons logging

I znowu projekt, który miał być liderem, nim nie został. Nie możesz stworzyć zwycięzcy, możesz tylko zostać zwycięzcą. Funkcjonalność JCLbyła bardzo słaba i nikt nie chciał z niej korzystać. Ten sam los spotkał logger, który miał zastąpić wszystkie loggery, ponieważ JULnie był używany.

Chociaż został dodany do wielu bibliotek wydanych przez społeczność Apache, zoo loggerów tylko się rozrosło.

2.4 Pierwszy ostatni rejestrator - Logback

Ale to nie wszystko. Deweloper log4juznał, że jest najmądrzejszy (no, bo z jego loggera korzystało najwięcej osób) i postanowił napisać nowy ulepszony logger, który łączyłby zalety log4jinnych loggerów.

Nowy rejestrator został nazwany Logback. To właśnie ten rejestrator miał stać się przyszłym pojedynczym rejestratorem, którego wszyscy będą używać. Opierał się na tym samym pomyśle co w log4j.

Możesz podłączyć ten rejestrator do projektu za pomocą kodu:

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.6</version>
</dependency>

Różnice dotyczyły Logback:

  • poprawiona wydajność;
  • dodano obsługę natywną slf4j;
  • rozbudowana opcja filtrowania.

Kolejną zaletą tego rejestratora były bardzo dobre ustawienia domyślne. A loggery trzeba było konfigurować tylko wtedy, gdy chciało się coś w nich zmienić. Również plik ustawień został lepiej dostosowany do oprogramowania korporacyjnego - wszystkie jego konfiguracje zostały ustawione jako xml/.

Domyślnie Logbacknie wymaga żadnych ustawień i zapisuje wszystkie logi od poziomu DEBUGwzwyż. Jeśli potrzebujesz innego zachowania, możesz je skonfigurować za pomocą xmlkonfiguracji:

<configuration>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>app.log</file>
        <encoder>
            <pattern>%d{HH:mm:ss,SSS} %-5p [%c] - %m%n</pattern>
        </encoder>
    </appender>
    <logger name="org.hibernate.SQL" level="DEBUG" />
    <logger name="org.hibernate.type.descriptor.sql" level="TRACE" />
    <root level="info">
        <appender-ref ref="FILE" />
    </root>
</configuration>

2.5 Najnowszy uniwersalny rejestrator — SLF4J: Simple Logging Facade for Java

Jak długo może trwać znalezienie złotego środka...

W 2006 roku jeden z twórców log4jodszedł z projektu i postanowił ponownie spróbować stworzyć uniwersalny logger. Ale tym razem nie był to nowy rejestrator, ale nowy uniwersalny standard (wrapper), który umożliwił interakcję różnych rejestratorów.

Ten rejestrator nazywał się slf4j — Simple Logging Facade for Java, był opakowaniem wokół log4j, JUL, common-loggins and logback. Ten logger rozwiązał prawdziwy problem - zarządzanie zoo drwali, więc wszyscy od razu zaczęli z niego korzystać.

Bohatersko rozwiązujemy problemy, które sami sobie stwarzamy. Jak widać postępy doszły do ​​tego stopnia, że ​​stworzyliśmy wrapper nad wrapperem...

Sama chusta składa się z dwóch części:

  • API, który jest używany w aplikacjach;
  • Implementacje, które są dodawane jako osobne zależności dla każdego rejestratora.

Możesz podłączyć rejestrator do projektu za pomocą kodu:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.17.2</version>
</dependency>

Wystarczy podłączyć poprawną implementację i już: cały projekt będzie z nią działał.

2.6 Optymalizacja w slf4j

Slf4jobsługuje wszystkie nowe funkcje, takie jak formatowanie ciągów do logowania . Wcześniej był taki problem. Powiedzmy, że chcesz wydrukować wiadomość do dziennika:

log.debug("User " + user + " connected from " + request.getRemoteAddr());

Wystąpił problem z tym kodem. Załóżmy, że Twoja aplikacja działa dalej productioni nie zapisuje żadnych danych w dzienniku DEBUG-messages, jednak metoda log.debug()nadal będzie wywoływana, a gdy zostanie wywołana, wywołane zostaną również następujące metody:

  • user.toString();
  • request.getRemoteAddr();

Wywołanie tych metod spowalnia aplikację. Ich wywołanie jest potrzebne tylko podczas debugowania, ale i tak są wywoływane.

Z logicznego punktu widzenia problem ten musiał zostać rozwiązany w samej bibliotece logowania. W pierwszej wersji log4j pojawiło się rozwiązanie:

if (log.isDebugEnabled()) {
    log.debug("User " + user + " connected from " + request.getRemoteAddr());
}

Zamiast jednej linii do dziennika, teraz trzeba było napisać trzy. Co dramatycznie pogorszyło czytelność kodu i obniżyło popularność log4j.

Logger slf4jbył w stanie nieco poprawić sytuację, oferując inteligentne logowanie. Wyglądało to tak:

log.debug("User {} connected from {}", user, request.getRemoteAddr());

gdzie {}oznacza wstawianie argumentów przekazywanych w metodzie. Oznacza to, że pierwszy {}odpowiada użytkownikowi, {}drugi request.getRemoteAddr().

Parametry te zostaną połączone w jedną wiadomość tylko wtedy, gdy poziom rejestrowania zezwala na rejestrowanie. Nie idealne, ale lepsze niż wszystkie inne opcje.

Potem SLF4Jzaczął szybko zyskiwać na popularności, w tej chwili jest to najlepsze rozwiązanie.

Dlatego rozważymy logowanie na przykładzie bundle slf4j-log4j12.