Créer un fichier de journalisation peut-être très pratique pour résoudre les
plantages d’une application. Mais qui dit fichier dit flux, ouvertures,
fermetures…tout un tas de complications en tout genre !
Java propose un
outil très pratique pour gérer ce type de problématiques sans trop de
difficulté : le Logger.Prenons un exemple concret : une application qui compte
de 1 à 10, en faisant des pauses de 10 secondes entre chaque nombre. Chaque
action du programme sera écrite dans un fichier avec la date, de même pour les
erreurs éventuelles.
Voici donc la classe principale sans la gestion de notre fichier journal :
On remarque que Logger est déjà utilisé lors du try !
Dans ce tutoriel je ne vais pas rentrer dans les détails de la classe
Logger qui est très vaste, je me concentrerai seulement sur la création d’un
fichier journal basique.
Les différents journaux sont identifiés par leur nom. Comme nous allons
utiliser le même fichier pour enregistrer à la fois le comportement et les
erreurs, appelons le “journal”.
Commençons par enregistrer les éléments dans “journal” sans utiliser de
fichier :
123456789101112131415161718
packagehellokitty;importjava.util.logging.Level;importjava.util.logging.Logger;publicclassMain{publicstaticvoidmain(String[]args){for(inti=1;i<11;i++){System.out.println(i);//On enregistre une nouvelle entrée dans le journalLogger.getLogger("journal").log(Level.INFO,"Je suis à la valeur "+i);try{Thread.sleep(10000);}catch(InterruptedExceptionex){//On réutilise notre journal pour les erreursLogger.getLogger("journal").log(Level.SEVERE,null,ex);}}}}
Tout nos évènements sont maintenant enregistrés dans
“journal”. Le code qui suit va écrire ces évènements dans un fichier appelé
“journal.txt” :
packagehellokitty;importjava.io.IOException;importjava.util.logging.FileHandler;importjava.util.logging.Level;importjava.util.logging.Logger;publicclassMain{publicstaticvoidmain(String[]args){FileHandlerfileHandler=null;try{//On crée un gestionnaire de fichier par défautfileHandler=newFileHandler("journal.txt");}catch(IOExceptionex){Logger.getLogger(Main.class.getName()).log(Level.SEVERE,null,ex);}catch(SecurityExceptionex){Logger.getLogger(Main.class.getName()).log(Level.SEVERE,null,ex);}//On assigne le gestionnaire de fichier précédent à notre LoggerLogger.getLogger("journal").addHandler(fileHandler);for(inti=1;i<11;i++){System.out.println(i);//On enregistre une nouvelle entrée dans le journalLogger.getLogger("journal").log(Level.INFO,"Je suis à la valeur "+i);try{Thread.sleep(10000);}catch(InterruptedExceptionex){Logger.getLogger("journal").log(Level.SEVERE,null,ex);}}}}
Voici un extrait de notre fichier
“journal.txt” après le fonctionnement du programme :
12345678910111213141516171819202122232425
<?xml version="1.0" encoding="windows-1252" standalone="no"?><!DOCTYPE log SYSTEM "logger.dtd"><log><record><date>2009-03-31T14:17:39</date><millis>1238501859578</millis><sequence>0</sequence><logger>journal</logger><level>INFO</level><class>hellokitty.Main</class><method>main</method><thread>10</thread><message>Je suis à la valeur 1</message></record><record><date>2009-03-31T14:17:49</date><millis>1238501869609</millis><sequence>1</sequence><logger>journal</logger><level>INFO</level><class>hellokitty.Main</class><method>main</method><thread>10</thread><message>Je suis à la valeur 2</message></record>
Et oui…c’est du XML ! Pas forcément pratique dans notre cas. C’est pour cela que nous allons configurer notre FileHandler pour créer un fichier non structuré en XML avec la directive fileHandler.setFormatter(new SimpleFormatter());
packagehellokitty;importjava.io.IOException;importjava.util.logging.FileHandler;importjava.util.logging.Level;importjava.util.logging.Logger;importjava.util.logging.SimpleFormatter;publicclassMain{publicstaticvoidmain(String[]args){FileHandlerfileHandler=null;try{//On crée un gestionnaire de fichier "simple"fileHandler=newFileHandler("journal.txt");//On assigne une mise en forme simplefileHandler.setFormatter(newSimpleFormatter());}catch(IOExceptionex){Logger.getLogger(Main.class.getName()).log(Level.SEVERE,null,ex);}catch(SecurityExceptionex){Logger.getLogger(Main.class.getName()).log(Level.SEVERE,null,ex);}//On assigne le gestionnaire de fichier précédent à notre LoggerLogger.getLogger("journal").addHandler(fileHandler);for(inti=1;i<11;i++){System.out.println(i);//On enregistre une nouvelle entrée dans le journalLogger.getLogger("journal").log(Level.INFO,"Je suis à la valeur "+i);try{Thread.sleep(10000);}catch(InterruptedExceptionex){Logger.getLogger("journal").log(Level.SEVERE,null,ex);}}}}
Voici maintenant la forme de notre
“journal.txt” :
31 mars 2009 14:22:51 hellokitty.Main main
INFO: Je suis à la valeur 1
31 mars 2009 14:23:01 hellokitty.Main main
INFO: Je suis à la valeur 2
Plus lisible, non ?
Nous allons maintenant améliorer notre FileHandler de telle manière que à
chaque lancement du programme le journal soit écrit à la suite du fichier :
fileHandler = new FileHandler("journal.txt");
Mais que va t-il se passer quand le
programme aura été lancé un bon millier de fois ? Et bien vous aurez un
fichier de log d’une taille très importante…
Ce que je fais habituellement c’est la mise en place d’une rotation de
journaux : je travaille sur 5 fichier de 1Mo maximum. Quand le 5ème fichier
est remplit, j’écrase le premier etc. Cela me permet de pouvoir remonter assez
loin dans le erreurs sans surcharger le disque de l’utilisateur inutilement :
fileHandler = new FileHandler("journal%g.txt",1000000, 5, true);
1000000 correspond à 1Mo (en octets) et “journal%g.txt” me donnera
“journal1.txt”,”journal2.txt”…