Journalisation avec SLF4J

Date de publication : 20 Janvier 2010 , Date de mise à jour : 29 Janvier 2010

Par Baptiste Wicht (Mon site) (Blog)
 

Cet article va vous présenter SLF4J qui est une couche d'abstraction de journalisation. Cette API a plusieurs avantages qui seront présentés dans cet article ainsi que les différentes fonctionnalités de cette librairie.
Version anglophone - English Version : Logging with SLF4J.

              Version PDF (Miroir)  Version hors-ligne (Miroir)

I. Introduction
2. Sélection de l'implémentation de journalisation
3. Redirection des appels depuis d'autres implémentations
4. Utilisation de l'API
5. Les Marker
6. Accès au MDC
7. Conclusion
7.1. Remerciements


I. Introduction

SLF4J est une couche d'abstraction pour les API de journalisation Java. Le principe est à peu près similaire à celui de Jakarta Commons Logging. Les avantages de l'utilisation d'une telle couche d'abstraction permettent de s'abstraire de l'implémentation utilisée. Ainsi, il est possible de changer facilement d'implémentation de journalisation sans avoir à toucher la base de code. Au plus, la configuration de l'implémentation de journalisation doit être modifiée. Et enfin, dans le cas de la conception d'une librairie, cela permet de laisser à l'utilisateur de cette librairie le choix du système de journalisation.

Vous me direz : si Commons Logging fait déjà cela, pourquoi un autre framework d'abstraction de logging ? Tout simplement parce que Commons Logging a ses défauts. Le premier gros défaut de Commons Logging concerne le chargement de l'implémentation de journalisation. En effet, la recherche de l'implémentation se fait dynamiquement à l'implémentation via un système de classloader. Or cette méthode peut poser problèmes dans certaines situations, par exemple lorsque l'application utilise des classloaders personnalisés ou alors au sein d'une architecture OSGi. De plus, l'implémentation utilisée par Commons Logging peut causer des fuites mémoires.

En outre, Commons Logging nous contraint à tester si un niveau de log est activé ou non avant de faire des logs contenant des concaténations pouvant se révéler lourdes au long de l'application.

Nous allons voir que SLF4J permet de résoudre ces problèmes de manière efficace.

Vous pouvez télécharger la distribution officielle sur le site de SLFJ4J.


2. Sélection de l'implémentation de journalisation

Contrairement à Commons Logging, SLF4J ne résout pas l'implémentation de journalisation à l'exécution mais à la compilation à l'aide d'une API de bridging. En plus du JAR de l'API de SLF4J, il faut inclure les JAR suivants : celui qui fait office de pont entre SLF4J et l'implémentation et celui de l'implémentation utilisée. Voici ce que cela pourrait donner avec Log4J :

Sélection d'une implémentation
Sélection d'une implémentation
Tout cela effectué uniquement par l'ajout de JAR au classpath. Aucun besoin de configurer quoi que ce soit mise à part l'implémentation. Il faut cependant veiller à n'utiliser que l'interface de SLF4J sans quoi l'utilisation d'une couche d'abstraction n'a plus aucun intérêt.


3. Redirection des appels depuis d'autres implémentations

En plus de permettre une abstraction de la couche de journalisation, SLF4J offre également la possibilité de rediriger des appels à une implémentation vers SLF4j qui lui-même les redirigera vers l'implémentation choisie.

Pour cela, il suffit d'utiliser le JAR xxx-to-slf4j.jar qui va intercepter les appels de xxx pour les rediriger vers l'API SLF4J.

Le diagramme suivant montre exactement comment sont redirigés les appels :

Redirection des appels
Redirection des appels
warning Il faut bien entendu ne pas mettre dans le classpath le JAR de l'implémentation que vous voulez rediriger. Et plus important encore, il ne faut surtout pas utiliser la redirection d'une API tout en utilisant cette API comme implémentation de journalisation car cela créerait un cycle infini qui ferait planter votre programme à coup sûr.

4. Utilisation de l'API

