Log4j2 Beispiel-Tutorial – Konfiguration, Ebenen, Appender

Willkommen zum Apache Log4j2 Beispiel-Tutorial. Wenn Sie einen Expertenentwickler nach der nervigsten Sache in einer Anwendung fragen, könnte die Antwort mit dem Logging zusammenhängen. Wenn es kein geeignetes Logging in einer Anwendung gibt, wird die Wartung zum Albtraum. Die meisten Anwendungen durchlaufen Entwicklungstests, Unittests, Integrationstests. Aber wenn es um die Produktion geht, werden Sie immer auf einzigartige Szenarien und Ausnahmen stoßen. Daher ist der einzige Weg herauszufinden, was in einem bestimmten Fall passiert ist, das Debuggen durch die Protokolle. Viele Frameworks bieten eine Art von Standard-Logging, aber es ist immer am besten, den branchenüblichen Logging-Mechanismus zu verwenden. Apache Log4j ist eines der am weitesten verbreiteten Logging-Frameworks. Apache Log4j 2 ist die nächste Version, die weit besser als Log4j ist.

Log4j Beispiel-Tutorial

In diesem Log4j2 Beispiel-Tutorial erfahren Sie, wie Sie mit Apache Log4j2 beginnen können. Wir werden auch die Log4j2-Architektur, Log4j2-Konfiguration, Log4j2-Protokollierungsstufen, Appender, Filter und vieles mehr erkunden.

  1. Log4j2 Überblick
  2. Log4j2 Architektur
  3. Log4j2 Konfiguration
  4. Log4j2 Stufen
  5. Log4j2 Lookups
  6. Log4j2 Appender
  7. Log4j2 Filter
  8. Log4j2 Layouts
  9. Welches Log4j2-Level sollte verwendet werden?
  10. Zusammenfassung des Log4j2-Tutorials

Überblick über Log4j2

Die Verwendung eines Logging-API in einer Anwendung ist kein Luxus, sondern ein Muss. Log4j ist eine Open-Source-Bibliothek, die unter der Lizenz der Apache Software veröffentlicht und lizenziert ist. Sie können eine Anwendung mithilfe der Eclipse-Debugging-Funktion oder anderer Tools debuggen, aber das ist in einer Produktionsumgebung nicht ausreichend und praktikabel. Das Logging-Mechanismus bietet Ihnen mehrere Vorteile, die Sie beim normalen Debuggen nicht finden werden.

Category / Operation (Debugging, Logging) Debugging Logging
Human Intervention There’s a need for human intervention No need for human intervention
Persistent Medium Can’t be integrated with persistent storage Can be integrated with persistent storage (Files, Database, NoSQL database, etc.)
May used for Auditing Can’t be used for achieving auditing Can be used for achieving auditing if it’s used efficiently
Sufficient for complicated structure and flow Not sufficient; you may get lost with flow. Sufficient
Productivity Less productive More productive

Wie oben gezeigt, ist die Verwendung des Logging-Mechanismus effizienter und kostengünstiger in der Wartung. Apache Log4j ist das führende Tool für das Logging in Java-Anwendungen, daher sollten Sie es verwenden.

Log4j2-Architektur

Bevor wir mit dem Log4j-Beispiel-Tutorial fortfahren, ist es gut, sich die Log4j2-Architektur anzusehen. Das folgende Bild zeigt die wichtigen Klassen in der Log4j2-API. Hier ist die ausführliche Erklärung für die oben gezeigte Architektur:

  • Anwendungen werden LogManager nach einem Logger mit einem bestimmten Namen fragen.

  • LogManager wird den entsprechenden LoggerContext finden und dann den Logger daraus erhalten.

  • Wenn der Logger noch nicht erstellt wurde, wird er erstellt und mit LoggerConfig gemäß der folgenden drei Auswahlmöglichkeiten verknüpft:

    1. Die Logger-Instanz wird erstellt und mit der LoggerConfig verknüpft, die denselben Namen hat. Zum Beispiel wird App.class in getLogger(App.class) zu einem String com.journaldev.App ausgewertet. Der Name der LoggerConfig ist identisch mit dem vollqualifizierten Klassennamen (Softwarekomponente).
    2. Die Logger-Instanz wird erstellt und mit der LoggerConfig verknüpft, die dasselbe Elternpaket wie die Logger hat. Zum Beispiel com.journaldev in getLogger("com.journaldev").
    3. Die Logger-Instanz wird erstellt und mit der Root-LoggerConfig verknüpft. Die Root-LoggerConfig wird verwendet, wenn keine Konfigurationsdatei vorhanden ist oder wenn Sie einen Logger mit einem Namen erhalten, der in den Logger-Deklarationen nicht definiert ist.
  • LoggerConfig-Objekte werden aus der Logger-Deklaration in der Konfigurationsdatei erstellt. LoggerConfig wird auch verwendet, um LogEvents zu verarbeiten und sie für ihre definierten Log4j2-Appender weiterzuleiten.

  • Der Root-Logger ist ein Ausnahmefall in Bezug auf seine Existenz. Er existiert immer und befindet sich oben in jeder Logger-Hierarchie.

  • Sie können den Root-Logger durch Verwendung der folgenden Anweisungen erhalten:

    Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
    Logger logger = LogManager.getRootLogger();
    
  • Die Namen der Log4j2-Logger sind Groß- und Kleinschreibung beachtend.

  • Außer dem Root-Logger können alle Logger erhalten werden, indem ihr Name an LogManager.getLogger() übergeben wird.

  • Der LoggerContext ist ein zentraler Punkt für das Protokollierungssystem, da Sie innerhalb Ihrer Anwendung mehrere LoggerContexts haben können. Für jeden LoggerContext sollte eine aktive Konfiguration festgelegt werden.

  • Die Log4j2-Konfiguration enthält alle Vermögenswerte des Protokollierungssystems; LoggerConfig(s), Appender(s), Filter(s) und viele andere.

  • Das Aufrufen von LogManager.getLogger() durch Übergabe des gleichen Namens liefert immer die Referenz auf die genau gleiche Logger-Instanz zurück.

  • Die Konfiguration des Protokollierungssystems erfolgt in der Regel während der Anwendungsinitialisierung. Dies kann in verschiedenen Formen erfolgen: programmgesteuert oder durch das Lesen einer log4j2-Konfigurationsdatei.

Jeder Logger ist mit einem LoggerConfig-Objekt verbunden, eine Reihe von LoggerConfig-Objekten bildet eine Hierarchie von Loggern. Dieses Konzept ist als Logger-Hierarchie bekannt. Logger-Hierarchie besteht aus einer Reihe von LoggerConfig-Objekten mit einer Eltern-Kind-Beziehung. Das oberste Element in jeder Logger-Hierarchie ist der Root-Logger. Wenn Log4j2 die Konfigurationsdatei nicht findet, wird nur der Root-Logger für das Protokollieren mit dem Protokollierungslevel ERROR verwendet. Im Folgenden wird die Warnmeldung angezeigt, die Sie in diesem Fall erhalten. Fehler-Statuslogger: Keine Log4j2-Konfigurationsdatei gefunden. Verwende die Standardkonfiguration: Nur Fehler auf die Konsole protokollieren. Die Tabelle unten zeigt die Eltern-Kind-Beziehung in der Logger-Hierarchie.

LoggerConfig (Is A) Root com com.journaldev com.journaldev.logging
Root X Child descendant descendant
com Parent X Child descendant
com.journaldev Ancestor Parent X Child
com.journaldev.logging Ancestor Ancestor Parent X

