Tutoriel d’exemple Log4j2 – Configuration, Niveaux, Appendices

Bienvenue dans le Tutoriel d’Exemple Apache Log4j2. Si vous demandez à un développeur expert la chose la plus ennuyeuse à propos d’une application, la réponse pourrait être liée au journalisation. S’il n’y a pas de journalisation appropriée dans une application, la maintenance deviendra un cauchemar. La plupart des applications passent par les tests de développement, les tests unitaires, les tests d’intégration. Mais lorsqu’il s’agit de production, vous rencontrerez toujours des scénarios uniques et des exceptions. Donc, le seul moyen de comprendre ce qui s’est passé dans un cas spécifique est de déboguer à travers les journaux. De nombreux frameworks fournissent une certaine forme de journalisation par défaut, mais il est toujours préférable d’opter pour un mécanisme de journalisation standard de l’industrie. Apache Log4j est l’un des frameworks de journalisation les plus largement utilisés. Apache Log4j 2 est la version suivante, qui est bien meilleure que Log4j.

Tutoriel d’Exemple Log4j

Dans ce Tutoriel d’Exemple Log4j2, vous apprendrez comment démarrer avec Apache Log4j2. Nous explorerons également l’architecture de Log4j2, la configuration de Log4j2, les niveaux de journalisation de Log4j2, les appenders, les filtres et bien plus encore.

  1. Aperçu de Log4j2
  2. Architecture de Log4j2
  3. Configuration de Log4j2
  4. Niveaux de Log4j2
  5. Recherches de Log4j2
  6. Appenders de Log4j2
  7. Filtres de Log4j2
  8. Dispositions de Log4j2
  9. Quel niveau de Log4j2 devriez-vous utiliser
  10. Résumé du Tutoriel Log4j2

Aperçu de Log4j2

L’utilisation de l’API de journalisation dans une application n’est pas un luxe, c’est une nécessité. Log4j est une bibliothèque open source publiée et sous licence de Apache Software. Vous pouvez déboguer une application à l’aide du débogage Eclipse ou d’autres outils, mais cela n’est pas suffisant et réalisable dans un environnement de production. Le mécanisme de journalisation vous fournira plusieurs avantages que vous ne trouverez pas dans le débogage normal.

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

Comme vous pouvez le voir ci-dessus, l’utilisation du mécanisme de journalisation sera plus efficace avec moins de coûts de maintenance. Apache Log4j est l’outil de premier plan pour la journalisation dans les applications Java, vous devriez donc l’utiliser.

Architecture de Log4j2

Avant de procéder au tutoriel de l’exemple Log4j, il est bon de se pencher sur l’architecture de Log4j2. L’image ci-dessous montre les classes importantes dans l’API Log4j2. Voici l’explication détaillée de l’architecture présentée ci-dessus :

  • Les applications demanderont à LogManager un Logger avec un nom spécifique.

  • LogManager localisera le LoggerContext approprié puis obtiendra le Logger à partir de celui-ci.

  • Si le Logger n’est pas encore créé, il sera créé et associé à LoggerConfig selon trois choix ci-dessous:

    1. L’instance du Logger sera créée et associée au LoggerConfig qui a le même nom. Par exemple, la classe App dans getLogger(App.class) sera évaluée pour être une chaîne com.journaldev.App. Le nom de LoggerConfig est identique au nom de classe entièrement qualifié (composant logiciel).
    2. L’instance du Logger sera créée et associée au LoggerConfig qui a le même package parent que le Logger. Par exemple, com.journaldev dans getLogger("com.journaldev")
    3. L’instance du Logger sera créée et associée au LoggerConfig Racine. LoggerConfig Racine sera utilisé lorsqu’il n’y a pas de fichier de configuration ou lorsque vous obtenez un journaliseur avec un nom non défini dans les déclarations de journalisation.
  • Les objets LoggerConfig sont créés à partir de la déclaration du journalisateur dans le fichier de configuration. LoggerConfig est également utilisé pour gérer les LogEvents et les déléguer à leurs appenders Log4j2 définis.

  • Le journalisateur racine est un cas exceptionnel en termes d’existence. Il existe toujours et est en haut de n’importe quelle hiérarchie de journalisateurs.

  • Vous pouvez obtenir le journalisateur racine en utilisant les instructions suivantes :

    Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
    Logger logger = LogManager.getRootLogger();
    
  • Le nom des journalisateurs log4j2 est sensible à la casse.

  • Sauf pour le journalisateur racine, tous les journalisateurs peuvent être obtenus en passant leur nom à LogManager.getLogger().

  • Le contexte du journal est un point central du système de journalisation car vous pouvez avoir plusieurs contextes de journalisation dans votre application. Pour chaque contexte de journalisation, une configuration active doit être définie.

  • La configuration de Log4j2 contient tous les éléments du système de journalisation; les configurations du journal, les appendices, les filtres et bien d’autres.

  • Appeler LogManager.getLogger() en passant le même nom renverra toujours la référence à la même instance de journal exacte.

  • La configuration du système de journalisation est généralement effectuée lors de l’initialisation de l’application. Cela peut prendre différentes formes ; de manière programmatique ou en lisant un fichier de configuration log4j2.

