Einführung in Log4j2 - Anhänge, Layouts und Filter

1. Übersicht

Das Protokollieren von Ereignissen ist ein kritischer Aspekt der Softwareentwicklung. Obwohl im Java-Ökosystem viele Frameworks verfügbar sind, ist Log4J aufgrund seiner Flexibilität und Einfachheit seit Jahrzehnten das beliebteste.

Log4j 2 ist eine neue und verbesserte Version des klassischen Log4j-Frameworks.

In diesem Artikel werden die gängigsten Appender, Layouts und Filter anhand praktischer Beispiele vorgestellt.

In Log4J2 ist ein Appender einfach ein Ziel für Protokollereignisse. Es kann so einfach wie eine Konsole sein und wie jedes RDBMS komplex sein. Layouts bestimmen, wie die Protokolle dargestellt werden, und Filter filtern die Daten nach den verschiedenen Kriterien.

2. Setup

Um mehrere Protokollierungskomponenten und ihre Konfiguration zu verstehen, richten wir verschiedene Testanwendungsfälle ein, die jeweils aus einer log4J2.xml- Konfigurationsdatei und einer JUnit 4- Testklasse bestehen .

Zwei Maven-Abhängigkeiten sind allen Beispielen gemeinsam:

 org.apache.logging.log4j log4j-core 2.7   org.apache.logging.log4j log4j-core 2.7 test-jar test 

Neben dem Hauptpaket log4j-core müssen wir das zum Paket gehörende 'test jar' einschließen, um Zugriff auf eine Kontextregel zu erhalten, die zum Testen ungewöhnlich benannter Konfigurationsdateien erforderlich ist.

3. Standardkonfiguration

ConsoleAppender ist die Standardkonfiguration des Log4J 2-Kernpakets . Es protokolliert Nachrichten in einem einfachen Muster an die Systemkonsole:

Lassen Sie uns die Tags in dieser einfachen XML-Konfiguration analysieren:

  • Konfiguration : Das Wurzelelement eines Log4J 2 - Konfigurationsdatei und Attribut - Status ist das Niveau der internen Log4J Ereignisse, dass wir protokollieren wollen
  • Appender : Dieses Element enthält einen oder mehrere Appender. Hier konfigurieren wir einen Appender, der standardmäßig an die Systemkonsole ausgegeben wird
  • Logger : Dieses Element kann aus mehreren konfigurierten Logger- Elementen bestehen. Mit dem speziellen Root- Tag können Sie einen namenlosen Standardlogger konfigurieren, der alle Protokollnachrichten von der Anwendung empfängt. Jeder Logger kann auf eine minimale Log-Ebene eingestellt werden
  • AppenderRef : Dieses Element definiert einen Verweis auf ein Element aus dem Abschnitt Appender . Daher ist das Attribut ' ref ' mit einem Attribut ' appendders' name ' verknüpft

Der entsprechende Unit-Test wird ähnlich einfach sein. Wir erhalten eine Logger- Referenz und drucken zwei Nachrichten:

@Test public void givenLoggerWithDefaultConfig_whenLogToConsole_thanOK() throws Exception { Logger logger = LogManager.getLogger(getClass()); Exception e = new RuntimeException("This is only a test!"); logger.info("This is a simple message at INFO level. " + "It will be hidden."); logger.error("This is a simple message at ERROR level. " + "This is the minimum visible level.", e); } 

4. ConsoleAppender mit PatternLayout

Definieren wir einen neuen Konsolen-Appender mit einem benutzerdefinierten Farbmuster in einer separaten XML-Datei und nehmen dies in unsere Hauptkonfiguration auf:

