Log4j2 Voorbeeld Tutorial – Configuratie, Niveaus, Appenders

Welkom bij de Apache Log4j2 Voorbeeld Handleiding. Als je een ervaren ontwikkelaar vraagt naar het meest vervelende aspect van een applicatie, is het antwoord waarschijnlijk gerelateerd aan logging. Als er geen geschikte logging is in een applicatie, zal het onderhoud een nachtmerrie zijn. De meeste applicaties doorlopen ontwikkelingstesten, eenheidstesten, integratietesten. Maar wanneer het aankomt op productie, zul je altijd unieke scenario’s en uitzonderingen tegenkomen. Dus de enige manier om uit te vinden wat er is gebeurd in een specifiek geval is door te debuggen via de logs. Veel frameworks bieden op de een of andere manier standaard logging, maar het is altijd het beste om te gaan met het loggingmechanisme dat de industrienorm is. Apache Log4j is een van de meest gebruikte logging frameworks. Apache Log4j 2 is de volgende versie, die veel beter is dan Log4j.

Log4j Voorbeeld Handleiding

In deze Log4j2 Voorbeeld Handleiding leer je hoe je aan de slag kunt met Apache Log4j2. We zullen ook de architectuur van Log4j2 verkennen, Log4j2 configuratie, log4j2 logging niveaus, appenders, filters en nog veel meer.

  1. Log4j2 Overzicht
  2. Log4j2 Architectuur
  3. Log4j2 Configuratie
  4. Log4j2 Niveaus
  5. Log4j2 Lookups
  6. Log4j2 Appenders
  7. Log4j2 Filters
  8. Log4j2-indelingen
  9. Welk Log4j2-niveau moet je gebruiken
  10. Samenvatting van de Log4j2-zelfstudie

Log4j2-overzicht

Het gebruik van de Logging API in een toepassing is geen luxe, het is een must. Log4j is een open source bibliotheek die wordt gepubliceerd en gelicentieerd onder Apache Software. U kunt een toepassing debuggen met Eclipse Debugging of enkele andere tools, maar dat is niet voldoende en haalbaar in een productieomgeving. Het logmechanisme biedt u verschillende voordelen die u niet zult vinden bij normaal debuggen.

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

Zoals u hierboven kunt zien, zal het gebruik van het logmechanisme efficiënter zijn met lagere onderhoudskosten. Apache Log4j is de belangrijkste tool voor logging in Java-toepassingen, dus u moet het gebruiken.

Log4j2-architectuur

Voor we verder gaan met de Log4j Voorbeeld tutorial, is het goed om eens te kijken naar de architectuur van Log4j2. Onderstaande afbeelding toont de belangrijke klassen in de Log4j2 API. Hier is de gedetailleerde uitleg voor de bovenstaande architectuur:

  • Applicaties zullen aan LogManager vragen om een Logger met een specifieke naam.

  • LogManager zal de passende LoggerContext lokaliseren en vervolgens de Logger ervan verkrijgen.

  • Als de Logger nog niet is aangemaakt, wordt deze aangemaakt en gekoppeld aan LoggerConfig volgens de drie keuzes hieronder:

    1. Logger-instantie wordt aangemaakt en gekoppeld aan de LoggerConfig met dezelfde naam. Bijvoorbeeld App.class in getLogger(App.class) wordt geëvalueerd als een String com.journaldev.App. LoggerConfig-naam is identiek aan volledig gekwalificeerde klassenaam (Softwarecomponent).
    2. Logger-instantie wordt aangemaakt en gekoppeld aan de LoggerConfig met dezelfde ouderpackage als de Loggers. Bijvoorbeeld com.journaldev in getLogger("com.journaldev")
    3. Logger-instantie wordt aangemaakt en gekoppeld aan de Root LoggerConfig. Root LoggerConfig wordt gebruikt wanneer er geen configuratiebestand is of wanneer je een logger verkrijgt met een naam die niet is gedefinieerd in de loggerverklaringen.
  • LoggerConfig-objecten worden aangemaakt vanuit de Logger-verklaring in het configuratiebestand. LoggerConfig wordt ook gebruikt om LogEvents te verwerken en ze door te verwijzen naar hun gedefinieerde Log4j2 Appenders.

  • Root logger is een uitzonderlijk geval, wat betreft zijn bestaan. Het bestaat altijd en bevindt zich bovenaan in elke loggerhiërarchie.

  • Je kunt de root logger verkrijgen door de onderstaande instructies te gebruiken:

    Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
    Logger logger = LogManager.getRootLogger();
    
  • De namen van log4j2 loggers zijn hoofdlettergevoelig.

  • Met uitzondering van de root logger kunnen alle loggers worden verkregen door hun naam door te geven aan LogManager.getLogger().

  • LoggerContext is een centraal punt voor het logboeksysteem omdat u meerdere LoggerContexts binnen uw toepassing kunt hebben. Voor elke LoggerContext moet een actieve configuratie worden ingesteld.

  • Log4j2-configuratie bevat alle activa van het logboeksysteem; LoggerConfig(s), Appender(s), Filter(s) en vele anderen.

  • Het aanroepen van LogManager.getLogger() door dezelfde naam door te geven, geeft altijd de referentie terug voor exact dezelfde logger-instantie.

  • De configuratie van het logboeksysteem wordt meestal uitgevoerd bij de initialisatie van de toepassing. Dit kan verschillende vormen aannemen; programmatisch of door het lezen van een log4j2-configuratiebestand.

