Accès rapide :
La vidéo
Introduction à la journalisation en Java
Les principales APIs de journalisation
Les meta-API de journalisation
Hibernate et la journalisation
Configuration de Log4J 2
La notion d'appender
Activer/désactiver des logs
Quelques loggeurs importants pour Hibernate
Travaux Pratiques
Un moteur de persistance JPA produit une grande quantité de logs (on parle de journalisation) : c'est aussi le cas d'Hibernate. Cette vidéo vous montre comment contrôler les logs produits. Cela peut être très utile pour vérifier les ordres SQL produits par votre ORM.
La journalisation (produire des logs) avec Java est relativement complexe, étant donné le nombre d'APIs de logging disponible. Commençons par débroussailler le sujet.
Historiquement parlant, la première API de log proposée en Java fut « Log4J ». Elle existe depuis 2001.
Avant elle, on se contentait de faire des System.out.println
: le problème de cette technique est qu'on peut difficilement
débrailler l'affichage de certains messages et qu'il n'y avait pas de notion de prioritarisation de messages.
Log4J ayant notamment répondu à ces problèmes, elle connut rapidement un très grand succès, à tel point qu'on peut dire qu'aujourd'hui c'est encore
la principale API de Log.
Aujourd'hui la version de Log4J est supérieure à la 2.11.1
, en notant bien que Log4J 2 constitue une réécriture totale du framework.
Vous pouvez télécharger Log4J 2 à partir de cette adresse : http://logging.apache.org.
Conscient de l'intérêt d'une telle API en Java, les développeurs du Java ont pris la décision de proposer une API de log intégrée au Java SE à partir de
sa version 1.4
(en 2002). Cette API est disponible dans le package java.util.logging
. Certains l'appellent JUL en rapport aux
premières lettres de chaque package dans lesquels elle est disponible. Bien que fonctionnellement proche de Log4J, JUL ne constitue pas l'API
préférée des développeurs Java. Les développeurs ayant commencé avec Log4J, ils lui sont certainement resté fidèles.
Etant donné l'existence de deux APIs majeures de journalisation, le besoin de s'abstraire du choix de l'API de log à utiliser s'est fait ressentir.
Cela a abouti à définir des meta-API de logs. Je vais, aujourd'hui, insister sur trois de ces meta-APIs : JCL (Jakarta Common Logging),
SLF4J (Simple Logging Facade for Java) et l'API JBoss Logging. Dans les trois cas, par défaut ces API s'appuient sur java.util.logging
.
Par contre, si Log4J est présent dans le CLASSPATH, automatiquement elles basculeront sur cette API de log.
Pour le moment nous avons choisi de travailler avec le moteur de persistance JPA Hibernate. Historiquement parlant, Hibernate s'est toujours
appuyé sur une meta-API de log. Jusqu'à ses versions 3.2.x, Hibernate s'appuyait sur JCL. A partir de la version 3.3.0 et jusqu'aux versions 4.x,
il a utilisé SLF4J. Enfin, depuis sa version 5.0, Hibernate utilise l'API JBoss Logging. Mais pour vous ces choix d'utilisation d'API sont
transparents. Notez simplement que par défaut Hibernate produit des logs via java.util.logging
, mais si vous ajoutez les fichiers jar
de Log4J au CLASSPATH, alors vous basculerez automatiquement sur Log4J. Personnellement, c'est ce que je vous recommande.
Voici un diagramme synthétisant les liens entre ces différentes APIs de log.
Il est possible de configurer la manière de produire les logs avec Log4J 2 : cela se fait au niveau d'un fichier XML de configuration.
Par défaut le nom de ce fichier doit être log4j2.xml
et il doit être présent à la racine du CLASSPATH. Sous Eclipse, placez le fichier de configuration
directement dans src
(il sera automatiquement recopié dans le répertoire bin
visible du CLASSPATH).
Voici le contenu de ce fichier de configuration :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?xml version="1.0" encoding="UTF-8" ?> <Configuration xmlns="http://logging.apache.org/log4j/2.0/config" status="WARN"> <Appenders> <!-- <Socket name="socket" host="localhost" port="4445"> <SerializedLayout /> </Socket> --> <!-- <File name="file" fileName="webstore.log"> <PatternLayout> <Pattern>%p %t %c - %m%n</Pattern> </PatternLayout> </File> --> <Console name="stdout" target="SYSTEM_OUT"> <PatternLayout pattern="[%t] %-5p | %-60c | %m (%F:%L)%n"/> </Console> </Appenders> <Loggers> <!-- Logger name="org.hibernate.SQL" level="debug" / --> <!-- Logger name="org.hibernate.type" level="trace" / --> <Root level="warn"> <!-- AppenderRef ref="file" / --> <AppenderRef ref="stdout" /> </Root> </Loggers> </Configuration> |
Avec Log4J 2, un appender permet de contrôler dans quel flux produire vos logs (la console, un fichier, une base de données, ...).
Dans l'exemple proposé, c'est la console (System.out
) qui est utilisée (voir en ligne 29).
Il est possible d'activer plusieurs appenders en même temps.
Avec Log4J 2, il existe plusieurs niveaux de logs. Voici l'échelle des logs supportés : all
, trace
, debug
,
info
, warn
, error
, fatal
et off
. Un niveau de log donné, contient les niveaux
suivants : ainsi, si vous activez les logs au niveau info
, vous tracerez les messages de niveau info
mais aussi les
warn
, les error
et les fatal
. Si vous activez les logs au niveau error
, nous n'afficherez plus que
les niveaux error
et fatal
. Dans l'exemple proposé, on affiche à partir du niveau warn
(cela est dit en ligne 27).
Mais il faut comprendre que cette configuration n'est que par défaut. Il est possible, pour un loggeur ou un ensemble de loggeurs donné, de changer
le niveau à utiliser. Par exemple en ajoutant le tag <Logger name="org.hibernate" level="info" />
dans votre configuration, vous
activez tous les loggeurs d'Hibernate en mode info
. Le fait de spécifier org.hibernate
est ici récursif.
Mais on peut aussi être plus précis en spécifiant le nom complet d'un loggeur : par exemple, org.hibernate.SQL
Je ne vais pas vous lister tous les loggeurs utilisé par Hibernate, ce serait trop long. Mais, de mon point de vue, il faut en connaître au moins deux. Ils vous permettront de mieux comprendre ce que fait votre moteur de persistance : nous en reparlerons dans les prochains chapitres.
org.hibernate.SQL : permet d'afficher tous les ordres SQL produit par votre moteur de persistance. En phase de développement, j'active systématiquement ce loggeur afin de contrôler les requêtes SQL produites. Cela est très important du point de vue des performances, car des fois on demande à Hibernate de faire des « bêtises » : nous y reviendrons plus tard.
org.hibernate.type : permet d'afficher tous les paramètres passés à vos ordres SQL. Je ne l'active pas systématiquement, mais il peut être très utile.
Nous allons reprendre le programme développé dans le chapitre précédent. Ajoutez un fichier de configuration pour Log4J 2. Ensuite, ajoutez/supprimez les jars de Log4J dans les CLASSPATH : notez les changements dans la manière de produire les logs (java.util.logging ou Log4J 2). Activez l'affichage des requêtes SQL produites par votre programme.
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :