slf4j: como registrar mensagem formatada, matriz de objetos, exceção

275

Qual é a abordagem correta para registrar uma mensagem preenchida e um rastreamento de pilha da exceção?

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

Eu gostaria de produzir uma saída semelhante a esta:

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

slf4j versão 1.6.1

rowe
fonte
3
Não entendo por que o slf4j usa sua própria sintaxe de seqüência de caracteres de formato em vez do estilo% s padrão. Irritante.
31519 Keith Tyler
@KeithTyler eu gosto {}mais, a questão do gosto ...
Betlista 23/01
@KeithTyler O toString()método dos argumentos pode ser caro. Com essa sintaxe, apenas uma referência a cada objeto é passada e o toString()método é chamado apenas se a mensagem específica estiver realmente sendo registrada. Objetos referenciados em uma info()chamada de log não terão seu toString()método chamado se o nível de log for WARNsuperior ou superior. A {}sintaxe é um lembrete para os usuários de que essa não é uma String.format()operação semelhante, ou seja, eles devem passar objetos em vez de representações de cadeias de caracteres.
user149408

Respostas:

427

A partir do SLF4J 1.6.0, na presença de vários parâmetros e se o último argumento em uma instrução de log for uma exceção, o SLF4J presumirá que o usuário deseja que o último argumento seja tratado como uma exceção e não como um parâmetro simples. Consulte também a entrada de FAQ relevante .

Então, escrevendo (no SLF4J versão 1.7.xe posterior)

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

ou gravação (no SLF4J versão 1.6.x)

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

vai render

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 ...

A saída exata dependerá da estrutura subjacente (por exemplo, logback, log4j, etc), bem como de como a estrutura subjacente está configurada. No entanto, se o último parâmetro for uma exceção, ele será interpretado como tal, independentemente da estrutura subjacente.

Ceki
fonte
4
Qual estrutura de log subjacente você está usando? Como mencionado na minha resposta acima, se o último parâmetro for uma exceção, ele será interpretado como tal, independentemente da estrutura subjacente. (Testado com logback, slf4j-log4j12, slf4j-jdk14 e slf4j-simples.)
Ceki
3
Desculpe, não reconheci que, no seu exemplo, você usou n = 3 espaços reservados na string de formato e n + 1 = 4 elementos na matriz de objetos. Eu tinha n espaços reservados na string de formato e também n elementos na matriz de objetos, além de uma exceção como terceiro parâmetro. Minha expectativa era que a exceção fosse impressa com stacktrace, mas isso nunca aconteceu. Isso funciona como projetado? Além disso, se eu tiver n espaços reservados e n elementos na matriz de objetos, com uma exceção sendo o último elemento, não vejo nenhum rastreamento de pilha. Talvez os n espaços reservados com n + 1 objetos em uma matriz devam ser um pouco mais enfatizados.
Rowe
7
Eu ia dar @Ceki um tempo duro sobre ele não estar no Javadocs mas sua no topo da Loggerclasse javadoc: slf4j.org/apidocs/org/slf4j/Logger.html
Adam Gent
1
Eu criei uma solicitação de melhoria , você pode votar se quiser.
Betlista 23/01
8

Além da resposta de @Ceki, se você estiver usando o logback e configurar um arquivo de configuração em seu projeto (geralmente logback.xml), poderá definir o log para plotar o rastreamento da pilha também usando

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

o% ex no padrão é o que faz a diferença

Yaniv
fonte