Einführung zu Log4j2 - Appenders, Layouts und Filter

Einführung in Log4j2 - Appender, Layouts und Filter

1. Überblick

Die Protokollierung von Ereignissen ist ein kritischer Aspekt der Softwareentwicklung. Während im Java-Ökosystem viele Frameworks verfügbar sind, ist Log4J aufgrund seiner Flexibilität und Einfachheit seit Jahrzehnten am beliebtesten.

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

In diesem Artikel werden die häufigsten 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 und so komplex wie jedes RDBMS sein. Layouts legen fest, wie die Protokolle dargestellt werden, und Filter filtern die Daten nach den verschiedenen Kriterien.

2. Konfiguration

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

Allen Beispielen sind zwei Maven-Abhängigkeiten gemeinsam:


    org.apache.logging.log4j
    log4j-core
    2.7


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

Neben dem Hauptpaketlog4j-coremüssen wir das zum Paket gehörende Testglas 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 KernpaketsLog4J 2. Es protokolliert Nachrichten in einem einfachen Muster an die Systemkonsole:



    
        
            
        
    
    
        
            
        
    

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

  • Configuration: Das Stammelement der Konfigurationsdatei und des Attributsstatus vonLog4J 2 ist die Ebene der internen Log4J-Ereignisse, die protokolliert werden sollen

  • Appenders: Dieses Element enthält einen oder mehrere Appender. Hier konfigurieren wir einen Appender, der standardmäßig an die Systemkonsole ausgegeben wird

  • Loggers: Dieses Element kann aus mehreren konfiguriertenLogger-Elementen bestehen. Mit dem speziellen TagRootkönnen Sie einen namenlosen Standardlogger konfigurieren, der alle Protokollnachrichten von der Anwendung empfängt. Jeder Logger kann auf einen minimalen Loglevel eingestellt werden

  • AppenderRef: Dieses Element definiert einen Verweis auf ein Element aus dem AbschnittAppenders. Daher ist das Attribut "ref" mit dem Attribut "name" des Appenders verknüpft

Der entsprechende Komponententest wird ähnlich einfach sein. Wir erhalten eineLogger-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 mitPatternLayout

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 durchLog4J 2 ersetzt werden:

  • %style\{…}{colorname}: Hiermit wird der Text im ersten Klammerpaar () in einer bestimmten Farbe (colorname) gedruckt.

  • %highlight\{…}\{FATAL=colorname, …}: Dies ähnelt der Variablen 'style'. Für jede Protokollebene kann jedoch eine andere Farbe angegeben werden.

  • %date{format}: Dies wird durch das aktuelle Datum in den angegebenenformat ersetzt. Hier verwenden wir das DateTime-Format "DEFAULT",yyyy_-MM-dd HH: mm: ss, SSS'_.

  • %-5level: Druckt die Ebene der Protokollnachricht rechtsbündig.

  • %message: Repräsentiert die Rohprotokollnachricht

Es gibt jedoch noch viel mehr Variablen und Formatierungen inPatternLayout.. Sie können sie auf die offizielle Dokumentation vonLog4J 2verweisen.

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



    
        
    
    
        
            
        
    

Der Komponententest:

@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 mitJSONLayout undBurstFilter

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 wirAsyncAppender. verwenden

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



    
        ...
        
            
            
        
        
            
        
    
    
        ...
        
            
        
        
            
        
    

Beachte das:

  • JSONLayout ist so konfiguriert, dass ein Protokollereignis pro Zeile geschrieben wird

  • DieBurstFilter löschen jedes Ereignis mit der Stufe "INFO" und höher, wenn mehr als zwei davon vorhanden sind, jedoch maximal 10 Ereignisse

  • AsyncAppender wird auf einen Puffer von 80 Protokollnachrichten gesetzt. 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 < count; i++) {
        logger.info("This is async JSON message #{} at INFO level.", count);
    }

    long logEventsCount
      = Files.lines(Paths.get("target/logfile.json")).count();
    assertTrue(logEventsCount > 0 && logEventsCount <= count);
}

6. RollingFile Appender undXMLLayout

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

Dieses Mal verwenden wir das Layout vonXML:



    
        
            
            
                
            
        
    
    
        
            
        
        
            
        
    

Beachte das:

  • Der Appender vonRollingFileverfü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 vonXMLLayout schreibt einzelne Protokollereignisobjekte ohne das Stammelement.

  • Wir verwenden eine größenbasierte Richtlinie zum Drehen unserer Protokolldateien.

Unsere Unit-Test-Klasse sieht wie die aus dem vorherigen Abschnitt aus:

@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 vonSyslog Appender:



    
        ...
        
        
    
    
        ...
        
            
        
        
            
        
    

Die Attribute im TagSyslog:

  • name: definiert den Namen des Appenders und muss eindeutig sein. Da wir mehrere Syslog-Appender für dieselbe Anwendung und Konfiguration haben können

  • format: kann entweder auf BSD oder RFC5424 gesetzt werden, und die Syslog-Datensätze werden entsprechend formatiert

  • host & port: ist der Hostname und der Port des Remote-Syslog-Servercomputers

  • protocol:, ob TCP oder UPD verwendet werden soll

  • facility:, in welche Syslog-Einrichtung das Ereignis geschrieben wird

  • connectTimeoutMillis: Wartezeit auf eine hergestellte Verbindung ist 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 istFailoverAppender praktisch.

Wenn beispielsweise der Appender vonSyslogkeine Ereignisse an den Remotecomputer sendet, können wir vorübergehend aufFileAppender zurückgreifen, anstatt diese Daten zu verlieren.

DasFailoverAppender nimmt einen primären Appender und die Anzahl der sekundären Appender. 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 ausDataSource oderConnectionFactory, ColumnConfigs undtableName:


    
    
    
    
    
    

Probieren wir es jetzt 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. Fazit

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

Die dem Artikel beigefügten Beispiele sindover on GitHub verfügbar.