CodeGym /Cours /JAVA 25 SELF /Bases de la journalisation : java.util.logging, Log4...

Bases de la journalisation : java.util.logging, Log4j, SLF4J

JAVA 25 SELF
Niveau 63 , Leçon 0
Disponible

1. Pourquoi journaliser

La journalisation ≠ l’affichage dans la console

Quand on commence à programmer, on a l’impression que pour chercher les problèmes il suffit d’insérer partout System.out.println("J’étais ici !"). Cela fonctionne tant que le programme est petit et s’exécute sur votre machine. Mais imaginez un grand projet, un serveur qui tourne 24/7, ou une application utilisée par des milliers de personnes — vous n’allez pas rester derrière l’épaule de chaque utilisateur pour regarder sa console, n’est-ce pas ?

La journalisation n’est pas qu’un simple affichage de messages. C’est un enregistrement systématisé d’informations sur le fonctionnement de l’application : erreurs, avertissements, événements métiers, détails techniques. Les journaux sont sauvegardés dans des fichiers, des bases de données, peuvent être envoyés sur le réseau — et ils permettent d’analyser le comportement du programme après son exécution ou même en cours d’exécution.

À quoi servent les journaux

  • Diagnostic des problèmes : si quelque chose se passe mal, les journaux sont votre meilleur allié. Ils permettent de comprendre où et pourquoi l’erreur est survenue.
  • Audit et sécurité : les journaux enregistrent les actions importantes des utilisateurs, ce qui aide à enquêter sur les incidents.
  • Débogage : parfois les bugs n’apparaissent que dans certaines conditions, et sans journaux ils sont impossibles à attraper.
  • Surveillance : les journaux permettent de suivre l’état de l’application, ses performances et sa « santé ».

Exemple de la vie réelle

S’il n’y avait pas de « boîtes noires » dans les avions (journaux de vol), il serait presque impossible d’enquêter sur les causes des accidents. En programmation, les journaux — ce sont vos boîtes noires.

2. Niveaux de journalisation de base

En journalisation, on utilise des niveaux (levels) de messages. C’est comme un feu tricolore : rouge — danger, jaune — prudence, vert — tout va bien.

Niveaux principaux (du plus « bruyant » au plus « silencieux ») :

Niveau Description
ERROR
Erreur critique, l’application ne peut pas continuer à fonctionner
WARN
Avertissement : quelque chose s’est mal passé, mais le programme fonctionne
INFO
Message d’information sur des événements normaux
DEBUG
Informations détaillées pour le débogage (visible uniquement par les développeurs)
TRACE
Informations les plus détaillées — pour un diagnostic approfondi

Exemple :

  • L’utilisateur n’a pas pu se connecter à cause d’un mot de passe incorrect — c’est WARN.
  • La base de données est tombée en panne — c’est ERROR.
  • L’application a démarré — c’est INFO.
  • L’affichage de la valeur d’une variable dans une boucle — c’est DEBUG ou TRACE.

Comment choisir le niveau

Il ne faut pas tout écrire au niveau ERROR — sinon vous vous noierez dans les vraies erreurs. Utilisez les niveaux de façon réfléchie : seuls les incidents réellement critiques doivent être des erreurs.

3. Journalisation standard en Java (java.util.logging)

Java est livré avec un système de journalisation intégré — le paquet java.util.logging (abrégé JUL). C’est l’outil « natif » toujours présent, même si vous n’ajoutez aucune bibliothèque.

Classes principales :

  • Logger — la classe principale pour écrire des journaux.
  • Level — l’énumération des niveaux de journalisation (SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST).
  • Handler — le gestionnaire indiquant où écrire les journaux (fichier, console, etc.).
  • Formatter — responsable du format des messages.

Exemple d’utilisation de JUL

import java.util.logging.Logger;
import java.util.logging.Level;

public class LoggingExample {
    // Obtention du logger par le nom de la classe
    private static final Logger logger = Logger.getLogger(LoggingExample.class.getName());

