JavaRush /Blog Java /Random-FR /Se connecter en Java : quoi, comment, où et avec quoi ?
Roman Beekeeper
Niveau 35

Se connecter en Java : quoi, comment, où et avec quoi ?

Publié dans le groupe Random-FR
Bonjour à tous, communauté JavaRush ! Aujourd'hui, nous allons parler de la journalisation Java :
  1. Qu'est-ce que c'est, pourquoi. Dans quels cas est-il préférable de l'utiliser, dans quels cas ne l'est-il pas ?
  2. Quelles sont les différentes implémentations de la journalisation en Java et que devons-nous faire de cette diversité ?
  3. Niveaux de journalisation. Discutons de ce qu'est l'appender et de comment le configurer correctement.
  4. Nœuds de journalisation et comment les configurer correctement pour que tout fonctionne comme nous le souhaitons.
Ce matériel est destiné à un large public. Cela sera clair à la fois pour ceux qui viennent tout juste de se familiariser avec Java et pour ceux qui travaillent déjà, mais qui ne l'ont compris qu'avec logger.info(“log something”); Let's Go !

Pourquoi la journalisation est-elle nécessaire ?

Examinons des cas réels dans lesquels la journalisation résoudrait le problème. Voici un exemple de mon travail. Il existe des points d'application qui s'intègrent à d'autres services. J'utilise la journalisation de ces points comme « alibi » : si l'intégration ne fonctionne pas, il sera facile de savoir de quel côté vient le problème. Il est également conseillé de consigner les informations importantes enregistrées dans la base de données. Par exemple, créer un utilisateur administrateur. C’est exactement ce qu’il serait bon de consigner.

Outils de journalisation Java

Exploitation forestière : quoi, comment, où et avec quoi ?  - 2Les solutions bien connues pour la journalisation en Java incluent :
  • log4j
  • JUILLET - java.util.logging
  • JCL - journalisation de Jakarta Commons
  • Reconnexion
  • SLF4J - façade de journalisation simple pour Java
Jetons un coup d'œil rapide à chacun d'eux, et dans la partie pratique du matériel, nous prendrons comme base la connexion Slf4j - log4j . Cela peut paraître étrange maintenant, mais ne vous inquiétez pas : à la fin de l’article, tout sera clair.

Système.err.println

Au départ, bien sûr, il y avait System.err.println (sortie d'enregistrement sur la console). Il est toujours utilisé pour obtenir rapidement un journal lors du débogage. Bien sûr, il n’est pas nécessaire de parler de paramètres ici, alors rappelons-nous-en et passons à autre chose.

Log4j

Il s'agissait déjà d'une solution à part entière, créée à partir des besoins des développeurs. Cela s’est avéré être un outil vraiment intéressant à utiliser. En raison de diverses circonstances, cette solution n'a jamais été intégrée au JDK, ce qui a grandement bouleversé l'ensemble de la communauté. log4j avait des options de configuration afin que la journalisation puisse être activée dans un package com.example.typeet désactivée dans un sous-package com.example.type.generic. Cela a permis de séparer rapidement ce qui devait être enregistré de ce qui ne l'était pas. Il est important de noter ici qu'il existe deux versions de log4j : 1.2.x et 2.x.x, qui sont incompatibles entre elles . log4j a ajouté un concept tel que appender , c'est-à-dire un outil avec lequel les journaux sont enregistrés et mis en page - le formatage des journaux. Cela vous permet d'enregistrer uniquement ce dont vous avez besoin et comment vous en avez besoin. Nous parlerons davantage d'appender un peu plus tard.

JUILLET - java.util.logging

L'un des principaux avantages est la solution : JUL est inclus dans le JDK (Java development kit). Malheureusement, lors de son développement, ce n'est pas le populaire log4j qui a été pris comme base, mais une solution d'IBM qui a influencé son développement. En fait, il existe actuellement JUL, mais personne ne l'utilise. Du « couci-couça » : dans JUL, les niveaux de journalisation sont différents de ceux de Logback, Log4j, Slf4j, et cela détériore la compréhension entre eux. Créer un enregistreur est plus ou moins similaire. Pour ce faire, vous devez importer :
java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggingJul.class.getName());
Le nom de la classe est spécifiquement transmis afin de savoir d'où vient la journalisation. Depuis Java 8, il est possible de passer Supplier<String>. Cela permet de compter et de créer une chaîne uniquement au moment où cela est vraiment nécessaire, et non à chaque fois, comme c'était le cas auparavant. Ce n'est qu'avec la sortie de Java 8 que les développeurs ont résolu des problèmes importants, après quoi JUL est devenu véritablement utilisable. À savoir, les méthodes avec l'argument Supplier<String> msgSuppliercomme indiqué ci-dessous :
public void info(Supplier<String> msgSupplier) {
   log(Level.INFO, msgSupplier);
}