Elke logger is geassocieerd met een LoggerConfig-object, een set LoggerConfig-objecten vormt een hiërarchie van loggers. Dit concept staat bekend als Logger Hiërarchie. Logger Hiërarchie bestaat uit een set LoggerConfig-objecten met een ouder-kindrelatie. Het bovenste element in elke Logger Hiërarchie is de Root Logger. Als Log4j2 het configuratiebestand niet vindt, zal alleen de Root Logger worden gebruikt voor logging met het logniveau ERROR. Onderstaande afbeelding toont het waarschuwingsbericht dat je in dit geval krijgt. Fout StatusLogger Geen log4j2-configuratiebestand gevonden. Standaardconfiguratie wordt gebruikt: alleen fouten worden gelogd naar de console. De tabel hieronder toont de ouder-kindrelatie in de Logger Hiërarchie.

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

Om de ouder-kindrelatie te verduidelijken, zou de tabel hierboven als volgt worden gelezen:

  • Root is een ouder voor com.
  • Root is een voorouder voor com.journaldev.
  • Root is een voorouder voor com.journaldev.logging.
  • com is een kind van Root.
  • com is een ouder voor com.journaldev.
  • com is een voorouder voor com.journaldev.logging.
  • com.journaldev.logging is een kind van com.journaldev enzovoort.

Een instantie van LoggerConfig wordt gezegd een voorouder te zijn van een andere LoggerConfig; als zijn naam gevolgd door een punt een prefix is voor de naam van de nakomeling. Een instantie van LoggerConfig wordt gezegd een ouder te zijn van een andere LoggerConfig; als er geen tussenliggende namen zijn tussen beide.

Log4j2 Configuratie

Er zijn veel manieren om Log4j2-configuratie in uw toepassing te gebruiken.

  1. Door middel van een configuratiebestand geschreven in XML, JSON, YAML of eigenschappenbestand.
  2. Programmatisch, door het maken van een configuratiefabriek en configuratie-implementatie.
  3. Programmatisch, door API’s aan te roepen die zijn blootgesteld in de configuratie-interface.
  4. Programmatisch, door methoden aan te roepen op de interne loggerklasse.

We zullen ons voornamelijk richten op het configuratiebestand. Het is echter goed om ook de programmeeraanpak te kennen, voor het geval u een specifieke logstrategie wilt configureren voor een specifieke Logger. Allereerst, laten we het geval overwegen waarin u geen configuratiebestand heeft verstrekt. Log4j2-implementatie gaat ervan uit dat er een systeemvariabele is genaamd log4j.configurationFile om de locatie van het log4j2-configuratiebestand aan te geven.

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>

En hier is de gedetailleerde uitleg voor de bovenstaande code:

  • De app heeft de Root-logger gerefereerd door de getRootLogger-methode van LogManager aan te roepen.
  • Referentie naar de logger vanuit LogManager heeft het Log4j-systeem gestart.
  • Log4j zal de log4j.configurationFile systeemeigenschap inspecteren om het log4j2-configuratiebestand te bepalen. Log4j-configuratie kan worden geschreven in JSON, YAML en XML.
  • We kunnen de log4j.configurationFile systeemeigenschap instellen via System.setProperties("log4j.configurationFile","BESTANDS_PAD") of door deze door te geven als een JVM-parameter zoals je ziet in de onderstaande figuur. Let ook op het bestand protocolvoorvoegsel.

  • Indien geen systeemeigenschap is gedefinieerd, heeft de configuratievolgorde de volgende prioriteit:
    • Property ConfigurationFactory zal zoeken naar log4j2-test.properties in het klassenpad.
    • YAML ConfigurationFactory zal zoeken naar log4j2-test.yaml of log4j2-test.yml in het klassenpad.
    • JSON ConfigurationFactory zal zoeken naar log4j2-test.jsn of log4j2-test.json in het klassenpad.
    • XML ConfigurationFactory zal zoeken naar log4j2-test.xml in het klassenpad.
    • Property ConfigurationFactory zal zoeken naar log4j2.properties in het klassenpad.
    • YAML ConfigurationFactory zal zoeken naar log4j2.yml of log4j2.yaml in het klassenpad.
    • JSON ConfigurationFactory zal zoeken naar log4j2.jsn of log4j2.json in het klassenpad.
    • XML ConfigurationFactory zal zoeken naar log4j2.xml in het klassenpad.
    • Indien er geen configuratiebestand is opgegeven, zal de DefaultConfiguration worden gebruikt en dat zou leiden tot een set standaardgedragingen:
      • De root-logger zal worden gebruikt.
      • Het niveau van de root-logger zal worden ingesteld op ERROR.
      • De root-logger zal logboekberichten doorsturen naar de console.
      • PatternLayout is ingesteld op %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n

