web-dev-qa-db-fra.com

Même avec slf4j, devriez-vous garder votre journalisation?

Aidez-moi dans un débat ici .. :)

Le site slf4j ici http://www.slf4j.org/faq.html#logging_performance indique qu'en raison de la journalisation paramétrée, les gardes de journalisation ne sont pas nécessaires. C'est à dire. au lieu d'écrire:

if(logger.isDebugEnabled()) {
  logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}

Vous pouvez vous en tirer avec:

Object entry = new SomeObject();
logger.debug("The entry is {}.", entry);

Est-ce vraiment correct, ou cela entraîne-t-il le coût (quoique inférieur) de la création de la chaîne statique transmise à la méthode trace ..?

35
Mark D

J'essaierai de mettre mes deux cents sous un autre angle

Quel est exactement l'avantage de la journalisation paramétrée?

Vous venez de différer toString() invocation et la concaténation de chaînes jusqu'à ce que vous en ayez vraiment besoin, c'est-à-dire lorsque vous devez vraiment enregistrer le message. Cela optimise les performances lorsque cette opération de journalisation particulière est désactivée. Vérifiez code source pour SLF4J si vous n'êtes pas sûr.

La journalisation paramétrée rend-elle les gardes inutiles dans tous les cas?

Non.

Dans quels cas les gardes de journalisation seraient-ils utiles?

Lorsqu'il existe d'autres opérations potentiellement coûteuses.

Par exemple (dans le cas où cette opération de journalisation particulière est désactivée), si nous avons pas de garde de journalisation

logger.debug("User name: {}", getUserService().getCurrentUser());
  1. Nous paierions le coût de obj = getUserService().getCurrentUser()
  2. Nous économiserions le coût de "User name: " + obj.toString()

Si nous utilisez la garde de journalisation:

if (logger.isDebugEnabled()) {
    logger.debug("User: {}", getUserService().getCurrentUser());
}
  1. Nous paierions le coût de logger.isDebugEnabled()
  2. On économiserait le coût de obj = getUserService().getCurrentUser()
  3. Nous économiserions le coût de "User name: " + obj.toString()

Dans le dernier cas, nous économiserions les deux coûts au prix de la vérification de isDebugEnabled() deux fois lorsque cette opération de journalisation particulière est activée.

REMARQUE: Ceci est juste un exemple, n'essayant pas de débattre des bonnes/mauvaises pratiques ici.

52
fglez

Ecrire et lire tous ces if(logger.isDebugEnabled()) {} vous coûtera probablement autant de temps qu'ils vous en feront gagner.

Bien sûr, appeler la méthode log n'est pas gratuit mais il en va de même pour l'appel de isDebugEnabled(). Vous payez donc plus pour chaque instruction de journal active si vous utilisez ce modèle (car le cadre de journalisation vérifiera le niveau deux fois).

Cela encombre également le code.

En pratique, je n'ai pas trouvé que la pénalité de performance était suffisamment importante pour déranger.

Si la journalisation est trop lente pour vous, écrivez un appender non bloquant qui pousse les événements du journal dans une file d'attente sans seulement quelques vérifications et utilisez un thread d'arrière-plan pour les traiter.

Contexte: les ajouts standard sont tous synchronisés, de sorte que la journalisation dans une application multithread peut provoquer de nombreuses petites pauses où tous les threads attendent qu'un message de journal soit écrit dans un fichier.

18
Aaron Digulla

La garde n'est pas utilisée en raison de la création de la chaîne.

Au lieu de cela, il est généralement utilisé pour éviter une expression d'argument potentiellement coûteuse, quelque chose comme entry[i].retrieveExtendedDebugInformation().formatNicely(). Pour cela, logback s'assure que l'argument n'est évalué que lorsque le message du journal est réellement imprimé, tandis que log4j évalue toujours l'argument avant d'appeler debug ().

Ici, le seul candidat est String.valueOf(entry[i]), ce qui n'est pas très cher non plus, vous pouvez donc faire valoir que cette garde est totalement inutile.

8
wallenborn

Le problème avec une instruction de journalisation comme celle-ci:

logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));

est que cela fera beaucoup de travail pour concaténer les valeurs dans un String, qui n'est alors jamais utilisé si la journalisation du débogage est désactivée. Dans ce cas, il est donc utile de vérifier si la journalisation du débogage est activée avant d'exécuter cette ligne. Lorsque vous ne faites que passer des paramètres:

logger.debug("The entry is {}.", entry);

alors il n'a pas besoin inutilement de construire un String qui n'est jamais utilisé, et la vérification n'est pas nécessaire; le simple fait de passer des arguments à une méthode n'entraîne pas une surcharge très élevée.

Notez que si vous avez des expressions relativement coûteuses pour les arguments dans une instruction de journalisation, il peut toujours être utile de vérifier d'abord le niveau de journalisation.

4
Jesper

Veuillez ne pas utiliser l'instruction if, car chaque fois que je regarde du code comme celui-ci

if (logger.isDebug()) {
   logger.debug("Of course it's debug {}", sadFace);
}

Je pleure.

J'espère que le coût de création de la chaîne statique est si bas qu'il est insignifiant pour 99% des utilisateurs.

3
Jeff Foster