slf4j: comment enregistrer un message formaté, un tableau d'objets, une exception

275

Quelle est la bonne approche pour consigner à la fois un message rempli et une trace de pile de l'exception?

logger.error(
    "\ncontext info one two three: {} {} {}\n",
    new Object[] {"1", "2", "3"},
    new Exception("something went wrong"));

Je voudrais produire une sortie similaire à ceci:

context info one two three: 1 2 3
java.lang.Exception: something went wrong
stacktrace 0
stacktrace 1
stacktrace ...

slf4j version 1.6.1

rowe
la source
3
Je ne comprends pas pourquoi slf4j utilise sa propre syntaxe de chaîne de format au lieu du style% s standard. Énervant.
Keith Tyler
@KeithTyler J'aime {}plus, la question du goût ...
Betlista
@KeithTyler La toString()méthode des arguments peut être coûteuse. Avec cette syntaxe, seule une référence à chaque objet est transmise et la toString()méthode n'est appelée que si le message particulier est réellement enregistré. Les objets référencés dans un info()appel de journal ne verront pas leur toString()méthode appelée si le niveau de journal est WARNsupérieur ou égal à. La {}syntaxe rappelle aux utilisateurs qu'il ne s'agit pas d'une String.format()opération de type similaire, c'est-à-dire qu'ils doivent passer des objets plutôt que des représentations de chaîne de ceux-ci.
user149408

Réponses:

427

À partir de SLF4J 1.6.0, en présence de plusieurs paramètres et si le dernier argument d'une instruction de journalisation est une exception, alors SLF4J supposera que l'utilisateur souhaite que le dernier argument soit traité comme une exception et non comme un simple paramètre. Voir également l' entrée FAQ appropriée .

Donc, l'écriture (dans SLF4J version 1.7.x et ultérieure)

 logger.error("one two three: {} {} {}", "a", "b", 
              "c", new Exception("something went wrong"));

ou en écriture (dans SLF4J version 1.6.x)

 logger.error("one two three: {} {} {}", new Object[] {"a", "b", 
              "c", new Exception("something went wrong")});

donnera

one two three: a b c
java.lang.Exception: something went wrong
    at Example.main(Example.java:13)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at ...

La sortie exacte dépendra du framework sous-jacent (par exemple logback, log4j, etc.) ainsi que de la façon dont le framework sous-jacent est configuré. Cependant, si le dernier paramètre est une exception, il sera interprété comme tel quel que soit le cadre sous-jacent.

Ceki
la source
4
Quelle infrastructure de journalisation sous-jacente utilisez-vous? Comme mentionné dans ma réponse ci-dessus, si le dernier paramètre est une exception, il sera interprété comme tel quel que soit le cadre sous-jacent. (Testé avec logback, slf4j-log4j12, slf4j-jdk14 et slf4j-simple.)
Ceki
3
Désolé, je n'ai pas reconnu que dans votre exemple, vous avez utilisé n = 3 espaces réservés dans la chaîne de format et n + 1 = 4 éléments dans le tableau d'objets. J'avais n espaces réservés dans la chaîne de format et aussi n éléments dans le tableau d'objets plus une exception comme troisième paramètre. Je m'attendais à ce que l'exception soit imprimée avec stacktrace, mais cela ne s'est jamais produit. Est-ce que cela fonctionne comme prévu? De plus, si j'ai des espaces réservés et n éléments dans le tableau d'objets, à l'exception du dernier élément, je ne vois aucune trace de pile. Peut-être que les n espaces réservés avec n + 1 objets dans un tableau devraient être un peu plus accentués.
rowe
7
J'allais donner du fil à retordre à @Ceki car il n'était pas dans les Javadocs mais en haut de la Loggerclasse javadoc: slf4j.org/apidocs/org/slf4j/Logger.html
Adam Gent
1
J'ai créé une demande d'amélioration , vous pouvez voter pour elle si vous l'aimez.
Betlista
8

En plus de la réponse de @Ceki, si vous utilisez logback et configurez un fichier de configuration dans votre projet (généralement logback.xml), vous pouvez définir le journal pour tracer également la trace de la pile en utilisant

<encoder>
    <pattern>%date |%-5level| [%thread] [%file:%line] - %msg%n%ex{full}</pattern> 
</encoder>

le% ex dans le motif est ce qui fait la différence

Yaniv
la source