Um die Eltern-Kind-Beziehung zu verdeutlichen, würde die obige Tabelle wie folgt gelesen:

  • Root ist ein Elternteil für com.
  • Root ist ein Vorfahr für com.journaldev.
  • Root ist ein Vorfahr für com.journaldev.logging.
  • com ist ein Kind für Root.
  • com ist ein Elternteil für com.journaldev.
  • com ist ein Vorfahr für com.journaldev.logging.
  • com.journaldev.logging ist ein Kind für com.journaldev und so weiter.

Eine Instanz von LoggerConfig gilt als Vorfahr einer anderen LoggerConfig, wenn ihr Name gefolgt von einem Punkt ein Präfix für den Namen des Nachkommens ist. Eine Instanz von LoggerConfig gilt als Elternteil für eine andere LoggerConfig, wenn es keine ineinander verschachtelten Namen zwischen beiden gibt.

Log4j2-Konfiguration

Es gibt viele Möglichkeiten, die Log4j2-Konfiguration in Ihrer Anwendung zu verwenden.

  1. Verwendung einer Konfigurationsdatei im XML-, JSON-, YAML- oder Eigenschaftenformat.
  2. Programmgesteuert, indem Sie eine Konfigurationsfabrik und eine Konfigurationsimplementierung erstellen.
  3. Programmgesteuert, durch Aufrufen der in der Konfigurationsschnittstelle freigegebenen APIs.
  4. Programmgesteuert, indem Sie Methoden auf der internen Logger-Klasse aufrufen.

Wir werden uns hauptsächlich auf die Konfigurationsdatei konzentrieren. Es ist jedoch auch gut, den Programmieransatz zu kennen, falls Sie eine bestimmte Protokollierungsstrategie für einen bestimmten Logger konfigurieren möchten. Zunächst einmal betrachten wir den Fall, in dem Sie keine Konfigurationsdatei bereitgestellt haben. Die Log4j2-Implementierung geht davon aus, dass es eine Systemvariable namens log4j.configurationFile gibt, um den Speicherort der Log4j2-Konfigurationsdatei anzugeben.

package com.journaldev;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class App
{
    public static void main( String[] args ) {
    	Logger logger = LogManager.getRootLogger();
    	logger.trace("Configuration File Defined To Be :: "+System.getProperty("log4j.configurationFile"));
    }
}

A simple log4j2 configuration file will look like below. configuration.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Appenders>
    <Console name="Console">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="trace">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

Und hier ist die ausführliche Erklärung für den oben aufgeführten Code:

  • Die App hat den Root-Logger referenziert, indem sie die getRootLogger-Methode von LogManager aufgerufen hat.
  • Die Referenzierung des Loggers von LogManager hat das Log4j-System gestartet.
  • Log4j wird die log4j.configurationFile-Systemeigenschaft überprüfen, um die Log4j2-Konfigurationsdatei zu bestimmen. Die Log4j-Konfiguration kann in JSON, YAML und XML geschrieben werden.
  • Wir können die log4j.configurationFile-Systemeigenschaft über System.setProperties("log4j.configurationFile","DATEIPFAD") setzen oder sie als JVM-Parameter übergeben, wie im folgenden Beispiel zu sehen ist. Beachten Sie auch das Datei-Protokollpräfix.

  • Falls keine Systemeigenschaft definiert ist, hat die Konfigurationsreihenfolge folgende Priorität:
    • Die Property ConfigurationFactory sucht nach log4j2-test.properties im Klassenpfad.
    • Die YAML ConfigurationFactory sucht nach log4j2-test.yaml oder log4j2-test.yml im Klassenpfad.
    • Die JSON ConfigurationFactory sucht nach log4j2-test.jsn oder log4j2-test.json im Klassenpfad.
    • Die XML ConfigurationFactory sucht nach log4j2-test.xml im Klassenpfad.
    • Die Property ConfigurationFactory sucht nach log4j2.properties im Klassenpfad
    • Die YAML ConfigurationFactory sucht nach log4j2.yml oder log4j2.yaml im Klassenpfad.
    • Die JSON ConfigurationFactory sucht nach log4j2.jsn oder log4j2.json im Klassenpfad.
    • Die XML ConfigurationFactory sucht nach log4j2.xml im Klassenpfad.
    • Wenn keine Konfigurationsdatei bereitgestellt wurde, wird die DefaultConfiguration verwendet und das führt zu einer Reihe von Standardverhaltensweisen:
      • Der Root-Logger wird verwendet.
      • Die Root-Logger-Ebene wird auf ERROR gesetzt.
      • Der Root-Logger leitet Protokollmeldungen in die Konsole weiter.
      • Das PatternLayout wird auf %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n festgelegt

Die Verwendung der log4j2-Konfigurationsdatei macht die log4j2-Konfiguration so einfach, aber schauen wir uns an, wie wir sie programmgesteuert konfigurieren können. Dies dreht sich alles um die Verwendung von ConfigurationFactory.

package com.journaldev;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;
public class App
{
    public static void main( String[] args ) throws FileNotFoundException, IOException {
 
    	// Holen Sie sich eine Instanz der Konfigurationsfabrik; Ihre Optionen sind die Standard-Konfigurationsfabrik, XMLConfigurationFactory,
    	// YamlConfigurationFactory & JsonConfigurationFactory
    	ConfigurationFactory factory =  XmlConfigurationFactory.getInstance();
 
    	// Suchen Sie die Quelle dieser Konfiguration, diese gefundene Datei ist eine Dummy-Datei, die nur ein leeres Konfigurations-Tag enthält
    	ConfigurationSource configurationSource = new ConfigurationSource(new FileInputStream(new File("C:/dummyConfiguration.xml")));
 
    	// Holen Sie sich eine Referenz aus der Konfiguration
    	Configuration configuration = factory.getConfiguration(configurationSource);
 
    	// Erstellen Sie den Standard-Konsolen-Anhang
    	ConsoleAppender appender = ConsoleAppender.createDefaultAppenderForLayout(PatternLayout.createDefaultLayout());
 
    	// Fügen Sie den Konsolen-Anhang zur Konfiguration hinzu
    	configuration.addAppender(appender);
 
    	// Erstellen Sie LoggerConfig
    	LoggerConfig loggerConfig = new LoggerConfig("com",Level.FATAL,false);
 
    	// Fügen Sie den Anhang hinzu
    	loggerConfig.addAppender(appender,null,null);
 
    	// Fügen Sie den Logger hinzu und verknüpfen Sie ihn mit der LoggerConfig-Instanz
    	configuration.addLogger("com", loggerConfig);
 
    	// Holen Sie sich eine Instanz des Kontextes
    	LoggerContext context = new LoggerContext("JournalDevLoggerContext");
 
    	// Starten Sie das Logging-System
    	context.start(configuration);
 
    	// Holen Sie sich eine Referenz für den Logger
    	Logger logger = context.getLogger("com");
 
    	// Loggen eines DEBUG-Nachrichtenereignisses
    	logger.log(Level.FATAL, "Logger Name :: "+logger.getName()+" :: Passed Message ::");
 
    	// Loggen einer Fehlermeldung für den als FATAL konfigurierten Logger
    	logger.log(Level.ERROR, "Logger Name :: "+logger.getName()+" :: Not Passed Message ::");
 
    	// Loggen einer ERROR-Nachricht, die vom Root-Logger behandelt würde
    	logger.getParent().log(Level.ERROR, "Root Logger :: Passed Message As Root Is Configured For ERROR Level messages");
    }
}
  • Sie können eine beliebige ConfigurationFactory verwenden, die von Log4j2 bereitgestellt wird, oder die Standardkonfiguration verwenden. Wir haben XMLConfigurationFactory verwendet, um eine Instanz der ConfigurationFactory zu erhalten.
  • Die Factory liefert Ihnen eine Instanz der erforderlichen Konfigurationsreferenz, indem Sie die entsprechende Konfigurationsdatei übergeben.
  • Die Konfigurationsinstanz wird in Verbindung mit dem LoggerContext verwendet, um das Logging-System zu starten.
  • A console Appender has been configured and added into configuration instance with default layout. This Appender would print out messages into your console.
  • Es wurde eine LoggerConfig-Instanz mit dem angegebenen Namen, LEVEL und ohne verwendeten Filter erstellt. Der erstellte Appender wird dieser Instanz von LoggerConfig zugewiesen.
  • Die LoggerConfig-Instanz wurde der Konfigurationsinstanz hinzugefügt.
  • A new instance of LoggerContext is created with defined name.
  • Die Konfigurationsinstanz wurde für die LoggerContext-Instanz übergeben und letztere wurde gestartet.
  • A logger instance has been acquired from LoggerContext. This logger instance will be used to fire set of Log events.
  • Der Logger hat drei Ereignisse ausgelöst, die im Abschnitt zu den Log4j2-Levels erläutert werden.
  • Der com-Logger wurde konfiguriert, um Nachrichten auszugeben, deren Level FATAL ist.
  • Standardmäßig ist der Root-Logger so konfiguriert, dass Nachrichten mit dem Level ERROR ausgegeben werden.
  • ERROR-Nachrichten werden vom ‚com‘-Logger nicht protokolliert, da sein Level FATAL ist.

Die gleiche Konfiguration kann über die Verwendung von YAML, JSON oder Properties-Dateien erfolgen. Die Konfiguration der log4j2-Properties-Datei unterscheidet sich jedoch von der Konfiguration der log4j-Properties-Datei. Stellen Sie daher sicher, dass Sie nicht versuchen, die Konfiguration der log4j-Properties-Datei mit log4j2 zu verwenden. Es wird folgenden Fehler auslösen:

ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.

Beim Verarbeiten des obigen Codes wird die folgende Ausgabe generiert:

Logger Name :: com :: Passed Message ::
00:01:27.705 [main] ERROR - Root Logger:: Passed Message As Root Is Configured For ERROR Level messages

Die erste Zeile der Protokolle stammt vom ‚com‘-Logger und die zweite vom Root-Logger. Die Fehlermeldung des ‚com‘-Loggers wird nicht gedruckt, weil ihr Level FATAL ist.

Log4j2 Levels

Sie können in den obigen Codebeispielen sehen, dass jedes Mal, wenn wir eine LoggerConfig definieren, auch das Logging-Level angegeben wird. Standardmäßig ist das Loggen mit log4j2 additiv. Das bedeutet, dass alle übergeordneten Logger verwendet werden, wenn ein bestimmter Logger verwendet wird. Das folgende Bild verdeutlicht diese Situation. Und hier sind die Klarstellungen dazu:

  • Wie bereits erwähnt, ist jedem Logger eine LoggerConfig-Instanz zugeordnet. Diese LoggerConfig wurde auf der Konfigurationsebene definiert.
  • Das Logging-Level kann auf der LoggerConfig-Ebene bestimmt werden.
  • Sie können den Logger nach seinem Namen, dem übergeordneten Paket oder durch direkte Verweisung auf den Root-Logger selbst erhalten.
  • Der Root-Logger ist der oberste Knoten für jede LoggerConfig-Hierarchie.
  • Wenn Sie den Logger com.journaldev erhalten und ein LogEvent für das Logging initiieren, wird die LoggerConfig (net.journaldev) die Nachricht protokollieren, und die Nachricht wird ebenfalls in der Hierarchie nach oben propagiert, ohne Rücksicht auf die Logging-Level der übergeordneten Elemente. Das Log-Ereignis wird also an die Logger com und Root weitergeleitet, und sie werden die Nachricht entsprechend gemäß den definierten Leveln protokollieren.
  • Wenn Sie den com-Logger erhalten und ein LogEvent für das Logging initiieren, wird die LoggerConfig (com) die Nachricht protokollieren, und die Nachricht wird ebenfalls in der Hierarchie nach oben propagiert, ohne Rücksicht auf die Logging-Level der übergeordneten Elemente. Das heißt, der Root-Logger wird das Protokollierungsereignis weiterleiten und die Nachricht ebenfalls protokollieren.
  • Das gleiche gilt für die Hierarchie net.journaldev.
  • Nächste Abschnitte werden weitere Klarstellungen zum Additivkonzept hinzufügen.
  • Es besteht die Möglichkeit, dass das Elternteil die Nachricht ignoriert, indem das Filterkonzept verwendet wird oder indem der additive Indikator auf false gesetzt wird, sodass Protokollereignisse nicht an Eltern weitergegeben werden.
  • Es besteht die Möglichkeit, dass der Logger die Nachricht ignoriert, wenn das entsprechende LoggerConfig-Level GRÖßER ALS das Log-Ereignis-Level ist.

Jetzt sehen wir uns das Beispiel an, das mit dem oben erklärten Additivkonzept verbunden ist:

import net.NetApp;
import net.journaldev.NetJournalDevApp;
import com.ComApp;
import com.journaldev.ComJournalDevApp;
public class Main {
	public static void main(String [] args){
		new ComApp();
		new ComJournalDevApp();
		new NetApp();
		new NetJournalDevApp();
	}
}
package com.journaldev;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class ComJournalDevApp {
	public ComJournalDevApp(){
		Logger logger = LogManager.getLogger(ComJournalDevApp.class);
		logger.trace("COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::");
	}
}
package net;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class NetApp {
	public NetApp(){
		Logger logger = LogManager.getLogger(NetApp.class);
		logger.error("NET :: LEVEL :: NetApp ERROR Message ::");
	}
}
package net.journaldev;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class NetJournalDevApp {
	public NetJournalDevApp(){
		Logger logger = LogManager.getLogger(NetJournalDevApp.class);
		logger.error("NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::");
	}
}

Während die Log4j2-Konfigurationsdatei wie folgt aussieht:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Appenders>
    <Console name="Console">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="ERROR">
      <AppenderRef ref="Console"/>
    </Root>
  	<logger name="com" level="TRACE">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="com.journaldev" level="TRACE">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="net" level="ERROR">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="net.journaldev" level="ERROR">
  		<AppenderRef ref="Console"/>
  	</logger>
  </Loggers>
</Configuration>

Wenn Sie die Hauptklasse ausgeführt haben, würden Sie die untenstehenden Ergebnisse finden:

10:34:47.168 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
10:34:47.168 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
10:34:47.170 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
10:34:47.170 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
10:34:47.170 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
10:34:47.171 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
10:34:47.171 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
10:34:47.171 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
10:34:47.171 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
10:34:47.171 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::

Hier ist eine detaillierte Erklärung für den oben aufgeführten Code:

  • Die Konfigurationsdatei enthält fünf LoggerConfig-Instanzen, die definiert sind: Root, com, com.journaldev, net & net.journaldev. Genau wie die oben gezeigte Logger-Hierarchie.
  • Das Level von Root ist auf ERROR konfiguriert, und das ist tatsächlich der Standardwert.
  • com & com.journaldev Levels sind auf TRACE konfiguriert.
  • net & net.journaldev Levels sind auf ERROR konfiguriert.
  • Sie haben möglicherweise bemerkt, dass die Nachrichten der ComAPP- und ComJournalDevApp-Logger jeweils zwei bzw. drei Mal angezeigt wurden. Diese Nachrichten werden gemäß der Logger-Hierarchie für ComApp & ComJournalDevApp angezeigt, wo sie sich in den Paketen com & com.journalDev befinden. Wir haben einen ähnlichen Fall mit den Klassen NetApp & NetJournalDevApp.
  • Eltern werden als additive Indikator standardmäßig weitergegeben.

Das Logging Space berücksichtigt die Ebenen von Log-Ereignissen sowie die Ebene der Logger-Konfiguration zusätzlich zur Logger-Hierarchie.

Was passiert, wenn wir die Logger-Konfiguration für „com“ auf INFO ändern und das gesamte Programm so belassen:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Appenders>
    <Console name="Console">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="ERROR">
      <AppenderRef ref="Console"/>
    </Root>
  	<logger name="com" level="INFO">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="com.journaldev" level="TRACE">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="net" level="ERROR">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="net.journaldev" level="ERROR">
  		<AppenderRef ref="Console"/>
  	</logger>
  </Loggers>
</Configuration>

Dann wäre das Ergebnis wie folgt:

11:08:10.305 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
11:08:10.305 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
11:08:10.305 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
11:08:10.307 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
11:08:10.307 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
11:08:10.308 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
11:08:10.308 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
11:08:10.308 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
  • Sicherlich fällt Ihnen auf, dass das Log-Ereignis „ComAPP“ ignoriert wurde, und das liegt am definierten Level der Logger-Konfiguration für das „com“-Paket. Das INFO (400) Level ist niedriger als das Level des Log-Ereignisses, das hier TRACE (600) ist. Daher wird die Nachricht von ComApp nicht mehr angezeigt, und um sie anzuzeigen, müssen Sie das Level der Logger-Konfiguration für „com“ auf TRACE (600) oder ALL (Integer.MAX_VALUE) ändern.

Um sicherzustellen, dass Log-Ereignisse angezeigt wurden, sollte das Level der Logger-Konfiguration größer oder gleich dem Level des Log-Ereignisses sein.

Die Tabelle unten zeigt Ihnen die Log4j2-Ebenen und das Gewicht für jede von ihnen:

LEVEL Weight
OFF 0
FATAL 100
ERROR 200
WARN 300
INFO 400
DEBUG 500
TRACE 600
ALL Integer.MAX_VALUE

Sicherlich klärt die obige Tabelle viel mehr als Worte und sie gibt Ihnen die Hauptursache dafür, dass das Log-Ereignis TRACE nicht angezeigt wird, während das Level der Logger-Konfiguration INFO ist.

Beachten Sie, dass die Weitergabe von Log-Ereignissen in der Logger-Hierarchie über diese Berechnung hinausgeht und die Ebenen ignoriert.

Aber was passiert, wenn wir die Logger-Konfiguration von com.journaldev aus der Konfiguration entfernen und eine neue für com.journaldev.logging hinzufügen, um die Konfigurationsdatei wie folgt aussehen zu lassen:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Appenders>
    <Console name="Console">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="ERROR">
      <AppenderRef ref="Console"/>
    </Root>
  	<logger name="com" level="TRACE">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="com.journaldev.logging" level="TRACE">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="net" level="ERROR">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="net.journaldev" level="ERROR">
  		<AppenderRef ref="Console"/>
  	</logger>
  </Loggers>
</Configuration>

Sie finden die untenstehende Abbildung möglicherweise praktischer, um zu verstehen, was in der obenstehenden Log4j2-Konfiguration geschehen ist. Hier sind einige Erläuterungen zur oben gezeigten Abbildung und wie sich dies auf das Verhalten von Protokollereignissen auswirken kann:

  • Wenn Protokollereignisse von einem Logger mit dem Namen com.journaldev.logging ausgelöst wurden, wurde der LoggerConfig verwendet, der mit diesem Namen (d. h. com.journaldev.logging) verknüpft ist, um es zu behandeln und die Nachricht auszugeben.
  • Da das additive Attribut des LoggerConfigs com.journaldev.logging standardmäßig auf true gesetzt ist, wurde das Protokollereignis für den übergeordneten Logger weitergeleitet, der in diesem Fall auf com.journaldev verweist.
  • Da der LoggerConfig com.journaldev in der Konfiguration nicht definiert ist, geschieht nichts und das Protokollereignis wird bis zu den Instanzen com und dann Root LoggerConfig weitergeleitet.
  • Com & Root werden das Protokollereignis empfangen und unabhängig vom gesendeten Level ausgeben.

Als Ergebnis der genannten Punkte würden Sie die folgenden Ausgaben sehen:

14:08:37.634 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
14:08:37.634 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
14:08:37.636 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
14:08:37.636 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
14:08:37.637 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
14:08:37.637 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
14:08:37.637 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
14:08:37.638 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
14:08:37.638 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
14:08:37.640 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
14:08:37.640 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
14:08:37.640 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::

Und Sie könnten folgendes bemerken:

  • Das Protokollereignis im com-Paket wird zweimal angezeigt. Einmal für com und einmal für Root.
  • Das Ereignisprotokoll bei com.journaldev wurde zweimal angezeigt. Einmal für com und einmal für Root. Obwohl es zuvor dreimal war, ist die LoggerConfig von com.journaldev derzeit nicht vorhanden und es könnte kein Protokollieren im com.journaldev-Paket stattgefunden haben, und das Ereignis würde für com und Root propagiert werden.
  • Das Ereignisprotokoll bei com.journaldev.logging wurde dreimal angezeigt, einmal für das com.journaldev.logging-Paket, einmal für com und einmal für Root. Gemäß der Logger-Hierarchie-Propagation sollte es viermal angezeigt werden, aber aufgrund der Abwesenheit der LoggerConfig von com.journaldev wird es dreimal angezeigt.

Wenn Sie eine com.journaldev LoggerConfig-Instanz definiert haben, ohne dass ein Level angegeben wurde, wird es das Level seines Elternelements erben.

Aber was ist, wenn Sie die com.journaldev LoggerConfig in Ihrer Konfigurationsdatei definiert haben und vergessen haben, das Level der LoggerConfig anzugeben? Glücklicherweise wird Sie das Konzept der Logger-Hierarchie hier retten, und com.journaldev würde seinen Level-Wert von seinem Elternelement erben. Nachstehend finden Sie eine Beispieldatei für die Konfiguration, gefolgt von der Tabelle für das Protokollierungslevel jeder Logger-Konfiguration.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Appenders>
    <Console name="Console">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="ERROR">
      <AppenderRef ref="Console"/>
    </Root>
  	<logger name="com" level="TRACE">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="com.journaldev">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="com.journaldev.logging" level="TRACE">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="net" level="ERROR">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="net.journaldev" level="ERROR">
  		<AppenderRef ref="Console"/>
  	</logger>
  </Loggers>
</Configuration>
Logger Name Assigned LoggerConfig LoggerConfig Level Logger Level
Root Root ERROR ERROR
com com TRACE TRACE
com.journaldev com TRACE TRACE
com.journaldev.logging com.journaldev.logging TRACE TRACE
  • Das com.journaldev.logging-Paket ist bereits mit einer LoggerConfig mit dem Protokollierungslevel TRACE verbunden.
  • Das com.journaldev-Paket ist bereits mit einer LoggerConfig ohne Protokollierungslevel angegeben, daher würde es das Protokollierungslevel seines übergeordneten Elements erben, und sicherlich wäre der Wert für das com-Paket TRACE.
  • Das com-Paket ist bereits mit einer LoggerConfig mit dem Protokollierungslevel TRACE verbunden.
  • Standardmäßig hat Root ERROR als Protokollierungslevel.
  • Wenn das com-Paket nicht deklariert ist, wird die LoggerConfig von com.journaldev das Protokollierungslevel von Root erben.

Nachfolgend das Ergebnis der Ausführung, während com.journaldev com Log-Level erbt:

14:41:37.419 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
14:41:37.419 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
14:41:37.421 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
14:41:37.421 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
14:41:37.421 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
14:41:37.422 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
14:41:37.422 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
14:41:37.422 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
14:41:37.422 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
14:41:37.423 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
14:41:37.423 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
14:41:37.423 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
14:41:37.423 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
14:41:37.423 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::

