Log4j

aus Wikipedia, der freien Enzyklopädie
(Weitergeleitet von Log4net)
Log4j
Basisdaten

Maintainer Scott Deboy, Ralph Goers, Gary Gregory, Christian Grobmeier
Entwickler Apache Software Foundation
Betriebssystem plattformübergreifend
Programmiersprache Java
Lizenz Apache-Lizenz 2.0
logging.apache.org

Log4j ist ein Framework zum Loggen von Anwendungsmeldungen in Java. Innerhalb vieler Open-Source- und kommerzieller Softwareprodukte hat es sich über die Jahre zu einem De-facto-Standard entwickelt. Log4j gilt als Vorreiter für andere Logging-Frameworks, auch in anderen Programmiersprachen.

Geschichte

Datei:Log4js.png
Logo von Log4js

Das Projekt wurde von Ceki Gülcü 1996 während seiner Arbeit am IBM-Entwicklungslabor in Zürich gegründet. Heute ist es ein Teil des Logging-Projekts der Apache Software Foundation und steht unter der Apache-Lizenz 2.0. Es entstand zu einer Zeit, als es in den Java-Standardbibliotheken noch keine Logging-Mechanismen gab. Heutzutage ist es durch seine Ausgereiftheit und Konfigurierbarkeit für viele Softwareentwickler das Log-System der ersten Wahl.

Die Ausstrahlung der Log4j-Konzepte auf andere Programmiersprachen bzw. Plattformen ist so groß, dass es mittlerweile etliche Adaptionen gibt. Einige werden vom Apache Logging Projekt selbst gepflegt. Zum Beispiel:

  • log4cxx für C++ mit zu Log4J kompatiblen Konfigurationsdateien
  • log4Net für das .Net-Framework
  • log4php für PHP

Viele Varianten werden jedoch außerhalb von Apache Logging entwickelt:

Seit Juli 2014 ist Log4j 2 als Nachfolger des Log4j 1.x verfügbar.

Das Apache-Logging-Projekt

Das Apache-Logging-Projekt versucht, Log4j-ähnliche Systeme für diverse Programmiersprachen zusammenzuführen. Bisher sind das log4j, log4cxx, log4net, log4php[4] und Chainsaw (ein Logdatei-Betrachter und -Analysewerkzeug).[5]

Außerdem werden sogenannte Companions entwickelt, die zusätzliche Funktionalität für Apache Log4j bereitstellen.

Funktionsweise

Anstatt auftretende Fehler und Infomeldungen auf der Standardausgabe auszugeben, dient Log4j dazu, die Meldungen über sogenannte Logger an das gewählte Loggingsystem weiterzuleiten („Appender“). Neben der Auswahl des Loggingsystems wird gleichzeitig aufgrund der Wichtigkeit („Log-Level“) der Meldung entschieden, ob diese überhaupt weitergeleitet wird. Der Programmierer muss sich beim Erstellen des Programms nur um die Wichtigkeit der Meldungen Gedanken machen. Die Filterung und Art der Ausgabe kann zur Laufzeit konfiguriert werden.

Log4j ist auf möglichst hohe Geschwindigkeit ausgelegt, damit das Loggen die Systemleistung nicht negativ beeinflusst. So dauert die Entscheidung, ob eine Meldung ausgegeben werden muss, auch auf einem veralteten System (AMD Duron mit 800 MHz, JDK 1.3.1) nur 5 Nanosekunden, die Ausgabe selbst – je nachdem, welches Layout verwendet wird – zwischen 21 und 37 Mikrosekunden.[6]

Ausgabe-Umfang

In der Konfigurationsdatei kann die Ausgabe je nach Wichtigkeit der Nachrichten gefiltert werden. Der Ausgabe-Umfang sinkt mit der zugewiesenen Wichtigkeitsstufe und umfasst alle Nachrichten der Stufe selbst, sowie aller noch dringenderen Stufen. Die Reihenfolge stellt sich dabei wie folgt dar: ALL → TRACE → DEBUG → INFO → WARN → ERROR → FATAL → OFF.

Für die Einstufung der Wichtigkeit gelten folgende Richtwerte:

ALL
Alle Meldungen werden ungefiltert ausgegeben
TRACE
ausführlicheres Debugging (ab Version 1.2.12[7]), Kommentare
DEBUG
allgemeines Debugging (Auffinden von Fehlern)
INFO
allgemeine Informationen (Programm gestartet, Programm beendet, Verbindung zu Host Foo aufgebaut, Verarbeitung dauerte SoUndSoviel Sekunden …)
WARN
Auftreten einer unerwarteten Situation
ERROR
Fehler (Ausnahme wurde abgefangen. Bearbeitung wurde alternativ fortgesetzt)
FATAL
Kritischer Fehler, Programmabbruch
OFF
Logging ist deaktiviert

