Salut! Lors de la rédaction des leçons, j'insiste particulièrement s'il y a un sujet précis qui sera absolument essentiel dans le vrai travail. Alors, ÉCOUTEZ-VOUS ! Le sujet que nous aborderons aujourd'hui vous sera certainement utile dans tous vos projets dès le premier jour de votre emploi. Nous allons parler de Java Logging. Ce sujet n'est pas du tout compliqué (je dirais même facile). Mais vous aurez suffisamment de choses évidentes sur lesquelles insister lors de votre premier emploi, il est donc préférable de bien le comprendre dès maintenant :) Eh bien, commençons.

Qu'est-ce que la journalisation en Java ?

La journalisation est l'acte d'enregistrer des données sur le fonctionnement d'un programme. L'endroit où nous enregistrons ces données s'appelle un "journal". Deux questions se posent immédiatement : quelles données sont écrites et où ? Commençons par le "où". Vous pouvez écrire des données sur le travail d'un programme dans de nombreux endroits différents. Par exemple, pendant vos études, vous avez souvent System.out.println()pour envoyer des données à la console. Il s'agit bien de journalisation, quoique dans sa forme la plus simple. Bien sûr, ce n'est pas très pratique pour les utilisateurs ou une équipe de support produit : évidemment, ils ne voudront pas installer un IDE et surveiller la console :) Il existe un format plus courant pour enregistrer les informations : les fichiers texte. Les humains sont beaucoup plus à l'aise pour lire des données dans ce format, et c'est certainement beaucoup plus pratique pour stocker des données ! Maintenant, la deuxième question : quelles données de programme doivent être enregistrées ? Cela dépend entièrement de vous ! Le système de journalisation de Java est très flexible. Vous pouvez le configurer pour enregistrer tout ce que fait votre programme. D'un côté, c'est bien. Mais d'un autre côté, imaginez la taille des journaux de Facebook ou de Twitter s'ils y écrivaient tout. Ces grandes entreprises ont probablement la capacité de stocker autant de données. Mais imaginez à quel point il serait difficile de trouver des informations sur une erreur critique dans 500 gigaoctets de journaux de texte ? Ce serait pire que de chercher une aiguille dans une botte de foin. Par conséquent, Java peut être configuré pour consigner uniquement les données d'erreur. Ou même juste des erreurs critiques ! Cela dit, il n'est pas tout à fait exact de parler du système de journalisation natif de Java. Le fait est que les programmeurs avaient besoin d'une journalisation avant que cette fonctionnalité ne soit ajoutée au langage. Au moment où Java a introduit sa propre bibliothèque de journalisation, tout le monde utilisait déjà la bibliothèque log4j. L'histoire de la journalisation en Java est en fait très longue et instructive. En bref, Java a sa propre bibliothèque de journalisation, mais presque personne ne l'utilise :) Plus tard, Lorsque plusieurs bibliothèques de journalisation différentes sont apparues et ont commencé à être utilisées par les programmeurs, des problèmes de compatibilité sont apparus. Pour empêcher les gens de réinventer la roue dans une douzaine de bibliothèques différentes avec des interfaces différentes, le framework abstrait SLF4J ("Service Logging Facade For Java") a été créé. C'est ce qu'on appelle abstrait, car même si vous utilisez et appelez les méthodes des classes SLF4J, sous le capot, elles utilisent en fait tous les frameworks de journalisation précédents : log4j, le standard java.util.logging, et d'autres. Si, à un moment donné, vous avez besoin d'une fonctionnalité spécifique de Log4j manquant dans d'autres bibliothèques, mais que vous ne souhaitez pas lier directement votre projet à cette bibliothèque, utilisez simplement SLF4J. Et puis laissez-le appeler les méthodes Log4j. Si vous changez d'avis et décidez que vous n'avez plus besoin des fonctionnalités de Log4j, il vous suffit de reconfigurer le "ici , et la bibliothèque Log4j ici . Ensuite, décompressez l'archive et utilisez IntelliJ IDEA pour ajouter les fichiers JAR au chemin de classe. Éléments de menu : Fichier -> Structure du projet -> Bibliothèques Sélectionnez les fichiers JAR nécessaires et ajoutez-les au projet (les archives que nous avons téléchargées contiennent de nombreux fichiers JAR — regardez les images pour voir celles dont vous avez besoin) Notez que cette instruction pour ces Pourquoi nous avons besoin de journalisation - 2Pourquoi nous avons besoin de journalisation - 3étudiants qui ne savent pas utiliser Maven. Si vous savez utiliser Maven, il est généralement préférable (beaucoup plus facile) d'essayer de commencer par là. Si vous utilisez Maven , ajoutez cette dépendance :

    	<dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.14.0</version>
    	</dependency>
Super! Nous avons compris les paramètres :) Voyons comment fonctionne SLF4J. Comment s'assurer que le travail du programme est enregistré quelque part ? Pour ce faire, nous avons besoin de deux choses : logger et appender. Commençons par le premier. Un logger est un objet qui permet un contrôle total de la journalisation. Créer un logger est très simple : nous le faisons en utilisant les méthodes statiques LoggerFactory.getLogger() . Le paramètre method est la classe dont l'opération sera journalisée. Exécutons notre code :

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

public class MyTestClass {

   public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);

   public static void main(String[] args) {

       LOGGER.info("Test log entry!!!");
       LOGGER.error("An error occurred!");
   }
}
Sortie console :

ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2 15:49:08.907 [main] ERROR MyTestClass - An error occurred!
Que voyons-nous ici ? Tout d'abord, nous voyons un message d'erreur. Cela est dû au fait que nous manquons maintenant des paramètres nécessaires. Par conséquent, notre enregistreur ne peut actuellement émettre que des messages d'erreur (ERROR) et uniquement sur la console. La méthode logger.info() n'a pas fonctionné. Mais logger.error() l'a fait ! Sur la console, on voit la date du jour, la méthode où l'erreur s'est produite ( main), le mot "ERROR", et notre message ! ERROR est le niveau de journalisation. En général, si une entrée de journal est marquée par le mot "ERROR", une erreur s'est produite à ce stade du programme. Si l'entrée est marquée du mot "INFO", le message représente simplement les informations actuelles sur le fonctionnement normal du programme. La bibliothèque SLF4J possède de nombreux niveaux de journalisation différents qui vous permettent de configurer la journalisation de manière flexible. Tout est très facile à gérer : toute la logique nécessaire est déjà dans la classe Java Logger . Il vous suffit d'appeler les méthodes appropriées. Si vous souhaitez consigner un message de routine, appelez la méthode logger.info() . Pour un message d'erreur, utilisez logger.error() . Pour un avertissement, utilisez logger.warn()

Parlons maintenant de l'appender

Un appender est l'endroit où vont vos données. En quelque sorte, l'opposé d'une source de données, c'est-à-dire "le point B". Par défaut, les données sont envoyées à la console. Notez que dans l'exemple précédent, nous n'avions rien à configurer : le texte apparaissait dans la console et le journal de la bibliothèque Log4j ne pouvait envoyer que des messages de niveau ERROR à la console. De toute évidence, il est plus pratique pour les utilisateurs de lire et d'écrire des journaux dans un fichier texte. Pour modifier le comportement par défaut du logger, nous devons configurer notre fichier appender. Pour commencer, vous devez créer un fichier log4j.xml directement dans le dossier src. Vous connaissez déjà le format XML : nous avons récemment eu une leçon à ce sujet :) Voici le contenu du fichier :

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
   <Appenders>
       <File name="MyFileAppender" fileName="C:\Users\Username\Desktop\testlog.txt" immediateFlush="false" append="false">
           <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
       </File>
   </Appenders>
   <Loggers>
       <Root level="INFO">
           <AppenderRef ref="MyFileAppender"/>
       </Root>
   </Loggers>
