Vous voulez regarder un cadre de journalisation, et peut-être un cadre de façade de journalisation.
Il existe plusieurs cadres de journalisation, souvent avec des fonctionnalités qui se chevauchent, à tel point qu'au fil du temps, beaucoup ont évolué pour s'appuyer sur une API commune, ou ont fini par être utilisés à travers un cadre de façade pour abstraire leur utilisation et leur permettre d'être échangés sur place si besoin.
Cadres
Quelques cadres de journalisation
Quelques façades forestières
Usage
Exemple de base
La plupart de ces frameworks vous permettraient d'écrire quelque chose du formulaire (ici en utilisant slf4j-api
et logback-core
):
package chapters.introduction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// copied from: http://www.slf4j.org/manual.html
public class HelloWorld {
public static void main(String[] args) {
final Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.debug("Hello world, I'm a DEBUG level message");
logger.info("Hello world, I'm an INFO level message");
logger.warn("Hello world, I'm a WARNING level message");
logger.error("Hello world, I'm an ERROR level message");
}
}
Notez l'utilisation d'une classe actuelle pour créer un enregistreur dédié, ce qui permettrait à SLF4J / LogBack de formater la sortie et d'indiquer la provenance du message de journalisation.
Comme indiqué dans le manuel SLF4J , un modèle d'utilisation typique dans une classe est généralement:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyClass {
final Logger logger = LoggerFactory.getLogger(MyCLASS.class);
public void doSomething() {
// some code here
logger.debug("this is useful");
if (isSomeConditionTrue()) {
logger.info("I entered by conditional block!");
}
}
}
Mais en fait, il est encore plus courant de déclarer l'enregistreur avec le formulaire:
private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class);
Cela permet également à l'enregistreur d'être utilisé à partir de méthodes statiques, et il est partagé entre toutes les instances de la classe. Il s'agit très probablement de votre forme préférée. Cependant, comme l'a noté Brendan Long dans les commentaires, vous voulez être sûr de comprendre les implications et de décider en conséquence (cela s'applique à tous les cadres de journalisation suivant ces idiomes).
Il existe d'autres façons d'instancier des enregistreurs, par exemple en utilisant un paramètre de chaîne pour créer un enregistreur nommé:
Logger logger = LoggerFactory.getLogger("MyModuleName");
Niveaux de débogage
Les niveaux de débogage varient d'un framework à l'autre, mais les plus courants sont (par ordre de criticité, de bénin à mauvais, et de probablement très commun à, espérons-le, très rare):
TRACE
Information très détaillée. Doit être écrit dans les journaux uniquement. Utilisé uniquement pour suivre le flux du programme aux points de contrôle.
DEBUG
Des informations détaillées. Doit être écrit dans les journaux uniquement.
INFO
Événements d'exécution notables. Doit être immédiatement visible sur une console, donc utilisez-le avec parcimonie.
WARNING
Curiosités d'exécution et erreurs récupérables.
ERROR
Autres erreurs d'exécution ou conditions inattendues.
FATAL
Erreurs graves entraînant une résiliation prématurée.
Blocs et gardes
Supposons maintenant que vous ayez une section de code où vous êtes sur le point d'écrire un certain nombre d'instructions de débogage. Cela pourrait rapidement affecter vos performances, à la fois en raison de l'impact de la journalisation elle-même et de la génération de tous les paramètres que vous pourriez transmettre à la méthode de journalisation.
Pour éviter ce genre de problème, vous voulez souvent écrire quelque chose de la forme:
if (LOGGER.isDebugEnabled()) {
// lots of debug logging here, or even code that
// is only used in a debugging context.
LOGGER.debug(" result: " + heavyComputation());
}
Si vous n'aviez pas utilisé ce garde avant votre bloc d'instructions de débogage, même si les messages peuvent ne pas être émis (si, par exemple, votre enregistreur est actuellement configuré pour imprimer uniquement les choses au-dessus du INFO
niveau), la heavyComputation()
méthode aurait quand même été exécutée .
Configuration
La configuration dépend assez de votre infrastructure de journalisation, mais ils offrent principalement les mêmes techniques pour cela:
- configuration programmatique (au moment de l'exécution, via une API - permet des changements d'exécution ),
- configuration déclarative statique (au démarrage, généralement via un fichier XML ou de propriétés - probablement ce dont vous avez besoin au début ).
Ils offrent également principalement les mêmes capacités:
- configuration du format du message de sortie (horodatages, marqueurs, etc ...),
- configuration des niveaux de sortie,
- configuration de filtres fins (par exemple pour inclure / exclure des packages ou des classes),
- configuration des annexes pour déterminer où se connecter (à la console, au fichier, à un service Web ...) et éventuellement ce qu'il faut faire avec les anciens journaux (par exemple, avec les fichiers de roulement automatique).
Voici un exemple courant de configuration déclarative, à l'aide d'un logback.xml
fichier.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Comme mentionné, cela dépend de votre framework et il peut y avoir d'autres alternatives (par exemple, LogBack permet également d'utiliser un script Groovy). Le format de configuration XML peut également varier d'une implémentation à l'autre.
Pour plus d'exemples de configuration, veuillez vous référer (entre autres) à:
Du plaisir historique
S'il vous plaît noter que Log4J est de voir une mise à jour majeure pour le moment, la transition de la version 1.x à 2.x . Vous voudrez peut-être jeter un œil à la fois pour plus de plaisir historique ou de confusion, et si vous choisissez Log4J, vous préférerez probablement la version 2.x.
Il convient de noter, comme Mike Partridge l'a mentionné dans les commentaires, que LogBack a été créé par un ancien membre de l'équipe Log4J. Qui a été créé pour combler les lacunes du cadre de journalisation Java. Et que la prochaine version majeure de Log4J 2.x intègre elle-même maintenant quelques fonctionnalités tirées de LogBack.
Recommandation
En bout de ligne, restez découplé autant que vous le pouvez, jouez avec quelques-uns et voyez ce qui vous convient le mieux. En fin de compte, ce n'est qu'un cadre de journalisation . Sauf si vous avez une raison très spécifique, en dehors de la facilité d'utilisation et des préférences personnelles, l'une d'entre elles serait plutôt OK, il n'y a donc pas de raison de s'y accrocher. La plupart d'entre eux peuvent également être étendus à vos besoins.
Pourtant, si je devais choisir une combinaison aujourd'hui, j'irais avec LogBack + SLF4J. Mais si vous me l'aviez demandé quelques années plus tard, j'aurais recommandé Log4J avec Apache Commons Logging, alors gardez un œil sur vos dépendances et évoluez avec elles.