Appender

Mittels Appender kann das Ausgabeziel/können die Ausgabeziele der erzeugten Loggingausgaben festgelegt werden.

Nachfolgend die wichtigsten Appender-Arten:

ConsoleAppender
Gibt auf Standardausgabe aus
FileAppender
Schreibt in eine Datei
RollingFileAppender
Beginnt eine neue Datei ab einer gewissen Größe
DailyRollingFileAppender
Beginnt zu gewissen Zeiten mit einer neuen Datei
SyslogAppender
Loggt mittels Syslog-Dienst
JDBCAppender
Schreibt in eine Datenbank
NTEventLogAppender
Schreibt ins Ereignisprotokoll des Windows-Systems
SMTPAppender
Schickt bei gewissen Meldungen eine Mail.
SocketAppender
Sendet die Log-Nachricht an einen konfigurierten Socket-Listener.
LogCatAppender
Loggt in den Android LogCat

Weitere Appender können jederzeit hinzugefügt werden.

Konfiguration

Es gibt drei Arten, Log4j zu konfigurieren: mittels einer Properties- oder einer XML-Datei oder im Programmcode. Es wird empfohlen, eine Properties- oder XML-Datei zu verwenden, damit ist die Konfiguration vom Code getrennt, was es ermöglicht, ohne Modifikation oder Neustart der Applikation das Loggen umzukonfigurieren. Somit kann beispielsweise eine Applikation so lange nur mit Log-Level FATAL betrieben werden, bis ein Fehler auftritt. Ab dann wird das Level WARN gesetzt, ohne die Applikation anzuhalten.

Die Konfigurationsdateien definieren mittels der folgenden Komponenten das Verhalten von Log4j:

Appender
Diese bestimmen mittels Konfiguration der entsprechenden Appender-Klasse, wohin die Log-Ausgaben geschrieben werden sollen, und mittels Konfiguration des Layouts, wie dorthin geschrieben werden soll. Neben der reinen Nachricht können mittels Muster zusätzlich Wichtigkeit, Datum, Loggername, Klassenname und Methodenname bis hin zur genauen Codezeile ausgegeben werden.
Logger
Ein Logger ist ein Objekt, welches die Logging-Aufgaben einer Klasse übernimmt. Es wird über seinen Namen identifiziert. Üblicherweise wird der Klassenname als Name für den Logger verwendet. Es ist allerdings auch möglich, einen Fantasie-Namen zu verwenden, der von mehreren Klassen benutzt wird. Ein typisches Beispiel könnte so aussehen: Logger log = Logger.getLogger(org.wikipedia.MyClass).
Damit kann das Logging-Verhalten einer Klasse gesteuert werden. Da der Logger auch die Paket-Informationen erhält, ist es auch möglich Logging für ganze (Super)-Pakete zu konfigurieren.
Die Konfigurationsdatei kann dann eben den Logger-Namen – also z. B. "org.wikipedia.MyClass" – und auch das gewünschte Log-Level enthalten. Es ist wie bereits erwähnt möglich, eine Konfiguration für ein Paket wie "org.wikipedia" festzulegen.
Darüber hinaus können entweder allgemein oder auch zu jedem Logger spezifisch ein oder mehrere Appender definiert werden. Somit ist es beispielsweise möglich, fatale Fehler nicht nur in eine Datei zu schreiben, sondern auch gleichzeitig per E-Mail an einen Administrator zu schicken.
Log4j 2.0 bietet neben diesen klassischen Konfigurationen auch modernere Möglichkeiten an, in das Logging-Verhalten einzugreifen. Beispielsweise werden sogenannte Marker unterstützt.

Ein weiteres nützliches Merkmal ist der Mapped Diagnostic Context. Dabei wird einer Kontextvariablen ein Wert zugewiesen und in der Konfigurationsdatei kann darauf referenziert werden. Dabei hat jeder Thread seinen eigenen Kontext und kann zusätzliche Informationen wie z. B. die Adresse des Clients bei einer Serveranwendung protokollieren.

Beispiel

