WriteOnly.pl / Posts by category / Resentiment / Biblioteki do logowania dla języka Java i platformy JVM

Biblioteki do logowania dla języka Java i platformy JVM

4 minutes to read

W artykule Konfiguracja fabryki loggerów z biblioteki Slogging w Scali autorytarnie stwierdziłem, że Backlog dla JVM jest najlepszym silnikiem do logowania. Czytając artykuł Programowanie w Rust: The Good, The Bad and The Ugly zszokowała mnie informacja, że programista nie wie która biblioteka logowania dla Javy jest najlepsza. Prawdziwa klęska urodzaju. I programista nie wie co wybrać

Opowieść w pięciu aktach o najlepszym rejestratorze logów dla Javy

To jest opowieść o bohaterze Ceki Gülcü i jego drużynie, którzy razem wyruszyli pokonać chaos, a spotkali hydrę standaryzacji oraz smoka. W roli smoka - Apache Software Foundation (ASF)

Prolog - System.out i System.err

Na początku był chaos. Dedykowane rejestratory logów jeszcze nie istniały. Aplikacje logowały do System.out (informacje) oraz System.err (błędy) W aplikacjach konsolowych CLI oraz z GUI to jest złe. W aplikacjach serwerowych też. Chyba że używa się Dockera. Wtedy wszystkie logi i tak są wyrzucane na standardowe wyjście. Ale Dockera jeszcze nie wymyślono. Problemem była też mała ilość poziomów logowania, brak możliwości zapisu logów do pliku i bazy danych oraz to, że System.out buforuje wyjście.

Akt pierwszy: rok 1999 - Apache Log4j (Log4j)

Powstaje pierwszy popularny silnik logowania Apache Log4j. Stworzony pod dowództwem naszego bohatera. Początkowo biblioteka zwana jest Log4j, a później Apache Log4j, gdy smok ASF przejmuje opiekę nad nią.

Posiada sześć poziomów logowania (TRACE, DEBUG, INFO, WARN, ERROR i FATAL) oraz możliwość konfigurowania poziomów logowania programowo, plikami XML lub plikami properties. Konfiguracja jest hierarchiczna i dla każdego pakietu, a nawet klasy, może być inna. Dodatkowo można zdefiniować wiele wyjść logów. Tzn. można jednocześnie logować do wiersza poleceń, pliku oraz bazy danych. Oczywiście z różnymi poziomami logowania dla różnych pakietów i klas.

Chaos pokonany. Problem rozwiązany. Żyć nie umierać.

Akt drugi: rok 2002 - java.util.logging (JUL)

Po trzech latach spokoju, hydra standaryzacji podnosi głowy i do Javy 1.4 zostaje dodany domyślny silnik logowania zwana JUL. Nazwa pochodzi od pakietu java.util.logging, w którym się znajduje. Posiada mniejsze możliwości niż Log4j, ale ponieważ znajduje się w standardowej bibliotece Javy, zyskuje sobie zwolenników.

Zaczynają się problemy.

Akt trzeci: rok 2002 - Jakarta Commons Logging (JCL)

Istnienie dwóch dobrych silników logowania narodziło problem. Niektóre biblioteki zależne używały Log4j, a inne JUL. Rozwiązaniem miała być wspólna fasada logowania - Jakarta Commons Logging. Ponieważ ładowała silniki logowania przez classloader powodowała często więcej problemów niż rozwiązywała.

Akt czwarty: rok 2005 - Simple Logging Facade for Java (SLF4J)

Po trzech latach niekończących się problemów z JCL do akcji ponownie wkracza bohater. Powstaje kolejna wspólna fasada logowania Simple Logging Facade for Java. Tym razem stworzona przez naszego bohatera i jego dzielną drużynę. Bohater rozwiązał problem ładowania silnika logowania w banalnie prosty sposób. W danej aplikacji może istnieć tylko jedna implementacja fasady. Wystarczy, że znajduje się w ścieżce przeszukiwania (ang. classpath) podczas uruchomienia aplikacji. Dzięki takiemu pomysłowi rozwiązano problemy czasu uruchomienia (ang. runtime), które występowały dla JCL.

SLF4J posiada wiele bindingów, będących adapterami istniejących interfejsów silników logowania do interfejsu SLF4J:

  • slf4j-log4j12 dla Log4j w wersji 1.2
  • slf4j-jdk14 dla JUL
  • slf4j-jcl dla JCL
  • slf4j-simple dla System.err
  • slf4j-nop - domyślna implementacja, która nic nie robi

Część bibliotek samodzielnie dostarcza binding jak np. Log4j w wersji 2.

Dzięki temu biblioteki zależne używają tylko SLF4J, a twórca aplikacji może zdecydować samodzielnie, który rejestrator logów użyje.

Akt piąty: rok 2006 - Logback

Wydawać by się mogło, że wszystkie problemy zostały już rozwiązanie. Bohatera dręczyło jednak to, że utrzymuje trzy biblioteki dla rozwiązania polecanego przez siebie, czyli:

  • interfejs fasady do logowania - slf4j-api
  • silnik logowania - log4j
  • binding - slf4j-log4j12, zmianiający interfejs log4j do interfejsu slf4j-api

Postanowił więc on połączyć silnik logowania z bindingiem. Tak powstał Logback. Nie posiada on własnego interfejsu i implementuje tylko i wyłącznie interfejs slf4j-api. Jest nowym kodem napisanym od początku i jednocześnie naprawia błędy istniejące w log4j, jak np. brak posiadania domyślnej konfiguracji.

A dlaczego pod inną nazwą? Ponieważ smok ASF sprawuje kontrolę nad silnikiem Log4j.

Epilog

Jest rok 2019. Nadal istnieją programiści, którzy nie potrafią wybrać właściwego rejestratora logów dla Javy. To smutne.