Het gebruik van het log4j2-configuratiebestand maakt de log4j2-configuratie zo eenvoudig, maar laten we eens kijken hoe we het programmatisch kunnen configureren. Dit gaat allemaal over het gebruik van 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 {
 
    	// Ontvang een instantie van de configuratiefabriek; je opties zijn standaard ConfigurationFactory, XMLConfigurationFactory,
    	// 	YamlConfigurationFactory & JsonConfigurationFactory
    	ConfigurationFactory factory =  XmlConfigurationFactory.getInstance();
 
    	// Zoek de bron van deze configuratie, dit gelegen bestand is een dummybestand dat alleen een lege configuratietag bevat
    	ConfigurationSource configurationSource = new ConfigurationSource(new FileInputStream(new File("C:/dummyConfiguration.xml")));
 
    	// Ontvang een referentie van de configuratie
    	Configuration configuration = factory.getConfiguration(configurationSource);
 
    	// Maak standaardconsoleappender
    	ConsoleAppender appender = ConsoleAppender.createDefaultAppenderForLayout(PatternLayout.createDefaultLayout());
 
    	// Voeg consoleappender toe aan configuratie
    	configuration.addAppender(appender);
 
    	// Maak loggerConfig
    	LoggerConfig loggerConfig = new LoggerConfig("com",Level.FATAL,false);
 
    	// Voeg appender toe
    	loggerConfig.addAppender(appender,null,null);
 
    	// Voeg logger toe en koppel het met instantie van loggerConfig
    	configuration.addLogger("com", loggerConfig);
 
    	// Ontvang instantie van context
    	LoggerContext context = new LoggerContext("JournalDevLoggerContext");
 
    	// Start logsysteem
    	context.start(configuration);
 
    	// Ontvang een referentie voor logger
    	Logger logger = context.getLogger("com");
 
    	// Loggebeurtenis van DEBUG-bericht
    	logger.log(Level.FATAL, "Logger Name :: "+logger.getName()+" :: Passed Message ::");
 
    	// Loggebeurtenis van foutbericht voor logger geconfigureerd als FATAAL
    	logger.log(Level.ERROR, "Logger Name :: "+logger.getName()+" :: Not Passed Message ::");
 
    	// Loggebeurtenis van FOUT-bericht dat door Root zal worden afgehandeld
    	logger.getParent().log(Level.ERROR, "Root Logger :: Passed Message As Root Is Configured For ERROR Level messages");
    }
}
  • Je kunt een van de ConfigurationFactory’s gebruiken die door Log4j2 worden geleverd of de standaardconfiguratie gebruiken. We hebben XMLConfigurationFactory gebruikt om een instantie van ConfigurationFactory te krijgen.
  • De fabriek zal je een instantie geven van de vereiste configuratiereferentie door het overeenkomstige configuratiebestand door te geven.
  • De configuratie-instantie zal worden gebruikt in combinatie met LoggerContext voor het starten van het logsysteem.
  • A console Appender has been configured and added into configuration instance with default layout. This Appender would print out messages into your console.
  • Een instantie van LoggerConfig is gemaakt met de opgegeven naam, NIVEAU en zonder gebruik van een filter. De gemaakte appender wordt toegewezen aan deze instantie van LoggerConfig.
  • De instantie van LoggerConfig is toegevoegd aan de configuratie-instantie.
  • A new instance of LoggerContext is created with defined name.
  • De configuratie-instantie is doorgegeven voor de LoggerContext-instantie en heeft laatstgenoemde gestart.
  • A logger instance has been acquired from LoggerContext. This logger instance will be used to fire set of Log events.
  • Logger-instantie heeft drie gebeurtenissen geactiveerd die zouden worden uitgelegd in de sectie Log4j2-niveaus.
  • De com-logger is geconfigureerd om berichten af te drukken waarvan de niveaus FATAL zijn.
  • Standaard is de Root-logger geconfigureerd om berichten af te drukken waarvan het niveau ERROR is.
  • ERROR-berichten worden niet gelogd door de ‘com’-logger omdat het niveau FATAL is.

Dezelfde configuratie kan worden uitgevoerd door gebruik te maken van YAML, JSON of properties-bestand. Echter, de log4j2-propertiesbestandsconfiguratie verschilt van het log4j-propertiesbestand, dus zorg ervoor dat u niet probeert de log4j-propertiesbestandsconfiguratie te gebruiken met log4j2. Het zal de onderstaande fout genereren;

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

Bij het verwerken van de bovenstaande code zou u de onderstaande uitvoer krijgen:

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

