2.1 Premier enregistreur - log4j

Comme vous le savez déjà, l'historique des journaux a commencé avec System.err.println()la sortie d'un enregistrement sur la console. Il est toujours activement utilisé pour le débogage, par exemple, Intellij IDEA l'utilise pour afficher des messages d'erreur sur la console. Mais cette option n'a aucun paramètre, alors passons à autre chose.

Le premier et le plus populaire des enregistreurs s'appelait Log4j. C'était une bonne solution hautement personnalisable. En raison de diverses circonstances, cette décision n'est jamais entrée dans le JDK, ce qui a grandement bouleversé toute la communauté.

Cet enregistreur n'était pas seulement capable de se connecter, il a été créé par des programmeurs pour des programmeurs et leur a permis de résoudre des problèmes qui se posaient constamment en rapport avec la journalisation.

Comme vous le savez déjà, les journaux sont écrits à la fin afin qu'une personne les lise et essaie de comprendre ce qui s'est passé pendant le fonctionnement du programme - quoi et quand s'est mal passé comme prévu.

Il y log4javait trois choses pour cela :

  • journalisation des sous-paquetages ;
  • ensemble d'appendices (résultats) ;
  • paramètres de rechargement à chaud.

Premièrement, les paramètres log4jpeuvent être écrits de manière à activer la journalisation dans un package et à la désactiver dans un autre. Par exemple, il était possible d'activer la journalisation dans le com.codegym.server, mais de la désactiver dans le com.codegym.server.payment. Cela a permis de supprimer rapidement les informations inutiles du journal.

Deuxièmement, log4jcela permettait d'écrire les résultats de journalisation dans plusieurs fichiers journaux à la fois. Et la sortie de chacun peut être configurée individuellement. Par exemple, dans un fichier, il était possible d'écrire uniquement des informations sur les erreurs graves, dans un autre - les journaux d'un module spécifique et dans un troisième - les journaux pendant un certain temps.

Chaque fichier journal était ainsi adapté à un type particulier de problème attendu. Cela simplifie grandement la vie des programmeurs qui n'aiment pas parcourir manuellement les fichiers journaux de gigaoctets.

Et enfin, troisièmement, log4jcela permettait de modifier les paramètres du journal directement pendant que le programme était en cours d'exécution, sans le redémarrer. C'était très pratique lorsqu'il fallait corriger le travail des journaux afin de trouver des informations supplémentaires sur une erreur spécifique.

Important! Il existe deux versions du journal log4j: 1.2.x et 2.xx , qui sont incompatibles entre elles .

Vous pouvez connecter le logger au projet en utilisant le code :

<dependencies>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.2</version>
  </dependency>

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

2.2 Premier enregistreur officiel - JUL : java.util.logging

Après l'apparition du zoo des enregistreurs dans la communauté Java, les développeurs JDKont décidé de créer un enregistreur standard que tout le monde utiliserait. Voici comment le logger est apparu JUL: package java.util.logging.

Cependant, lors de son développement, les créateurs de l'enregistreur n'ont pas pris pour base log4j, mais une variante de l'enregistreur d'IBM, qui a influencé son développement. La bonne nouvelle est que l'enregistreur JULest inclus JDK, la mauvaise nouvelle est que peu de gens l'utilisent.

JUIL

Non seulement les développeurs JULont créé "un autre standard universel" , mais ils ont également créé leurs propres niveaux de journalisation, qui différaient de ceux acceptés par les enregistreurs populaires à l'époque.

Et c'était un gros problème. Après tout, les produits sont Javasouvent collectés dans un grand nombre de bibliothèques, et chacune de ces bibliothèques avait son propre enregistreur. Il a donc fallu configurer tous les loggers qui se trouvent dans l'application.

Bien que l'enregistreur lui-même soit plutôt bon. La création d'un enregistreur est plus ou moins la même chose. 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écialement passé afin de savoir d'où vient la journalisation.

Ce n'est qu'avec la version que les développeurs ont résolu des problèmes importants, après quoi il JULest vraiment pratique à utiliser. Avant cela, c'était une sorte d'enregistreur de second ordre.

Cet enregistreur prend également en charge les expressions lambda et l'évaluation paresseuse. À partir de Java 8, vous pouvez passer Supplier<String>. Cela permet de lire et de créer une chaîne uniquement au moment où elle est vraiment nécessaire, et pas à chaque fois, comme c'était le cas auparavant.

Les méthodes avec un argument Supplier<String> msgSupplierressemblent à ceci :

public void info(Supplier msgSupplier) {
   log(Level.INFO, msgSupplier);
}

2.3 Premier wrapper de journalisation - JCL : jakarta commons logging

Pendant longtemps il n'y a pas eu de standard unique chez les bûcherons, ça JULaurait dû en devenir un, mais c'était pire log4j, donc un standard unique n'est jamais apparu. Mais tout un zoo de bûcherons est apparu, chacun voulant devenir le même.

JCL

Cependant, les développeurs Java ordinaires n'aimaient pas que presque chaque bibliothèque ait son propre enregistreur et doive être configurée d'une manière spéciale. Par conséquent, la communauté a décidé de créer un emballage spécial par rapport aux autres enregistreurs - c'est ainsi queJCL: jakarta commons logging

Et encore une fois, le projet, qui a été créé pour être un leader, ne l'est pas devenu. Vous ne pouvez pas créer un gagnant, vous ne pouvez que devenir un gagnant. La fonctionnalité JCLétait très médiocre et personne ne voulait l'utiliser. Le logger, destiné à remplacer tous les loggers, a connu le même sort puisqu'il JULn'a pas été utilisé.

Bien qu'il ait été ajouté à de nombreuses bibliothèques publiées par la communauté Apache, le zoo des enregistreurs n'a fait que croître.

2.4 Premier dernier enregistreur - Logback

Mais ce n'est pas tout. Le développeur log4ja décidé qu'il était le plus intelligent (enfin, après tout, la plupart des gens utilisaient son enregistreur) et a décidé d'écrire un nouvel enregistreur amélioré qui combinerait les avantages log4jdes autres enregistreurs.

Le nouvel enregistreur s'appelait Logback. C'est cet enregistreur qui devait devenir le futur enregistreur unique que tout le monde utiliserait. Il était basé sur la même idée que dans log4j.

Vous pouvez connecter ce logger au projet en utilisant le code :

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.6</version>
</dependency>

Les différences portaient sur Logback:

  • performance améliorée;
  • support natif ajouté slf4j;
  • option de filtrage étendue.

Un autre avantage de cet enregistreur était qu'il avait de très bons paramètres par défaut. Et vous deviez configurer l'enregistreur uniquement si vous vouliez y changer quelque chose. De plus, le fichier de paramètres était mieux adapté aux logiciels d'entreprise - toutes ses configurations étaient définies en tant que xml/.

Par défaut, Logbackil ne nécessite aucun paramètre et enregistre tous les journaux du niveau DEBUGet au-dessus. Si vous avez besoin d'un comportement différent, il peut être configuré via xmlconfiguration :

<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>

2.5 Dernier enregistreur universel - SLF4J : Façade de journalisation simple pour Java

Combien de temps peut-il falloir pour trouver le juste milieu...

En 2006, l'un des créateurs log4ja quitté le projet et a décidé de réessayer de créer un enregistreur universel. Mais cette fois, il ne s'agissait pas d'un nouveau logger, mais d'un nouveau standard universel (wrapper) qui permettait à différents loggers d'interagir ensemble.

Cet enregistreur s'appelait slf4j — Simple Logging Facade for Java, c'était un wrapper autour de log4j, JUL, common-loggins and logback. Cet enregistreur a résolu un vrai problème - gérer un zoo d'enregistreurs, donc tout le monde a immédiatement commencé à l'utiliser.

Nous résolvons héroïquement les problèmes que nous nous créons. Comme vous pouvez le voir, les progrès ont atteint le point où nous avons créé un wrapper sur le wrapper ...

L'enveloppe elle-même se compose de deux parties :

  • API, qui est utilisé dans les applications ;
  • Implémentations ajoutées en tant que dépendances distinctes pour chaque enregistreur.

Vous pouvez connecter le logger au projet en utilisant le code :

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.17.2</version>
</dependency>

Il suffit de connecter la bonne implémentation et c'est tout : tout le projet fonctionnera avec.

2.6 Optimisation dans slf4j

Slf4jprend en charge toutes les nouvelles fonctionnalités telles que le formatage des chaînes pour la journalisation . Avant cela, il y avait un tel problème. Supposons que vous souhaitiez imprimer un message dans le journal :

log.debug("User " + user + " connected from " + request.getRemoteAddr());

Il y a un problème avec ce code. Supposons que votre application fonctionne productionet n'en écrive pas dans le log DEBUG-messages, cependant, la méthode log.debug()sera toujours appelée, et lorsqu'elle sera appelée, les méthodes suivantes seront également appelées :

  • user.toString();
  • request.getRemoteAddr();

L'appel de ces méthodes ralentit l'application. Leur appel n'est nécessaire que pendant le débogage, mais ils sont quand même appelés.

Du point de vue de la logique, ce problème devait être résolu dans la bibliothèque de journalisation elle-même. Et dans la première version de log4j, la solution est apparue :

if (log.isDebugEnabled()) {
    log.debug("User " + user + " connected from " + request.getRemoteAddr());
}

Au lieu d'une ligne pour le journal, il fallait maintenant en écrire trois. Ce qui a considérablement aggravé la lisibilité du code et réduit la popularité de log4j.

L'enregistreur slf4ja pu améliorer légèrement la situation en proposant une journalisation intelligente. Ça ressemblait à ça :

log.debug("User {} connected from {}", user, request.getRemoteAddr());

{}dénotent l'insertion d'arguments passés dans la méthode. Autrement dit, le premier {}correspond à l'utilisateur, le second {}à request.getRemoteAddr().

Ces paramètres seront concaténés en un seul message uniquement si le niveau de journalisation autorise la journalisation. Pas parfait, mais mieux que toutes les autres options.

Après cela, SLF4Jil a commencé à gagner rapidement en popularité, pour le moment c'est la meilleure solution.

Par conséquent, nous considérerons la journalisation en utilisant l'exemple d'un bundle slf4j-log4j12.