JCL - journalisation de Jakarta Commons

Étant donné que pendant longtemps il n'y avait pas de norme industrielle en matière de journalisation et qu'il fut un temps où de nombreuses personnes créaient leur propre enregistreur personnalisé, ils ont décidé de publier JCL - un wrapper commun qui serait utilisé par rapport aux autres. Pourquoi? Lorsque certaines dépendances étaient ajoutées au projet, elles pouvaient utiliser un enregistreur différent de celui du projet. Pour cette raison, ils ont été ajoutés de manière transitoire au projet, ce qui a créé de réels problèmes lors de la tentative de mise en place du tout. Malheureusement, le wrapper était très peu fonctionnel et n'introduisait aucun ajout. Ce serait probablement pratique si tout le monde utilisait JCL pour faire son travail. Mais en réalité, cela n’a pas fonctionné de cette façon, donc utiliser JCL n’est pas une bonne idée pour le moment.

Reconnexion

Comme le chemin de l'open source est épineux... Logback a été écrit par le même développeur que log4j pour lui créer un successeur. L'idée était la même que celle de log4j. Les différences étaient celles de la connexion :
  • performance améliorée;
  • ajout du support natif pour slf4j ;
  • L'option de filtrage a été étendue.
Par défaut, la reconnexion ne nécessite aucun paramètre et enregistre tous les journaux du niveau DEBUG et supérieur. Si une configuration est nécessaire, elle peut être effectuée via la configuration XML :
<configuration>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>app.log</file>
        <encoder>
            <pattern>%d{HH:mm:ss,SSS} %-5p [%c] - %m%n</pattern>
        </encoder>
    </appender>
    <logger name="org.hibernate.SQL" level="DEBUG" />
    <logger name="org.hibernate.type.descriptor.sql" level="TRACE" />
    <root level="info">
        <appender-ref ref="FILE" />
    </root>
</configuration>

SLF4J - façade de journalisation simple pour Java

Vers 2006, l'un des pères fondateurs de log4j a quitté le projet et a créé slf4j - Simple Logging Facade for Java - un wrapper autour de log4j, JUL, common-loggins et logback. Comme vous pouvez le constater, les progrès ont atteint le point où ils ont créé un wrapper au-dessus du wrapper... De plus, il est divisé en deux parties : l'API, qui est utilisée dans l'application, et l'implémentation, qui est ajoutée en tant que dépendances distinctes pour chaque type de journalisation. Par exemple, slf4j-log4j12.jar, slf4j-jdk14.jar. Il suffit de connecter la bonne implémentation et c'est tout : tout le projet fonctionnera avec elle. Slf4j prend en charge toutes les nouvelles fonctionnalités telles que le formatage des chaînes pour la journalisation. Il y avait un tel problème auparavant. Disons qu'il y a une entrée de journal :
log.debug("User " + user + " connected from " + request.getRemoteAddr());
userIl y a une conversion implicite dans l'objet user.toString()en raison de la concaténation de chaînes, et cela prend du temps, ce qui ralentit le système. Et tout va bien si nous débogueons l’application. Les problèmes commencent si le niveau de journalisation pour cette classe est INFO ou supérieur. Autrement dit, ce journal ne doit pas être écrit et la concaténation de chaînes ne doit pas non plus être effectuée. En théorie, cela aurait dû être décidé par la bibliothèque de journalisation elle-même. De plus, cela s’est avéré être le plus gros problème de la première version de log4j. Ils n’ont pas proposé de solution normale, mais ont suggéré de procéder comme ceci :
if (log.isDebugEnabled()) {
    log.debug("User " + user + " connected from " + request.getRemoteAddr());
}
Autrement dit, au lieu d'une ligne de journalisation, ils ont suggéré d'en écrire 3 (!). La journalisation devrait minimiser les modifications apportées au code, et trois lignes contredisaient clairement l'approche générale. slf4j n'a eu aucun problème de compatibilité avec le JDK et l'API, donc une belle solution a immédiatement émergé :
log.debug("User {} connected from {}", user, request.getRemoteAddr());
{}désignent les insertions d’arguments passés dans la méthode. Autrement dit, le premier {}correspond à user, le second {}- request.getRemoteAddr(). De ce fait, ce message ne peut être concaténé en un seul que si le niveau de journalisation le permet. Après cela, SJF4J a rapidement gagné en popularité et constitue actuellement la meilleure solution. Par conséquent, nous envisagerons la journalisation en utilisant l'exemple d'un bundle slf4j-log4j12.