    public static void main(String[] args) {
        logger.info("L’application a démarré");
        logger.warning("Ceci est un avertissement !");
        logger.severe("Et ceci est déjà une erreur !");

        int x = 42;
        logger.fine("Variable de débogage x=" + x); // Non affiché par défaut
    }
}

Point important : par défaut, JUL affiche uniquement les niveaux INFO et supérieurs. Pour voir fine et d’autres messages détaillés, il faut configurer le niveau de journalisation.

Configuration via fichier

JUL peut être configuré via le fichier logging.properties (généralement situé dans le dossier JRE). On peut y indiquer :

  • Le niveau minimal pour le logger
  • Où écrire les journaux (fichier, console)
  • Le format des messages

Exemple de ligne dans logging.properties :

.level=INFO

4. Bibliothèques de journalisation externes

Log4j (Apache)

Log4j — l’une des bibliothèques de journalisation les plus connues pour Java. Elle est flexible, puissante, prend en charge différents formats, l’écriture asynchrone, la rotation de fichiers et bien plus encore.

Exemple de configuration Log4j 2 (XML) la plus simple :

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

Exemple d’utilisation de Log4j 2 dans le code :

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4jExample {
    private static final Logger logger = LogManager.getLogger(Log4jExample.class);

    public static void main(String[] args) {
        logger.info("Hello from Log4j!");
        logger.error("C'est une erreur via Log4j");
    }
}

Pour que cela fonctionne, vous devez ajouter les dépendances Log4j à votre projet (par exemple via Maven ou Gradle).

SLF4J : façade de journalisation

SLF4J (Simple Logging Facade for Java) — ce n’est pas un système de journalisation distinct, mais une « couche » entre votre code et une implémentation concrète (Log4j, Logback, JUL, etc.).

La façade est nécessaire pour écrire le code une seule fois et, si besoin, changer le système de journalisation réel sans réécrire le code, même si différentes bibliothèques utilisent des loggers différents.

Exemple d’utilisation de SLF4J :

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Slf4jExample {
    private static final Logger logger = LoggerFactory.getLogger(Slf4jExample.class);

    public static void main(String[] args) {
        logger.info("Bonjour, journalisation via SLF4J !");
        logger.warn("Attention: quelque chose peut mal se passer");
        logger.error("Erreur via SLF4J");
    }
}

Comment ça marche ?

  • Vous écrivez le code via SLF4J.
  • Vous ajoutez dans le classpath l’implémentation nécessaire (par exemple Logback ou Log4j).
  • SLF4J « redirige » lui-même les appels vers l’implémentation choisie.

Interaction de SLF4J avec d’autres loggers : SLF4J peut fonctionner au-dessus de JUL, Log4j, Logback, etc., ce qui permet de migrer facilement sans réécrire le code.

5. Pratique : comparaison entre System.out.println et la journalisation

Exemple 1 : System.out.println

public class PrintlnExample {
    public static void main(String[] args) {
        System.out.println("L’application a démarré");
        System.out.println("Une erreur s’est produite: quelque chose s’est mal passé");
    }
}

Ce qui ne va pas :

  • Pas de niveau de message (erreur, information, avertissement — tout est pareil).
  • Pas d’heure, pas de nom de classe, pas de thread.
  • Tous les messages vont dans le même « sac ».
  • Impossible de configurer finement l’affichage (par exemple, n’écrire que les erreurs).

Exemple 2 : journalisation via SLF4J + Logback

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggingVsPrintln {
    private static final Logger logger = LoggerFactory.getLogger(LoggingVsPrintln.class);

    public static void main(String[] args) {
        logger.info("L’application a démarré");
        logger.error("Une erreur s’est produite: quelque chose s’est mal passé");
    }
}

Avantages :

  • Chaque message est accompagné de l’heure, du niveau, du nom de la classe, du thread.
  • Possibilité de filtrer les messages par niveau.
  • Possibilité d’écrire les journaux dans un fichier, de les envoyer sur le réseau, de les formater, de les archiver.
  • La journalisation est thread-safe (pertinent pour les applications multithread).

Démonstration de la différence