De eerste regel logs is van com logger en de tweede is van de Root Logger. De foutmelding van de com-logger wordt niet afgedrukt omdat het niveau fataal is.

Log4j2-niveaus

U kunt in bovenstaande codevoorbeelden zien dat telkens wanneer we een LoggerConfig definiëren, we ook het logniveau opgeven. Standaard is log4j2-loggen cumulatief. Dit betekent dat alle bovenliggende loggers ook worden gebruikt wanneer een specifieke logger wordt gebruikt. De onderstaande afbeelding verduidelijkt deze situatie. En hierin punten van verduidelijking ervoor:

  • Zoals we eerder hebben gezegd, heeft elke logger een bijbehorende LoggerConfig-instantie. Deze loggerConfig is gedefinieerd op het configuratieniveau.
  • Het logniveau kan worden bepaald op het niveau van LoggerConfig.
  • U kunt de logger verkrijgen op basis van zijn naam, de bovenliggende pakket of door rechtstreeks naar de Root Logger te wijzen.
  • Root Logger is de top-level knoop voor elke LoggerConfig-hiërarchie.
  • Zodra u de logger com.journaldev verkrijgt en een logEvent initieert voor het loggen, zal de loggerConfig (net.journaldev) het bericht loggen en zal het bericht ook worden doorgegeven naar boven in de hiërarchie zonder enige respect voor de logniveaus van ouders. Dus loggebeurtenis zal worden doorgegeven aan com en Root loggers en ze zullen ook respectievelijk het bericht loggen volgens de gedefinieerde niveaus.
  • Zodra u de com-logger verkrijgt en een logEvent initieert voor het loggen, zal de loggerConfig(com) het bericht loggen en zal het bericht ook worden doorgegeven naar boven in de hiërarchie zonder enig respect voor de logniveaus van ouders. Dat wil zeggen, de Root-logger zal de loggebeurtenis doorgeven en zal ook het bericht loggen.
  • Hetzelfde geval voor de hiërarchie van net.journaldev.
  • Volgende secties, zullen meer verduidelijkingen toevoegen voor het additieve concept.
  • Er bestaat een kans dat de ouder het bericht negeert door het Filterconcept te gebruiken of door de additieve indicator op false in te stellen, zodat loggebeurtenissen niet naar ouders worden doorgegeven.
  • Er bestaat een kans dat de logger het bericht negeert als het niveau van de respectieve loggerConfig GROTER IS DAN het loggebeurtenisniveau.

Nu, laten we het voorbeeld bekijken dat geassocieerd is met het hierboven uitgelegde additieve concept:

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 ::");
	}
}

Terwijl het log4j2-configuratiebestand er als volgt uitziet:

<?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>

Als je de hoofdklasse uitvoert, zul je de onderstaande resultaten vinden:

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 ::

Hieronder volgt een gedetailleerde uitleg voor de bovenstaande code:

  • Het configuratiebestand bevat vijf loggerConfig-instanties gedefinieerd en dat zijn Root, com, com.journaldev, net & net.journaldev. Net als de Logger-hiërarchie hierboven weergegeven.
  • Het niveau van Root is geconfigureerd als ERROR en dat is eigenlijk de standaardwaarde.
  • Niveaus van com & com.journaldev zijn geconfigureerd als TRACE.
  • Niveaus van net & net.journaldev zijn geconfigureerd als ERROR.
  • Je hebt misschien gemerkt dat de berichten van ComAPP en ComJournalDevApp respectievelijk twee en drie keer worden weergegeven. Deze berichten worden weergegeven volgens de Logger-hiërarchie voor ComApp & ComJournalDevApp waar ze zich respectievelijk in de com & com.journalDev-pakketten bevinden. We hebben een soortgelijk geval met NetApp & NetJournalDevApp-klassen.
  • Ouders worden doorgegeven omdat de additieve indicator standaard op true is ingesteld.

Logging Space houdt rekening met Loggebeurtenisniveaus en het niveaus van de loggerConfig naast Logger Hierarchy.

Dus wat als we de LoggerConfig voor com zouden wijzigen naar INFO en het hele programma zoals het is zouden laten:

<?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>

Dan zou het resultaat als volgt zijn:

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 ::
  • Zeker, je zult merken dat de loggebeurtenis van ComAPP genegeerd wordt en dat komt door het gedefinieerde niveau van de loggerConfig voor het com-pakket. Het niveau INFO (400) is lager dan het niveau van de loggebeurtenis, die hier TRACE(600) is. Dus, de boodschap van ComApp zal niet meer worden getoond en om het te tonen, moet je het niveau van de LoggerConfig voor com wijzigen naar TRACE(600) of ALLES(Integer.MAX_VALUE).

Om ervoor te zorgen dat Loggebeurtenissen worden weergegeven, moet het niveau van de LoggerConfig groter zijn dan of gelijk zijn aan het niveau van de Loggebeurtenis.

De onderstaande tabel toont de log4j2-niveaus en het gewicht voor elk van hen:

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