Ce qui doit être enregistré

Bien sûr, vous ne devriez pas tout enregistrer. Cela s’avère parfois inutile et même dangereux. Par exemple, si vous mettez en gage les données personnelles d’une personne et que celles-ci sont révélées d’une manière ou d’une autre, il y aura de réels problèmes, notamment dans les projets orientés vers l’Occident. Mais il y a aussi quelque chose qui est obligatoire à loguer :
  1. Début/fin de l'application. Nous devons savoir que l’application s’est réellement lancée comme prévu et s’est terminée comme prévu.
  2. Questions de sécurité. Ici, il serait bon de consigner les tentatives de deviner le mot de passe, les connexions des utilisateurs importants, etc.
  3. Certains états d'application . Par exemple, le passage d’un état à un autre dans un processus métier.
  4. Quelques informations pour le débogage , avec un niveau de journalisation approprié.
  5. Quelques scripts SQL. Il existe des cas réels où cela est nécessaire. Encore une fois, en ajustant habilement les niveaux, d’excellents résultats peuvent être obtenus.
  6. Les threads exécutés (Thread) peuvent être enregistrés dans les cas où le bon fonctionnement est vérifié.

Erreurs de journalisation courantes

Il existe de nombreuses nuances, mais voici quelques erreurs courantes :
  1. Journalisation excessive. Vous ne devriez pas enregistrer chaque étape qui pourrait théoriquement être importante. Il existe une règle : les journaux ne peuvent pas charger les performances de plus de 10 %. Sinon, il y aura des problèmes de performances.
  2. Enregistrer toutes les données dans un seul fichier. Cela rendra la lecture/écriture très difficile à un certain moment, sans compter qu'il existe des limites de taille de fichier sur certains systèmes.
  3. Utilisation de niveaux de journalisation incorrects. Chaque niveau de journalisation a des limites claires et doit être respecté. Si la limite est vague, vous pouvez vous mettre d’accord sur le niveau à utiliser.

Niveaux de journalisation

