Welches Logging-Framework für Java nutzen?

Einer der größten Vorteile von Java ist das reichhaltige Ökosystem, in dem viele Bibliotheken und Frameworks für die Programmiersprache existieren. Auch der Bereich Logging hat gleich mehrere Frameworks zu bieten, was die Frage aufwirft, welches davon man nutzen soll. Dieser Artikel stellt die Frameworks kurz vor und soll als Entscheidungshilfe bei der Auswahl des passenden Frameworks dienen.

Die Logging-Frameworks

Zunächst muss unterschieden werden zwischen Logging-API und -Implementierung. Eine API stellt das Interface mit den Logmethoden sowie weitere dafür benötigte Klassen und Interfaces bereit. Der Entwickler programmiert grundsätzlich gegen die API. Die konkrete Implementierung, d.h. das genutzte Framework, ergibt sich dynamisch aus den zur Laufzeit vorhandenen *.jar-Files. Der Vorteil dabei ist, dass das genutzte Logging-Framework durch reinen Austausch der *.jar- und Konfigurations-Dateien geändert werden kann, ohne dass der Anwendungscode angefasst werden muss. Die Dokumentation von SLF4J veranschaulicht dies sehr schön wie folgt:

Beispiel Logging-API und -Implementierungen
Quelle: https://www.slf4j.org/manual.html

SLF4J (Simple Logging Facade for Java) und Apache Commons Logging verstehen sich als Logging-API. Sie bringen jeweils sehr einfache Implementierungen mit (z.B. Ausgabe aller Lognachrichten auf System.err). In der Regel benötigt man jedoch einen größeren Funktionsumfang, so dass man die Implementierung von einem der nachfolgenden Frameworks nutzt:

  • java.util.logging: Die seit Java 1.4 im JDK enthaltene Logging-API & -Implementierung
  • Apache Log4J, wohl eines der bekanntesten Logging-Frameworks.
  • Logback: Die Standard-Implementierung für SLF4J.
  • Tinylog: ein schlankes, performantes, aber doch Feature-reiches Framework.

Bezüglich Log4J sei noch zu erwähnen, dass in Version 2 API und Implementierung getrennt sind, und die Log4J 2 API ggf. auch zusammen mit einem anderen Framework genutzt werden kann (obwohl dies kein primäres Designziel von Log4J 2 ist).

Entscheidungskriterien

Um die Entscheidung für ein Framework zu erleichtern, habe ich ein paar für mich wichtigen Kriterien ausgewählt:

Open-Source-Lizenz

Alle genannten Frameworks sind Open Source, werden aber unter verschiedenen Lizenzen veröffentlicht. Ausgenommen ist java.util.logging, das unter die Lizenz des verwendeten JDK fällt, da es im JDK enthalten ist. Die zu beantwortenden Fragen sind, ob die jeweilige Lizenz den kommerziellen Einsatz erlaubt, und ob der Quellcode der nutzenden Anwendung offengelegt werden muss.

Java Platform Module System („Jigsaw“)

Um zukunftsfähig zu sein, sollte das Framework für die Nutzung mit dem Java Platform Module System (JPMS, auch bekannt als „Jigsaw“) aus Java 9 modularisiert sein.

Unterstützung von Java 8 Lambdas

Die Erzeugung von Lognachrichten kann unter Umständen recht ressourcenaufwändig sein. Beispielsweise wenn ein Objekt für die Ausgabe in einer Lognachricht nach JSON serialisiert werden muss. Der herkömmliche Weg war eine Abfrage des Loglevels im Clientcode, um sicher zu stellen, dass die Serialisierung nur dann stattfindet, wenn die Nachricht auch tatsächlich geloggt wird:

Mit einem Lambda kann der oben stehende Code auf eine Zeile reduziert werden, sofern die API dies anbietet:

In diesem Fall wird der Loglevel intern von der debug(…)-Methode geprüft. Statt des bereits serialisierten Objekts wird ein Supplier als Lambda übergeben; die Serialisierung findet nur statt wenn der Loglevel auf DEBUG gestellt ist. Um die Prüfung des Loglevels muss sich der Clientcode nun nicht mehr kümmern.

Rolling File Appender

Appender sind dafür zuständig, die Logmeldungen in eine konfigurierte Datensenke zu schreiben – dies kann z.B. die Konsole, eine Datei, eine Datenbank o.ä. sein. Ein Rolling File Appender schreibt in eine Logdatei und sorgt dafür, dass nach bestimmten zu konfigurierenden Bedingungen jeweils neue Logdateien angelegt werden. Zum Besipiel zu jedem Datumswechsel, oder wenn die Datei eine definierte Maximalgröße erreicht.