Zeker, de bovenstaande tabel verduidelijkt veel meer dan woorden en het geeft je de belangrijkste reden waarom de Loggebeurtenis TRACE niet wordt weergegeven terwijl het niveau van de LoggerConfig INFO is.

Merk op dat de verspreiding van loggebeurtenissen omhoog in de logger-hiërarchie buiten deze berekening valt en dat het de niveaus negeert.

Maar wat gebeurt er als we LoggerConfig van com.journaldev uit de configuratie verwijderen en een nieuwe toevoegen voor com.journaldev.logging om het configuratiebestand er als volgt uit te laten zien:

<?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>

U kunt de onderstaande figuur wellicht handiger vinden om te begrijpen wat er is gebeurd in de bovenstaande log4j2-configuratie. Hier is wat verduidelijking voor de hierboven getoonde figuur en hoe dit van invloed kan zijn op het gedrag van loggebeurtenissen:

  • Wanneer loggebeurtenissen worden gegenereerd door een Logger met de naam com.journaldev.logging, is de LoggerConfig die aan die naam is gekoppeld (d.w.z. com.journaldev.logging) gebruikt om deze te verwerken en het bericht af te drukken.
  • Omdat de additieve eigenschap van de LoggerConfig com.journaldev.logging standaard is ingesteld op true, wordt de loggebeurtenis doorgegeven aan de bovenliggende LoggerConfig, die in dit geval verwijst naar com.journaldev.
  • Omdat de LoggerConfig com.journaldev niet is gedefinieerd in de configuratie, gebeurt er niets en wordt de loggebeurtenis doorgegeven aan de instanties van com en vervolgens van Root LoggerConfig.
  • Com en Root zullen de loggebeurtenis ontvangen en afdrukken, ongeacht het niveau waarop deze is verzonden.

Als gevolg van de genoemde punten ziet u de volgende uitvoer:

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 ::

En u kunt het volgende opmerken:

  • Een loggebeurtenis in het com-pakket wordt tweemaal weergegeven. Een keer voor com en een keer voor Root.
  • Loggebeurtenis bij com.journaldev is tweemaal weergegeven. Eén keer voor com en de tweede keer voor Root. Hoewel het eerder drie keer was, maar op dit moment ontbreekt de LoggerConfig van com.journaldev en dus kan er geen logging hebben plaatsgevonden in het com.journaldev-pakket en zou het gebeurtenis worden doorgegeven voor com en Root.
  • Loggebeurtenis bij com.journaldev.logging is drie keer weergegeven, één keer voor het com.journaldev.logging-pakket, de tweede keer voor com en de derde keer voor Root. Volgens de propagatie van de Logger-hiërarchie zou het vier keer moeten worden weergegeven, maar door de afwezigheid van com.journaldev LoggerConfig wordt het slechts drie keer weergegeven.

In het geval dat u een com.journaldev LoggerConfig-instantie hebt gedefinieerd zonder opgegeven niveau, zal het het niveau erven van zijn ouder.

Maar wat als u com.journaldev LoggerConfig in uw configuratiebestand hebt gedefinieerd en het niveau van de LoggerConfig niet hebt gespecificeerd. Gelukkig zal het concept van Logger-hiërarchie u hier redden en com.journaldev zou zijn niveauwaarde erven van zijn ouder. Hieronder volgt een voorbeeldconfiguratiebestand gevolgd door de tabel voor het logniveau van elke logger-configuratie.

<?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
  • Het com.journaldev.logging-pakket is al gekoppeld aan een LoggerConfig met Logniveau TRACE.
  • Het com.journaldev-pakket is al gekoppeld aan een LoggerConfig zonder Logniveau gespecificeerd, dus het zou zijn Ouder Logniveau erven en zeker zal de waarde TRACE zijn voor het com-pakket.
  • Het com-pakket is al gekoppeld aan Loggerconfig met logniveau TRACE.
  • Standaard heeft Root ERROR als logniveau.
  • In het geval dat com-pakket niet is aangegeven, zal com.journaldev LoggerConfig het logniveau van Root erven.

Hieronder is het resultaat van de uitvoering terwijl com.journaldev de logniveaus van com erft:

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 ::

En hieronder volgt het resultaat als u LoggerConfig voor het com-pakket verwijdert:

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 ::

U zult merken dat er geen berichten zijn gelogd voor com en com.journaldev, hieronder staan de redenen.

  • Het verwijderen van LoggerConfig die is gekoppeld aan het com-pakket zal ervoor zorgen dat alle loggebeurtenissen die in dat pakket worden genoemd, worden genegeerd.
  • Aangezien er geen LoggerConfig is gedefinieerd voor het com-pakket in de configuratie, zal de LoggerConfig die is gekoppeld aan com.journaldev het logniveau erven van zijn bovenliggende niveau. Com is niet gedefinieerd, en de Logger-hiërarchie reikt nu tot aan de Top en verwijst nu naar Root. Het root-logniveau is ERROR(200) en het loggebeurtenisniveau in com.journaldev is TRACE(600) – Zie ComJournalDevApp – en volgens de eerder gedefinieerde vergelijking moet het niveau van LoggerConfig groter zijn dan of gelijk aan het loggebeurtenisniveau en dat is onjuist, dus er worden geen berichten weergegeven voor com.journaldev.