x : Visible
FATAL ERREUR AVERTIR INFO DÉBOGUER TRACER TOUS
DÉSACTIVÉ
FATAL X
ERREUR X X
AVERTIR X X X
INFO X X X X
DÉBOGUER X X X X X
TRACER X X X X X X
TOUS X X X X X X X
Que sont les niveaux de journalisation ? Afin de classer les journaux d'une manière ou d'une autre, il était nécessaire de donner certaines désignations et distinctions. À cette fin, des niveaux de journalisation ont été introduits. Le niveau est défini dans l'application. Si une entrée appartient à un niveau inférieur à celui désigné, elle n'est pas inscrite dans le journal. Par exemple, nous avons des journaux utilisés pour déboguer l'application. Dans le cadre d'un travail de production normal (lorsque l'application est utilisée aux fins prévues), ces journaux ne sont pas nécessaires. Par conséquent, le niveau de journalisation sera plus élevé que celui du débogage. Regardons les niveaux en utilisant log4j comme exemple. D'autres solutions, sauf JUL, utilisent les mêmes niveaux. Les voici par ordre décroissant :
  • OFF : aucun journal n'est écrit, tous seront ignorés ;
  • FATALE : une erreur après laquelle l'application ne pourra plus fonctionner et sera arrêtée, par exemple, erreur JVM hors mémoire ;
  • ERREUR : le taux d'erreur lorsqu'il y a des problèmes qui doivent être résolus. L'erreur n'arrête pas l'application dans son ensemble. D'autres requêtes peuvent fonctionner correctement ;
  • WARN : indique les journaux qui contiennent un avertissement. Une action inattendue s'est produite, mais le système a résisté et a complété la demande ;
  • INFO : un journal qui enregistre les actions importantes dans l'application. Ce ne sont pas des erreurs, ce ne sont pas des avertissements, ce sont des actions attendues du système ;
  • DEBUG : journaux nécessaires au débogage de l’application. Pour s’assurer que le système fait exactement ce qu’on attend de lui, ou pour décrire l’action du système : « la méthode 1 a commencé à fonctionner » ;
  • TRACE : journaux de priorité inférieure pour le débogage, avec le niveau de journalisation le plus bas ;
  • ALL : niveau auquel tous les journaux du système seront enregistrés.
Il s'avère que si le niveau de journalisation INFO est activé à un endroit de l'application, tous les niveaux seront enregistrés, à partir de INFO jusqu'à FATAL. Si le niveau de journalisation est FATAL, seuls les journaux avec ce niveau seront enregistrés.

Logs d’enregistrement et d’envoi : Appender

Nous considérerons ce processus en utilisant log4j comme exemple : il offre de nombreuses possibilités d'enregistrement/envoi de journaux :
  • pour écrire dans un fichier - solution DailyRollingFileAppender ;
  • pour recevoir des données dans la console de l'application - ConsoleAppender ;
  • pour écrire des journaux dans la base de données - JDBCAppender ;
  • pour contrôler la transmission via TCP/IP - TelnetAppender ;
  • pour garantir que la journalisation n'affecte pas les performances - AsyncAppender .
Il existe plusieurs autres implémentations : la liste complète peut être trouvée ici . À propos, si l'appender requis n'est pas disponible, ce n'est pas un problème. Vous pouvez écrire votre propre appender en implémentant l' interface Appender , qui accepte simplement log4j.

Nœuds de journalisation

Pour la démonstration, nous utiliserons l'interface slf4j et l'implémentation de log4j. Créer un logger est très simple : vous devez écrire ce qui suit dans une classe nommée MainDemo, dans laquelle la journalisation sera effectuée :
org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MainDemo.class);
Cela créera un enregistreur pour nous. Pour créer une entrée de journal, vous pouvez utiliser de nombreuses méthodes qui indiquent à quel niveau les entrées seront effectuées. Par exemple:
logger.trace("Method 1 started with argument={}", argument);
logger.debug("Database updated with script = {}", script);
logger.info("Application has started on port = {}", port);
logger.warn("Log4j didn't find log4j.properties. Please, provide them");
logger.error("Connection refused to host = {}", host);
Même si nous réussissons la classe, c'est finalement le nom complet de la classe avec les packages qui est écrit. Ceci est fait afin que vous puissiez ensuite diviser la journalisation en nœuds et configurer un niveau de journalisation et un appender pour chaque nœud. Par exemple, le nom de la classe : com.github.romankh3.logginglecture.MainDemo- un logger y a été créé. Et c'est ainsi qu'il peut être divisé en nœuds de journalisation. Le nœud principal est le RootLogger nul . C'est le nœud qui reçoit tous les journaux de l'ensemble de l'application. Le reste peut être représenté comme indiqué ci-dessous : Exploitation forestière : quoi, comment, où et avec quoi ?  - 4Les appenders configurent leur travail spécifiquement sur les nœuds de journalisation. Maintenant, en utilisant log4j.properties comme exemple , nous verrons comment les configurer.

Configuration étape par étape de Log4j.properties

