70 votes

Log4J: Stratégies de création d'instances de journalisation

J'ai décidé d'utiliser Log4J de journalisation pour un nouveau projet Java. Je me demande quelle stratégie dois-je utiliser pour la création/gestion de l'Enregistreur de cas et pourquoi?

  • un exemple d'Enregistreur de données par classe par exemple

    class Foo {
        private static final Logger log = Logger.getLogger(Foo.class);
    }
    
  • un exemple d'Enregistreur de données par fil
  • un exemple d'Enregistreur de données par application
  • découpe horizontaux : un exemple d'Enregistreur de données dans chaque couche de la demande (par exemple, la couche de la vue, le contrôleur de couche et la couche de persistance)
  • verticale de découpage : un exemple d'Enregistreur de données au sein de la fonctionnelle de partitions de l'application

Remarque: Ce problème est déjà considéré, dans une certaine mesure dans ces articles:

La meilleure façon de sortir du [sic] Log4J bûcherons

Quelle est la surcharge de la création d'un Enregistreur de Log4j

46voto

PSpeed Points 2388

Généralement, vous auriez enregistreurs de configuration par classe parce que c'est une belle composant logique. Les fils sont déjà une partie des messages de log (si votre filtre s'affiche), le découpage des enregistreurs de cette manière est sans doute superflu.

Au sujet de l'application ou de la couche de base de bûcherons, le problème est que vous devez trouver un endroit pour coller que l'exploitant de l'objet. Pas vraiment une grosse affaire. Le plus gros problème, c'est que certaines classes peuvent être utilisées à de multiples niveaux de partir de multiples applications... il pourrait être difficile d'obtenir votre enregistreur de droit. Ou au moins difficile.

...et la dernière chose que vous voulez est de mauvaises hypothèses dans votre journalisation de la configuration.

Si vous vous souciez des applications et des couches et facilement points de séparation, le NDC est le chemin à parcourir. Le code peut être un peu excessif parfois, mais je ne sais pas combien de fois j'ai été sauvé par un contexte précis de la pile en me montrant que Foo.bar() a été appelée à partir de l'application de X dans la couche Y.

33voto

rsp Points 14367

La stratégie la plus utilisée est de créer un logger par classe. Si vous créez de nouveaux threads de leur donner une tâche de ce nom, donc la connexion est facile à distinguer.

La création de bûcherons par classe a l'avantage d'être en mesure d'activer/désactiver la journalisation dans le package de la structure de vos classes:

log4j.logger.org.apache = INFO
log4j.logger.com.example = DEBUG
log4j.logger.com.example.verbose = ERROR

Le ci-dessus serait de définir toutes apache code de la bibliothèque d' INFO niveau de l'interrupteur enregistrement à partir de votre propre code à l' DEBUG à l'exception de la verbose paquet.

13voto

Dean J Points 10987

Je suis certain que ce n'est pas une bonne pratique, mais j'ai pillé quelques temps de démarrage sur les applications avant d'enregistrer des lignes de code. Plus précisément, lorsque le copier-coller:

Logger logger = Logger.getLogger(MyClass.class);

...les développeurs oublient souvent de changer "MyClass" de l'actuel nom de la classe, et plusieurs enregistreurs toujours du vent pointent vers le mauvais endroit. Ce Qui Est Mauvais.

J'ai parfois écrit:

static Logger logger = LogUtil.getInstance(); 

Et:

class LogUtil {
   public Logger getInstance() {
      String callingClassName = 
         Thread.currentThread().getStackTrace()[2].getClass().getCanonicalName();
      return Logger.getLogger(callingClassName);
   }
}

Le "2" dans ce code peut se tromper, mais l'essentiel est là; prendre des performances à (sur charge de classe, comme une variable statique) trouver le nom de la classe, de sorte qu'un développeur n'a pas vraiment d'avoir un moyen pour cette faute de frappe ou d'introduire toute erreur.

Je suis généralement pas très heureux avec perte de performance pour empêcher les développeurs erreur lors de l'exécution, mais si cela arrive comme un singleton, une fois? Souvent ressemble à une bonne affaire pour moi.

10voto

Matthew Farwell Points 31257

Comme il a été dit par d'autres, je voudrais créer un Logger par classe:

private final static Logger LOGGER = Logger.getLogger(Foo.class);

ou

private final Logger logger = Logger.getLogger(this.getClass());

Cependant, j'ai trouvé utile dans le passé pour avoir d'autres informations dans l'enregistreur. Par exemple, si vous avez un site web, vous pouvez inclure l'ID utilisateur dans chaque message de journal. De cette façon,, vous pouvez suivre tout ce qu'un utilisateur est en train de faire (très utile pour le débogage des problèmes etc).

La façon la plus simple pour ce faire est d'utiliser un MDC, mais vous pouvez utiliser un Enregistreur créé pour chaque instance de la classe avec le nom de l'ID d'utilisateur.

Un autre avantage de l'utilisation d'un MDC si vous utilisez SL4J, vous pouvez modifier les paramètres en fonction des valeurs de votre MDC. Donc, si vous souhaitez enregistrer toutes les activités pour un utilisateur en particulier au niveau de DÉBOGAGE, et de laisser toutes les autres utilisateurs en ERREUR, vous pouvez. Vous pouvez également rediriger la sortie différents à des endroits différents en fonction de votre MDC.

Quelques liens utiles:

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html

http://www.slf4j.org/api/index.html?org/slf4j/MDC.html

4voto

yawn Points 2823
  • Créer un logger par classe.
  • Si vous avez des dépendances qui nécessitent Commons Logging (très probable) d'utiliser slf4j du pont pour Commons Logging. L'instanciation de vos enregistreurs (par classe) à l'aide de l'Commons Logging interface: private static final Log log = LogFactory.getLog(MyClass.class);
  • Manifeste de ce modèle dans votre IDE à l'aide de raccourcis. J'utilise IDÉE de vivre des modèles à cette fin.
  • Fournir de l'information contextuelle de threads à l'aide d'un NDC (thread local pile de chaînes de caractères) ou un MDC (thread carte locale de la Chaîne → ?).

Exemples de modèles:

private static final Log log = LogFactory.getLog($class$.class); // live template 'log'

if (log.isDebugEnabled())
    log.debug(String.format("$string$", $vars$)); // live template 'ld', 'lw', 'le' ...

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