Chaque enregistreur est associé à un objet LoggerConfig, un ensemble d’objets LoggerConfig constitue une hiérarchie de journaux. Ce concept est connu sous le nom de Hiérarchie des journaux. Hiérarchie des journaux est constituée d’un ensemble d’objets LoggerConfig avec une relation parent-enfant. L’élément le plus haut dans chaque hiérarchie de journaux est le journal racine. Si Log4j2 ne trouve pas le fichier de configuration, seul le journal racine sera utilisé pour le journal avec le niveau de journalisation ERROR. L’image ci-dessous montre le message d’avertissement que vous obtiendrez dans ce cas. Statut d’erreur du journal No log4j2 trouvé. Utilisation de la configuration par défaut : journalisation uniquement des erreurs vers la console. Le tableau ci-dessous montre la relation parent-enfant dans la hiérarchie des journaux.

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

Pour clarifier la relation parent-enfant, le tableau ci-dessus serait lu comme suit :

  • Racine est un parent pour com.
  • Racine est un ancêtre pour com.journaldev.
  • Racine est un ancêtre pour com.journaldev.logging.
  • com est un enfant pour Racine.
  • com est un parent pour com.journaldev.
  • com est un ancêtre pour com.journaldev.logging.
  • com.journaldev.logging est un enfant pour com.journaldev et ainsi de suite.

Une instance de LoggerConfig est considérée comme un ancêtre d’une autre LoggerConfig si son nom suivi d’un point est un préfixe du nom du descendant. Une instance de LoggerConfig est considérée comme un parent pour une autre LoggerConfig s’il n’y a pas de noms intercalés entre les deux.

Configuration de Log4j2

Il existe de nombreuses façons d’utiliser la configuration de Log4j2 dans votre application.

  1. En utilisant un fichier de configuration écrit en XML, JSON, YAML ou fichier de propriétés.
  2. Programmatiquement, en créant une fabrique de configuration et une implémentation de configuration.
  3. Programmatiquement, en appelant les API exposées dans l’interface de configuration.
  4. Programmatiquement, en appelant des méthodes sur la classe de journal interne.

Nous nous concentrerons principalement sur le fichier de configuration. Cependant, il est bon de connaître également l’approche de programmation, au cas où vous voudriez configurer une stratégie de journalisation spécifique pour un Logger spécifique. Tout d’abord, considérons le cas où vous n’avez pas fourni de fichier de configuration. L’implémentation de Log4j2 suppose qu’il existe une variable système appelée log4j.configurationFile pour indiquer l’emplacement du fichier de configuration de log4j2.

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>

Et voici l’explication détaillée du code répertorié ci-dessus:

  • L’application a référencé le journal Root en appelant la méthode getRootLogger de LogManager.
  • La référence au journal à partir de LogManager a démarré le système Log4j.
  • Log4j inspectera la propriété système log4j.configurationFile pour déterminer le fichier de configuration log4j2. La configuration de Log4j peut être écrite en JSON, YAML et XML.
  • On peut définir la propriété système log4j.configurationFile en utilisant System.setProperties("log4j.configurationFile","CHEMIN_DU_FICHIER") ou en le passant comme paramètre JVM comme vous le voyez dans la figure ci-dessous. Remarquez également le préfixe du protocole de fichier.

  • Au cas où aucune propriété système n’est définie, l’ordre de configuration prend la priorité suivante :
    • La ConfigurationFactory des propriétés recherchera log4j2-test.properties dans le classpath.
    • La ConfigurationFactory YAML recherchera log4j2-test.yaml ou log4j2-test.yml dans le classpath.
    • La ConfigurationFactory JSON recherchera log4j2-test.jsn ou log4j2-test.json dans le classpath.
    • La ConfigurationFactory XML recherchera log4j2-test.xml dans le classpath.
    • La ConfigurationFactory des propriétés recherchera log4j2.properties dans le classpath
    • La ConfigurationFactory YAML recherchera log4j2.yml ou log4j2.yaml dans le classpath.
    • La ConfigurationFactory JSON recherchera log4j2.jsn ou log4j2.json dans le classpath.
    • La ConfigurationFactory XML recherchera log4j2.xml dans le classpath.
    • Si aucun fichier de configuration n’a été fourni, la DefaultConfiguration est utilisée et cela entraînerait un ensemble de comportements par défaut :
      • Le journal racine sera utilisé.
      • Le niveau du journal racine sera défini sur ERROR.
      • Le journal racine propagera les messages de journalisation dans la console.
      • PatternLayout est défini comme %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n

L’utilisation d’un fichier de configuration log4j2 rend la configuration de log4j2 si simple, mais voyons comment nous pouvons le configurer de manière programmatique. C’est tout à propos de l’utilisation de 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 {
 
    	// Obtenir une instance de la fabrique de configuration; vos options sont la ConfigurationFactory par défaut, XMLConfigurationFactory,
    	// YamlConfigurationFactory & JsonConfigurationFactory
    	ConfigurationFactory factory =  XmlConfigurationFactory.getInstance();
 
    	// Localisez la source de cette configuration, ce fichier localisé est un fichier fictif contenant juste une balise de configuration vide
    	ConfigurationSource configurationSource = new ConfigurationSource(new FileInputStream(new File("C:/dummyConfiguration.xml")));
 
    	// Obtenir une référence de la configuration
    	Configuration configuration = factory.getConfiguration(configurationSource);
 
    	// Créer un appendeur console par défaut
    	ConsoleAppender appender = ConsoleAppender.createDefaultAppenderForLayout(PatternLayout.createDefaultLayout());
 
    	// Ajouter l'appendeur console à la configuration
    	configuration.addAppender(appender);
 
    	// Créer LoggerConfig
    	LoggerConfig loggerConfig = new LoggerConfig("com",Level.FATAL,false);
 
    	// Ajouter l'appendeur
    	loggerConfig.addAppender(appender,null,null);
 
    	// Ajouter le journaliseur et l'associer à l'instance de LoggerConfig
    	configuration.addLogger("com", loggerConfig);
 
    	// Obtenir une instance de contexte
    	LoggerContext context = new LoggerContext("JournalDevLoggerContext");
 
    	// Démarrer le système de journalisation
    	context.start(configuration);
 
    	// Obtenir une référence pour le journaliseur
    	Logger logger = context.getLogger("com");
 
    	// Événement de journalisation du message DEBUG
    	logger.log(Level.FATAL, "Logger Name :: "+logger.getName()+" :: Passed Message ::");
 
    	// Événement de journalisation du message d'erreur pour le journaliseur configuré en FATAL
    	logger.log(Level.ERROR, "Logger Name :: "+logger.getName()+" :: Not Passed Message ::");
 
    	// Événement de journalisation du message d'erreur qui sera géré par la racine
    	logger.getParent().log(Level.ERROR, "Root Logger :: Passed Message As Root Is Configured For ERROR Level messages");
    }
}
  • Vous pouvez utiliser n’importe quelle ConfigurationFactory fournie par Log4j2 ou utiliser celle par défaut. Nous avons utilisé XMLConfigurationFactory pour obtenir une instance de ConfigurationFactory.
  • La fabrique vous donnera une instance de la référence de Configuration requise en passant le fichier de configuration correspondant.
  • L’instance de configuration sera utilisée en conjonction avec LoggerContext pour démarrer le système de journalisation.
  • A console Appender has been configured and added into configuration instance with default layout. This Appender would print out messages into your console.
  • Une instance de LoggerConfig a été créée avec le nom, le NIVEAU fournis et sans filtre utilisé. L’appendeur créé sera assigné à cette instance de LoggerConfig.
  • L’instance de LoggerConfig ajoutée à l’instance de configuration.
  • A new instance of LoggerContext is created with defined name.
  • L’instance de configuration a été passée pour l’instance de LoggerContext, puis a été invoquée par cette dernière.
  • A logger instance has been acquired from LoggerContext. This logger instance will be used to fire set of Log events.
  • L’instance de Logger a déclenché trois événements qui seront expliqués dans la section Niveaux de Log4j2.
  • Le journal com est configuré pour imprimer les messages dont les niveaux sont FATAL.
  • Par défaut, le journal Root est configuré pour imprimer les messages dont le niveau est ERROR.
  • Les messages ERROR ne seront pas enregistrés par le journal ‘com’ car son niveau est FATAL.

La même configuration peut être réalisée en utilisant un fichier YAML, JSON ou properties. Cependant, la configuration du fichier de propriétés de log4j2 est différente de celle du fichier de propriétés de log4j, donc assurez-vous de ne pas essayer d’utiliser la configuration du fichier de propriétés de log4j avec log4j2. Cela générera l’erreur suivante ;

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

En traitant le code ci-dessus, vous obtiendrez la sortie suivante :

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

La première ligne des journaux provient du journal com et la seconde vient du Journal Racine. Le message d’erreur du journal com n’est pas imprimé car son niveau est Fatal.

Niveaux de Log4j2

Vous pouvez voir dans les exemples de code ci-dessus que chaque fois que nous définissons une LoggerConfig, nous fournissons également le niveau de journalisation. Par défaut, la journalisation de log4j2 est additive. Cela signifie que tous les loggers parents seront également utilisés lorsque un logger spécifique est utilisé. L’image ci-dessous clarifie cette situation. Et voici les points de clarification à ce sujet:

  • Comme nous l’avons déjà indiqué, chaque logger est associé à une instance de LoggerConfig. Ce loggerConfig a été défini au niveau de configuration.
  • Le niveau de journalisation peut être déterminé au niveau de LoggerConfig.
  • Vous pouvez obtenir le logger par son nom, le package parent ou en pointant directement vers le Root Logger lui-même.
  • Le Root Logger est le nœud de niveau supérieur pour chaque hiérarchie de LoggerConfig.
  • Une fois que vous obtenez le logger com.journaldev et que vous lancez un logEvent pour le journal, le loggerConfig (net.journaldev) enregistrera le message et le message sera propagé également dans la hiérarchie sans tenir compte des niveaux de journalisation des parents. Ainsi, l’événement de journalisation sera propagé aux loggers com et Root et ils enregistreront également le message respectivement selon les niveaux définis.
  • Une fois que vous obtenez le logger com et que vous lancez un logEvent pour le journal, le loggerConfig(com) enregistrera le message et le message sera propagé également dans la hiérarchie sans tenir compte des niveaux de journalisation des parents. Autrement dit, le Root logger propagera l’événement de journalisation et enregistrera également le message.
  • Le même cas pour la hiérarchie net.journaldev.
  • Les sections suivantes ajouteront plus de clarifications pour le concept additif.
  • Il existe une possibilité pour le parent d’ignorer le message en utilisant le concept de filtre ou en définissant l’indicateur additif sur faux, de sorte que les événements de journalisation ne seront pas propagés aux parents.
  • Il existe une possibilité pour le journalisateur d’ignorer le message si le niveau de configuration du journalisateur respectif est SUPÉRIEUR AU niveau des événements de journalisation.

Maintenant, voyons l’exemple associé au concept d’additivité expliqué ci-dessus:

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

Alors que le fichier de configuration de log4j2 ressemble à ceci:

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

Si vous exécutez la classe principale, vous obtiendrez les résultats suivants:

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

Voici ci-dessous une explication détaillée du code répertorié ci-dessus:

  • Le fichier de configuration contient cinq instances de loggerConfig définies et ce sont Root, com, com.journaldev, net et net.journaldev. Tout comme la hiérarchie des enregistreurs indiquée ci-dessus.
  • Le niveau de Root est configuré pour être ERROR et c’est en fait la valeur par défaut.
  • Les niveaux de com et com.journaldev sont configurés pour être TRACE.
  • Les niveaux de net et net.journaldev sont configurés pour être ERROR.
  • Vous avez peut-être remarqué que les messages des enregistreurs ComAPP et ComJournalDevApp ont été affichés deux et trois fois respectivement. Ces messages sont affichés selon la hiérarchie des enregistreurs pour ComApp et ComJournalDevApp où ils se trouvent respectivement dans les packages com et com.journalDev. Nous avons un cas similaire avec les classes NetApp et NetJournalDevApp.
  • Les parents sont propagés car l’indicateur additif est défini sur vrai par défaut.

L’espace de journalisation prend en considération les niveaux des événements de journalisation et le niveau de configuration du journalisateur en plus de la hiérarchie des journalisateurs.

Alors que se passerait-il si nous changions la configuration du journalisateur pour com en INFO et laissions le programme tel quel:

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

Le résultat serait alors le suivant:

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 ::
  • Vous remarquerez sûrement que l’événement de journalisation ComAPP a été ignoré, et cela est dû au niveau défini dans la configuration du journalisateur pour le package com. Le niveau INFO (400) est inférieur au niveau de l’événement de journalisation, qui est ici TRACE (600). Ainsi, le message de ComApp ne sera plus affiché, et pour le voir, vous devez modifier le niveau de la configuration du journalisateur pour com en TRACE (600) ou ALL (Integer.MAX_VALUE).

Pour s’assurer que les événements de journalisation sont affichés, le niveau de configuration du journalisateur doit être supérieur ou égal au niveau de l’événement de journalisation.

Le tableau ci-dessous vous montre les niveaux de log4j2 et leur poids respectif:

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

Le tableau ci-dessus clarifie certainement beaucoup plus que des mots et vous donne la principale raison pour laquelle l’événement de journalisation TRACE n’est pas affiché lorsque le niveau de configuration du journalisateur est INFO.

Notez que la propagation des événements de journalisation dans la hiérarchie des journalisateurs va au-delà de ce calcul et ignore les niveaux.

Mais que se passe-t-il si nous supprimons la configuration du journalisateur pour com.journaldev du fichier de configuration et en ajoutons une nouvelle pour com.journaldev.logging, de sorte que le fichier de configuration ressemble à ceci :

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

Vous pouvez trouver ci-dessous une figure qui vous aidera à comprendre ce qui s’est passé dans la configuration log4j2 ci-dessus. Voici quelques clarifications sur la figure ci-dessus et comment cela peut affecter le comportement des événements de journalisation :

  • Lorsque des événements de journalisation sont lancés par un Logger nommé com.journaldev.logging, le LoggerConfig associé à ce nom (c’est-à-dire com.journaldev.logging) a été utilisé pour le gérer et afficher le message.
  • Comme l’attribut additif du LoggerConfig com.journaldev.logging est défini par défaut sur true, l’événement de journalisation a été propagé au parent, qui dans ce cas fait référence à com.journaldev.
  • Comme le LoggerConfig com.journaldev n’est pas défini dans la configuration, aucune action n’est entreprise et l’événement de journalisation sera propagé jusqu’à com, puis aux instances de LoggerConfig Root.
  • Com et Root recevront l’événement de journalisation et l’afficheront quel que soit le niveau auquel il a été envoyé.

En conséquence des points mentionnés, vous verriez les sorties suivantes :

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

Et vous pouvez remarquer ce qui suit :

  • L’événement de journalisation dans le package com est affiché deux fois. Une fois pour com et une fois pour Root.
  • Un événement de journalisation à com.journaldev a été affiché deux fois. Une fois pour com et une deuxième fois pour Root. Même s’il a été affiché trois fois auparavant, actuellement la LoggerConfig de com.journaldev est absente et donc aucune journalisation n’a pu se produire dans le package com.journaldev et l’événement serait propagé pour com et Root.
  • Un événement de journalisation à com.journaldev.logging a été affiché trois fois, une fois pour le package com.journaldev.logging, une deuxième fois pour com et une troisième fois pour Root. Selon la propagation de la hiérarchie des loggers, il devrait être affiché quatre fois, mais en raison de l’absence de LoggerConfig com.jounraldev, il est affiché trois fois.

Si vous avez défini une instance LoggerConfig com.journaldev sans spécifier de niveau, elle héritera du niveau de son parent.

Mais que se passe-t-il si vous avez défini LoggerConfig com.journaldev dans votre fichier de configuration et omis de spécifier le niveau du LoggerConfig. Heureusement, le concept de hiérarchie des loggers vous sauvera ici et com.journaldev héritera de sa valeur de niveau de son parent. Ci-dessous se trouve un exemple de fichier de configuration suivi du tableau des niveaux de journalisation de chaque configuration de logger.

<?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
  • Le package com.journaldev.logging est déjà associé à une LoggerConfig avec le niveau de journal TRACE.
  • Le package com.journaldev est déjà associé à une LoggerConfig sans niveau de journalisation spécifié, il héritera donc du niveau de journalisation de son parent et la valeur sera certainement TRACE pour le package com.
  • Le package com est déjà associé à une LoggerConfig avec un niveau de journalisation TRACE.
  • Par défaut, Root a ERROR comme niveau de journalisation.
  • Si le package com n’est pas déclaré, la LoggerConfig de com.journaldev héritera du niveau de journalisation de Root.

Ci-dessous est le résultat de l’exécution lorsque com.journaldev hérite du niveau de journalisation com :

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

Et ci-dessous est le résultat si vous supprimez la déclaration LoggerConfig pour le package com :

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

Vous remarquerez qu’aucun message n’a été journalisé pour com et com.journaldev, voici les raisons.

  • La suppression de LoggerConfig associé au package com rendra tous les événements de journalisation mentionnés dans ce package ignorés.
  • Puisqu’aucune LoggerConfig n’est définie pour le package com dans la configuration, LoggerConfig associé à com.journaldev héritera du niveau de journalisation de son parent. Com n’est pas défini, et la hiérarchie des enregistreurs atteint le sommet et se réfère maintenant à Root. Le niveau de journalisation de base est ERROR(200) et le niveau de l’événement de journalisation dans com.journaldev est TRACE(600) – Voir ComJournalDevApp – et selon l’équation précédemment définie, le niveau de LoggerConfig doit être supérieur ou égal au niveau de l’événement de journalisation et ce n’est pas le cas, donc aucun message ne serait affiché ici pour com.journaldev.

Enfin, mais non des moindres, le tableau ci-dessous montre tous les scénarios de journalisation possibles auxquels vous pourriez être confronté lors de l’utilisation du système de journalisation :

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
  • Il n’y a pas de méthode directe qui peut être utilisée pour envoyer des événements de journalisation OFF/ALL.
  • Principalement, pour envoyer des événements de journalisation OFF/ALL, vous pouvez utiliser logger.log(Level.OFF, “Msg”) ou logger.log(LEVEL.ALL,“Msg”), respectivement.
  • La méthode de journalisation est responsable de gérer l’événement de journalisation selon l’équation mentionnée.

L’équation de gestion dit : Si le niveau de LoggerConfig est supérieur ou égal au niveau de l’événement de journalisation, l’événement sera accepté pour un traitement ultérieur.

L’événement de journalisation serait accepté pour un traitement ultérieur – c’est tellement important car vous avez la capacité d’empêcher certains événements d’être traités même s’ils sont acceptés en utilisant des filtres Log4j2. Vous pouvez définir la propriété additive sur false pour éviter la propagation des événements de journalisation aux journaux parents. Suivant le même exemple que celui que vous avez vu précédemment mais cette fois avec un attribut d’additivité, vous pouvez remarquer la différence.

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

Et le résultat de l’exécution serait comme ci-dessous:

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

Et vous pouvez remarquer qu’il n’y a pas de propagation des événements de journalisation vers les journaux parents.

Recherches Log4j2

Idéalement, vous pouvez définir des recherches comme un moyen de passer des valeurs pour votre fichier de configuration de journalisation. Log4j2 vous fournit un ensemble différent de recherches qui peuvent être utilisées indépendamment pour définir des valeurs à partir de différents contextes:

  • Recherche de Map de contexte
  • Recherche de date
  • Recherche d’environnement
  • Recherche Java
  • Recherche JNDI
  • Recherche d’argument d’entrée JVM (JMX)
  • Recherche d’arguments principaux
  • Recherche de carte
  • Recherche de données structurées
  • Recherche de propriétés système
  • Recherche Web

Vous pouvez consulter la documentation de Log4j2 pour plus de détails sur chaque type de recherche, mais examinons quelques exemples ici pour couvrir les bases de la recherche Log4j2. La Recherche d’Environnement représente la manière dont vous pouvez transmettre une valeur d’environnement (soit par Linux, etc/profile, les variables d’environnement système Windows ou les scripts de démarrage de l’application). Comme la plupart d’entre nous le savent, nous avons la possibilité de définir un ensemble de valeurs environnementales à utiliser par l’application. Voyons les façons les plus courantes de définir vos variables environnementales.

  1. Définir une variable d’environnement en utilisant les fonctionnalités d’environnement Windows :
    • Cliquez avec le bouton droit sur l’icône de votre ordinateur et sélectionnez Propriétés. Le panneau de configuration principal devrait s’afficher.
    • Cliquez sur Paramètres système avancés, puis ouvrez la fenêtre Variables d’environnement.
    • Sous la section Variables Système, définissez la variable JournalDevVar avec la valeur JournalDev.
    • Mise à jour du PatternLayout à l’intérieur de votre fichier log4j2.xml pour contenir votre variable nouvellement ajoutée.

  1. Définissez vos variables d’environnement en utilisant la fonction de script de démarrage.
    • Au lieu d’utiliser le script par défaut normal, vous pouvez utiliser la fonctionnalité de script en cours d’exécution de l’IDE Eclipse, cliquez sur votre menu Exécuter et choisissez Configuration d’exécution.
    • Naviguez jusqu’à l’onglet Environnement et définissez votre variable à l’intérieur.

Regardez maintenant le fichier log4j2.xml modifié et remarquez l’utilisation des variables d’environnement.

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

Et le résultat de l’exécution ressemblerait à ce qui suit:

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

Mais vous pourriez rencontrer un petit problème ici, surtout lorsque vous définissez les variables d’environnement d’un système d’exploitation, notamment le cache Eclipse. Idéalement, Eclipse met en cache toutes les variables système lors de son exécution et vous pouvez toutes les trouver sous Exécuter – Configuration d’exécution – Onglet Environnement – Cliquez sur le bouton Sélectionner. Vous pourriez donc être confus lorsque vous les avez définies mais que l’application ne les reconnaît pas. Même si vous redémarrez Eclipse, vous n’obtiendrez pas de solution et pour résoudre le problème, vous devez exécuter eclipse.exe -clean lors de l’installation d’Eclipse. Pour vous assurer que vos variables d’environnement sont correctement définies et que votre système va les trouver volontiers, vous pouvez utiliser le type de plugin de correspondance fourni par l’API Log4j2. Créez une instance de EnvironmentLookup et demandez-lui de rechercher certaines variables, et si elles sont définies, vous les trouverez facilement.

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

Log4j2 Appenders

Vous avez vu précédemment comment utiliser les Lookups pour injecter des variables dans votre fichier de configuration. Cependant, vous pouvez vouloir modifier le moyen par lequel vos messages sont transmis. Au lieu d’utiliser directement la console, vous pouvez utiliser un fichier ou un référentiel de base de données pour vous assurer que vos messages sont conservés de manière permanente. Log4j2 a fourni de nombreux Appenders, et vous pouvez consulter la documentation de Log4j2 pour obtenir plus de détails sur les Appenders. De manière concise, voici la liste de tous les Appenders Log4j2.

  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

Les médias les plus couramment utilisés pour journaliser les événements sont la console, le fichier et la base de données. Comme le fichier enregistrerait vos messages, la base de données pourrait être utilisée pour les auditer. À cette fin, cette section se concentrera sur l’efficacité d’utilisation de JDBCAppender.

JDBCAppender

L’objectif principal de JDBCAppender est d’écrire des événements de journal dans une table relationnelle via des connexions JDBC. Nous ne perdons pas beaucoup de temps à expliquer comment vous pouvez optimiser vos pools de connexions car ce tutoriel n’est pas destiné à cet usage. Mais vous obtiendrez certainement un exemple entièrement fonctionnel qui vous aidera à écrire vos événements de journal dans une base de données. Avant de continuer, examinons tous les paramètres nécessaires et une description de chacun pour configurer correctement JDBCAppender.

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.

Étant donné que vous êtes obligé d’utiliser JNDI, notre exemple configurera une source de données de connexion pour la base de données Oracle et Apache Tomcat 7.

  • Si vous n’avez pas installé la base de données Oracle dans votre environnement, il est apprécié si vous le faites. Si vous n’êtes pas très familier avec Oracle, je vous recommande d’installer sa Édition Express.
  • Installez Apache Tomcat 7 dans votre environnement.
  • Créez un projet Maven WebApp dans votre Eclipse.

  • Assurez-vous que votre projet est créé avec succès et si vous remarquez des erreurs dans le pom, assurez-vous de les corriger.
  • Ajoutez les dépendances Log4j2.
<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>
  • Configurez votre contexte pour inclure une déclaration de source de données MySQL. Selon la documentation d’Apache, ce fichier doit être à l’intérieur du dossier META-INF de votre application Web.

<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>
  • Configurez votre base de données et créez votre table de journalisation.

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;
  • Configurez votre fichier log4j2.xml comme ci-dessous :
<?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>
  • Créez une ressource Web qui vous permet d’obtenir une référence pour un journal et ensuite de journaliser un événement.
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 !");
	}
}
  • Vous pouvez éventuellement configurer un ServletContextListener qui garantit que l’initialisation de la source de données est effectuée correctement.
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 {
			 // Obtenez le contexte initial 
			context = new InitialContext();
			 // Obtenez une référence pour le sous-contexte env 
			Context envContext = (Context)context.lookup("java:comp/env");
			 // Obtenez une référence pour le sous-contexte jdbc puis localisez la source de données définie 
			LogManager.getRootLogger().error(((Context)envContext.lookup("jdbc")).lookup("JournalDevDB"));
		} catch (NamingException e) {
			LogManager.getRootLogger().error(e);
		}
	}
}
  • Définissez votre Servlet à l’intérieur de votre fichier web.xml.
  • Exécutez l’application et accédez au Servlet défini ci-dessus. Vous verrez les journaux ci-dessous.
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

Filtres Log4j2

Même s’il existe un candidat LoggerConfig pour gérer l’événement Log, vous pouvez le configurer pour refuser de transmettre les événements Log aux appendices en aval. Cela peut être fait par un filtre log4j2. Cette section n’est pas destinée à vous fournir un tutoriel envahissant, massif et énorme sur l’utilisation des filtres dans Log4j2, car ils nécessitent de nombreux articles couvrant chacun d’eux. Mais ici, vous verrez comment utiliser le filtre le plus simple pour comprendre le concept. Un des filtres les plus simples que vous pouvez utiliser est BurstFilter qui vous offre un mécanisme pour contrôler le taux auquel les événements Log sont traités en supprimant silencieusement les événements après que la limite maximale a été atteinte. Pour l’instant, vous pouvez voir ci-dessous tous les détails nécessaires pour utiliser BurstFilter.

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