Last but not least, de onderstaande tabel toont alle mogelijke loggingscenario’s die u kunt tegenkomen bij het gebruik van het loggingsysteem:

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
  • Er is geen directe methode die kan worden gebruikt voor het gooien van OFF/ALL loggebeurtenissen.
  • Voornamelijk, voor het gooien van OFF/ALL loggebeurtenissen kunt u logger.log(Level.OFF, “Msg”) of logger.log(LEVEL.ALL, “Msg”) gebruiken, respectievelijk.
  • De log-methode is verantwoordelijk voor het verwerken van loggebeurtenissen volgens de genoemde vergelijking.

De vergelijking voor het verwerken zegt: Als het niveau van de LoggerConfig groter is dan of gelijk is aan het loggebeurtenisniveau, wordt het evenement geaccepteerd voor verdere verwerking.

Het loggebeurtenis zou worden geaccepteerd voor verdere verwerking – dit is zo belangrijk omdat je de mogelijkheid hebt om te voorkomen dat sommige gebeurtenissen worden afgehandeld, zelfs als ze worden geaccepteerd door het gebruik van Log4j2-filters. U kunt de additieve eigenschap op false instellen om de propagatie van loggebeurtenissen naar bovenliggende loggers te vermijden. Hieronder volgt hetzelfde voorbeeld dat je eerder hebt gezien, maar deze keer met een additiviteitsattribuut, zodat je het verschil kunt opmerken.

<?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>

En het resultaat van de uitvoering zou als volgt zijn:

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 ::

En je zult merken dat er geen propagatie van loggebeurtenissen is naar de bovenliggende loggers.

Log4j2 Lookups

Ideaal gezien kun je lookups definiëren als een manier waarop je waarden kunt doorgeven voor je logging configuratiebestand. Log4j2 biedt je een verschillende set Lookups die onafhankelijk kunnen worden gebruikt voor het instellen van waarden uit verschillende contexten:

  • Context Map Lookup
  • Datum Lookup
  • Omgevingslookup
  • Java Lookup
  • JNDI Lookup
  • JVM Invoerargument Lookup (JMX)
  • Belangrijkste Argumenten Lookup
  • Map Lookup
  • Gestructureerde Data Lookup
  • Systeemeigenschappen Lookup
  • Web Lookup

Je kunt voor verdere details over alle soorten lookups verwijzen naar de Log4j2 documentatie, maar laten we hier wat voorbeelden bekijken om de basis van de Log4j2 Lookup te behandelen. Omgevingslookup vertegenwoordigt de manier waarop je een omgevingswaarde kunt doorgeven (door Linux etc/profile, Windows-systeemomgeving of opstartscripts voor de applicatie). Zoals de meesten van ons weten, hebben we de mogelijkheid om een reeks omgevingswaarden te definiëren voor de applicatie om te gebruiken. Laten we de meest bekende manieren bekijken om je omgevingsvariabelen te definiëren.

  1. Definieer een omgevingsvariabele door gebruik te maken van de Windows omgevingsfaciliteit:
    • Klik met de rechtermuisknop op het pictogram van je computer en selecteer eigenschappen. Het startscherm van het configuratiescherm moet worden weergegeven.
    • Klik op Geavanceerde systeeminstellingen en open vervolgens het venster Omgevingsvariabelen.
    • Onder de Systeemvariabelen sectie, definieer de variabele JournalDevVar met de waarde JournalDev.
    • Update de PatternLayout in je log4j2.xml om je nieuw toegevoegde variabele te bevatten.

  1. Definieer uw omgevingsvariabelen door gebruik te maken van de opstartscript faciliteit.
    • In plaats van het normale standaardscript te gebruiken, kunt u de Eclipse IDE Running Script-faciliteit gebruiken, klik op uw Run-menu en kies Run Configuration.
    • Navigeer naar het tabblad Omgeving & definieer uw variabele daarin.

Kijk nu naar het aangepaste log4j2.xml-bestand en let op het gebruik van omgevingsvariabelen.

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

En het resultaat van de uitvoering zou er als volgt uitzien:

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 ::