Diese Datei verwendet einige Mustervariablen, die zur Laufzeit durch Log4J 2 ersetzt werden:

  • % style {…} {colorname} : Hiermit wird der Text im ersten Klammerpaar ( ) in einer bestimmten Farbe ( colorname ) gedruckt .
  • % Highlight {…} {FATAL = Farbname,…} : Dies ähnelt der Variablen 'style'. Für jede Protokollstufe kann jedoch eine andere Farbe angegeben werden.
  • % date {format} : Dies wird durch das aktuelle Datum im angegebenen Format ersetzt . Hier verwenden wir das DateTime-Format 'DEFAULT', ' JJJJ- MM-TT HH: MM: SS, SSS' .
  • % -5level : Druckt die Ebene der Protokollnachricht rechtsbündig.
  • % message : Repräsentiert die Rohprotokollnachricht

Das PatternLayout enthält jedoch noch viel mehr Variablen und Formatierungen . Sie können sie auf die offizielle Dokumentation des Log4J 2 verweisen.

Jetzt nehmen wir den definierten Konsolen-Appender in unsere Hauptkonfiguration auf:

Der Unit Test:

@Test public void givenLoggerWithConsoleConfig_whenLogToConsoleInColors_thanOK() throws Exception { Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_MARKER"); logger.trace("This is a colored message at TRACE level."); ... } 

5. Async File Appender mit JSONLayout und BurstFilter

Manchmal ist es nützlich, Protokollnachrichten asynchron zu schreiben. Zum Beispiel, wenn die Anwendungsleistung Vorrang vor der Verfügbarkeit von Protokollen hat.

In solchen Anwendungsfällen können wir einen AsyncAppender verwenden.

In unserem Beispiel konfigurieren wir eine asynchrone JSON- Protokolldatei. Darüber hinaus enthalten wir einen Burst-Filter, der die Protokollausgabe auf eine bestimmte Rate begrenzt:

   ...          ...        

Beachte das:

  • Das JSONLayout ist so konfiguriert, dass ein Protokollereignis pro Zeile geschrieben wird
  • Der BurstFilter löscht jedes Ereignis mit der Stufe 'INFO' und höher, wenn mehr als zwei davon vorhanden sind, jedoch maximal 10 Ereignisse
  • Der AsyncAppender ist auf einen Puffer von 80 Protokollnachrichten eingestellt. Danach wird der Puffer in die Protokolldatei geleert

Schauen wir uns den entsprechenden Unit-Test an. Wir füllen den angehängten Puffer in einer Schleife, lassen ihn auf die Festplatte schreiben und überprüfen die Zeilenanzahl der Protokolldatei:

@Test public void givenLoggerWithAsyncConfig_whenLogToJsonFile_thanOK() throws Exception { Logger logger = LogManager.getLogger("ASYNC_JSON_FILE_APPENDER"); final int count = 88; for (int i = 0; i  0 && logEventsCount <= count); }

6. RollingFile Appender und XMLLayout

Als Nächstes erstellen wir eine fortlaufende Protokolldatei. Nach einer konfigurierten Dateigröße wird die Protokolldatei komprimiert und gedreht.

Dieses Mal verwenden wir ein XML- Layout:

Beachte das:

  • Der RollingFile-Appender verfügt über das Attribut 'filePattern', mit dem gedrehte Protokolldateien benannt werden und das mit Platzhaltervariablen konfiguriert werden kann. In unserem Beispiel sollte es ein Datum und einen Zähler vor dem Dateisuffix enthalten.
  • Die Standardkonfiguration von XMLLayout schreibt einzelne Protokollereignisobjekte ohne das Stammelement .
  • Wir verwenden eine größenbasierte Richtlinie zum Drehen unserer Protokolldateien.

Unsere Unit-Test-Klasse sieht aus wie im vorherigen Abschnitt:

@Test public void givenLoggerWithRollingFileConfig_whenLogToXMLFile_thanOK() throws Exception { Logger logger = LogManager.getLogger("XML_ROLLING_FILE_APPENDER"); final int count = 88; for (int i = 0; i < count; i++) { logger.info( "This is rolling file XML message #{} at INFO level.", i); } }

7. Syslog Appender

Angenommen, wir müssen protokollierte Ereignisse über das Netzwerk an einen Remotecomputer senden. Der einfachste Weg, dies mit Log4J2 zu tun, wäre die Verwendung des Syslog Appender:

   ...     ...        

Die Attribute im Syslog- Tag:

  • name : Definiert den Namen des Appenders und muss eindeutig sein. Da können wir mehrere Syslog-Appender für dieselbe Anwendung und Konfiguration haben
  • Format : Es kann entweder auf BSD oder RFC5424 eingestellt werden, und die Syslog-Datensätze werden entsprechend formatiert
  • Host & Port : Der Hostname und der Port des Remote-Syslog-Servercomputers
  • Protokoll : ob TCP oder UPD verwendet werden soll
  • Einrichtung : In welche Syslog-Einrichtung wird das Ereignis geschrieben?
  • connectTimeoutMillis : Wartezeit auf eine hergestellte Verbindung, standardmäßig Null
  • reconnectionDelayMillis : Wartezeit, bevor erneut versucht wird, eine Verbindung herzustellen

8. FailoverAppender

Jetzt kann es Fälle geben, in denen ein Appender die Protokollereignisse nicht verarbeitet und wir die Daten nicht verlieren möchten. In solchen Fällen ist der FailoverAppender praktisch.

Wenn der Syslog- Appender beispielsweise keine Ereignisse an den Remotecomputer sendet , greifen wir möglicherweise vorübergehend auf FileAppender zurück, anstatt diese Daten zu verlieren .

Der FailoverAppender verwendet einen primären Appender und eine Anzahl von sekundären Appendern. Falls das primäre Ereignis fehlschlägt, versucht es, das Protokollereignis mit sekundären Ereignissen zu verarbeiten, bis eines erfolgreich ist oder keine sekundären Ereignisse mehr zu versuchen sind:

Testen wir es:

@Test public void givenLoggerWithFailoverConfig_whenLog_thanOK() throws Exception { Logger logger = LogManager.getLogger("FAIL_OVER_SYSLOG_APPENDER"); Exception e = new RuntimeException("This is only a test!"); logger.trace("This is a syslog message at TRACE level."); logger.debug("This is a syslog message at DEBUG level."); logger.info("This is a syslog message at INFO level. This is the minimum visible level."); logger.warn("This is a syslog message at WARN level."); logger.error("This is a syslog message at ERROR level.", e); logger.fatal("This is a syslog message at FATAL level."); }

9. JDBC Appender

Der JDBC-Appender sendet Protokollereignisse unter Verwendung von Standard-JDBC an ein RDBMS. Die Verbindung kann entweder mit einer beliebigen JNDI-Datenquelle oder einer beliebigen Verbindungsfactory hergestellt werden.

Die Grundkonfiguration besteht aus einer DataSource oder ConnectionFactory , ColumnConfigs und tableName:

Jetzt probieren wir mal aus:

@Test public void givenLoggerWithJdbcConfig_whenLogToDataSource_thanOK() throws Exception { Logger logger = LogManager.getLogger("JDBC_APPENDER"); final int count = 88; for (int i = 0; i < count; i++) { logger.info("This is JDBC message #{} at INFO level.", count); } Connection connection = ConnectionFactory.getConnection(); ResultSet resultSet = connection.createStatement() .executeQuery("SELECT COUNT(*) AS ROW_COUNT FROM logs"); int logCount = 0; if (resultSet.next()) { logCount = resultSet.getInt("ROW_COUNT"); } assertTrue(logCount == count); }

10. Schlussfolgerung

Dieser Artikel zeigt sehr einfache Beispiele, wie Sie mit Log4J2 verschiedene Protokollierungs-Appender, Filter und Layouts verwenden und wie Sie sie konfigurieren können.

Die Beispiele zum Artikel sind auf GitHub verfügbar.