Nous allons maintenant tout configurer étape par étape et voir ce qui peut être fait :
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
Cette ligne indique que nous enregistrons un appender CONSOLE qui utilise l'implémentation org.apache.log4j.ConsoleAppender. Cet appender écrit des données sur la console. Ensuite, enregistrons un autre appender qui écrira dans un fichier :
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
Il est important de noter que les appenders devront toujours être configurés. Une fois que nous avons déjà enregistré les appenders, nous pouvons déterminer quel niveau de journalisation sera dans les nœuds et quels appenders seront utilisés.

log4j.rootLogger=DEBUG, CONSOLE, FICHIER

  • log4j.rootLogger signifie que nous allons configurer le nœud principal, qui contient tous les journaux ;
  • après le signe égal, le premier mot indique à quel niveau et plus les logs seront enregistrés (dans notre cas, il s'agit de DEBUG) ;
  • puis après la virgule, tous les appendeurs qui seront utilisés sont indiqués.
Pour configurer un nœud de journalisation spécifique, vous devez utiliser l'entrée suivante :
log4j.logger.com.github.romankh3.logginglecture=TRACE, OWN, CONSOLE
log4j.logger.il est utilisé pour configurer un nœud spécifique, dans notre cas c'est le cas. com.github.romankh3.logginglecture. Parlons maintenant de la configuration de l'appender CONSOLE :
# CONSOLE appender customisation
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.threshold=DEBUG
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%-5p] : %c:%L : %m%n
Ici, nous voyons que nous pouvons définir le niveau à partir duquel l'appender sera traité. Situation réelle : un message avec le niveau info a été reçu par le nœud de journalisation et transmis à l'appender qui lui est attribué, mais l'appender, avec le niveau warn et supérieur, a accepté ce journal, mais n'en a rien fait. Ensuite, vous devez décider quel modèle figurera dans le message. J'utilise PatternLayout dans l'exemple, mais il existe de nombreuses solutions. Ils ne seront pas divulgués dans cet article. Un exemple de configuration d'un appender FILE :
# File appender customisation
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.File=./target/logging/logging.log
log4j.appender.FILE.MaxFileSize=1MB
log4j.appender.FILE.threshold=DEBUG
log4j.appender.FILE.MaxBackupIndex=2
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[ %-5p] - %c:%L - %m%n
Ici, vous pouvez configurer dans quel fichier les journaux seront écrits, comme le montre
log4j.appender.FILE.File=./target/logging/logging.log
L'enregistrement va dans le fichier logging.log. Pour éviter des problèmes avec la taille du fichier, vous pouvez définir le maximum : dans ce cas, 1 Mo. MaxBackupIndex - indique le nombre de fichiers de ce type. Si plus de ce nombre est créé, le premier fichier sera supprimé. Pour voir un exemple réel de configuration de la journalisation, vous pouvez accéder au référentiel ouvert sur GitHub.

Consolidons le résultat

Essayez de faire tout ce qui est décrit vous-même :
  • Créez votre propre projet similaire à celui de l'exemple ci-dessus.
  • Si vous connaissez l’utilisation de Maven, nous l’utiliserons ; sinon, voici un lien vers un article décrivant comment connecter la bibliothèque.

Résumons-le

  1. Nous avons parlé des solutions disponibles en Java.
  2. Presque toutes les bibliothèques de journalisation connues ont été écrites sous le contrôle d'une seule personne :D
  3. Nous avons appris ce qui doit être enregistré et ce qui ne l'est pas.
  4. Nous avons déterminé les niveaux de journalisation.
  5. Nous nous sommes familiarisés avec les nœuds de journalisation.
  6. Nous avons examiné ce qu'est un appender et à quoi il sert.
  7. Nous avons configuré le fichier log4j.proterties étape par étape.

Matériaux additionnels

  1. JavaRush : journalisation. Dérouler une boule de stectrace
  2. JavaRush : conférence sur l'enregistreur
  3. Habr : journalisation Java. Bonjour le monde
  4. Habr : Journalisation Java : l'histoire d'un cauchemar
  5. Youtube : cours Golovach. Enregistrement. Partie 1 , Partie 2 , Partie 3 , Partie 4
  6. Log4j : appendeur
  7. Log4j : mise en page
Voir aussi mes autres articles :
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION