Connexion à Java et en général: Meilleures pratiques?

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

Cours de bibliothèque

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

Est-ce la bonne façon? Peut-être que l’utilisateur de cette classe de bibliothèque ne souhaite aucun message de mon implémentation ou souhaite le redirect vers un journal spécifique à une application. Dois-je permettre à l’utilisateur de définir un enregistreur à partir du “monde extérieur”? Comment gérez-vous ces 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. (C.-à-d. HTTP Request log ) Quelle est la meilleure façon de faire une telle chose? Un service de consultation vient à l’esprit …

Vos conventions sont assez standard et très bien (à mon humble avis).

La seule chose à surveiller est la fragmentation de la mémoire à cause des appels excessifs au débogage, donc avec Log4J (et la plupart des autres structures de journalisation Java), vous vous retrouvez avec quelque chose comme ceci:

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

car la construction de ce message de journal (que vous n’utilisez probablement pas) pourrait être coûteuse, surtout si vous le faites des milliers ou des millions de fois.

Votre enregistrement de niveau INFO ne devrait pas être trop “bavard” (et d’après ce que vous dites, cela ne semble pas être le cas). Les messages INFO doivent être généralement significatifs et significatifs, comme l’application démarrée et arrêtée. Les choses que vous pourriez vouloir savoir si vous rencontrez un problème. La journalisation de débogage / niveau fin est plus utilisée lorsque vous rencontrez un problème que vous essayez de diagnostiquer. Le débogage / la journalisation fine est généralement activé uniquement lorsque cela est nécessaire. Info est généralement allumé tout le temps.

Si quelqu’un ne veut pas de messages INFO spécifiques de vos classes, il est bien entendu libre de modifier votre configuration log4j pour ne pas les recevoir. Log4j est parfaitement simple dans ce département (contrairement à la journalisation Java 1.4).

En ce qui concerne votre object HTTP, je n’ai généralement pas trouvé que cela posait problème avec la journalisation Java, car une seule classe est généralement responsable de ce qui vous intéresse, il vous suffit donc de la placer au même endroit. Dans le (rare dans mon expérience) lorsque vous voulez des messages de journal communs à travers des classes apparemment sans rapport, il suffit de mettre un jeton qui peut facilement être goulot.

Dans la réponse de @cletus , il a écrit sur le problème de

 if (log.isDebugEnabled()) { log.debug("val is " + value); } 

ce qui pourrait être surmonté en utilisant SL4J . Il fournit une aide au formatage

 log.debug("val is {}", value); 

où le message n’est construit que si le niveau est debug.

Ainsi, l’utilisation de SL4J et de son enregistreur compagnon, Logback, est aujourd’hui recommandée pour des raisons de performances et de stabilité.

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 de la migration de la JVM avec votre trace de stack et réduit (sortingvialement) la surcharge liée à la création de la trace de la stack en premier lieu.

La meilleure chose à propos de l’utilisation d’un modèle comme celui-ci est que vous pouvez le partager avec votre équipe si vous souhaitez définir une norme cohérente pour tous les enregistreurs.

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 comment le faire facilement dans NetBeans.

L’option préférée pour le type de configuration log4j que vous décrivez est d’utiliser le fichier de configuration log4j . Cela permet aux utilisateurs de votre implémentation de faire exactement ce que vous demandez, car ils peuvent modifier votre configuration ultérieurement avec quelque chose de plus adapté à leur propre implémentation. Voir ici pour une introduction très approfondie.

Je l’ai probablement volé quelque part, mais c’est bien.

Cela réduit le risque de confondre les enregistreurs lors de la copie et du pasti ^ h ^ h ^ h du refactoring, et il est moins difficile de 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 effectué lors de l’initialisation. Le stacktrace ne sera probablement pas optimisé par la JVM mais il n’y a aucune garantie)