</Configuration>
Rien de particulièrement spécial ou difficile ici :) Mais tout de même, passons en revue le contenu.
<Configuration status="INFO">
C'est le soi-disant StatusLogger. Il n'est pas lié à notre logger et est utilisé dans les processus internes de Log4j. Si vous définissez status="TRACE" au lieu de status="INFO", et toutes les informations sur le travail interne de Log4j seront affichées sur la console (StatusLogger affiche les données sur la console, même si notre appender est un fichier). Nous n'en avons pas besoin maintenant, alors laissons-le tel quel.

<Appenders>
   <File name="MyFileAppender" fileName="C:\Users\Evgeny\Desktop\testlog.txt" append="true">
       <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
   </File>
</Appenders>
Ici, nous créons notre appender. La balise <File> indique qu'il s'agira d'un ajout de fichier. name="MyFileAppender" définit le nom de l'appender. fileName="C:\Users\Username\Desktop\testlog.txt" indique le chemin vers le fichier journal où toutes les données seront écrites. append="true" indique si les données doivent être écrites à la fin du fichier. Dans notre cas, c'est précisément ce que nous allons faire. Si vous définissez la valeur sur false, l'ancien contenu du fichier journal sera supprimé à chaque démarrage du programme. <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>indique les paramètres de formatage. Ici, nous pouvons utiliser des expressions régulières pour personnaliser la mise en forme du texte dans notre journal.

<Loggers>
       <Root level="INFO">
           <AppenderRef ref="MyFileAppender"/>
       </Root>
</Loggers>
Ici, nous indiquons le niveau racine. Nous avons défini le niveau "INFO", ce qui signifie que tous les messages dont les niveaux sont supérieurs à INFO (selon le tableau que nous avons consulté ci-dessus) ne seront pas enregistrés. Notre programme aura 3 messages : un INFO, un WARN et un ERROR. Avec la configuration actuelle, les 3 messages seront enregistrés. Si vous modifiez le niveau racine en ERROR, seul le dernier message de l'appel de la méthode LOGGER.error() se retrouvera dans le journal. De plus, une référence à l'appender va également ici. Pour créer une telle référence, vous devez créer une balise <ApprenderRef> à l'intérieur de la balise <Root> et y ajouter l'attribut ref='your appender's name' . Au cas où vous l'auriez oublié, c'est ici que nous définissons le nom de l'appender : <. Et voici notre code !

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

public class MyTestClass {

   public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);

   public static void main(String[] args) {

       LOGGER.info("The program is starting!!!");

       try {
           LOGGER.warn("Attention! The program is trying to divide a number by another.
           System.out.println(12/0);
       } catch (ArithmeticException x) {

           LOGGER.error("Error! Division by zero!");
       }
   }
}
Bien sûr, c'est un peu farfelu (attraper une RuntimeException est une idée discutable), mais c'est parfait pour nos besoins :) Exécutons notre méthode main() 4 fois de suite et regardons notre fichier testlog.txt. Vous n'avez pas besoin de le créer à l'avance : la bibliothèque le fera automatiquement. Tout a fonctionné ! :) Vous avez maintenant un enregistreur configuré. Vous pouvez jouer avec certains de vos anciens programmes, en ajoutant des appels d'enregistreur à chaque méthode. Ensuite, regardez le journal résultant :) Il considère le sujet de la journalisation en profondeur. Il serait difficile de tout lire en une seule séance. Cela dit, il contient de nombreuses informations utiles supplémentaires. Par exemple, vous apprendrez à configurer le logger pour qu'il crée un nouveau fichier texte si notre fichier testlog.txt atteint une certaine taille :) Et cela conclut notre cours ! Aujourd'hui, vous vous êtes familiarisé avec un sujet très important, et cette connaissance vous sera certainement utile dans vos futurs travaux. Jusqu'à la prochaine fois! :)