79 votes

La journalisation en Java et en général : Meilleures pratiques ?

Parfois, lorsque je vois mon code d'enregistrement, je me demande si je le fais bien. Il n'y a peut-être pas de réponse définitive à cette question, mais j'ai les préoccupations suivantes :

Cours de bibliothèque

J'ai plusieurs classes de bibliothèque qui pourraient enregistrer des INFO messages. Les erreurs fatales sont signalées comme des exceptions. Actuellement, j'ai une instance de logger statique dans mes classes avec le nom de la classe comme nom de logging. (Log4j : Logger.getLogger(MyClass.class) )

Est-ce la bonne méthode ? Peut-être que l'utilisateur de cette classe de bibliothèque ne veut pas de messages de mon implémentation ou veut les rediriger vers un journal spécifique à l'application. Devrais-je permettre à l'utilisateur de définir un enregistreur depuis le "monde extérieur" ? Comment gérez-vous de tels cas ?

Journaux généraux

Dans certaines applications, mes classes peuvent vouloir écrire un message de journal dans un journal spécifique non identifié par le nom de la classe. (Par exemple : HTTP Request log ) Quelle est la meilleure façon de procéder ? Un service de consultation me vient à l'esprit...

45voto

cletus Points 276888

Vos conventions sont assez standard et très bien (imho).

La seule chose à surveiller est la fragmentation de la mémoire due à un nombre excessif d'appels de débogage non intégrés. Avec Log4J (et la plupart des autres cadres de journalisation Java), vous obtenez quelque chose comme ceci :

if (log.isDebugEnabled()) {
  log.debug("...");
}

parce que la construction de ce message de journal (que vous n'utilisez probablement pas) peut être coûteuse, surtout si elle est effectuée des milliers ou des millions de fois.

Votre journalisation de niveau INFO ne doit pas être trop "bavarde" (et d'après ce que vous dites, il semble qu'elle ne le soit pas). Les messages INFO doivent être généralement significatifs et importants, comme le démarrage et l'arrêt de l'application. Des choses que vous pourriez vouloir savoir si vous rencontrez un problème. La journalisation de niveau débogage/fin est plutôt utilisée lorsque vous avez réellement un problème que vous essayez de diagnostiquer. La journalisation de débogage/fin est généralement activée uniquement en cas de besoin. L'information est généralement activée en permanence.

Si quelqu'un ne veut pas de messages INFO spécifiques de vos classes, il est bien sûr libre de modifier votre configuration log4j pour ne pas les obtenir. Log4j est très simple dans ce domaine (contrairement à la journalisation de Java 1.4).

Pour ce qui est de l'aspect HTTP, je n'ai généralement pas trouvé que c'était un problème avec la journalisation Java car, en général, une seule classe est responsable de ce qui vous intéresse et vous n'avez donc besoin de le placer qu'à un seul endroit. Dans les cas (rares selon mon expérience) où vous souhaitez obtenir des messages de journalisation communs à des classes apparemment sans rapport entre elles, il suffit de mettre un jeton qui peut facilement être recherché.

4 votes

Pour information, en Scala, on peut écrire une méthode de débogage qui fait exactement ce code sans la verbosité en utilisant des paramètres by-name. Le compilateur convertit automatiquement le code dans l'argument debug() en une fonction qui n'est évaluée que si debug() décide de l'appeler. Ainsi, il ne concaténerait pas la chaîne de caractères à moins que la fonction isDebugEnabled() ne soit vraie. Exemple de code qui implémente ceci : override def debug(msg : => AnyRef) = if (isDebugEnabled) logger.debug(msg) github.com/dpp/liftweb/blob/

8 votes

C'est une autre bonne raison d'utiliser la construction {} fournie par slf4j.

7voto

justinpitts Points 377

En ce qui concerne l'instanciation des enregistreurs, j'ai eu un certain succès en utilisant un modèle Java Eclipse pour configurer mes enregistreurs :

private static Logger log = Logger.getLogger(${enclosing_type}.class);

Cela évite le problème d'une JVM qui se mêle de votre trace de pile, et réduit (de façon triviale, peut-être) la surcharge de la création de la trace de pile en premier lieu.

L'avantage d'utiliser un modèle comme celui-ci est que vous pouvez le partager avec votre équipe si vous souhaitez établir une norme cohérente pour tous les bûcherons.

Il semble qu'IntelliJ prenne en charge le même concept pour une variable de modèle représentant le nom du type englobant. Je ne vois pas de moyen de le faire facilement dans NetBeans.

4voto

John Feminella Points 116878

L'option préférée pour le type de configuration de log4j que vous décrivez est d'utiliser la fonction fichier de configuration de log4j . Cela permet aux utilisateurs de votre implémentation de faire exactement ce que vous demandez, puisqu'ils peuvent remplacer votre configuration ultérieurement par quelque chose de plus adapté à leur propre implémentation. Voir aquí pour une introduction très complète.

0 votes

...il existe également un format non-xml qui est légèrement plus lisible.

4voto

KarlP Points 3246

J'ai probablement volé ça quelque part, mais c'est sympa.

Cela réduit le risque de mélanger les loggers lors de la copie et du refactoring pasti^h^h^h, et c'est moins à taper.

Dans votre code :

private final static Logger logger = LoggerFactory.make();

...et dans LoggerFactory :

public static Logger make() {
    Throwable t = new Throwable();
    StackTraceElement directCaller = t.getStackTrace()[1];
    return Logger.getLogger(directCaller.getClassName());
}

(Notez que le stackdump est fait pendant l'initialisation. La trace de la pile sera probablement ne soit pas optimisée par la JVM, mais il n'y a en fait aucune garantie)

0 votes

* ...très probablement volé au Dr Heinz M. Kabutz. Mais je ne suis pas sûr

10 votes

N'oubliez pas qu'une VM est libre d'omettre les trames de pile ou d'effectuer d'autres optimisations, de sorte que vous pouvez vous retrouver avec un tableau vide de StackTraceElements. Voir [java.sun.com/j2se/1.5.0/docs/api/java/lang/](http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Throwable.html#getStackTrace()) pour plus d'informations.

1 votes

Vous avez omis le type dans la définition de votre variable de classe.

3voto

Yauhen Points 351

En outre, je pense qu'il est important de parler de Simple Logging Facade for Java (SLF4J) ( http://www.slf4j.org/ ). En raison de certains problèmes liés à l'utilisation de différents cadres de journalisation dans diverses parties d'un grand projet, SLF4J est la norme de facto pour résoudre un problème de gestion de ces parties avec succès, n'est-ce pas ?

La deuxième notion : il semble que certaines tâches de l'ancienne école puissent être remplacées par des tâches de l'ancienne école. Programmation orientée aspect , Spring frmwrk a son propre mise en œuvre L'approche AOP pour la journalisation a été examinée. aquí à StackOverflow et aquí sur le blog de Spring.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X