System.out.println
Journalisation (SLF4J/Logback)
L’application a démarré 12:34:56 [main] INFO LoggingVsPrintln - L’application a démarré
Une erreur s’est produite: quelque chose s’est mal passé 12:34:56 [main] ERROR LoggingVsPrintln - Une erreur s’est produite: quelque chose s’est mal passé

6. Comment ajouter la journalisation à votre projet

Pour le logger standard (JUL)

Tout est déjà dans le JDK, vous pouvez l’utiliser immédiatement :

import java.util.logging.Logger;

public class MyApp {
    private static final Logger logger = Logger.getLogger(MyApp.class.getName());

    public static void main(String[] args) {
        logger.info("Ceci est un message d’info");
    }
}

Pour Log4j ou SLF4J

  1. Ajoutez les dépendances (par exemple, via Maven).

    Pour Log4j 2 :

    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.20.0</version>
    </dependency>
    

    Pour SLF4J + Logback :

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>2.0.7</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.4.7</version>
    </dependency>
    
  2. Créez un fichier de configuration (par exemple, logback.xml pour Logback ou log4j2.xml pour Log4j).
  3. Utilisez le logger dans votre code (voir les exemples ci-dessus).

7. Mini‑application : ajoutons la journalisation

Supposons que nous ayons une application simple — une calculatrice en ligne de commande. Ajoutons-y la journalisation.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Scanner;

public class CalculatorApp {
    private static final Logger logger = LoggerFactory.getLogger(CalculatorApp.class);

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        logger.info("La calculatrice est lancée");

        try {
            System.out.print("Saisissez le premier nombre: ");
            int a = Integer.parseInt(scanner.nextLine());
            logger.debug("Premier nombre saisi: {}", a);

            System.out.print("Saisissez le deuxième nombre: ");
            int b = Integer.parseInt(scanner.nextLine());
            logger.debug("Deuxième nombre saisi: {}", b);

            int sum = a + b;
            logger.info("Somme des nombres: {}", sum);
            System.out.println("Résultat: " + sum);
        } catch (NumberFormatException ex) {
            logger.error("Erreur de saisie du nombre", ex);
            System.out.println("Erreur: saisissez un nombre correct !");
        } catch (Exception ex) {
            logger.error("Erreur inconnue", ex);
            System.out.println("Une erreur s’est produite !");
        }
        logger.info("La calculatrice a terminé son travail");
    }
}

Ce qui se passe ici :

  • Tous les événements clés sont consignés dans le journal.
  • Les erreurs sont journalisées au niveau ERROR avec la trace de pile complète.
  • Toutes les informations sont disponibles pour analyse après l’exécution du programme.

8. Erreurs typiques lors de l’utilisation de la journalisation

Erreur n° 1 : utiliser uniquement System.out.println pour le débogage et le diagnostic.
C’est pratique au début, mais totalement inadapté aux applications réelles. Vous ne pourrez pas gérer le niveau des messages, vous ne verrez pas l’heure et vous ne pourrez pas analyser les journaux si le programme fonctionne sur un serveur.

Erreur n° 2 : journaliser un volume d’informations trop important au niveau ERROR.
Si vous écrivez tout comme une erreur, vous ne distinguerez plus ce qui est réellement important de ce qui est juste une information de débogage.

Erreur n° 3 : journaliser des données sensibles (mots de passe, jetons, numéros de carte).
Les journaux doivent être sûrs ! N’y écrivez pas ce que d’autres ne doivent pas voir.

Erreur n° 4 : absence de configuration de la journalisation.
Si vous ne configurez pas les niveaux, le format, l’emplacement de stockage des journaux — vous risquez de « vous noyer » dans des giga-octets d’informations inutiles ou de ne pas voir une erreur du tout.

Erreur n° 5 : ne pas utiliser de façade de journalisation (SLF4J) dans les grands projets.
Si votre projet grandit et passe d’une bibliothèque à une autre — sans façade, ce sera pénible. SLF4J permet de changer facilement le « moteur » de journalisation sans réécrire le code.

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION