Loggen in Java

tinylog: Die schlanke log4j-Alternative

Martin Winandy

Loggen ist mittlerweile in jeder komplexen Anwendung üblich. Als Logging Framework war log4j der Vorreiter in der Java-Welt und hat sich zum De-facto-Standard entwickelt. Aber genügt log4j immer allen Anforderungen? Tinylog wagt als schlanke Alternative den Vorstoß.

Protokollieren des Programmablaufs vereinfacht die Fehlersuche und das Reproduzieren von Bugs. Dabei macht die Anwendung mit Hilfe eines Loggers regelmäßig Ausschriebe über den Programmablauf und aufgetretene Fehler. Später kann der Entwickler für gemeldete Bugs anhand der erzeugten Log-Dateien problemlos nachvollziehen, was im Programm genau während des Fehlers passiert ist. Dies ist besonders bei Bugs hilfreich, die in Produktion oder beim Kunden auftauchen. Damit Log-Dateien wirklich hilfreich sind, muss eine Anwendung genügend und vor allem aussagekräftige Log-Einträge ausgeben, und das liegt alleine in der Hand der Entwickler. Je einfacher ein Logging-Framework zu verwenden ist, desto häufiger wird es auch tatsächlich genutzt und damit der Programmablauf umso lückenloser protokolliert.

Tinylog [1] ist ein schlankes Logging Framework für Java und stellt eine Alternative zum De-Facto-Standard log4j dar. Die Idee für tinylog entstand aus mehreren Verbesserungsvorschlägen für log4j [2] und ist schließlich in ein eigenes Open-Source Projekt gemündet:

  • Das Erzeugen einer Logger-Instanz für jede Klasse, in der geloggt werden soll, ist umständlich und fehleranfällig.
  • Texte in den Logging-Methoden können weder formatiert noch mit Parametern versehen werden.
  • In Anwendungen, bei denen es auf schnelle Reaktionszeiten ankommt, kann das Erzeugen und Schreiben von Log-Einträgen zu Performance-Problemen führen.
Statischer Logger

In den drei großen bekannten Logging-Frameworks log4j, Logback [3] und der Java Logging API [4] wird üblicherweise für jede Klasse eine eigene Logger-Instanz erzeugt. Dies sieht beispielsweise in log4j wie folgt aus:

Listing 1
import org.apache.log4j.Logger;

public class Application {

  private static final Logger logger = Logger.getLogger(Application.class);

  public static void main(String[] args) {
    logger.info("Mein Log-Eintrag ...");
  }
}

Die Instanziierungs-Anweisung in Zeile 5 wird in jeder Klasse benötigt und daher oft per Copy & Paste aus einer anderen Klasse herauskopiert. Dabei kann leicht vergessen werden, den Klassen-Parameter zu ändern. Dies führt dazu, dass falsche Log-Einträge erzeugt werden. In tinylog gibt es nur einen einzigen Logger, der statisch ist. Damit entfällt das Instanziieren eines Loggers:

Listing 2
import org.pmw.tinylog.Logger;

public class Application {

  public static void main(final String[] args) {
    Logger.info("Mein Log-Eintrag ...");
  }

}

Zu loggende Texte können in tinylog formatiert und mit Parametern versehen werden. Dies funktioniert genau wie beim bekannten MessageFormat.format() [5]. Der Unterschied zwischen Logger.info(„Pi ist {0,number,0.00} und die Antwort auf alle Fragen lautet {1}“, Math.PI, 42) und Logger.info(MessageFormat.format(„Pi ist {0,number,0.00} und die Antwort auf alle Fragen lautet {1}“, Math.PI, 42)) ist neben dem kompakteren Code, dass der Text nur dann erzeugt wird, wenn der Log-Eintrag wirklich ausgegeben werden soll. Ist der Logger deaktiviert oder sollen nur Fehler und Warnungen ausgegeben werden, wird der Log-Eintrag, und damit der Text, erst gar nicht erzeugt und Rechenzeit eingespart. Tinylog verfügt über fünf Logging-Level: ERROR, WARNING, INFO, DEBUG und TRACE. Standardmäßig werden nur die Logging-Level ERROR, WARNING und INFO ausgegeben. Dies kann über das Property „tinylog.level=<level>“ geändert werden. Properties werden typischerweise als Parameter (z.B. „-Dtinylog.level=DEBUG“) übergeben oder befinden sich in der Properties-Datei „tinylog.properties“. Liegt diese im Root-Package, so wird die Datei beim Start automatisch angezogen.

Geschrieben von
Martin Winandy
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.