Maintenant, regardez l’emplacement de BurstFilter à l’intérieur de votre Appender de base de données.

<?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>
  • Le Database Appender prend en compte BurstFilter tandis que le console Appender ne le fait pas.
  • L’utilisation du journal Console entraînerait l’enregistrement de tous les événements de journalisation, alors que le Database Appender ne le ferait pas car BurstFilter en refuserait certains.
  • Cette réduction des événements de journalisation est réalisée même si les Loggers utilisés sont candidats pour gérer les événements de journalisation. Cela est tout à fait logique comme le montre le JournalDevServlet ci-dessous.

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

Même si ces LoggerConfigs sont candidats pour gérer les événements de journalisation émis, le filtre a empêché certains d’entre eux d’être traités et ensuite enregistrés. Vous pouvez ajouter ceci pour le concept d’espace de journalisation afin de comprendre l’ensemble du concept de journalisation.

Dispositions Log4j2

En raison des différents appenders qui consomment des événements de journalisation et de la nature de chaque appender, les mises en page sont conçues pour former l’événement de journal dans le format qui répond aux besoins de celui qui va consommer l’événement de journal. Dans les API Log4j 1.x et Logback, la transformation de mise en page des événements de journal se faisait en une chaîne de caractères, tandis que les mises en page de Log4j2 ont envisagé une manière différente de transformation ; et c’est en transformant l’événement de journal en tableau d’octets. Ce nouveau type de transformation vous obligerait à configurer le Charset pour garantir que le tableau d’octets contient les valeurs correctes. Il est fortement recommandé de retourner sur le site officiel d’Apache Log4j2 et d’en savoir plus sur la Mise en page et les différents types que Log4j2 fournit. Dans cette section, nous considérerons la Mise en page la plus célèbre qui est toujours utilisée par la plupart de nos développeurs et que vous avez probablement entendu parler ; c’est la PatternLayout.

Mise en page de modèle Log4j2

La mise en forme du modèle est un motif de chaîne configurable et flexible destiné à formater le LogEvent. Ce type de mise en forme dépend du concept de motif de conversion. Cette section vous présentera les fonctionnalités les plus importantes fournies par la mise en forme du modèle. Le motif de conversion est lié au motif de conversion que printf fournit dans le langage C. Généralement, le motif de conversion est composé de texte littéral et d’ expressions de contrôle de format appelées spécificateurs de conversion. La figure ci-dessous vous montre de quels éléments est composé le motif de conversion : Cette figure ci-dessus est une tentative de simplification du motif de conversion, mais il est préférable de consulter la documentation Apache Log4j2 pour plus de détails sur les mises en page et en particulier sur la mise en forme du modèle. De plus, vous pouvez vous référer ci-dessus pour les événements de journalisation et voir à chaque fois quel motif de conversion est utilisé pour formater les messages.

Quel niveau Log4j2 devriez-vous utiliser

La plus grande question que vous pouvez vous poser est quand un niveau spécifique d’événement de journalisation doit être utilisé. Dans le domaine du développement, il est normal d’utiliser l’événement de journalisation DEBUG alors que dans la production nous devrions utiliser le niveau INFO ou WARN. Le tableau ci-dessous devrait vous guider sur le niveau log4j2 à utiliser dans chaque cas.

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

Résumé du Tutoriel Log4j2

Log4j2 est une version revue du framework de journalisation Apache. Log4j2 a introduit un ensemble de nouvelles fonctionnalités et améliorations de performances par rapport à Log4j1.x. Ce tutoriel sur log4j2 vise à vous aider à tout comprendre en un seul endroit. Étant donné que certains de ces concepts ne sont pas si faciles à couvrir tous en une fois, nous avons décidé de concentrer nos efforts sur l’explication du concept et l’utilisation de quelques exemples pour une meilleure clarification. Les appendices, les filtres, les mises en forme et les recherches sont soumis à cette règle. Quelques points importants Pour vous assurer que vous êtes en mesure de faire fonctionner l’application ci-dessous et d’éviter tout obstacle, vérifiez ce qui suit :

  • Votre IDE Eclipse est activé pour Maven.
  • Votre Apache Tomcat a un fichier JAR mysql-connector dans le dossier lib de votre dossier Apache Home.
  • Vous savez comment utiliser Maven.

Téléchargez le Projet d’Exemple Apache Log4j 2

C’est tout pour le tutoriel log4j2, j’espère que la plupart des points importants sont couverts pour vous aider à commencer à utiliser Log4j2 dans votre application.

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