Maar je kunt hier mogelijk een klein probleem tegenkomen, vooral bij het definiëren van de omgevingsvariabelen van een besturingssysteem en met name de Eclipse-cache. Ideaal gezien heeft Eclipse alle systeemvariabelen in de cache opgeslagen wanneer het wordt uitgevoerd en je kunt ze allemaal vinden onder Run – Run Configuration – Environment Tab – Klik op de knop Selecteren. Dus, het kan verwarrend zijn als je het hebt gedefinieerd maar de applicatie herkent het niet. Zelfs als je Eclipse opnieuw start, krijg je geen oplossing en om het op te lossen, moet je eclipse.exe -clean uitvoeren bij je Eclipse-installatie. Om ervoor te zorgen dat je omgevingsvariabelen correct zijn gedefinieerd en je systeem ze graag zal vinden, kun je het overeenkomstplugin-type gebruiken dat wordt geleverd door de Log4j2 API. Maak een instantie van EnvironmentLookup en vraag het om een bepaalde variabele op te zoeken en als deze is gedefinieerd, vind je ze gemakkelijk.

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

Log4j2 Appenders

Je hebt eerder gezien hoe je Lookups kunt gebruiken om variabelen in je configuratiebestand in te voegen. Misschien wil je echter het medium wijzigen waar je berichten doorheen gaan. In plaats van rechtstreeks de console te gebruiken, wil je misschien zo’n bestand of databaseopslagplaats gebruiken om ervoor te zorgen dat je berichten permanent worden bewaard. Log4j2 heeft veel Appenders geleverd, en je kunt de log4j2-documentatie raadplegen voor meer details over de Appender. Hieronder staat in het kort een lijst met alle Log4j2 Appenders.

  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

De meest gebruikte mediums voor het loggen van gebeurtenissen zijn console, bestand en database. Aangezien het bestand je berichten zou opslaan, zou de database kunnen worden gebruikt om ze te controleren. In dit verband zal deze sectie zich richten op hoe de JDBCAppender efficiënt kan worden gebruikt.

JDBCAppender

Het hoofddoel van JDBCAppender is om Log-gebeurtenissen in een relationele tabel te schrijven via JDBC-verbindingen. We besteden niet veel tijd aan het uitleggen hoe je je verbindingspools kunt optimaliseren, aangezien deze handleiding daar niet voor bedoeld is. Maar je krijgt zeker een volledig functioneel voorbeeld dat helpt bij het schrijven van je log-gebeurtenissen naar de database. Voordat we verder gaan, laten we alle benodigde parameters en een beschrijving van elk zien om JDBCAppender correct geconfigureerd te krijgen.

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.

Aangezien je verplicht bent om JNDI te gebruiken, zou ons voorbeeld een verbinding gegevensbron configureren voor de Oracle database en Apache Tomcat 7.

  • Als je Oracle database niet hebt geïnstalleerd in je omgeving, wordt het op prijs gesteld als je dat wel doet. Als je niet goed op de hoogte bent van Oracle, raad ik je aan de Express Edition te installeren.
  • Installeer Apache Tomcat 7 in je omgeving.
  • Maak een Maven WebApp-project in je Eclipse.

  • Zorg ervoor dat je project succesvol is aangemaakt en als je fouten opmerkt in de pom, zorg er dan voor dat je ze oplost.
  • Voeg Log4j2-afhankelijkheden toe.
<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>
  • Configureer je context om een MySQL-gegevensbronverklaring op te nemen. Volgens de Apache-documentatie moet dit bestand zich bevinden in de META-INF-map van je webtoepassing.

<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>
  • Configureer je database en maak je Logging-tabel aan.

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;
  • Configureer je log4j2.xml om er als volgt uit te zien:
<?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>
  • Maak een webresource aan waarmee je een verwijzing kunt krijgen naar een logger en vervolgens een gebeurtenis kunt vastleggen.
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 !");
	}
}
  • Je kunt optioneel een ServletContextListener configureren die ervoor zorgt dat de initialisatie van de gegevensbron correct wordt uitgevoerd.
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 {
			// Haal de initiële context op
			context = new InitialContext();
			// Krijg een verwijzing naar de subcontext env
			Context envContext = (Context)context.lookup("java:comp/env");
			// Krijg een verwijzing naar de subcontext jdbc en zoek vervolgens de gedefinieerde gegevensbron op
			LogManager.getRootLogger().error(((Context)envContext.lookup("jdbc")).lookup("JournalDevDB"));
		} catch (NamingException e) {
			LogManager.getRootLogger().error(e);
		}
	}
}
  • Definieer je Servlet binnen je web.xml-bestand.
  • Voer de toepassing uit en benader de bovenstaande gedefinieerde Servlet. Je zult hieronder logboeken zien.
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-filters

Zelfs als er een LoggerConfig-kandidaat is om Log-gebeurtenissen te verwerken, kun je deze configureren om het doorgeven van de Log-gebeurtenissen naar backend Appenders te weigeren. Dit kan worden gedaan door een log4j2-filter. Deze sectie is niet bedoeld om je een invasieve, massieve en enorme hoeveelheid tutorials te bieden over het gebruik van filters in Log4j2, aangezien ze veel artikelen nodig hebben die elk ervan behandelen. Maar hier zie je hoe je het meest eenvoudige filter kunt gebruiken om het concept te leren. Een van de meest eenvoudige filters die je kunt gebruiken, is BurstFilter, dat je een mechanisme biedt om de snelheid te regelen waarmee LogEvents worden verwerkt door gebeurtenissen stilzwijgend te negeren nadat het maximale limiet is bereikt. Voor nu zie je hieronder alle details die nodig zijn om BurstFilter te gebruiken.

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