Die folgende XML Konfiguration konfiguriert eine Applikation so, dass FATAL-Fehler von Fremdbibliotheken auf die Konsole geloggt werden, ERROR-Fehler der eigenen Applikation zusätzlich auch per E-Mail geschickt werden, bei einer spezifischen Komponente darüber hinaus auch noch INFO-Meldungen geloggt werden und bei einer bestimmten Klasse sogar noch DEBUG-Meldungen.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN"
    "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration>
  <!-- Appender für eine einzeilige Ausgabe an der Konsole -->
  <appender name="Konsole" class="org.apache.log4j.ConsoleAppender">
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern"
        value="%d{ABSOLUTE} %5p %c{1}:%L - %m%n" />
    </layout>
  </appender>

  <!-- Appender für dieselbe Ausgabe via email -->
  <appender name="mail" class="org.apache.log4j.net.SMTPAppender">
    <param name="SMTPHost" value="smtp.myservername.xx" />
    <param name="From" value="email@fromemail.xx" />
    <param name="To" value="toemail@toemail.xx" />
    <param name="Subject" value="[LOG] ..." />
    <param name="BufferSize" value="1" />
    <param name="threshold" value="error" />
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern"
        value="%d{ABSOLUTE} %5p %c{1}:%L - %m%n" />
    </layout>
  </appender>

  <!-- ERROR-Logger für alle Klassen meiner Applikation -->
  <logger name="com.myapp">
    <level value="error"/>
    <appender-ref ref="Konsole" />
    <appender-ref ref="mail" />
  </logger>

  <!-- INFO-Logger für eine spezifische Komponente -->
  <logger name="com.myapp.mycomponent">
    <level value="info"/>
  </logger>

  <!-- DEBUG-Logger für eine spezifische Klasse -->
  <logger name="com.myapp.mycomponent.MyClass">
    <level value="debug"/>
  </logger>

  <!-- FATAL-Logger für die gesamte Applikation (inkl. Bibliotheken) -->
  <root>
    <level value="fatal" />

    <!-- loggt auf Konsole - wenn nicht in Sub-Loggern anders definiert -->
    <appender-ref ref="Konsole" />
  </root>
</log4j:configuration>

Apache Log4j 2

Version 2 wurde von Grund auf neu geschrieben, auch wenn Teile von Log4j 1.x übernommen wurden. Die neue Version verfügt über eine moderne Schnittstelle, wie sie auch von logback bekannt ist. Außerdem unterstützt sie slf4j native. Zugleich wurden Schwächen von logback analysiert und versucht zu verbessern. Somit verliert Log4j 2 beispielsweise keine Logging-Events, wenn sich das System neu konfiguriert. Außerdem wurde eine Plugin-Architektur bereitgestellt und die Konfiguration mittels JSON ermöglicht.[8]

Das Projekt gab im August 2015 bekannt, dass der 1.x Zweig das "End of Life" erreicht hat und damit die Weiterentwicklung eingestellt wird. Entwickler werden deswegen gebeten, auf den 2.x Zweig zu migrieren.[9][10]

Auf der Website von Apache werden einige Unterschiede zwischen Log4j 1 und Log4j 2 aufgelistet.[11]

Log4j 2 Konfigurationsbeispiel

In Log4j 2 hat sich die Syntax der Konfiguration geändert. Es folgt ein beispielhaftes Konfigurationsfile nach dem neuen Standard:

<?xml version="1.0" encoding="UTF-8" ?>
<Configuration >
	<Properties>
	    <Property name="logfile">C:/logs/logfile</Property>  
		<Property name="LOG_PATTERN">%d{dd.MM.yyyy - HH:mm:ss} %-5p [%t] - %C - %M - %m%n</Property>
	</Properties>

	<Appenders>
		<!-- Appender für eine einzeilige Ausgabe an der Konsole -->
		<Console name="Konsole" target="SYSTEM_OUT"> 
			<ThresholdFilter level="DEBUG" onMatch="ACCEPT"	onMismatch="DENY" />
			<PatternLayout pattern="${LOG_PATTERN}"/> 
		</Console> 
	
		<!-- Appender für alle Logs ab Level Debug in maximal 20 Dateien die jede maximal 20MB groß werden dürfen-->
		<RollingFile name="DEBUG_LOG"
			fileName="${logfile}_Debug.log"
			filePattern="${logfile}_Debug-%i.log">
			<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY" />
			<PatternLayout pattern="${LOG_PATTERN}" />
			<Policies>
				<TimeBasedTriggeringPolicy />
				<SizeBasedTriggeringPolicy size="20000KB" />
			</Policies>
			<DefaultRolloverStrategy max="20" />
		</RollingFile>
  
		<!-- Appender für alle Logs ab Level Error in maximal 20 Dateien die jede maximal 20MB groß werden dürfen-->
		<RollingFile name="ERROR_LOG"
			fileName="${logfile}/${project}_Error.log"
			filePattern="${logfile}/${project}_Error-%i.log">
			<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY" />
			<PatternLayout pattern="${LOG_PATTERN}" />
			<Policies>
				<TimeBasedTriggeringPolicy />
				<SizeBasedTriggeringPolicy size="20000KB" />
			</Policies>
			<DefaultRolloverStrategy max="20" />
		</RollingFile>
	</Appenders>
    <Loggers>
	
		<logger name="com.myapp" additivity="false">
			<AppenderRef ref="DEBUG_LOG" />
			<AppenderRef ref="ERROR_LOG" />
			<AppenderRef ref="Konsole" />
		</logger>

        <Root level="all">
			<AppenderRef ref="Konsole" />
         </Root>
	</Loggers>