L'API de SLF4J n'est pas très compliquée et ressemble beaucoup à celles des autres implémentations ou abstractions telles que Log4J ou Jakarta Commons Logging. Voici comment récupérer un logger :
org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(HelloWorld.class);
Ensuite, vous pouvez l'utiliser comme les autres implémentations à l'aide des méthodes debug(), info(), warn(), trace() et error(). Par exemple :
logger.info("Hello World");
Mais ce n'est pas là que réside la force de SLF4J. Prenons un exemple simple de logging :
logger.debug("Info : x = " + info.getX() + ", y = " + info.getY() + ", str = " + infos.getStr());
Cela veut dire qu'à chaque fois que cette ligne de code sera exécutée, une concaténation sera faite. Cela peut vite s'avérer être lourd si la méthode est exécutée de manière régulière. C'est pourquoi il faut préalablement tester si le niveau est activé :
if(logger.isDebugEnabled()){
	logger.debug("Info : x = " + info.getX() + ", y = " + info.getY() + ", str = " + infos.getStr());
}
Cette fois, les performances sont garanties, mais ce genre de code n'est pas du tout esthétique et devient rapidement lourd. D'autant plus que le test est déjà fait dans la méthode debug qui n'affichera rien si le niveau n'est pas activé. Alors pourquoi faire le travail deux fois ? SLF4J propose donc une nouvelle alternative assez équivalente à la méthode printf de Java :
logger.debug("Info : x = {}, y = {}, str = {}", new Object[]{info.getX(), info.getY(), infos.getStr()});
Les {} vont être remplacés par les valeurs passées en paramètres. Ainsi, la concaténation va se faire uniquement si le niveau de log est activé. De plus, esthétiquement, ce code est beaucoup plus propre que les deux précédents.

warning Dans le cas où la récupération des informations à journaliser serait lourde, il faudrait néanmoins utiliser la première technique consistant à tester si le niveau de log est activé avant de faire la journalisation. Par exemple, nous pourrions imaginer une méthode getDebugInfos() sur un objet qui fait beaucoup d'opérations pour récupérer des informations. Cette méthode ne doit pas être exécutée si le niveau de log n'est pas activé.

5. Les Marker

Les Marker permettent essentiellement d'associer des tags à des logs. Ces tags permettent ensuite aux différents appenders de prendre en charge différemment certains logs. Imaginons par exemple un appender qui écrirait de manière cryptée les données et qui ne devrait être utilisé que sur les données markées comme confidentielles. Les Marker vont nous permettre d'implémenter une telle chose.

Cette fonctionnalité n'est accessible qu'avec l'implémentation LogBack : il s'agit en effet de la seule qui implémente les Marker. Néanmoins, vous pourrez utiliser les Marker avec les autres implémentations, bien que cela n'aura aucun effet.

Imaginons par exemple un appender nommé CryptAppender qui encode le log selon un algorithme quelconque. Nous pourrions le configurer ainsi :
<appender name="CRYPTED" class="CryptAppender">
  <layout class="ch.qos.logback.classic.html.HTMLLayout">
    <pattern>%date%-5level%logger%msg</pattern>
    <throwableRenderer class="ch.qos.logback.classic.html.DefaultThrowableRenderer" />
  </layout>
  <evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
    <marker>CONFIDENTIAL</marker>
  </evaluator>
</appender>
Le OnMarkerEvaluator permet de ne sélectionner que les logs ayant été markés avec un certain tag. Dans notre cas, il faut marker les logs confidentiels avec CONFIDENTIAL. Voici comment procéder :
Marker confidentialMarker = MarkerFactory.getMarker("CONFIDENTIAL");
logger.error(confidentialMarker, "C'est confidentiel !");
Cela n'affichera donc pas le log directement, mais le log de manière cryptée.

Une autre utilisation de cette fonctionnalité pourrait, par exemple, concerner l'envoi par email de certains logs.
Vous pouvez bien entendu configurer plusieurs appenders pour le même tag. Vous pouvez également créer une hiérarchie de Marker.
Marker parentMarker = MarkerFactory.getMarker(“parent”);
Marker childMarker = MarkerFactory.getMarker(“child”);

parentMarker.add(childMarker);
Ce faisant, tout ce qui est journalisé avec parentMarker ou childMarker sera traité dans les appenders configurés pour parent tandis que les appenders configurés pour child ne verront que ce qui est journalisé avec child.


6. Accès au MDC

Le "Mapped Diagnostic Context" (MDC) est, en résumé, une simple map (ensemble clés-valeurs) maintenue par le framework de journalisation dans laquelle l'application peut insérer des couples clés-valeurs qui pourront ensuite être utilisés pour ajouter des informations dans le système de log.

Imaginons que nous traitons des informations sur des personnes et que nous les affichons en logging. Le nom et le prénom de la personne devront être affichés sur chacune des lignes de logging. Nous pourrions automatiser l'inclusion du nom et du prénom dans les logs avec MDC.