J’examine les niveaux de journalisation d’une application et je détecte actuellement un modèle:

 private static final Logger logger = Logger.getLogger(Things.class) public void bla() { logger.debug("Starting " + ...) // Do stuff ... logger.debug("Situational") // Algorithms for(Thing t : things) { logger.trace(...) } // Breaking happy things if(things.isEmpty){ logger.warn("Things shouldn't be empty!") } // Catching things try { ... } catch(Exception e) { logger.error("Something bad happened") } logger.info("Completed "+...) } 

Un fichier log4j2 définit un socket-appender, avec un appender de fichier de basculement. Et une console-appender. Parfois, j’utilise les marqueurs log4j2 lorsque la situation l’exige.

Pensé qu’une perspective supplémentaire pourrait aider.

En outre, je pense qu’il est important de parler de Simple Logging Facade pour Java (SLF4J) ( http://www.slf4j.org/ ). En raison de problèmes liés à l’utilisation de différentes structures de journalisation dans des parties diversifiées d’un grand projet, SLF4J est la norme de facto pour résoudre un problème de gestion de ces pièces, n’est-ce pas?

La seconde notion: il semble que certaines tâches à l’ancienne puissent être remplacées par la programmation orientée aspect , Spring frmwrk a sa propre implémentation , l’approche AOP pour la journalisation est considérée ici chez StackOverflow et ici sur le blog de Spring.

Voici les lignes direcsortingces que je suis dans tous mes projets pour assurer de bonnes performances. Je suis venu pour former cet ensemble de lignes direcsortingces sur la base des consortingbutions de diverses sources sur Internet.

Comme aujourd’hui, je crois que Log4j 2 est de loin la meilleure option pour la connexion à Java.

Les repères sont disponibles ici . La pratique que je suis pour obtenir les meilleures performances est la suivante:

  1. J’évite d’utiliser SLF4J pour le moment pour les raisons suivantes:
    • Il y a des problèmes de concurrence avec les marqueurs que je veux utiliser pour gérer la journalisation des instructions SQL ( marqueurs pas aussi puissants que slf4j – Reportez-vous au premier commentaire de Ralph Goers)
    • Il ne supporte pas le Java 8 Lambda que, encore une fois, je veux utiliser pour de meilleures performances ( supporte l’expression lambda dans le Logger )
  2. Effectuez tous les enregistrements réguliers à l’aide d’un enregistreur asynchrone pour de meilleures performances
  3. Consigner les messages d’erreur dans un fichier séparé à l’aide du journal synchrone, car nous souhaitons afficher les messages d’erreur dès qu’ils se produisent
  4. N’utilisez pas les informations d’emplacement, telles que nomfichier, nom de classe, nom de méthode, numéro de ligne dans la journalisation régulière car, pour dériver ces informations, la structure prend une photo de la stack et la parcoure. Cela affecte la performance. Par conséquent, utilisez les informations de localisation uniquement dans le journal des erreurs et non dans le journal normal.
  5. Comme nous enregistrons des erreurs dans un fichier séparé, il est très important que nous consignions également les informations de contexte dans le journal des erreurs. Par exemple, si l’application a rencontré une erreur lors du traitement d’un fichier, imprimez le nom du fichier et l’enregistrement du fichier en cours de traitement dans le fichier journal des erreurs avec la trace de la stack.
  6. Le fichier journal doit être accessible et facile à comprendre. Par exemple, si une application traite des enregistrements de clients dans plusieurs fichiers, chaque message de journal doit être similaire à celui-ci:
 12:01:00,127 INFO FILE_NAME=file1.txt - Processing starts 12:01:00,127 DEBUG FILE_NAME=file1.txt, CUSTOMER_ID=756 12:01:00,129 INFO FILE_NAME=file1.txt - Processing ends 
  1. Consignez toutes les instructions SQL à l’aide d’un marqueur SQL, comme indiqué ci-dessous, et utilisez un filtre pour l’activer ou le désactiver:
 private static final Marker sqlMarker = MarkerManager.getMarker("SQL"); private void method1() { logger.debug(sqlMarker, "SELECT * FROM EMPLOYEE"); } 
  1. Consignez tous les parameters à l’aide de Java 8 Lambdas. Cela enregistrera l’application du formatage du message lorsque le niveau de journal donné est désactivé:
 int i=5, j=10; logger.info("Sample output {}, {}", ()->i, ()->j); 
  1. N’utilisez pas de concaténation de chaîne. Utiliser un message paramétré comme indiqué ci-dessus

  2. Utilisez le rechargement dynamic de la configuration de la journalisation pour que l’application recharge automatiquement les modifications de la configuration de journalisation sans redémarrage de l’application

  3. N’utilisez pas printStackTrace() ou System.out.println()

  4. L’application doit arrêter l’enregistreur avant de quitter:

 LogManager.shutdown(); 
  1. Enfin, pour la référence de chacun, j’utilise la configuration suivante:
    ${env:LOG_ROOT}/SAMPLE ${env:LOG_ROOT}/SAMPLE/sample  10 MB        %d{HH:mm:ss,SSS} %m%n          %d{HH:mm:ss,SSS} %p %c{1.}[%L] [%t] %m%n                  
  1. Les dépendances Maven requirejses sont ici:
  org.apache.logging.log4j log4j-api 2.8.1   org.apache.logging.log4j log4j-core 2.8.1   com.lmax disruptor 3.3.6    org.apache.logging.log4j log4j-1.2-api 2.8.1