slf4j: як записати відформатоване повідомлення, масив об'єктів, виняток


275

Який правильний підхід до журналу як заселеного повідомлення, так і стека сліду виключення?

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

Я хотів би отримати результат, подібний до цього:

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

версія slf4j 1.6.1


3
Я не розумію, чому slf4j використовує власний синтаксис рядкових форматів замість стандартного стилю% s. Дратівливий.
Кіт Тайлер

@KeithTyler Мені подобається {}більше, справа смаку ...
Betlista

@KeithTyler toString()Метод аргументів може бути дорогим. За допомогою цього синтаксису передається лише посилання на кожен об'єкт, а toString()метод викликається лише в тому випадку, якщо конкретне повідомлення насправді отримує реєстрацію. Об'єкти, на які посилається в info()дзвінку журналу, не матимуть toString()методу виклику, якщо рівень журналу є WARNвищим. {}Синтаксис нагадує користувачам , що це не String.format()-як операція, тобто вони повинні передавати об'єкти , а не рядкові представлення їх.
користувач149408

Відповіді:


427

Що стосується SLF4J 1.6.0, за наявності декількох параметрів і якщо останній аргумент у операторі реєстрації є винятком, то SLF4J припускає, що користувач хоче, щоб останній аргумент трактувався як виняток, а не простий параметр. Дивіться також відповідний запис FAQ .

Отже, написання (у SLF4J версії 1.7.x та пізнішої)

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

або письмовій формі (у SLF4J версії 1.6.x)

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

дасть урожай

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

Точний вихід буде залежати від базової основи (наприклад, logback, log4j тощо), а також від того, як налаштований базовий фреймворк. Однак якщо останній параметр є винятком, він буде інтерпретуватися як такий незалежно від основи, що лежить в основі.


4
Який базовий фреймворк ви використовуєте? Як було сказано у моїй відповіді вище, якщо останній параметр є винятком, він буде інтерпретуватися як такий незалежно від основи, що лежить в основі. (Тестовано з logback, slf4j-log4j12, slf4j-jdk14 та slf4j-simple.)
Чекі

3
На жаль, я не визнав, що у вашому прикладі ви використовували n = 3 заповнювачів у рядку формату та n + 1 = 4 елементи в масиві об'єктів. Я мав n заповнювачів у рядку формату, а також n елементів у масиві об'єктів плюс виняток як третій параметр. Моє сподівання було, що виняток буде надруковано стек-треком, але цього ніколи не було. Чи працює це як розроблено? Крім того, якщо я маю n заповнювачів та n елементів у масиві об'єктів, за винятком, що є останнім елементом, я не бачу жодного стека. Можливо, п ять заповнювачів з n + 1 об'єктами в масиві повинні бути трохи підкреслені.
rowe

7
Я збирався дати @Ceki важкий час, коли він не перебуває в Javadocs, але його знаходиться у вершині Loggerкласу javadoc: slf4j.org/apidocs/org/slf4j/Logger.html
Адам Гент

1
Я створив запит на покращення , ви можете проголосувати за нього, якщо вам це подобається.
Betlista

8

На додаток до відповіді @Ceki: Якщо ви використовуєте logback та налаштовуєте конфігураційний файл у своєму проекті (як правило, logback.xml), ви можете визначити журнал, щоб також побудувати трасування стека, використовуючи

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

% коли в шаблоні - це те, що робить різницю

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.