Il est possible d'ajouter des valeurs dans le MDC avec la méthode put :
MDC.put("prenom", "Baptiste");
MDC.put("nom", "Wicht");
Ensuite, il faut les prendre en compte dans le layout de journalisation. Ce layout se configure au niveau de l'implémentation qui doit supporter MDC. Les implémentations qui supportent MDC sont Log4J, JUL et Logback. Voici un layout prenant en compte MDC :
%X{prenom} %X{nom} - %m%n
Désormais pour afficher des informations, il suffit de faire :
logger.info("Age {}", age);
logger.info("Localisation {}", localisation);
Ce qui pourrait donner :
Baptiste Wicht - Age 22
Baptiste Wicht - Localisation Suisse
Enfin, si le MDC est modifié entre 2 instructions de logging, cela va directement changer la journalisation :
logger.info("Age {}", age);
MDC.put("prenom", "Jacques");
logger.info("Localisation {}", localisation);
affichera :
Baptiste Wicht - Age 22
Jacques Wicht - Localisation Suisse
Cela peut donc se révéler très pratique pour stocker et afficher des informations globales à l'application. Par exemple un login, un id de session ou n'importe quelle autre donnée.


7. Conclusion

En conclusion, SLF4J se révèle être une très bonne couche d'abstraction de journalisation. Elle se révèle très puissante, tout en étant très simple à utiliser et restant dans le même style que les autres systèmes de journalisation existants.

L'auteur de SLF4J conseille d'utiliser l'implémentation de journalisation LogBack qui est l'implémentation de référence de SLF4J.

Si vous avez des commentaires sur cet article, n'hésitez pas à vous exprimer sur le forum : 10 commentaires Donner une note à l'article (4.5)
Ou alors directement sur le site avec le formulaire de commentaire au bas de cette page.


7.1. Remerciements

Un grand merci à eusebe19 et à Wachter pour leur correction orthographique.



              Version PDF (Miroir)  Version hors-ligne (Miroir)






Java

   Création d'un système de mise à jour en Java
   Création d'éxécutables en Java
   Utilisation d'une base de données embarquée HSQLDB
   Les librairies d'Apache Software Foundation
   Implémentation du pattern MVC
   Les mots réservés du langage Java
   Améliorez l'intégration au système de votre programme Java
   Bien débuter en Java
   Développer une application modulaire en Java
   Créer un site avec Maven 2
   Développer une application modulaire avec JTheque Core
   Installer l'environnement JR sous Windows
   Introduction au langage JR

Swing

   Vos premiers pas dans la création d'interfaces graphiques avec Swing
   Gestion du focus dans vos applications Swing
   Création interface graphique avec Swing : les tableaux (JTable)

Eclipse

   Découverte de WOJ pour Eclipse
   Utilisation de Subversion avec Eclipse
   Calculer les métriques de vos projets avec Metrics

PHP

   Utilisation du DOM en PHP 4 et 5 pour la création d'un fil RSS
   Implémenter le Full Loading sur Zend Framework

SQL

   Débuter en SQL

SQL-Server

   Les procédures et les fonctions avec MS-SQL Server
   Gestion des transactions avec SQL-Server
   Le type DATETIME de SQL-Server

Windows

   Découverte d'IE7 Pro
   Accélérer le démarrage de Windows XP avec Microsoft Bootvis

Outils

   Présentation d'IntelliJ Idea 6.0m, la rolls des EDI Java
   Présentation et utilisation de Launch4j
   Présentation et utilisation de Exe4J
   Présentation et utilisation de JSmooth
   Présentation et utilisation de JExeCreator
   Installer Code::Blocks sous Windows XP et Vista
   Revue de l'IDE Jetbrains Intellij Idea 9 Ultimate Edition

Hardware

   Introduction au réseau
   Comprendre la séquence de démarrage d'un PC
   Quelques conseils pour bien choisir vos disques durs
   Quelques conseils pour bien choisir votre boitier
   Quelques conseils pour bien choisir votre alimentation
   Quelques conseils pour bien choisir vos barrettes mémoire
   Quelques conseils pour bien choisir votre écran
   Quelques conseils pour bien choisir votre carte graphique
   Quelques conseils pour bien choisir une carte mère pour votre PC
   Présentation et test de la souris Logitech MX1000
   Présentation et test du clavier Microsoft Reclusa
   Présentation et test de la webcam Microsoft LifeCam VX7000
   Présentation et test du set clavier/souris Microsoft Wireless Entertainment Desktop 8000
   Présentation et test de la souris Microsoft Wireless Laser Mouse 7000

VBS

   Créer un nouveau format d'entrée pour LogParser en VBScript
   Manipuler des fichiers XML en VBScript avec XPath

Tools

   Review of Jetbrains Intellij Idea 9 Ultimate Edition

Swing

   Creation of Swing User Interface : Tables (JTable)

Java

   Install the JR environment on Windows
   Introduction to JR programming language
   Develop a modular application with JTheque Core 2.0.3

Web

   Développer une communauté autour de votre site avec Google Friend Connect
   Analyser l'audience de votre site web avec Google Analytics




Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2009 Baptiste Wicht. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Cette page est déposée.

 
 
 
 
Partenaires

Hébergement Web