Logging dans Java

Par :
ka
lun, 03/11/2008 - 18:51
Niveau :
Facile

Les développeurs, en général, et les développeurs Java en particulier ont l'habitude d'utiliser des instructions d'écriture sur la sortie standard ou la sortie d'erreur pour observer le comportement d'un programme à un endroit précis.

 

System.out.println(" message ") et System.err.println(" message ") sont deux instructions très utilisées en langage Java. Ce genre d'instructions, même en permettant de trouver des erreurs, complique le cycle de développement. Il faut penser à effacer ces instructions quand le programme est fini. En cas de changement de code les placer à nouveau dans le code.

 

Une meilleure pratique consiste à utiliser le système de " Logging " disponible dans Java (JDK 1.4 et sup) ou dans des programmes séparés comme par exemple LOG4J.

 

Avec des techniques de " logging " il est possible d'afficher ou non des messages à volonté, la sortie est optimisée et formatée. Il est possible de diriger en même temps les messages vers plusieurs sorties, utiliser des messages spécifiques pour les phases de développement et de production.

 

Ce tutoriel présente le système et les techniques de " Logging " disponibles en standard dans JDK à partir de la version 1.4

 

La version de Java utilisée est Java 1.6 update 10

 

La version d'Eclipse est 3.4

 

Un exemple très simple

Un exemple de logging le plus simple consiste à obtenir un logger pour afficher un message et utiliser toutes les propriétés par défaut. La date, l'heure et la source de l'information sont affichées par défaut.

 

package fr.iipt.ka.templates;

 

import java.util.logging.Level;

import java.util.logging.Logger;

 

 

public class SimpleLogger {

 

/**

* @param args

*/

public static void main(String[] args) {

Logger logger = Logger.getLogger("logger");

logger.log(Level.INFO, "Test de logger");

 

 

}

 

}

 

Affichage :

 

Oct 28, 2008 4:38:32 PM fr.iipt.ka.templates.SimpleLogger main

INFO: Test de logger

 

 

 

Un logger dirige des messages vers des sorties ou handlers (sortie d'erreurs standard, fichiers etc. L'affichage de l'exemple précédent est dirigé vers la sortie d'erreurs par défaut.

 

Les messages sont sélectionnés pour l'affichage selon un niveau fixé à la fois pour le logger utilisé et pour son/ses handlers. Tous les messages au-dessus du niveau fixé sont affichés. L'exemple utilise le niveau (level) " INFO " pour ses messages. Le niveau fixé par la configuration par défaut pour les loggers et la sortie d'erreurs est " INFO " donc les messages de ce niveau et des niveaux supérieurs à " INFO " sont affichés.

 

Note :

Ou pour le logger :

private static final Logger logger = Logger.getLogger("nom_de_logger");

Après la déclaration de la classe

,Levels

Logger :

A chaque logger est associé un level (niveau). Le level est un seuil permettant uniquement à des messages qui ont un niveau supérieur d'être envoyer vers un Handler. Tous les messages qui ont un niveau inférieur au niveau de logger sont ignorés.

Handler :

De même à chaque Handler est associé un niveau (level) et utilisé de la même manière

Sept Levels ou (niveau) sont définis et sont en ordre décroissant

SEVERE

WARNING

INFO

CONFIG

FINE

FINER

FINEST

 

Level par défaut :

Le level par défaut pour les loggers et les sortie d'erreurs est " INFO " . Pour FileHandler il est fixé par défaut à " ALL "

Définir un level (niveau) :

 

logger.setLevel(Level.FINE);

handler.setLevel(Level.FINE);

 

A partir de ces instructions tous les messages qui ont un niveau FINE et supérieur seront affichés

 

ATTENTION !!!

Il faut définir le level pour le logger et le handler

 

Exemple :

Afficher des messages à partir de FINE

----------------------------------------

public class SimpleLogger {

 

/**

* @param args

*/

public static void main(String[] args) {

Logger logger = Logger.getLogger("flogger");

logger.setLevel(Level.FINE);

 

ConsoleHandler ch=new ConsoleHandler();

logger.addHandler(ch);

ch.setLevel(Level.FINE);

 

logger.fine("Msg in fine");

 

 

}

 

}

 

,Annuler tous les messages d'un logger :

Avec une seule instruction tous les messages de n'importe quel niveau sont annulés

 

logger.setLevel(Level.OFF);

 

Exemple :

---------

public class SimpleLogger {

 

/**

* @param args

*/

public static void main(String[] args) {

Logger logger = Logger.getLogger("finelogger");

logger.setLevel(Level.OFF);

ConsoleHandler ch=new ConsoleHandler();

logger.addHandler(ch);

ch.setLevel(Level.FINE);

logger.fine("Msg in fine");

 

 

}

 

}

 

 

Note :

Dans l'exemple précédent l'instruction suivante n'a aucun effet

ch.setLevel(Level.FINE);

 

Note :

Avec l'instruction suivante :

 

logger.setLevel(Level.ALL);

 

Tous les messages de tous les niveaux sont affichés

 

,Handlers

Les handlers sont des sorties de loggers.

Dans JDK 5 des handlers disponibles :

  • StreamHandler : Les messages sont envoyés vers OutputStream

  • ConsoleHandler : Les messages sont envoyés vers System.err

  • FileHandler : Les messages sont dirigés vers un fichier

  • SocketHandler : Les messages sont envoyés vers un port TCP

  • MemoryHandler : Les messages sont envoyés à la mémoire

Note:

 

Par défaut logger envoie des messages vers la sortie standard d'erreurs " System.err " via " ConsoleHandler " et fixe son niveau (level) comme suite :

 

java.util.logging.ConsoleHandler.level=INFO

 

et comme formatter " SimpleFormat "

 

Note:

Par défaut la configuration fixe le niveau (level) de logger à INFO

 

Note:

Par défaut un logger envoie des messages à son handler et aux handlers de ses parents, voir plus loin.

 

 

 

ATTENTION !!!

 

Pour écrire un message " fine " par exemple il faut à la fois changer le niveau (level) pour logger et handler

,Envoyer des messages vers un fichier

Pour envoyer des messages vers un fichier au lieu (ou avec) de la sortie erreurs, il suffit de définir un handler de fichier (FileHandler) et l'ajouter au logger

 

try {

FileHandler fh=new FileHandler();

logger.addHandler(fh);

} catch (Exception e) {}

 

Note :

Sans spécifier un nom pour notre fichier le logger utilise un FileHandler par défaut. Le fichier de log aura comme nom " java0.log " ou un autre chiffre pour rendre ce fichier unique. Ce fichier est écrit dans le dossier local de l'utilisateur (sauf dans Windows 95/98/Me le fichier est placé dans la racine de disque)

 

Important :

Dans Eclipse le fichier n'est pas placé dans le projet en-cours

 

Exemple :

---------

package fr.iipt.ka.templates;

 

import java.io.*;

import java.util.logging.*;

 

 

 

 

public class SimpleLogger {

 

public static void main(String[] args) {

Logger logger = Logger.getLogger("flogger");

try {

FileHandler fh=new FileHandler();

logger.addHandler(fh);

} catch (SecurityException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

 

 

}

 

}

 

,Spécifier un nom pour le fichier de log

En construisant un objet FileHandler, il est possible de donner un nom au fichier (avec le chemin). Dans Eclipse un fichier sans chemin est un fichier avec un chemin implicite dans le projet en-cours.

 

Exemple :

---------

package fr.iipt.ka.templates;

 

import java.io.IOException;

import java.util.logging.*;

 

 

 

 

public class SimpleLogger {

 

public static void main(String[] args) {

Logger logger = Logger.getLogger("flogger");

try {

FileHandler fh=new FileHandler("myLog.txt");

logger.addHandler(fh);

} catch (SecurityException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

 

 

}

 

}

 

,Rotation de fichiers

Avec " FileHandler " il est possible d'envoyer des messages vers plusieurs fichiers en rotation. En claire si un fichier est plein la sortie est dirigée vers le prochain fichier dans la série. Quand le dernier fichier est plein (selon le nombre spécifié de fichiers), le premier fichier est réutilise.

Pour le FileHandler suivant :

  • Les noms des fichiers sont : MonLog0.txt, MonLog1.txt et MonLog2.txt.

  • La taille de fichiers est fixée à 200 octets.

  • %h signifie dans le dossier local de l'utilisateur.

  • %g donne automatiquement un numéro aux fichiers de 0 à 3.

FileHandler fh=new FileHandler("%hMonLog%g.txt",200,3);

Exemple :

---------------

package fr.iipt.ka.templates;

import java.io.IOException;

import java.util.logging.FileHandler;

import java.util.logging.Logger;

import java.util.logging.SimpleFormatter;

/**

* @author Kaesar ALNIJRES

*

*/

public class TestFichiers {

 

public static void main(String[] args) {

Logger logger=Logger.getLogger(TestFichiers.class.getName());

try {

//%h = le dossier local de l'utilisateur

//%g = Le numéro de fichiers est inséré automatiquement

FileHandler fh=new FileHandler("%hMonLog%g.txt",200,3);

fh.setFormatter(new SimpleFormatter());

logger.addHandler(fh);

} catch (SecurityException e) {

e.printStackTrace();

} catch (IOException e) {

 

e.printStackTrace();

}

for (int i = 0; i < 10; i++) {

logger.info("Ligne n " + i);

}

}

}

,Variables pour les nom de fichiers

 

 

Il existe quelques variables utilisables avec le nom du fichier dans un FileHandler

 

Par exemple :

FileHandler fh=new FileHandler("%h/myLog.txt");

 

Ecrit le fichier dans le dossier local de l'utilisateur, c’est comme si on a donné le chemin complet vers le dossier utilisateur

 

%h

Dossier local de l'utilisateur " %h/myLog.txt "

%t

Le dossier " tmp " du système " %t/myLog.txt "

%g

Le fichier est donné un numéro automatiquement(rotation de fichiers)

%u

Un chiffre pour avoir un fichier unique

/

Séparateur de fichiers ou dossiers

 

,Les méthodes logp

Cette méthode reçoit en arguments le nom de la classe de log, nom de la méthode et autres paramètres, permettant ainsi d'avoir les noms exacts de ses éléments, en cas d'optimisation de code et de modifications éventuelles de ces noms par la JVM

 

Exemple :

--------------

package fr.iipt.ka.templates;

 

import java.util.logging.Level;

import java.util.logging.Logger;

 

public class TestLogp {

 

public static void main(String[] args) {

 

Logger logger = Logger.getLogger(TestLogp.class.getName());

logger.logp(Level.INFO, "TestLogp", "main", "Message de main en utilisant \"logp\"");

}

 

}

,Le point d'entrée et sortie d'une méthode

Il est très utile pendant la phase de développement de recevoir des messages pour indiquer chaque entrée et sortie d'une méthode. Des méthodes spécifiques sont définies pour des Logger à cette fin

 

Les noms de ces méthodes est " entering " et " exiting " et plusieurs variantes sont disponibles

 

ATTENTION !!!

Le niveau par défaut pour " entering " et " exiting " est " FINER ". Il faut donc modifier le niveau (level) pour le logger, et le handler utilisés, sinon pas de messages. Les modifications sont à effectuer dans le programme ou dans le fichier de configuration.

 

Note :

Le message d'entrée " entering " commence par " ENTER " après l'affichage du niveau, et le message de sortie " exiting " par " RETURN "

 

Exemple :

---------

package fr.iipt.ka.templates;

 

import java.io.File;

import java.util.logging.*;

 

 

 

 

public class SimpleLogger {

 

private static Logger logger = Logger.getLogger("loggerEntreeSortie");

public static void main(String[] args) {

logger.setLevel(Level.FINER);

ConsoleHandler ch=new ConsoleHandler();

logger.addHandler(ch);

ch.setLevel(Level.FINER);

//appler lireFichier()

lireFichier(new File("fichier.txt"),true);

 

 

}

private static String lireFichier(File fichier,boolean ajouter)

{

logger.entering(SimpleLogger.class.getName(), "lireFichier",new Object[]{fichier,ajouter});

System.out.println("\n\nLe corps de la méthode ...\n\n");

String s="";

for(int i=0;i<10;i++)

s+="\n"+i;

 

 

//La méthode retourne le String " s "

logger.exiting(SimpleLogger.class.getName(), "lireFichier", s);

return s;

}

 

}

 

Affichage :

---------------

Nov 1, 2008 11:47:36 AM fr.iipt.ka.templates.SimpleLogger lireFichier

FINER: ENTRY fichier.txt true

 

 

Le corps de la méthode ...

 

 

Nov 1, 2008 11:47:36 AM fr.iipt.ka.templates.SimpleLogger lireFichier

FINER: RETURN

0

1

2

3

4

5

6

7

8

9

 

,Formatters :

  • Les formatters sont chargés de formater les messages.

  • Avec chaque handler est associé un formatter.

Deux formatters définis par défaut :

  • SimpleFormatter: Simple messages avec date et temps

  • XMLFormatter : Messages au format XML

Le formatter à utiliser est à spécifier :

  • Avec la méthode setFormatter de Handler

  • Dans le fichier de propriétés " JRE/lib/logging.properties ".Le formatter spécifié dans ce fichier est utilisé par défaut et n'a pas besoin de " setFormatter "

  • Dans un fichier personnalisé de propriétés.

Note :

SimpleFormatter est le format par défaut de " ConsoleHandler "

XMLFormatter est le format par défaut de " FileHandler "

Exemple SimpleFormatter :

---------------------------

package fr.iipt.ka.templates;

import java.io.IOException;

import java.util.logging.FileHandler;

import java.util.logging.Logger;

import java.util.logging.SimpleFormatter;

/**

* @author Kaesar ALNIJRES

*

*/

public class TestFichiers {

public static void main(String[] args) {

Logger logger=Logger.getLogger(TestFichiers.class.getName());

try {

FileHandler fh=new FileHandler("simpleFormatterLog.txt");

fh.setFormatter(new SimpleFormatter());

logger.addHandler(fh);

logger.info("Message en utilisant Formatter");

} catch (SecurityException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

}

Affichage : SimpleFormatterLog.txt

-------------------------------------

Oct 31, 2008 6:59:46 PM fr.iipt.ka.templates.TestFichiers main

INFO: Message en utilisant SimpleFormatter

Exemple XMLFormater :

----------------------

package fr.iipt.ka.templates;

import java.io.IOException;

import java.util.logging.FileHandler;

import java.util.logging.Logger;

import java.util.logging.SimpleFormatter;

/**

* @author Kaesar ALNIJRES

*

*/

public class TestFichiers {

public static void main(String[] args) {

Logger logger=Logger.getLogger(TestFichiers.class.getName());

try {

FileHandler fh=new FileHandler("XMLFormaterLog.txt");

logger.addHandler(fh);

logger.info("Message en utilisant XML Formatter");

} catch (SecurityException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

}

Affichage XMLFormatterLog.txt

------------------------------

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

dtd">

2008-10-31T19:21:21

1225477281668

0

fr.iipt.ka.templates.TestFichiers

INFO

fr.iipt.ka.templates.TestFichiers

main

10

Message en utilisant XML Formatter

 

,Formatter Personnalisé

 

Chaque Handler doit avoir un formatter (un format pour la sortie)

Les deux Formatters définis par défaut SimpleFormatter et XMLFormatter sont des enfants de la classe " Formatter ". Il est possible donc de définir son propre " Formatter " en implantent la méthode " format ". Cette méthode retourne une chaîne (String), les données à mettre dans la sortie. Cette méthode reçoit un " LogRecord ", un enregistrement contenant les commandes de loggers vers les Handlers ou sorties et des informations sur le Logger.

Note :

Le Formatter d'exemple est attaché au " ConsoleHandler " avec la méthode " setFormatter "

Note:

Une autre façon pour attacher le Formatter au " ConsoleHandler " ou un autre Handler est de modifier le fichier " JRS/lib/logging.properties " comme suite en mettant en commentaire, le formatter par défaut et en ajoutant le formatter TestFormatter :

#java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

java.util.logging.ConsoleHandler.formatter = fr.iipt.ka.templates.TestFormatter

Exemple d'un formatter très simple

--------------------------------

package fr.iipt.ka.templates;

 

import java.util.logging.*;

 

/**

* @author Kaesar ALNIJRES

*

*/

public class TestFormatter extends Formatter{

 

public String format(LogRecord record) {

return

"Formatter perso"+'\n'+

"====================="+'\n'+

"Level : " + record.getLevel() + '\n' +

"LoggerName : " + record.getLoggerName() + '\n' +

"Message : " + record.getMessage() + '\n'+

"Classe : " + record.getSourceClassName() + '\n' +

"Méthode : " + record.getSourceMethodName()+"\n\n";

}

 

 

}

Exemple d'utilisation :

-----------------------

 

 

package fr.iipt.ka.templates;

 

import java.util.logging.*;

 

 

 

 

public class SimpleLogger {

 

/**

* @param args

*/

public static void main(String[] args) {

Logger logger = Logger.getLogger("finelogger");

logger.setLevel(Level.FINE);

ConsoleHandler ch=new ConsoleHandler();

ch.setFormatter(new TestFormatter());

logger.addHandler(ch);

ch.setLevel(Level.FINE);

Logger loggerEnfant = Logger.getLogger("finelogger.enfant");

logger.fine("Logger : -->Msg niveau fine\n");

loggerEnfant.fine("Logger : -->Msg niveau fine\n");

 

 

}

 

}

 

Affichage :

------------

 

Formatter perso

=====================

Level : FINE

LoggerName : finelogger

Message : Logger : -->Msg niveau fine

 

Classe : fr.iipt.ka.templates.SimpleLogger

Méthode : main

 

Formatter perso

=====================

Level : FINE

LoggerName : finelogger.enfant

Message : Logger : -->Msg niveau fine

 

Classe : fr.iipt.ka.templates.SimpleLogger

Méthode : main

 

,Hiérarchie de loggers

Chaque logger enfant hérite les propriétés de son parent et utilise son Handler

 

,Hiérarchie de loggers suite

 

 

Logger logger = Logger.getLogger("finelogger");

 

est le parent de

 

Logger loggerEnfant = Logger.getLogger("finelogger.enfant");

 

Résultat en fixant le niveau Logger/Handler à " FINE " pour fineLogger, fineLogger.enfant aura aussi " FINE " comme niveau

 

Note :

La relation parent/enfant est à l'image de packages de Java et sont décrit à l'aide d'un point

 

Note:

Si aucun niveau ou level n’est fixé pour un logger ou son parent tous les parents sont inspectés en montant et jusque " root " pour trouver un niveau (le niveau pour root est INFO)

 

 

Exemple :

---------

package fr.iipt.ka.templates;

 

import java.util.logging.*;

 

 

 

 

public class SimpleLogger {

 

public static void main(String[] args) {

Logger logger = Logger.getLogger("finelogger");

logger.setLevel(Level.FINE);

ConsoleHandler ch=new ConsoleHandler();

logger.addHandler(ch);

ch.setLevel(Level.FINE);

Logger loggerEnfant = Logger.getLogger("finelogger.enfant");

//niveau Logger et Handler hérités de son parent

loggerEnfant.fine("Logger : "+loggerEnfant.getName()+"-->Msg niveau fine\n");

loggerEnfant.fine("Le parent de loggerEnfant est : "+loggerEnfant.getParent().getName()+"\n");

 

 

}

 

}

 


Affichage :

-----------

Oct 30, 2008 10:33:29 AM fr.iipt.ka.templates.SimpleLogger main

FINE: Logger : finelogger.enfant-->Msg niveau fine

 

Oct 30, 2008 10:33:29 AM fr.iipt.ka.templates.SimpleLogger main

FINE: Le parent de loggerEnfant est : finelogger

 

,Hiérarchie de loggers suite 2

Chaque logger ayant terminé l'envoi de ses messages vers son Handler envoie des messages vers le handler de son parent

 

Dans l'exemple suivant le niveau pour le deuxième message de loggerEnfant utilise la méthode " info " pour envoyer le message aussi vers le handler root (le niveau par défaut pour le root est " INFO ". Maintenant le dernier message est affiché deux fois, une sur le handler parent de loggerEnfant et l'autre sur le handler de root

 

Exemple :

---------

package fr.iipt.ka.templates;

 

import java.util.logging.*;

 

 

 

 

public class SimpleLogger {

 

public static void main(String[] args) {

Logger logger = Logger.getLogger("finelogger");

logger.setLevel(Level.FINE);

ConsoleHandler ch=new ConsoleHandler();

logger.addHandler(ch);

ch.setLevel(Level.FINE);

Logger loggerEnfant = Logger.getLogger("finelogger.enfant");

//niveau Logger et Handler hérités de son parent

loggerEnfant.fine("Logger : "+loggerEnfant.getName()+"-->Msg niveau fine\n");

//info a un niveau sup au niveau FINE donc affichage

loggerEnfant.info("Le parent de loggerEnfant est : "+loggerEnfant.getParent().getName()+"\n");

 

 

}

 

}

 

L'affichage est comme suite :

------------------------------

Oct 30, 2008 10:24:13 AM fr.iipt.ka.templates.SimpleLogger main

FINE: Logger : finelogger.enfant-->Msg niveau fine

 

Oct 30, 2008 10:24:13 AM fr.iipt.ka.templates.SimpleLogger main

INFO: Le parent de loggerEnfant est : finelogger

 

Oct 30, 2008 10:24:13 AM fr.iipt.ka.templates.SimpleLogger main

INFO: Le parent de loggerEnfant est : finelogger

,Propriétés de logging :

Par défaut Java utilise des propriétés pour ses loggers, handlers, filters etc.

 

Le fichier contenant les propriétés est dans le dossier d’installation de JRE

 

chemin_vers_JRE/lib/logging.properties

 

Note :

Dans ce fichier de propriétés :

 

Handlers si plusieurs, sont séparés par virgule " , "

.level Le seuil pour un logger

.level préfixé par un point " . " est le niveau ou level pour un
logger racine (root).

 

Note :

Essayer de modifier le fichier de configuration en utilisant :

 

System.setProperty("java.util.logging.config.file", file)

 

Dans " main " ne donne rien, car LogManager est initialisé au démarrage de JVM

 

Note:

En changeant le niveau pour logger et handler dans le fichier de configuration vers " FINE " par exemple on peut recevoir des messages pendant le développement. Quand le programme est terminé on peut modifier le niveau vers " WARNING "

 

,Modifier les propriétés :

Plusieurs méthodes sont disponibles pour modifier les propriétés utilisées dans le système de logging :

 

  • Modifier les propriétés dans le fichier de configurations

  • Ecrire un fichier de propriétés et indiquer à la JVM de l'utiliser

      java -Djava.util.logging.config.file=configFile MainClass

  • Modifier des propriétés d'une façon dynamique dans le programme

  • java.util.logging.config.class pointe vers un LogManager(responsable de lire ses configurations)

 

,Fichier de configuration Personnalisé

Parmi les avantages énormes du système de logging la possibilité d'utiliser un/plusieurs fichiers de configuration pour les diverses phases de vie d'un programme. En autorisant comme dans l'exemple suivant la plupart des messages en cycle de développement et en n'autorisant que ceux destinés à l'utilisateur final dans la phase de production.

 

Exemple : Fichier de configuration :

 

############################################################

# ka.properties

# Fichier personnalisé pour les configuration de logging

#

# Utilisation :

# java -Djava.util.logging.config.file=ka.properties

############################################################

 

 

# Utilise la sortie erreur standard et sortie fichier

handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

 

# Le niveau de tous les loggers est FINER

.level= FINER

 

 

 

############################################################

# CONFIG pour les handlers

############################################################

 

# les fichiers de logs auront comme noms ka0.log, ka1.log, 2 fichiers en rotation et seront #dans le dossier local de l'utilisateur, taille

# 50000, et utilisent SimpleFormatter

 

java.util.logging.FileHandler.pattern = %h/ka%g.log

java.util.logging.FileHandler.limit = 50000

java.util.logging.FileHandler.count = 2

java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter

 

 

java.util.logging.ConsoleHandler.level = FINER

java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

 

Utilisation du fichier :

  1. A partir de la ligne de commande :

    java -Djava.util.logging.config.file=Chemin_vers_le_fichier.properties MainClass

  2. Dans Eclipse :
    Un clic droit sur le fichier.java (à exécuter) -> " Run As " -> " Run Configurations " -> un clic sur l'onglet " Arguments " -> Entrer dans la zone " VM Arguments " la ligne suivante :

    -Djava.util.logging.config.file=/home/kas/ka.properties "

 

Note :

/home/kas/ka.properties est le nom du fichier de configuration avec son chemin

 

Note :

Dans le fichier d'exemple le niveau est modifié pour le root. Il est aussi possible de ne modifier que le niveau d'un logger spécifique en suffixant son nom avec " .level "

 

fr.iipt.ka.templates.SimpleLogger.level=FINER

,LogManager

 

Tout le système de logging pour une application est contrôlé par une instance de LogManger ;

 

Loggers, propriétés utilisées par les handlers

 

Il est possible avec un LogManager d'obtenir des informations détaillées concernant les loggers et leurs propriétés

 

Avoir des informations sur les loggers

 

getLoggerNames() de LoggerManager retourne une Enumetation, les noms de tous les logger actifs, y compris parents et root

 

getLevel() de Logger le niveau utilisé dans le logger

 

getParent() de Logger le parent du logger

 

 

 

Exemple :

System.out.println() est utilisée au lieu de logger pour limiter l'interférence.

-------------------------------

package fr.iipt.ka.templates;

import java.util.Enumeration;

import java.util.logging.*;

/**

* @author Kaesar ALNIJRES

*

*/

public class InformationDeLoggers {

 

public static void main(String[] args) {

Logger logger = Logger.getLogger("finelogger");

logger.setLevel(Level.FINE);

ConsoleHandler ch=new ConsoleHandler();

logger.addHandler(ch);

ch.setLevel(Level.FINE);

 

//+++++++++++++++++++++++++++++++++++++++++++++

LogManager lm = LogManager.getLogManager();

Enumeration nomsDeLoggers = lm.getLoggerNames();

System.out.println("***Informations***");

// For each logger: show name, level, handlers etc.

while (nomsDeLoggers.hasMoreElements()) {

String nomLogger = (String)nomsDeLoggers.nextElement();

Logger logger4Informations = lm.getLogger(nomLogger);

System.out.println("-----------------------");

System.out.println("Nom : ["+nomLogger+"]");

System.out.println("Level : " + logger.getLevel());

Logger parent = logger4Informations.getParent();

System.out.print("Parent : ");

if (parent == null)

System.out.println("Le root n'a pas de parent");

else if(parent.getName().equals(""))

System.out.println("Root");

else

System.out.println(""+parent.getName());

// Les handlers du logger

Handler[] handlers = logger.getHandlers();

for(Handler handler: handlers)

{

System.out.println("Handler : "+handler.getClass().getName() );

System.out.println("level par le handler: " + handler.getLevel());

}

 

}

}

 

}

 

Affichage :

-----------

***Informations***

-----------------------

Nom : [finelogger]

Level : FINE

Parent : Root

Handler : java.util.logging.ConsoleHandler

level par le handler: FINE

-----------------------

Nom : [global]

Level : FINE

Parent : Root

Handler : java.util.logging.ConsoleHandler

level par le handler: FINE

-----------------------

Nom : []

Level : FINE

Parent : Le root n'a pas de parent

Handler : java.util.logging.ConsoleHandler

level par le handler: FINE

 

,Localization :

C'est la possibilité de présenter un programme en plusieurs langues (ici les messages de logging)

L'internationalisation de programmes en Java " i18n " est un sujet très vaste. Ici, je présente très brièvement les étapes pour sortir des messages en anglais et en français :

 

  1. Création de deux fichiers à mettre avec les fichiers .class du programme :

  • logmessages_en.properties

  • logmessages_fr.properties

  1. Le format des fichiers :

    mot_clé=valeur

    Exemple Pour le fichier en anglais :

    readingFile=I m reading the file ! Please wait.
    writingFile=I m writing the file ...

    Exemple le même fichier en français

    readingFile=En train de lire le fichier ! Patience.
    writingFile=Ecrire dans le fichier

 

  1. Obtenir une instance de logger avec le nom d’un resourceBundle comme suite :
    Logger logger=Logger.getLogger(" nom_logger ",  "fr.iipt.ka.templates.logmessages"

  2. Utilier des mots clés dans des messages log et non des chaînes
    Par exemple " readingFile " est un mot clé défini dans des fichiers de mapping :

    logger.info(" readingFile ");

  3. Selon le local utilisé par défaut le message est affiché en français ou anglais

 

Note :

Il est possible de spécifier un local à utiliser pour un programme comme suite :

 

java -Duser.language=FR MainClass

 

 

Note :

Dans Eclipse " -Duser.language=FR " dans " Run As -> Run configurations -> Arguments -> JVM arguments "

 

Note :

Utiliser logger.log(level,msg) au lieu de logger.level(msg) permet d'afficher des messages traduits y compris les niveaux de logger

 

 

Exemple logging en français ou en anglais :

---------------------------------------------------------------

package fr.iipt.ka.templates;

 

import java.util.logging.Level;

import java.util.logging.Logger;

 

public class LocalizationLogger {

 

/**

* @param args

*/

public static void main(String[] args) {

Logger logger=Logger.getLogger(LocalizationLogger.class.getName(), "fr.iipt.ka.templates.logmessages");

logger.log(Level.SEVERE,"readingFile");

 

}

 

}

 

Affichage, langue et local en français :

-----------------------------------------

1 nov. 2008 19:30:05 fr.iipt.ka.templates.LocalizationLogger main

GRAVE: En train de lire le fichier ! Patience.

 

Affichage, langue et local en anglais :

---------------------------------------

Nov 1, 2008 7:42:13 PM fr.iipt.ka.templates.LocalizationLogger main

SEVERE: I'm reading the file ! Please wait.

 

,ConsoleHandler

-Par défaut un logger envoie des messages vers un " ConsoleHandler " qui utilise System.err pour l’affichage.

-Il utilise par défaut " SimpleFormatter "

-Son niveau par défaut est "Level.INFO "

Il est possible d'installer un nouveau " ConsoleHandler " et n'utiliser pas le " ConsoleHandler " défini par défaut.

 

Note :

Chaque logger affiche des messages via son handler et les handlers de ses parents et il y a déjà un ConsoleHandler défini par défaut.

 

logger.setUseParentHandlers(false);

 

Permet d’annuler l’utilisation de handler des parents.

 

Exemple :

----------

package fr.iipt.ka.templates;

 

import java.util.logging.ConsoleHandler;

import java.util.logging.Handler;

import java.util.logging.Level;

import java.util.logging.Logger;

 

public class DeuxConsoleHandler {

 

/**

* @param args

*/

public static void main(String[] args) {

Logger logger=Logger.getLogger(DeuxConsoleHandler.class.getName());

logger.setLevel(Level.FINE);

Handler handler=new ConsoleHandler();

handler.setLevel(Level.FINE);

logger.addHandler(handler);

logger.setUseParentHandlers(false);

logger.info("message new console");

 

}

 

}

 

 

,FileHandler

 

-Les messages de loggers sont envoyés vers un fichier simple ou plusieurs fichiers en rotation

-Par défaut XMLFormatter est utilisé

-Le niveau par défaut est " Level.ALL "

-L'encodage utilisée est le l'encodage de caractères sur le système

-Par défaut pas de rotation de fichiers

Variables à utiliser dans les noms de fichiers

%h

Dossier local de l'utilisateur " %h/myLog.txt "

%t

Le dossier " tmp " du système " %t/myLog.txt "

%g

Le fichier est donné un numéro automatiquement dans des rotations

%u

Un chiffre pour avoir un fichier unique

/

Séparateur de fichiers ou dossiers

 

 

Note :

Normalement la variable %u est remplacé par un " 0 "

Si un processus essaye d'ouvrir un fichier en-cours d'utilisation par un autre processus le zéro " 0 " est remplacé par " 1 " etc.

Note :

Envoyer des messages vers FileHandler par défaut :

 

FileHandler handler = new FileHandler();

logger.addHandler(handler);

 

 

Note :

Pour envoyer plusieurs sorties d'applications vers un seul fichier, utiliser " append " dans le fichier log.properties, ou en utilisant le constructeur :

 

FileHandler(String pattern, boolean append)

 

,Il reste encore des choses ?

 

Le système de logging a encore beaucoup de fonctionnalités non abordées dans ce tutoriel, SocketHandler, utiliser des arguments dans des messages, utiliser Jconsole, instrumentation, pour ne citer que quelques exemples.

 

Ajouter un commentaire

Filtered HTML

Plain text

CAPTCHA
Cette question permet de vérifier que vous n'êtes pas un robot spammeur :-)
 DDD    GGG    QQQ    TTTTTT  RRRR  
D D G Q Q TT R R
D D G GG Q Q TT RRRR
D D G G Q QQ TT R R
DDD GGG QQQQ TT R RR
Q