Как зарегистрировать исключение и сообщение с заполнителями с помощью SLF4J

#java #logging #slf4j

#java #ведение журнала #slf4j

Вопрос:

Каков правильный подход для регистрации как сообщения об ошибке, так и исключения с использованием SLF4J?

Я пытался это сделать, но трассировка стека исключений никогда не печатается:

logger.error("Unable to parse data {}", inputMessage, e);

В этом случае я хочу заполнить {} с помощью inputMessage , а также вывести из системы трассировку стека исключений.

Единственный способ, который я вижу, чтобы сделать это, было бы сделать это:

logger.error("Unable to parse data " inputMessage, e);

что не очень приятно.

Комментарии:

1. Ваша строка fist logger.error работает так, как вы хотите, в slf4j версии 1.7.25.

Ответ №1:

Начиная с SLF4J версии 1.6, SLF4J будет интерпретировать последний параметр так, как вы предполагали, то есть как исключение. Вы, должно быть, используете более старую версию SLF4J API.

Эта функция описана в разделе часто задаваемых вопросов, на который также есть ссылки в javadocs for Logger.

Комментарии:

1. Описано ли это в Javadoc? Я ожидал найти подобную информацию здесь: slf4j.org/apidocs/org/slf4j/Logger.html

2. Я верю вам, но, как и @Scot, я надеялся, что это поведение будет задокументировано.

3. Scot, @Stephan — вышеупомянутое поведение, похоже, задокументировано в их часто задаваемых вопросах здесь .

4. Это похоже на то, что лучше хранить в секрете. Спасибо, что указали на это. Мой последующий вопрос заключается в том, почему они скрывают тот факт, что это возможно в var-arg? Почему они не могут создать новый перегруженный метод, который принимает Throwable , а затем имеет var-arg после этого? Есть ли проблемы со стиранием? Является ли это стандартом в других библиотеках для передачи исключения в качестве последнего аргумента?

5. Это (с тех пор?) было задокументировано в FAQ: slf4j.org/faq.html#paramException . Я согласен, что эта функция должна быть задокументирована более четко.

Ответ №2:

из http://www.slf4j.org/faq.html#paramException:

Да, начиная с SLF4J 1.6.0, но не в предыдущих версиях. API SLF4J поддерживает параметризацию при наличии исключения, предполагая, что исключение является последним параметром. Таким образом,

 String s = "Hello world";
try {
  Integer i = Integer.valueOf(s);
} catch (NumberFormatException e) {
  logger.error("Failed to format {}", s, e);
}
  

будет выведено исключение NumberFormatException с его трассировкой стека, как и ожидалось. Компилятор java вызовет метод error, принимая строку и два аргумента объекта. SLF4J, в соответствии с наиболее вероятным намерением программиста, интерпретирует экземпляр NumberFormatException как выбрасываемый вместо неиспользуемого параметра объекта. В версиях SLF4J до 1.6.0 экземпляр NumberFormatException был просто проигнорирован.

Если исключение не является последним аргументом, оно будет обработано как обычный объект, и его трассировка стека не будет напечатана. Однако такие ситуации не должны возникать на практике.