Zudem sollte der Appender die Möglichkeit bieten, Logdateien zu komprimieren, sowie alte Dateien zu löschen, z.B. wenn diese älter als 30 Tage sind. So benötigt man keinen zusätzlichen Cronjob, der sich um das Komprimieren und Aufräumen der Dateien kümmern muss.

Entscheidungstabelle

Die nachfolgende Tabelle zeigt, welche der oben beschriebenen Kriterien durch die jeweiligen Frameworks erfüllt sind.

Framework Lizenz Lambdas JPMS
(„Jigsaw“)
Rolling File Appender
mit Komprimier- und Löschfunktion
Logging-API
(Nutzung mit
anderen Frameworks)
Anmerkungen
Apache Commons Logging   Apache 2.0 API mit sehr geringem Funktionsumfang
SLF4J   MIT   erst ab V. 1.8 (aktuell Beta)
Logback   LGPL / EPL 1.0 (duale Lizenz)   erst ab V. 1.3 (aktuell Alpha)

(als API sollte SLF4J genutzt werden)

EPL-Lizenz fordert Offenlegung des Quellcodes
Log4J 2   Apache 2.0
Tinylog   Apache 2.0 (seit V. 2.0) löschen

komprimieren

kann via alternativer Logging-APIs genutzt werden (Apache Commons Logging, Log4J u. SLF4J)
java.util.logging   (via JDK)

= Kriterium erfüllt

= Kriterium nicht erfüllt

Bewertung der Frameworks

Log4J 2 ist am weitesten entwickelt und bietet den größten Funktionsumfang. Es unterstützt Lambdas und ist modularisiert. Zudem bietet es Vorteile in Sachen Performance. So hat die Implementierung beispielsweise so gut wie keine Auswirkungen auf die Garbage Collection, da die Implementierung bestehende Objekte so gut es geht wiederverwendet, anstatt immer wieder neue zu erzeugen und zu verwerfen. Die API ist von der Implementierung separiert, so dass sie bei Bedarf mit der Implementierung eines anderen Frameworks genutzt werden kann. Für mich ist Log4J 2 der eindeutige Gewinner.

Sofern Lambdas und Modularisierung zum aktuellen Zeitpunkt nicht so wichtig sind, und man sich nicht auf ein bestimmtes Framework festlegen möchte, könnte auch SLF4J einen Blick wert sein.

java.util.logging hat den Vorteil, dass man sich keine externen Abhängigkeiten für Logging ins Projekt holt. Dies wird jedoch erkauft durch einen geringeren Funktionsumfang beim FileAppender (in java.util.logging FileHandler genannt), sowie den Umstand, dass der spätere Umstieg auf ein anderes Logging-Framework nicht ohne Änderungen des Anwendungscodes möglich ist. Und da Logging eine zentrale Funktion ist die in der Regel von sehr vielen Klassen genutzt wird, dürfte der Aufwand dafür nicht unerheblich sein. Zudem gibt es hier die gewöhnungsbedürftigen Loglevel FINE, FINER und FINEST, welche an Stelle von DEBUG und TRACE stehen, die man von den anderen Frameworks gewöhnt ist.

Tinylog ist schlank und effizient (laut Benchmark des Herstellers wohl das performanteste der verglichenen Frameworks), geizt aber dennoch nicht mit Funktionen. Zudem ist es einfach zu nutzen. Die Logger-Klasse ist statisch und kann sofort verwendet werden. Das Initialisieren von Logger-Klasses ist somit nicht notwendig, was Boilerplate-Code einspart. Für kleinere Projekte ist Tinylog sicher einen zweiten Blick wert. Seit Version 2 (veröffentlicht am 21.08.2019) ist es gemäß JPMS modularisiert und bringt spezielle APIs für Scala und Kotlin mit – letzteres dürfte vor allem Android-Entwickler interessieren.

Apache Commons Logging würde ich persönlich wegen des sehr geringen Funktionsumfangs der API nicht mehr einsetzen.

Korrektur bzgl. Lizenzierung, 14.05.2019 – 9:50: Die Nutzung von Logback, das unter einer dualen Lizenzierung steht (EPL 1.0 u.  LGPL 2.1), ist erlaubt, ohne dass der Quellcode der nutzenden Anwendung offen gelegt werden muss.

Update, 20.08.2019: Tinylog ergänzt.

Update, 21.08.2019: Tinylog 2 ist jetzt offiziell released (war vorher RC2)

Quellen:

Zurück zur Übersicht

2 Kommentare zu “Welches Logging-Framework für Java nutzen?

  1. Hallo Matthias,

    danke für den Hinweis. Tinylog kannte ich bisher noch nicht. Ich werde es mir anschauen und bei Gelegenheit hier mit aufnehmen.

    Schöne Grüße
    Stefan

  2. Es wäre schön, wenn tinylog hier noch in der Betrachtung ergänzt werden könnte.

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

*Pflichtfelder

*