Und unten das Ergebnis, wenn Sie LoggerConfig für das com-Paket entfernen:

14:43:28.809 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
14:43:28.809 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
14:43:28.809 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
14:43:28.811 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
14:43:28.811 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
14:43:28.812 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
14:43:28.812 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::
14:43:28.812 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::

Sie werden feststellen, dass keine Nachrichten für com und com.journaldev protokolliert wurden. Unten sind die Gründe.

  • Das Löschen von LoggerConfig, die dem com-Paket zugeordnet ist, führt dazu, dass alle Protokollereignisse, die in diesem Paket erwähnt werden, ignoriert werden.
  • Da für das com-Paket keine LoggerConfig definiert ist, erbt die LoggerConfig, die mit com.journaldev verknüpft ist, das Log-Level von seinem Elternobjekt. Da Com nicht definiert ist und die Logger-Hierarchie die oberste Ebene erreicht hat und nun auf Root verweist. Das Root-Log-Level ist ERROR(200) und das Log-Ereignis-Level in com.journaldev ist TRACE(600) – siehe ComJournalDev – und gemäß der zuvor definierten Gleichung sollte das LoggerConfig-Level größer oder gleich dem Log-Ereignis sein, was jedoch falsch ist. Daher werden keine Nachrichten für com.journaldev angezeigt.

Zu guter Letzt zeigt die folgende Tabelle alle möglichen Protokollierungsszenarien, auf die Sie stoßen können, wenn Sie das Protokollierungssystem verwenden:

X (N/A) LoggerConfig Level OFF(0) FATAL(100) ERROR(200) WARN(300) INFO(400) DEBUG(500) TRACE(600) ALL(MAX)
Event Level X X X X X X X X X
OFF(0) X YES NO NO NO NO NO NO NO
FATAL(100) X NO YES YES YES YES YES YES YES
ERROR(200) X NO NO YES YES YES YES YES YES
WARN(300) X NO NO NO YES YES YES YES YES
INFO(400) X NO NO NO NO YES YES YES YES
DEBUG(500) X NO NO NO NO NO YES YES YES
TRACE(600) X NO NO NO NO NO NO YES YES
ALL(MAX) X NO NO NO NO NO NO NO YES
  • Es gibt keine direkte Methode, die für das Auslösen von OFF/ALL-Protokollereignissen verwendet werden kann.
  • Hauptsächlich können Sie zum Auslösen von OFF/ALL-Protokollereignissen die Methode logger.log(Level.OFF, „Msg“) bzw. logger.log(LEVEL.ALL, „Msg“) verwenden.
  • Die log-Methode ist dafür verantwortlich, Protokollereignisse gemäß der genannten Gleichung zu verarbeiten.

Die Gleichung besagt: Wenn das LoggerConfig-Level größer oder gleich dem Ereignis-Level ist, wird das Ereignis zur weiteren Verarbeitung akzeptiert.

Das Ereignisprotokoll würde zur weiteren Verarbeitung akzeptiert werden – dies ist so wichtig, weil Sie die Möglichkeit haben, zu verhindern, dass ein Ereignis behandelt wird, selbst wenn es von Log4j2-Filtern akzeptiert wird. Sie können die additive-Eigenschaft auf false setzen, um die Propagierung von Ereignissen an übergeordnete Logger zu vermeiden. Nachfolgend dasselbe Beispiel wie zuvor, aber diesmal mit einem Additivattribut, sodass Sie den Unterschied bemerken können.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="ERROR">
      <AppenderRef ref="Console"/>
    </Root>
  	<logger name="com" level="TRACE" additivity="false">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="com.journaldev" additivity="false">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="com.journaldev.logging" level="TRACE" additivity="false">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="net" level="ERROR" additivity="false">
  		<AppenderRef ref="Console"/>
  	</logger>
  	<logger name="net.journaldev" level="ERROR" additivity="false">
  		<AppenderRef ref="Console"/>
  	</logger>
  </Loggers>
</Configuration>

Und das Ergebnis der Ausführung würde wie folgt aussehen:

17:55:30.558 [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
17:55:30.560 [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
17:55:30.561 [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
17:55:30.561 [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
17:55:30.562 [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::

Und Sie können feststellen, dass keine Propagierung von Ereignissen an übergeordnete Logger erfolgt.

Log4j2 Lookups

Idealerweise können Sie Lookups definieren als eine Möglichkeit, Werte für Ihre Logging-Konfigurationsdatei zu übergeben. Log4j2 bietet Ihnen eine verschiedene Reihe von Lookups, die unabhängig voneinander verwendet werden können, um Werte aus verschiedenen Kontexten zu setzen:

  • Kontextkarten-Lookup
  • Datum-Lookup
  • Umgebungs-Lookup
  • Java-Lookup
  • JNDI-Lookup
  • JVM-Eingabeargument-Lookup (JMX)
  • Hauptargumente-Lookup
  • Karten-Lookup
  • Strukturiertes Daten-Lookup
  • Systemeigenschaften-Lookup
  • Web-Lookup

Sie können sich für weitere Details zu Log4j2 Dokumentation auf alle Arten von Lookups beziehen, aber lassen Sie uns hier einige Beispiele betrachten, um die Grundlagen des Log4j2 Lookups abzudecken. Umgebung Lookup repräsentiert die Art und Weise, wie Sie einen Umgebungsvariablenwert übergeben können (entweder über Linux etc/profile, Windows-Systemumgebung oder Startskripte für die Anwendung. Wie die meisten von uns wissen, haben wir die Möglichkeit, einen Satz von Umgebungsvariablen für die Anwendung zu definieren. Lassen Sie uns die bekanntesten Möglichkeiten sehen, Ihre Umgebungsvariablen zu definieren.

  1. Definieren Sie die Umgebungsvariable, indem Sie die Windows-Umgebungseinrichtung verwenden:
    • Klicken Sie mit der rechten Maustaste auf das Computersymbol und wählen Sie Eigenschaften. Das Control Panel-Startmenü sollte angezeigt werden.
    • Klicken Sie auf Erweiterte Systemeinstellungen und öffnen Sie dann das Fenster Umgebungsvariablen.
    • Unter Systemvariablen definieren Sie die Variable JournalDevVar mit dem Wert JournalDev.
    • Aktualisieren Sie das PatternLayout in Ihrer log4j2.xml, um Ihre neu hinzugefügte Variable zu enthalten.

  1. Definieren Sie Ihre Umgebungsvariablen mithilfe der Startskriptfunktion.
    • Statt des normalen Standardskripts können Sie die Eclipse IDE Running Script-Funktion verwenden. Klicken Sie auf das Run-Menü und wählen Sie „Run Configuration“.
    • Navigieren Sie zum Umgebungs-Tab und definieren Sie dort Ihre Variable.

Schauen Sie sich nun die modifizierte Datei log4j2.xml an und beachten Sie die Verwendung von Umgebungsvariablen.

<Console name="Console" target="SYSTEM_OUT">
    <PatternLayout pattern="%d{HH:mm:ss.SSS} $${env:JournalDevVar} $${env:JournalDevSecondVar} [%t] %-5level %logger{36} - %msg%n"/>
</Console>

Und das Ergebnis der Ausführung würde wie folgt aussehen:

23:57:02.511 JournalDev www.journaldev.com [main] TRACE com.ComApp - COM :: LEVEL :: ComApp TRACE Message ::
23:57:02.517 JournalDev www.journaldev.com [main] TRACE com.journaldev.ComJournalDevApp - COM :: JournalDev :: LEVEL :: ComJournalDevApp TRACE Message ::
23:57:02.520 JournalDev www.journaldev.com [main] TRACE com.journaldev.logging.ComJounralDevLoggingApp - COM :: JournalDev :: LOGGING :: LEVEL :: ComJounralDevLoggingApp TRACE Message ::
23:57:02.523 JournalDev www.journaldev.com [main] ERROR net.NetApp - NET :: LEVEL :: NetApp ERROR Message ::
23:57:02.527 JournalDev www.journaldev.com [main] ERROR net.journaldev.NetJournalDevApp - NET :: JournalDev :: LEVEL :: NetJournalDevApp ERROR Message ::

Aber hier könnte ein kleines Problem auftreten, besonders wenn Sie die Umgebungsvariablen eines Betriebssystems definieren, und es geht um den Eclipse Cache. Idealerweise hat Eclipse alle Systemvariablen zwischengespeichert, wenn es gestartet wird, und Sie finden alle unter Ausführen – Ausführungskonfiguration – Registerkarte Umgebung – Klicken Sie auf die Schaltfläche „Auswählen“. Also könnten Sie verwirrt sein, wenn Sie es definiert haben, aber die Anwendung erkennt es nicht. Selbst wenn Sie Eclipse neu starten, erhalten Sie keine Lösung, und um das zu lösen, müssen Sie eclipse.exe -clean in Ihrer Eclipse-Installation ausführen. Um sicherzustellen, dass Ihre Umgebungsvariablen ordnungsgemäß definiert sind und Ihr System sie bereitwillig finden wird, können Sie den entsprechenden Plugin-Typ verwenden, der von der Log4j2-API bereitgestellt wird. Erstellen Sie eine Instanz von EnvironmentLookup und fragen Sie es nach der Suche nach bestimmten Variablen, und wenn diese definiert sind, finden Sie sie leicht.

EnvironmentLookup lookup = new EnvironmentLookup();
LogManager.getRootLogger().error(lookup.lookup("JournalDevSecondVar"));

Log4j2 Appender

Sie haben zuvor gesehen, wie Sie Lookups verwenden können, um Variablen in Ihre Konfigurationsdatei einzufügen. Möglicherweise möchten Sie jedoch das Medium ändern, über das Ihre Nachrichten übermittelt werden. Anstatt direkt die Konsole zu verwenden, möchten Sie möglicherweise eine Datei oder Datenbankrepository verwenden, um sicherzustellen, dass Ihre Nachrichten dauerhaft gespeichert werden. Log4j2 hat viele Appender bereitgestellt, und Sie können die Log4j2-Dokumentation für weitere Details zu den Appendern konsultieren. Nachfolgend finden Sie eine kurze Liste aller Log4j2-Appender.

  1. ConsoleAppender
  2. AsyncAppender
  3. FailoverAppender
  4. FileAppender
  5. FlumeAppender
  6. JDBCAppender
  7. JMSAppender
  8. JPAAppender
  9. MemoryMappedFileAppender
  10. NoSQLAppender
  11. OutputStreamAppender
  12. RandomAccessFileAppender
  13. RewriteAppender
  14. RollingFileAppender
  15. RollingRandomAccessFileAppender
  16. RoutingAppender
  17. SMTPAppender
  18. SocketAppender
  19. SyslogAppender

Die bekanntesten Medien zur Protokollierung von Ereignissen sind Konsole, Datei und Datenbank. Da die Datei Ihre Nachrichten speichern würde, könnte die Datenbank verwendet werden, um sie zu überprüfen. Zu diesem Zweck wird sich dieser Abschnitt darauf konzentrieren, wie der JDBCAppender effizient verwendet werden kann.

JDBCAppender

Das Hauptziel von JDBCAppender besteht darin, Logereignisse über JDBC-Verbindungen in eine relationale Tabelle zu schreiben. Wir verwenden nicht viel Zeit darauf zu erklären, wie Sie Ihre Verbindungspools optimieren können, da dieses Tutorial nicht für diesen Zweck gedacht ist. Aber sicher erhalten Sie ein voll funktionsfähiges Beispiel, das Ihnen beim Schreiben Ihrer Protokollereignisse in die Datenbank hilft. Bevor wir fortfahren können, lassen Sie uns alle benötigten Parameter und eine Beschreibung für jeden sehen, um JDBCAppender ordnungsgemäß zu konfigurieren.

Parameter Name Type Description
Name String Required, The name of the Appender
ignoreExceptions boolean Default value is set to true, making exceptions thrown to be logged also and then ignored. False value means the exception will be propagated for the caller.
filter Filter The filter that should be used to make a decision whether the log events are going to be handled by this Appender or not.
bufferSize int Default value is zero, indicating there’s no buffering have been done upon log events. Value greater than 0 would lead the Appender to buffer log events and then flush them once the buffer reaches the limit specified.
connectionSource ConnectionSource Required, the connections source from which the database connections should be retrieved.
tableName String Required, the name of the Table on which your log events should be persisted.
columnConfigs ColumnConfig[] Required, additional information may be set upon those used columns and how the data should be persisted on each of them. This can be handled with multiple <Column> elements.
Parameter Name Type Description
jndiName String Required, full prefixed JNDI name that the javax.sql.Datasource is bound to.
Parameter Name Type Description
class String Requird, The fully qualified name for a class containg a static factory method for obtaining JDBC connections.
method boolean Required, The name of the static factory method for obtaining JDBC connections.
Parameter Name Type Description
name String Required, the name of the database column
pattern String Ability to specify any legal pattern that Log event would be formatted with
literal String Ability to specify literal value in this column (i.e. SEQ.NEXTVAL)
isEventTimestamp boolean Indicating whether the event would consider Timestamp
isUnicode boolean For unicode purpose as you may refer for Log4j2 documentation for further details
isClob boolean For storing character large object, you may refer for Log4j2 documentation for further details.

Da Sie JNDI verwenden müssen, würde unser Beispiel eine Verbindungsdatenquelle für die Oracle-Datenbank und Apache Tomcat 7 konfigurieren.

  • Wenn Sie Oracle-Datenbank nicht in Ihrer Umgebung installiert haben, wäre es hilfreich, wenn Sie dies tun könnten. Wenn Sie nicht viel über Oracle wissen, empfehle ich Ihnen, dessen Express Edition zu installieren.
  • Installieren Sie Apache Tomcat 7 in Ihrer Umgebung.
  • Erstellen Sie ein Maven-WebApp-Projekt in Ihrem Eclipse.

  • Vergewissern Sie sich, dass Ihr Projekt erfolgreich erstellt wurde, und wenn Sie Fehler im pom bemerken, stellen Sie sicher, dass Sie diese beheben.
  • Fügen Sie Log4j2-Abhängigkeiten hinzu.
<dependency>
   <groupId>org.apache.logging.log4j</groupId>
   <artifactId>log4j-api</artifactId>
   <version>2.2</version>
</dependency>
<dependency>
   <groupId>org.apache.logging.log4j</groupId>
   <artifactId>log4j-core</artifactId>
   <version>2.2</version>
</dependency>
  • Konfigurieren Sie Ihren Kontext so, dass eine MySQL-Datenquellendeklaration enthalten ist. Gemäß der Apache-Dokumentation sollte diese Datei im META-INF-Ordner Ihrer Webanwendung sein.

<Context path="/JournalDevWebLogging"
	privileged="true" antiResourceLocking="false" antiJARLocking="false">
	<Resource name="jdbc/JournalDevDB" auth="Container"
			factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
			type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000"
			username="root" password="root" driverClassName="com.mysql.jdbc.Driver"
			url="jdbc:mysql://localhost:3306/journaldev" />
</Context>
  • Konfigurieren Sie Ihre Datenbank und erstellen Sie Ihre Protokollierungstabelle.

CREATE TABLE `logging` (
  `EVENT_ID` int(11) NOT NULL AUTO_INCREMENT,
  `EVENT_DATE` datetime DEFAULT NULL,
  `LEVEL` varchar(45) DEFAULT NULL,
  `LOGGER` varchar(45) DEFAULT NULL,
  `MSG` varchar(45) DEFAULT NULL,
  `THROWABLE` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`EVENT_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
  • Konfigurieren Sie Ihre log4j2.xml so, dass sie wie folgt aussieht:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
	<Appenders>
		<Console name="Console" target="SYSTEM_OUT">
			<PatternLayout
				pattern="%d{HH:mm:ss.SSS} $${env:JournalDevVar} $${env:JournalDevSecondVar} [%t] %-5level %logger{36} - %msg%n" />
		</Console>
		<JDBC name="databaseAppender" tableName="journaldev.logging">
			<DataSource jndiName="java:/comp/env/jdbc/JournalDevDB" />
			<Column name="EVENT_DATE" isEventTimestamp="true" />
			<Column name="LEVEL" pattern="%level" />
			<Column name="LOGGER" pattern="%logger" />
			<Column name="MSG" pattern="%message" />
			<Column name="THROWABLE" pattern="%ex{full}" />
		</JDBC>
	</Appenders>
	<Loggers>
		<Root level="ERROR">
			<AppenderRef ref="Console" />
		</Root>
		<logger name="com" level="TRACE" additivity="false">
			<AppenderRef ref="databaseAppender" />
		</logger>
		<logger name="com.journaldev" additivity="false">
			<AppenderRef ref="databaseAppender" />
		</logger>
	</Loggers>
</Configuration>
  • Erstellen Sie eine beliebige Web-Ressource, die es Ihnen ermöglicht, eine Referenz für einen Logger zu erhalten, und protokollieren Sie dann ein Ereignis.
package com.journaldev;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class JournalDevServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
			Logger logger = LogManager.getLogger(JournalDevServlet.class);
			logger.trace("JournalDev Database Logging Message !");
	}
}
  • Sie können optional einen ServletContextListener konfigurieren, der sicherstellt, dass die Initialisierung der Datenquelle ordnungsgemäß erfolgt.
package com.journaldev;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.logging.log4j.LogManager;
public class JournalDevServletContextListener implements ServletContextListener{
	private InitialContext context = null;
	public void contextDestroyed(ServletContextEvent event) {
	}
	public void contextInitialized(ServletContextEvent event) {
		try {
			// Initialen Kontext abrufen
			context = new InitialContext();
			// Eine Referenz für den Unterkontext env abrufen
			Context envContext = (Context)context.lookup("java:comp/env");
			// Eine Referenz für den Unterkontext jdbc abrufen und dann die definierte Datenquelle lokalisieren
			LogManager.getRootLogger().error(((Context)envContext.lookup("jdbc")).lookup("JournalDevDB"));
		} catch (NamingException e) {
			LogManager.getRootLogger().error(e);
		}
	}
}
  • Definieren Sie Ihr Servlet innerhalb Ihrer web.xml-Datei.
  • Führen Sie die Anwendung aus und greifen Sie auf das oben definierte Servlet zu. Sie werden untenstehende Protokolle sehen.
Mar 15, 2015 2:31:41 PM org.apache.catalina.core.AprLifecycleListener init
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\Program Files\Java\jdk1.6.0_26\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\Program Files\Java\jdk1.6.0_26\jre\bin;C:/Program Files/Java/jdk1.6.0_26/bin/../jre/bin/server;C:/Program Files/Java/jdk1.6.0_26/bin/../jre/bin;C:/Program Files/Java/jdk1.6.0_26/bin/../jre/lib/amd64;D:\OracleWebCenter\OracleWC\Oracle11g\app\oracle\product\11.2.0\server\bin;;C:\Program Files\Common Files\Microsoft Shared\Windows Live;C:\Program Files (x86)\Common Files\Microsoft Shared\Windows Live;D:\OracleDB\app\product\11.2.0\dbhome_1\bin;org.C:\Program Files (x86)\Common Files\NetSarang;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;D:\SpringRoo\spring-roo-1.2.5.RELEASE\bin;D:\Ant\apache-ant-1.9.2\bin;C:\Python27;C:\Program Files\Java\jdk1.6.0_26\bin;D:\Maven\apache-maven-3.2.1/bin;D:\bower-master\bin;C:\Program Files (x86)\Git\cmd;C:\Program Files\nodejs\;C:\Program Files\Microsoft Windows Performance Toolkit\;D:\Grails\grails-2.4.0\bin;D:\Gradle\gradle-2.0\bin;C:\Program Files (x86)\Windows Live\Shared;C:\Program Files\TortoiseSVN\bin;D:\Strawberry\perl\bin;D:\Strawberry\perl\site\bin;D:\Strawberry\c\bin;C:\Users\mohammad.amr\AppData\Roaming\npm;D:\JournalDev\eclipse;;.
Mar 15, 2015 2:31:41 PM org.apache.tomcat.util.digester.SetPropertiesRule begin
WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.j2ee.server:JournalDevWebLogging' did not find a matching property.
Mar 15, 2015 2:31:41 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8080"]
Mar 15, 2015 2:31:41 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-bio-8009"]
Mar 15, 2015 2:31:41 PM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 1020 ms
Mar 15, 2015 2:31:41 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Mar 15, 2015 2:31:41 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.35
14:31:43.847 [localhost-startStop-1] ERROR  - org.apache.tomcat.jdbc.pool.DataSource@10fd0a62{ConnectionPool[defaultAutoCommit=null; defaultReadOnly=null; defaultTransactionIsolation=-1; defaultCatalog=null; driverClassName=com.mysql.jdbc.Driver; maxActive=100; maxIdle=30; minIdle=10; initialSize=10; maxWait=10000; testOnBorrow=false; testOnReturn=false; timeBetweenEvictionRunsMillis=5000; numTestsPerEvictionRun=0; minEvictableIdleTimeMillis=60000; testWhileIdle=false; testOnConnect=false; password=root; url=jdbc:mysql://localhost:3306/journaldev; username=root; validationQuery=null; validatorClassName=null; validationInterval=30000; accessToUnderlyingConnectionAllowed=true; removeAbandoned=false; removeAbandonedTimeout=60; logAbandoned=false; connectionProperties=null; initSQL=null; jdbcInterceptors=null; jmxEnabled=true; fairQueue=true; useEquals=true; abandonWhenPercentageFull=0; maxAge=0; useLock=false; dataSource=null; dataSourceJNDI=null; suspectTimeout=0; alternateUsernameAllowed=false; commitOnReturn=false; rollbackOnReturn=false; useDisposableConnectionFacade=true; logValidationErrors=false; propagateInterruptState=false; }
Mar 15, 2015 2:31:43 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Mar 15, 2015 2:31:43 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Mar 15, 2015 2:31:43 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 1909 ms

Log4j2-Filter

Auch wenn es einen LoggerConfig-Kandidaten zur Behandlung von Log-Ereignissen gibt, können Sie ihn so konfigurieren, dass er das Weiterleiten der Log-Ereignisse an Back-End-Appenders verweigert. Dies kann über einen log4j2-Filter erfolgen. Dieser Abschnitt soll Ihnen keine invasive, massive und riesige Menge an Tutorials zum Verwenden von Filtern in Log4j2 bieten, da sie viele Artikel benötigen, die jeden einzelnen von ihnen abdecken. Aber hier sehen Sie, wie Sie den einfachsten Filter verwenden, um das Konzept zu erlernen. Einer der einfachsten Filter, die Sie verwenden können, ist der BurstFilter, der Ihnen einen Mechanismus zur Steuerung der Geschwindigkeit bietet, mit der LogEvents verarbeitet werden, indem Ereignisse nach Erreichen des maximalen Limits stillschweigend verworfen werden. Für den Moment finden Sie unten alle Details, die benötigt werden, um den BurstFilter zu verwenden.

Parameter Name Type Description
level String Level of messages to be filtered
rate float The average number of events per second to allow
maxBurst integer The maximum number of events that can occur before events are filtered for exceeding the average rate. The default is 10 times the rate.
onMatch String Action to take when filter matches. May be Accept, DENY or NEUTRAL. The default is NEUTRAL
onMismatch String Action to tale when filter doesn’t match. May be Accept, DENY or NEUTRAL. The default is NEUTRAL

Schauen Sie sich nun den Speicherort des BurstFilters innerhalb Ihres Datenbank-Appenders an.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
	<Appenders>
		<Console name="Console" target="SYSTEM_OUT">
			<PatternLayout
				pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
		</Console>
		<JDBC name="databaseAppender" tableName="journaldev.logging">
			<DataSource jndiName="java:/comp/env/jdbc/JournalDevDB" />
			<BurstFilter level="TRACE" rate="20" maxBurst="2"/>
			<Column name="EVENT_DATE" isEventTimestamp="true" />
			<Column name="LEVEL" pattern="%level" />
			<Column name="LOGGER" pattern="%logger" />
			<Column name="MSG" pattern="%message" />
			<Column name="THROWABLE" pattern="%ex{full}" />
		</JDBC>
	</Appenders>
	<Loggers>
		<Root level="ERROR">
			<AppenderRef ref="Console" />
		</Root>
		<logger name="com" level="TRACE" additivity="false">
			<AppenderRef ref="databaseAppender" />
		</logger>
		<logger name="com.journaldev" additivity="false">
			<AppenderRef ref="databaseAppender" />
		</logger>
	</Loggers>
</Configuration>
  • Database Appender berücksichtigt BurstFilter, während Console Appender es nicht tut.
  • Die Verwendung des Console-Loggers würde dazu führen, dass alle Protokollereignisse protokolliert werden, während der Database Appender dies nicht tun würde, da der BurstFilter einige davon davon abhalten würde, fortzufahren.
  • Diese Verweigerung von LogEvents wird auch dann erreicht, wenn die verwendeten Logger für die Verarbeitung der LogEvents geeignet sind. Dies ist so vernünftig, wie im folgenden JournalDevServlet gezeigt.

package com.journaldev;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class JournalDevServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		Logger logger = LogManager.getLogger(JournalDevServlet.class);
		for(int i = 0 ; i < 1000 ; i++){
			logger.trace("Index :: "+i+" :: JournalDev Database Logging Message !");
			LogManager.getRootLogger().error("Index :: "+i+" :: JournalDev Database Logging Message !");
		}
	}
}

Auch wenn diese LoggerConfigs geeignet sind, um LogEvents zu verarbeiten, hat der Filter einige davon daran gehindert, verarbeitet und protokolliert zu werden. Sie können dies für das Konzept des Logging Space hinzufügen, um das gesamte Konzept des Loggings zu verstehen.

Log4j2-Layouts

Aufgrund der unterschiedlichen Appender, die Log Events verarbeiten, und der Natur jedes Appenders werden die Layouts so gestaltet, dass das LogEvent im Format erstellt wird, das den Anforderungen derjenigen entspricht, die das LogEvent verarbeiten werden. In den Log4j 1.x- und Logback-APIs wurde die Layout-Transformation von Log Events in einen String durchgeführt, während Log4j2-Layouts eine andere Transformationsmethode berücksichtigt haben; und zwar durch die Umwandlung des LogEvents in ein Byte-Array. Diese neue Art der Transformation erfordert, dass Sie das Charset konfigurieren, um sicherzustellen, dass das Byte-Array die korrekten Werte enthält. Es wird dringend empfohlen, die offizielle Website von Apache Log4j2 zu besuchen und mehr über Layouts und die verschiedenen Typen zu erfahren, die Log4j2 bietet. In diesem Abschnitt werden wir das bekannteste Layout betrachten, das von den meisten unserer Entwickler immer verwendet wird und von dem Sie sicherlich schon gehört haben; es handelt sich um PatternLayout.

Log4j2 PatternLayout

Das Musterlayout ist ein konfigurierbares, flexibles Zeichenmuster, das darauf abzielt, das LogEvent zu formatieren. Diese Art der Formatierung hängt vom Konzept des Konvertierungsmusters ab. Dieser Abschnitt zeigt Ihnen die wichtigsten Funktionen auf, die das Musterlayout bietet. Das Konvertierungsmuster steht im Zusammenhang mit dem Konvertierungsmuster, das printf in der Sprache C bietet. Im Allgemeinen besteht das Konvertierungsmuster aus wörtlichem Text und Formatsteuerungsausdrücken namens Konvertierungsspezifizierer. Die folgende Abbildung zeigt Ihnen, aus welchen Teilen das Konvertierungsmuster besteht: Diese Abbildung oben ist ein Versuch, das Konvertierungsmuster zu vereinfachen, aber es ist sicherlich besser für Sie, die Apache Log4j2-Dokumentation für weitere Details zu Layouts und speziell zum Musterlayout zu konsultieren. Außerdem können Sie oben nach Logereignissen suchen und jedes Mal sehen, welches Konvertierungsmuster verwendet wird, um die Nachrichten zu formatieren.

Welches Log4j2-Level sollten Sie verwenden?

Die größte Frage, die Sie sich stellen können, ist, wann ein bestimmtes Log-Ereignislevel verwendet werden sollte. Im Entwicklungsbereich ist es normal, DEBUG-Logereignisse zu verwenden, während wir in der Produktion das INFO- oder WARN-Level verwenden sollten. Die folgende Tabelle sollte Sie darüber informieren, welches Log4j2-Level in welchem Fall verwendet werden sollte.

Log Event Level When It Should Be Used
OFF When no events will be logged
FATAL When a severe error will prevent the application from continuing
ERROR When an error in the application, possibly recoverable
WARN When an event that might possible lead to an error
INFO When an event for informational purposes
DEBUG When a general debugging event required
TRACE When a fine grained debug message, typically capturing the flow through the application
ALL When all events should be logged

Log4j2 Tutorial Zusammenfassung

Log4j2 ist eine überarbeitete Version des Apache-Protokollierungsframeworks. Log4j2 hat eine Reihe neuer Funktionen und Leistungsverbesserungen gegenüber Log4j1.x bereitgestellt. Dieses Log4j2-Tutorial soll Ihnen helfen, alles an einem Ort zu bekommen. Da es nicht so einfach ist, alle diese Konzepte auf einmal zu behandeln, haben wir beschlossen, unsere Bemühungen darauf zu konzentrieren, die Konzepte zu erklären und einige Beispiele zur weiteren Erläuterung zu verwenden. Appender, Filter, Layouts und Lookups unterliegen dieser Regel. Einige wichtige Punkte Um sicherzustellen, dass Sie die unten aufgeführte Anwendung ausführen können und um etwaige Hindernisse zu vermeiden, überprüfen Sie bitte Folgendes:

  • Ihr Eclipse-IDE ist maven-fähig.
  • Ihr Apache Tomcat hat eine mysql-connector JAR im lib-Ordner Ihres Apache-Startordners.
  • Sie wissen, wie Sie Maven verwenden.

Projektbeispiel für Apache Log4j 2 herunterladen

Das ist alles für das Log4j2-Tutorial, ich hoffe, die meisten wichtigen Punkte sind abgedeckt, um Sie beim Einsatz von Log4j2 in Ihrer Anwendung zu unterstützen.

Source:
https://www.digitalocean.com/community/tutorials/log4j2-example-tutorial-configuration-levels-appenders