Kijk nu naar de locatie van BurstFilter binnen je database Appender.

<?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 houdt rekening met BurstFilter terwijl Console Appender dat niet doet.
  • Als je de Console-logger gebruikt, worden alle loggebeurtenissen volledig gelogd, terwijl Database Appender dat niet doet omdat BurstFilter sommige gebeurtenissen tegenhoudt om door te gaan.
  • Deze weigering van LogEvents wordt zelfs bereikt wanneer de gebruikte loggers geschikt zijn om de LogEvents te verwerken. Dit is zeer redelijk, zoals getoond in de JournalDevServlet hieronder.

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 !");
		}
	}
}

Zelfs al zijn die LoggerConfigs geschikt om Log Events te verwerken die daar zijn gegooid, heeft de filter voorkomen dat sommige ervan worden afgehandeld en vervolgens gelogd. Je kunt dit toevoegen voor het concept van Logging Space om het hele concept van logging te begrijpen.

Log4j2 Layouts

Als gevolg van verschillende Appenders die Log Events verbruiken en de aard van elke appender, worden de lay-outs gemaakt om de LogEvent te vormen in het formaat dat voldoet aan de behoeften van wie de loggebeurtenis zal consumeren. In Log4j 1.x en Logback API’s was de lay-outtransformatie van Log Events naar een String, terwijl Log4j2-lay-outs een andere manier van transformatie hebben overwogen; en dat is door de LogEvent om te zetten in een array van bytes. Dit nieuwe type transformatie zou u dwingen de Charset te configureren om ervoor te zorgen dat de byte-array de juiste waarden bevat. Het is sterk aan te raden om terug te keren naar de officiële site van Apache Log4j2 en meer te weten te komen over Lay-out en de verschillende typen die Log4j2 biedt. In deze sectie zullen we de meest bekende Lay-out overwegen die altijd wordt gebruikt door de meeste van onze ontwikkelaars en waar je zeker over hebt gehoord; het is PatternLayout.

Log4j2 PatternLayout

Patroonlay-out is een configureerbaar, flexibel String-patroon bedoeld om de LogEvent te formatteren. Dit soort opmaak is afhankelijk van het concept van de conversiepatroon. In deze sectie zullen we de belangrijkste kenmerken beschrijven die patroonlay-out biedt. Conversiepatroon heeft betrekking op het conversiepatroon dat printf in de C-taal biedt. Over het algemeen bestaat het conversiepatroon uit letterlijke tekst en opmaakbesturingsuitdrukkingen genaamd conversiespecificators. De onderstaande figuur toont uit welke delen het conversiepatroon bestaat: Deze figuur hierboven is een poging om het Conversiepatroon te vereenvoudigen, maar het is beter om te verwijzen naar de documentatie van Apache Log4j2 voor meer details over Lay-outs en Patroonlay-out specifiek. Ook kunt u hierboven kijken voor loggebeurtenissen en telkens zien welk Conversiepatroon wordt gebruikt om de berichten te formatteren.

Welk Log4j2-niveau moet u gebruiken

De grootste vraag die u zichzelf kunt stellen is wanneer een specifiek Loggebeurtenisniveau moet worden gebruikt. In het ontwikkelingsveld is het normaal om DEBUG-loggebeurtenissen te gebruiken, terwijl we in productie INFO- of WARN-niveau moeten gebruiken. De onderstaande tabel moet u leiden bij welk log4j2-niveau moet worden gebruikt in welk geval.

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 Zelfstudie Samenvatting

Log4j2 is een vernieuwde versie van het Apache Logging-framework. Log4j2 heeft een reeks nieuwe functies en prestatieverbeteringen geleverd ten opzichte van Log4j1.x. Deze log4j2-zelfstudie is bedoeld om u alles op één locatie te helpen begrijpen. Aangezien sommige van deze concepten niet zo gemakkelijk zijn om in één keer te behandelen, hebben we besloten onze inspanningen te concentreren op het uitleggen van het concept en het gebruik van enkele voorbeelden voor verduidelijking. Appenders, Filters, layouts en lookups vallen onder deze regel. Enkele belangrijke punten Om ervoor te zorgen dat u de onderstaande toepassing kunt uitvoeren en eventuele obstakels kunt vermijden, controleer het volgende:

  • Uw Eclipse IDE is Maven-enabled.
  • Uw Apache Tomcat heeft een mysql-connector JAR in de lib-map van uw Apache Home.
  • U weet hoe u Maven moet gebruiken.

Download Apache Log4j 2 Voorbeeldproject

Dat is alles voor de log4j2-zelfstudie, ik hoop dat de meeste belangrijke punten zijn behandeld om u op weg te helpen met het gebruik van Log4j2 in uw toepassing.

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