Logowanie w Javie – dobre praktyki

Logowanie ułatwia debugownie aplikacji, dlatego warto robić to dobrze!

  1. Loguj możliwie dużo istotnych informacji. Zadbaj o ich konsolidacje, dostępność i czytelność. Zgromadź wszystkie logi w jedym miejscu, zorientuj je na osi czasu z całą infrastrukturą i ułatw jego przeszukiwanie.
  2. Dodawaj logger w obsłudze wyjątków (try-catch)
  3. Informuj o stanie utworzonego obiektu używając metody toString() lub wyświetlając jako json.
  4. Zbieraj informację o kontekście zdarzenia by szybciej zlokalizować problem. Sprawdź co oferuje biblioteka, której używasz.
  5. Dobierz odpowiednie poziomy logowania, dzięki czemu zamiast modyfikować kod wystarczy drobna zmiana w konfiguracji loggera na produkcję.

src: stackify.com/java-logging-best-practices/

#log4j #java

Logowanie w Javie z Log4j cz.2

Konfiguracja

Zależności

Dodajemy log4j-core w wersji 2.x (1.x jest niewspierana)

Ustawiamy odpowiednią wersję kompilatora:

Plik konfiguracyjny

W katologu Resources umieszczamy log4j2.xml

Jest skonfigurowany tak by wyświetlał informacje w konsoli oraz zapisywał je do pliku (to są dwa oddzielnie skonfigurowane zadania).

Ważne: Logowanie nie będzie działało dopóki nie umieścisz Appendera w sekcji Loggers!

Praktyka

Przykład

Rezultat

Stworzyliśmy, więc folder logs, z plikiem .log. Ponadto -co na załączniku nie jest widoczne – po spełnieniu warunku (tutaj 50MB) tworzy się nowy folder zawierający datę oraz plik z nazwą wg. wzorca.

src: https://stackify.com/log4j2-java/ – how it works

Dobre praktyki

Polecam artykuł Najlepsze praktyki. Zrobiłem też mega krótką ściągę https://wilamowski.it/blog/?p=345

 

Java Best Practices for Smarter Application Logging & Exception Handling

Logowanie w Javie z Log4j cz.1

Wstęp

Po co mi logowanie?

Z czasem, gdy piszesz kolejny projekt w Javie zauważasz, że coś jest nie tak. I nie tylko chodzi o to ze okopales się kodem i zaczynasz czuć o co tu chodzi, a o wypisywanie informacji do tego co się dzieje w coraz to bardziej rozbudowanej aplikacji zaczyna być nieco niepraktyczne przy pomocy dotychczasowego wyświetlania tego w konsoli funkcja System.out.println() …
Pozwoli Tobie to organizacje logow, a umieszczenie metod logujacych w kluczowych miejscach, może pozwolić Tobie łatwiej obsługiwać i debugować aplikacje. Zdecydujesz o tym jak je wyświetlać i gdzie je przechowywać.

Cel wpisu

Przykładowa konfiguracja, tak by uzyskać zapisywanie logów w pliku tekstowym. Możliwości konfiguracyjny są oczywiście znacznie większe, celem nie jest jednak przepisywanie dokumentacji, raczej przykładowe minimalne, użyteczne użycie.

Jak przechowywać logi?

Biblioteka pozwala nie tylko na wyświetlnie danych w terminalu, ale również ich zapis do pliku .txt, bazy danych (przy użyciu JDBC).
W poniższym przykładzie pokaże jak zapisać je do pliku z roszerzeniem .out.

Konfiguracja

Zanim zaczniesz

Zanim przystąpisz do konfiguracji nie popełnij mojego błędu… 🙂
Biblioteka przestała być wspierana już jakiś czas temu, an stronie Apache znajdziemy ostatnią informację o poniższej treści.

On August 5, 2015 the Logging Services Project Management Committee announced that Log4j 1.x had reached end of life. For complete text of the announcement please see the Apache Blog. Users of Log4j 1 are recommended to upgrade to Apache Log4j 2.

src: https://logging.apache.org/log4j/1.2/

Pod linkiem znajdziesz wpis z aktualną wersją log4j2

Konfiguracja log4j2

Biblioteki i narzędzia

Poslugujac się InteliJ Idea oraz systemem budowania Maven z repozytorium pobieram poniższe zależności

TIP: Czasami IDE nie widzi nowych zależności, więc jeśli np. nie będziesz widział podpowiedzi, a to co napiszesz „z palca” system przyodziewa w czerwień użyj Reimport all Maven Projects (ikonka ze strzałkami).

PS Nie zapominamy o ustawieniu kompilatora na wersje 1.8

Konfiguracja pliku properties biblioteki log4j

W katalogu Resources zamieszczamy plik konfiguracyjny .properties. Może mieć on również postać .xml.

Sprawdzamy czy plik jest widoczny. Powinnismy dostać parametry wraz wartościami jako odpowiedź.

Gratulacje, konfiguracja zakończona 😊

Użycie obiektu klasy logger

W parametrze metody podajemy treść komunikatu, który pojawi się logu oraz w zależności od konfiguracji np. datę i godzina wywołania.

Przykładowe wywołanie:

Rozważ czy warto zamieścić w nim również np. parametry metod,  wartości zmiennych czy tych zwracanych przez metody. W określeniu poziomu logowania pomoże kolejny podpunkt.

Rodzaje logowania

Rodzaje logowania, które chcesz rejestrować muszą być dopisane w parametrze log4j.rootLogger pliku konfiguracyjnego.

ALL All levels including custom levels.
DEBUG Designates fine-grained informational events that are most useful to debug an application.
INFO Designates informational messages that highlight the progress of the application at coarse-grained level.
WARN Designates potentially harmful situations.
ERROR Designates error events that might still allow the application to continue running.
FATAL Designates very severe error events that will presumably lead the application to abort.
OFF The highest possible rank and is intended to turn off logging.
TRACE Designates finer-grained informational events than the DEBUG.

src: tutorialspoint.com

Praktyka

Krok po kroku

W każdej z klas która będzie korzystać tej funkcjonalności, umieszczamy na początku klasy

Importujemy…

Teraz w main (tutaj App) czy metodach programu umieszczamy funkcje wywołującą log.

Przejdźmy do klasy, wyglądać to ma, o, tak:

Uruchamiamy aplikację…

P.S.
Dla purystów: warto wspomnieć, że Lombok pozwala na umieszczenie adnotacji @Log4j2 dla każdej z klas w której korzystamy z logowania. Zmniejszenie ilość kodu sprawia, że kod jest czytelniejszy, choć sprawa jest kontrowersyjna 😊

Alternatywy dla log4j

Powyższa biblioteka jest kompletna, lecz istnieja tez bardziej zlozone rozwiązania jak np

Abstrakcja Simple Loggin Facade for Java, tj. SLF4J

Implementacje abstrakcji SLF4J, czyli jeden z komponentów które można dowolnie wymieniać. Tutaj użyć np. biblioteki log4j2, choć równie dobrze mógłby być to np. logback.

JDBC w 5 minut

JDBC (Java Database Connector) to niskopoziomowe operacje na bazie danych przy pomocy sterownika producenta.
Daje większe możliwości niż popularne frameworki wykorzystujące mapowanie obiektowo-relacyjne, jednak obsługa zapytań odbywa się większym nakładem pracy. Warto zacząć od nich nauke, bo bywają przydatne tam gdzie ORM nie dają rady 🙂

Tworzymy klasę  do połączenia z bazą stosując wzorzec Singleton. Dlaczego zastosujemy ten wzorzec? Potrzebujemy tylko jednej instancji tego obiektu, więc tworzymy prywatny konstruktor.

Obiekt stworzymy przy użyciu statycznej (czyli nie potrzebującej obiektu) metody. Tworzymy też warunek, w którym sprawdzamy czy obiekt istnieje.

Wczytujemy parametry połączenia z naszego pliku db.properties* do zmiennych przy użyciu FileReader

I rejestrujemy sterownik przy pomocy Class.forName oraz przekazujemy DriverManager.getConnection ze szczegółami połączenia do obiektu connection.

Zwracamy obiekt

*zawartość pliku db.properties

Ważne: nie zapominamy o dołączeniu sterownika bazy Oracle w IDE Intelij IDEA.
https://wilamowski.it/index.php/2019/07/28/how-to-import-jdbc-oracle-driver-to-intelij-idea-project-ojdbc6-jar/

 

Przejdźmy do klasy testowej. Tworzymy obiekt  connection przy pomocy metody statycznej:

Do wykonania zapytania SQL i połączenia z bazą tworzymy obiekt statement (interfejs Statement, java.sql). Potrzebny nam jest do wysłania zapytania do bazy. PS Jeżeli potrzebujemy zapytań zparametryzowanych lub zapytanie będzie używane wielokrotnie warto zainteresować się PreparedStatment.

Metoda executeQuery zwraca wynik zapytania. W tym samym momencie może być otwarty jeden Statement i jeden ResultSet.

Mapujemy encje i wyświetlamy rezultat wiersz po wierszu (.next() zwraca wartość logiczną)


 —————————————————–

Projekt przedstawiający przykład połączenia z plikiem parametrów wzorcem singleton i prostym zapytaniem. Myślę, że dobrze to ukazuje idee bez zbędnego kodu

https://github.com/connoisseur0/JDBC-example

Source:
1. https://docs.oracle.com/javase/tutorial/jdbc/basics/processingsqlstatements.html#creating_statements
2. https://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html