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
Biblioteki i narzędzia
Poslugujac się InteliJ Idea oraz systemem budowania Maven z repozytorium pobieram poniższe zależności
1 2 3 4 5 |
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> |
Konfiguracja pliku properties biblioteki log4j
W katalogu Resources zamieszczamy plik konfiguracyjny .properties. Może mieć on również postać .xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# Define the root logger with appender file log4j.rootLogger = DEBUG, FILE # Define the file appender log4j.appender.FILE=org.apache.log4j.RollingFileAppender # Set the name of the file log4j.appender.FILE.File=log.out # Set the immediate flush to true (default) log4j.appender.FILE.ImmediateFlush=true # Set the threshold to debug mode log4j.appender.FILE.Threshold=debug # Set the append to false, should not overwrite log4j.appender.FILE.Append=true # Set the maximum file size before rollover log4j.appender.FILE.MaxFileSize=5MB # Set the the backup index log4j.appender.FILE.MaxBackupIndex=2 # Define the layout for file appender log4j.appender.FILE.layout=org.apache.log4j.PatternLayout #log4j.appender.FILE.layout.conversionPattern=%m%n log4j.appender.FILE.layout.ConversionPattern=[%p] %c - %m - Date: %d %n |
Sprawdzamy czy plik jest widoczny. Powinnismy dostać parametry wraz wartościami jako odpowiedź.
1 2 3 4 5 6 7 8 9 10 11 12 |
Properties props = new Properties(); private final String nameOfPropertiesFile = „log4j.properties”; try { final InputStream inStream = App.class.getClassLoader().getResourceAsStream(nameOfPropertiesFile); if (inStream != null) { props.load(inStream); } else { System.out.println("not on classpath"); } } catch (IOException e) { log.info("Exception "); } |
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:
1 |
log.info("Application started"); |
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
1 |
static Logger log = Logger.getLogger(App.class.getName()); |
Importujemy…
1 2 |
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; |
Teraz w main (tutaj App) czy metodach programu umieszczamy funkcje wywołującą log.
1 |
log.info("Application started"); |
Przejdźmy do klasy, wyglądać to ma, o, tak:
1 2 3 4 5 6 |
public class App { static Logger log = Logger.getLogger(App.class.getName()); public static void main(String[] args) { log.info("Application started"); } } |
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
1 2 3 4 5 |
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.5</version> </dependency> |
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.