</Configuration>

Bekanntwerden einer Sicherheitslücke im Dezember 2021

Am 10. Dezember 2021 wurde eine Zero-Day-Lücke in Log4j-Version 2 bekannt (CVE-2021-44228, oft als Log4Shell bezeichnet), die Angreifer ausnutzen konnten, um Code auf dem jeweiligen Hostsystem auszuführen (Remote Code Execution) und somit zum Beispiel Rechenleistung von den infizierten Servern zu benutzen, um Krypto-Mining zu betreiben. Laut F-Secure gab es auch Ransomware-Angriffe. Betroffene Dienste sind unter anderem Amazon Web Services, Steam und iCloud.[12][13]

Laut Bundesamt für Sicherheit in der Informationstechnik (BSI) ergeben Berichte von CERT-Quellen, dass weltweite Massenscans und versuchte Kompromittierungen im Zuge der Zero-Day-Lücke stattfanden.[14][13] Das BSI verwies auf eine „unvollständige Auflistung“ von 140 Unternehmen, die besonders anfällig seien.[15][13]

Nur wenige Tage nach Veröffentlichung wurde die Sicherheitslücke schon kriminell ausgenutzt.[16]

  • Am 16. Dezember 2021 wurden mit dem Internet verbundene Systeme des belgischen Militärs über die Lücke angegriffen.[17]
  • Am 17. Dezember 2021 wurde die Webseite des Bundesfinanzhofs wegen einer solchen Attacke abgeschaltet.[18]

Alternativen

  • Java Logging – seit Java 1.4 Bestandteil der Java-Klassenbibliothek; ähnlich wie Log4j, weniger Appender, kein PatternLayout
  • Apache Commons Logging – Schnittstelle für beliebig austauschbare Logging-Frameworks, unter anderem Log4j
  • tinylog – schlankes Logging-Framework mit einem statischen Logger[19]

Literatur

Weblinks

Einzelnachweise

  1. Rolf Kulemann: android-logging-log4j. Logging with Log4J in Android ¦ providing LogCat appender and configuration facade. Abgerufen am 29. November 2011.
  2. 14.5 logging -- Logging facility for Python. Abgerufen am 16. März 2020.
  3. Logger Toolkit for LabVIEW - Download - VIPM by JKI. Abgerufen am 10. Februar 2022.
  4. Apache log4php - Welcome - Apache log4php. Abgerufen am 16. März 2020.
  5. Welcome - Apache Logging Services. Abgerufen am 16. März 2020.
  6. Apache log4j 1.2 -. Abgerufen am 16. März 2020 (englisch).
  7. Level (Apache Log4j 1.2.17 API). Logging.apache.org. 9. Juni 2012. Abgerufen am 24. Juli 2014.
  8. The new log4j 2.0. Abgerufen am 16. März 2020.
  9. Log4j – Migrating from Log4j 1.x to 2.x. Abgerufen am 12. Januar 2022.
  10. Apache log4j 1.2 -. Abgerufen am 12. Januar 2022.
  11. Log4j – Migrating from Log4j 1.x. Abgerufen am 16. März 2020.
  12. heise online: Kritische Zero-Day-Lücke in Log4j gefährdet zahlreiche Server und Apps. Abgerufen am 10. Dezember 2021.
  13. a b c Max Hoppenstedt: Log4-J-Schwachstelle: »Leider machen auch Hacker Überstunden«. In: Der Spiegel. 12. Dezember 2021 (spiegel.de [abgerufen am 12. Dezember 2021]).
  14. Kritische Schwachstelle in log4j veröffentlicht (CVE-2021-44228). (PDF) In: www.bsi.bund.de. Abgerufen am 14. Dezember 2021.
  15. 262588213843476: BlueTeam CheatSheet * Log4Shell* | Last updated: 2021-12-14 0006 UTC. Abgerufen am 14. Dezember 2021 (englisch).
  16. Christof Kerkmann: Gefährliche Sicherheitslücke: Die Angriffe auf Unternehmen und Behörden beginnen. In: handelsblatt.com. 17. Dezember 2021, abgerufen am 18. Dezember 2021.
  17. Log4j-Schwachstelle: Belgisches Militär von Angriff über Sicherheitslücke betroffen - DER SPIEGEL. In: spiegel.de. 21. Dezember 2021, abgerufen am 23. Dezember 2021.
  18. Schwachstelle Log4j: Bundesfinanzhof schaltet Website nach Hackerangriff ab. In: faz.net. 17. Dezember 2021, abgerufen am 17. Dezember 2021.
  19. tinylog 2 - Lightweight Logging Framework for Java, Scala, Kotlin, and Android. Abgerufen am 31. Dezember 2021.