сообщения каких уровней мы увидим задав уровень info

para siluety obiatiia 130614 1280x720 Статьи

Java logging. Hello World

Вступление

Думаю, ни для кого не секрет, что такое логгеры и для чего они нужны. За время существования java было создано немало фреймворков логгирования. Среди самых известных можно выделить:

System.err.println

Первым и самым примитивным способом логгирования был метод System.err.println. Думаю, комментарии излишние, достаточно взглянуть на приведенный ниже код:

Java.util.logging

Данный фреймворк включен в стандарт и поставляется вместе с JDK, поэтому ничего дополнительно скачивать и подключать вам не надо. JUL имеет следующие уровни логгирования по возрастанию: FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, а так же ALL и OFF, включающий и отключающий все уровни соответственно.
Логгер создается вызовом одного из статических методов класса java.util.logging.Logger:

Методы логгера могут принимать в качестве аргументов строковые сообщения, шаблоны сообщений, исключения, ресурсы локализованных текстовок сообщений, а также, начиная с Java 8, поставщиков строковых сообщений:

Выделяется две группы методов: название которых соответствует уровню логгирования и методы log, loggp, logrb, принимающие уровень логгирования в качестве параметра с типом Level. Первая группа содержит методы двух типов: принимающих строковое сообщение или поставщика строковых сообщений:

Вторая группа методов имеет следующие вариации:

Теперь обратимся к конфигурации фреймворка. По умолчанию JUL будет выводить сообщения на консоль, однако можно задать конфигурацию в файле свойств. Для задания способа вывода сообщений необходимо для вашего логгера указать какие хендлеры он будет использовать. Существует следующие классы хендлеров: FileHandler, ConsoleHandler, StreamHandler, SocketHandler, MemoryHandler. Особенностью JUL является то, что настройки хендлеров задаются в целом для всего класса, а не для конкретного экземпляра, что может порождать не мало проблем, например если вам потребуется сообщения различных логгеров выводить в различные файлы или с различным форматированием. Рассмотрим простой пример конфигурационного файла:

Log4j

Данный фреймворк на текущий момент имеет уже вторую версию, которая увы не совместима с первой. Поскольку первая версия log4j существует достаточно давно и, в виду ее большой популярности, существует не мало статей на просторах интернета, сегодня мы рассмотрим вторую. Для использования log4j2 вам необходимо подключить библиотеки log4j-api-2.x и log4j-core-2.x. Log4j имеет несколько отличное от JUL именование уровней логгирования: TRACE, DEBUG, INFO, WARN, ERROR, FATAL, а так же ALL и OFF включающий и отключающий все уровни соответственно.
Логгер создается вызовом статического метода класса org.apache.logging.log4j.Logger:

Логгер умеет принимать помимо привычных нам String, Object и Throwable еще два новых типа — MapMessage и Marker:

В классическом для логгеров стиле методы делятся на два типа: совпадающие с названием уровня логгирования и методы log, принимающие уровень логгирования в качестве параметра. Первые имеют вид:

Методы log в log4j2 выглядят так:

Commons-logging

Довольно старый проект, который представляет собой обертку над JUL и log4j, не привносящая никакого дополнительного функционала. Уровни логгирования у JCL совпадают с log4j, а в случае взаимодействия с JUL происходит следующее сопоставление:

Для использования JCL подключаем commons-logging-1.x.jar. Создаем логгер вызовом метода фабрики:

Методы JCL очень простые, совпадают с названием уровней логгирования, принимают только объекты и исключения и имеют две вариации:

Конфигурация JCL содержит отдельные блоки для log4j, JUL и собственной реализации. Если не задать конфигурацию, то используется собственная реализация, именуемая SimpleLog, которая выводит сообщения на консоль. Рассмотрим пример конфигурационного файла:

Указать файл конфигурации JCL можно следующим образом:

Logback

Данный фреймворк используется только в связке с оберткой SLF4J, которую мы будем рассматривать позднее. Для начала работы вам необходимы logback-core-1.x.jar и logback-classic-1.x.x.jar, а также slf4j-api-1.x.x.jar.
Взаимодействие с логгером мы будем осуществлять через API предоставляемый оберткой SLF4J. Уровни логгирования совпадают с log4j. Создание логгера в таком случае выглядит следующим образом:

API позволяет выводить строковые сообщения, шаблоны строковых сообщений, исключения, а также использовать маркеры:

Названия методов совпадают с уровнями логгирования и имеют вид:

SLF4J

Как уже говорилось ранее SLF4J является оберткой над logback, а также над JUL, log4j, или JCL, а также над любым логгером, который реализует ее интерфейс. Для работы с SLF4J нужны библиотека slf4j-api-1.x.x.jar и реализация одного из логгеров либо заглушка. Как правило реализации всех логгеров ( кроме logback) поставляются вместе с SLF4J и имеют названия на подобии slf4j-jcl-1.x.jar, slf4j-log4j12-1.x.jar, slf4j-nop-1.x.jar и т.п. Если в classpath не будет найдена реализация логгера ( или заглушка nop) SLF4J гневно ругнется и работать откажется. Конфигурация соответственно будет искаться в зависимости от положенной в classpath реализации.
API SLF4J мы рассмотрели в предыдущем пункте, поэтому давайте рассмотрим еще одну возможность обертки. В идеальном мире мы должны выводить сообщения через интерфейс обертки, и тогда у нас все будет хорошо, но реальный жестокий мир говорит о том, что всем нам приходится взаимодействовать со сторонними библиотеками или кодом, в которых используются другие логгеры и которые знать не знают о SLF4J. Что бы не подстраиваться под каждый логгер, а пустить все сообщения через одну реализацию интерфейса SLF4J, можно использовать bridging. В поставке обертки содержаться библиотеки jcl-over-slf4j.jar, log4j-over-slf4j.jar и jul-to-slf4j.jar, которые переопределяют поведение соответствующих логгеров и перенаправляют сообщения в обертку.
Что бы стало понятнее выше сказанное, рассмотрим пример. Допустим у нас имеются следующие логгеры:

Мы хотим, что бы сообщение от JUL записывались в один файл, от log4j в другой, а от slf4j выводились на консоль. В качестве реализации обертки будем использовать logback, конфигурация сего безобразия будет выглядеть следующим образом:

Для того, что бы мост заработал необходимо выполнить код:

Источник

Логирование в Java / quick start

В ходе моей работы в компании DataArt я, в числе прочего, занимаюсь менторской деятельностью. В частности это включает в себя проверку учебных заданий сделанных практикантами. В последнее время в заданиях наметилась тенденция «странного» использования логеров. Мы с коллегами решили включить в текст задания ссылку на статью с описанием java logging best practices, но оказалось, что такой статьи в которой бы просто и без лишних деталей на практике объяснялось бы как надо писать в лог на Java, вот так вот с ходу не находится.

Данная статья не содержит каких-то откровений, в ней не рассматриваются тонкости какого либо из многочисленных java logging frameworks. Здесь рассказываю как записать в лог так, чтобы это не вызвало удивления у Ваших коллег, основная цель написания включить ее в список обязательного чтения для практикантов. Если все еще интересно, читайте дальше

Пример №1
Хорошо
Плохо

По сути тоже самое но букв больше и читается не так легко.

Замечание между примерами
Пример №2
Хорошо
Плохо

Если логировать только ex.toString(), то потом Вы не сможете понять в какой строке изначально сработало исключение.

Пример №3

Логер надо конфигурировать. Есть конфигурация по умолчанию она выводит в консоль все сообщения с уровнем INFO и выше. Она достаточно хороша, для разработки из IDE, но для реального приложения ее обычно неплохо бы подправить.

Какие тут есть варианты

По умолчанию: Файл logging.properties для уровня INFO, вывод в консоль

#Console handler
handlers= java.util.logging.ConsoleHandler
.level=INFO

Делаем логирование более подробным выводим еще и сообщения уровня FINE

#Console handler
handlers= java.util.logging.ConsoleHandler
.level=FINE
java.util.logging.ConsoleHandler.level = FINE

Выводим лог сообщения куда-то еще

Чтобы решить эти проблемы был придуман java.util.logging.FileHandler — хэндлер который выводит лог сообщения в файл. При этом он умеет ротировать файлы, т.е. после достижения максимально допустимого размера, он дописывает в файл текщуее лог сообщение и открывает новый файл с инкрементальным префиксом. И так по кругу. Например

создаст вот такие файлы (последняя колонка — размер в байтах)

Мы указали максимальный размер 50 байтов, в реальной жизни надо скорее указывать не меньше мегабайта, например вот так (я знаю, что 1000000 это чуть меньше мегабайта, но кому охота по памяти писать 1048576, если суть дела это фактически не меняет)

В примере, как мы видим, файлы получились больше 50 байт потому что размер по сути округляется вверх до последнего целого лог сообщения. Т.е. если Вы укажете размер 1 байт и запишете лог сообщение размером в 1000 байт то размер файла станет 1000 байт и после этого лог сообщения файл закроется и откроется следующий.

copy & paste конфиг для реальной жизни, его вполне хватает для большинства service, console и desktop приложений.

Последняя часть магии

Первый чуть более правильный ибо он декларативный и работает сразу, до того как начал работать код Вашего приложения.

Вот так

java Djava.util.logging.config.file=logging.properties com.dataart.application.ClassName

Но к сожалению менять строку запуска не всегда можно или не всегда удобно. Второй способ тоже неплохо работает.

Что осталось за кадром

Источник

Заметки разработчика

узнал сам – поделись с другими

26 октября 2012 г.

Простое логирование при помощи Log4j

В большинстве информационных систем среди уровней логирования выделяют следующие (от более низкого к более высокому):

В качестве примера рассмотрим простое приложение, состоящее всего из одного класса и одного конфигурационного файла. Если вы разрабатываете в Idea, то вот вам пошаговая инструкция:

Screenshot 4

Создайте в папке src вашего проекта какой-нибудь пакет (например, ru.nordmine), а в нём создайте класс SimpleMain с таким содержимым:

public class SimpleMain <

private static final Logger logger = Logger.getLogger(SimpleMain.class);

public static void main(String[] args) <
for(int i = 0; i try <
logger.info(«result: » + divide(i));
> catch (Exception e) <
logger.error(e.getMessage(), e);
>
>
>

public static int divide(int x) <
logger.debug(«divide method invoked; 2 / » + x);
if(x == 0) <
logger.warn(«x = 0; exception may occur»);
>
return 2 / x;
>
>

В классе SimpleMain логгер определён в виде приватного статического и неизменяемого поля. В качестве параметра метода, который его создаёт, передаём текущий класс. В самом методе main в цикле вызывается метод divide, который выполняет какую-то работу. Неважно какую, в качестве примера он делит 2 на то число, которое ему передали. Обратите внимание на уровни логирования.

В методе divide при старте выводится сообщение уровня debug о том, что метод запущен и с каким параметром. Предположим, что мы используем уровень логирования INFO, поэтому данное сообщение будет выводится не будет. И зачем, ведь нам не интересно знать о каждом выводе метода и с каким параметром.

Далее, поскольку метод делит 2 на то, что к нему пришло, есть некая вероятность деления на нуль (что и прозойдёт в нашем примере). Поэтому лучше проверять входные аргументы и выводить предупреждение, если что-то будет не так. Уровень WARN выше, чем INFO, поэтому при текущем уровне логирования предупреждение будет выведено.

В методе main в цикле мы вызываем метод divide, передавая ему последовательно аргументы от 0 до 2. Зная, что в вызываемом методе потенциально может возникнуть ошибка, обернём его вызов в конструкцию try-catch. Обратите внимание, что она внутри цикла, а не снаружи. То есть ошибочный аргумент метода не остановит весь цикл, а только одну итерацию, что логично. Если вызов пройдёт успешно, будет показан результат с уровнем INFO, если произойдёт исключение, то будет выведен текст ошибки с уровнем ERROR и полный stack trace, ведь мы передаём логгеру не только текст ошибки, но и объект исключения. И это правильно, т.к. среди однотипных записей лога гораздо быстрее обнаружить stack trace, чем неприметную запись ERROR.

Теперь осталось сконфигурировать логгер. Его конфигурация может быть в двух форматах: обычном текстовом property-файле (log4j.properties) и в формате xml (log4j.xml). Начнём с более простого текстового. Положите файл log4j.properties со следующим содержимым в корень вашего проекта:

# Root logger option
log4j.rootLogger=INFO, stdout

Это пожалуй самый простой вариант настройки логгирования, при котором сообщения в указанном формате будут выводить только на консоль, причём только если уровень не ниже INFO.

А теперь давайте сконфигурируем логгер таким образом, чтобы сообщения выводились в консоль и в файл. Поместим эту конфигурацию в файл log4j.xml, который положим в корень папки src.

В этой конфигурации мы отключаем вывод отладочной информации самого логгера (иногда это тоже может пригодиться). Для добавления записи в лог используется так называемый аппендер. В библиотеке определено множество различных типов аппендеров, мы же здесь рассмотрим два из них: ConsoleAppender (вывод в консоль) и DailyRollingFileAppender (запись в файл).

Если с консолью всё понятно, то почему был выбран именно DailyRollingFileAppender? Дело в том, что этот тип аппендера позволяет не просто записывать в файл, а ещё и автоматически архивировать эти файлы. Например, создавать каждые сутки новый файл для лога. Имя файла, а заодно и правила ротации, задаёт параметр DatePattern. В нашем примере файлы будут создаваться каждые сутки. Имя файла будет иметь формат «messages-ГГГГ-ММ-ДД». Файл, в который в настоящий момент ведётся запись, имеет имя «messages» (параметр File) без метки времени. Можно настроить ротацию также каждый час и даже каждую минуту. В зависимости от того, как много записей добавляется в лог.

В конце указываем минимальный корневой уровень логирования (INFO) для обоих аппендеров. Записи ниже этого уровня добавляться не будут.

Теперь, если запустить наше приложение, мы увидим только одну строку с уровнем INFO (в файл была добавлена точно такая же строка):

Здесь мы видим, что сначала было предупреждение, а затем произошла ошибка, поэтому понижаем уровень логирования до DEBUG, чтобы получить больше отладочной информации, и тогда мы увидим, какие методы вызывались и с какими параметрами:

Источник

Что такое логирование?

cover

Известно, что программисты проводят много времени, отлаживая свои программы, пытаясь разобраться, почему они не работают — или работают неправильно. Когда говорят про отладку, обычно подразумевают либо отладочную печать, либо использование специальных программ – дебагеров. С их помощью отслеживается выполнение кода по шагам, во время которого видно, как меняется содержимое переменных. Эти способы хорошо работают в небольших программах, но в реальных приложениях быстро становятся неэффективными.

debugger

Сложность реальных приложений

Возьмем для примера типичный сайт. Что он в себя включает?

И это только самый простой случай. Реальность же значительно сложнее: множество разноплановых серверов, системы кеширования (ускорения доступа), асинхронный код, очереди, внешние сервисы, облачные сервисы. Все это выглядит как многослойный пирог, внутри которого где-то работает нами написанный код. И этот код составляет лишь небольшую часть всего происходящего. Как в такой ситуации понять, на каком этапе был сбой, или все пошло не по плану? Для этого, как минимум, нужно определить, в каком слое произошла ошибка. Но даже это не самое сложное. Об ошибках в работающем приложении узнают не сразу, а уже потом, — когда ошибка случилась и, иногда, больше не воспроизводится.

Логирование

И для всего этого многообразия систем существует единое решение — логирование. В простейшем случае логирование сводится к файлу на диске, куда разные программы записывают (логируют) свои действия во время работы. Такой файл называют логом или журналом. Как правило, внутри лога одна строчка соответствует одному действию.

Выше небольшой кусок лога веб-сервера Хекслета. Из него видно ip-адрес, с которого выполнялся запрос на страницу и какие ресурсы загружались, метод HTTP, ответ бекенда (кода) и размер тела ответа в HTTP. Очень важно наличие даты. Благодаря ей всегда можно найти лог за конкретный период, например на то время, когда возникла ошибка. Для этого логи грепают:

Когда программисты только начинают свой путь, они, часто не зная причину ошибки, опускают руки и говорят «я не знаю, что случилось, и что делать». Опытный же разработчик всегда первым делом говорит «а что в логах?». Анализировать логи — один из базовых навыков в разработке. В любой непонятной ситуации нужно смотреть логи. Логи пишут все программы без исключения, но делают это по-разному и в разные места. Чтобы точно узнать, куда и как, нужно идти в документацию конкретной программы и читать соответствующий раздел документации. Вот несколько примеров:

Многие программы логируют прямо в консоль, например Webpack показывает процесс и результаты сборки:

Во фронтенде файлов нет, поэтому логируют либо прямо в консоль, либо к себе в бекенды (что сложно), либо в специализированные сервисы, такие как LogRocket.

Уровни логирования

Чем больше информации выводится в логах, тем лучше и проще отладка, но когда данных слишком много, то в них тяжело искать нужное. В особо сложных случаях логи могут генерироваться с огромной скоростью и в гигантских размерах. Работать в такой ситуации нелегко. Чтобы как-то сгладить ситуацию, системы логирования вводят разные уровни. Обычно это:

Поддержка уровней осуществляется двумя способами. Во-первых, внутри самой программы расставляют вызовы библиотеки логирования в соответствии с уровнями. Если произошла ошибка, то логируем как error, если это отладочная информация, которая не нужна в обычной ситуации, то уровень debug.

Во-вторых, во время запуска программы указывается уровень логирования, необходимый в конкретной ситуации. По умолчанию используется уровень info, который используется для описания каких-то ключевых и важных вещей. При таком уровне будут выводиться и warning, и error. Если поставить уровень error, то будут выводиться только ошибки. А если debug, то мы получим лог, максимально наполненный данными. Обычно debug приводит к многократному росту выводимой информации.

Уровни логирования, обычно, выставляются через переменную окружения во время запуска программы. Например, так:

Существует и другой подход, основанный не на уровнях, а на пространствах имен. Этот подход получил широкое распространение в JS-среде, и является там основным. Фактически, он построен вокруг одной единственной библиотеки debug для логирования, которой пронизаны практически все JavaScript-библиотеки как на фронтенде, так и на бекенде.

debug

Принцип работы здесь такой. Под нужную ситуацию создается специализированная функция логирования с указанием пространства имен, которая затем используется для всех событий одного процесса. В итоге библиотека позволяет легко отфильтровать только нужные записи, соответствующие нужному пространству.

Запуск с нужным пространством:

debug http

Ротация логов

Со временем количество логов становится большим, и с ними нужно что-то делать. Для этого используется ротация логов. Иногда за это отвечает сама программа, но чаще — внешнее приложение, задачей которого является чистка. Эта программа по необходимости разбивает логи на более мелкие файлы, сжимает, перемещает и, если нужно, удаляет. Подобная система встроена в любую операционную систему для работы с логами самой системы и внешних программ, которые могут встраиваться в нее.

С веб-сайтами все еще сложнее. Даже на небольших проектах используется несколько серверов, на каждом из которых свои логи. А в крупных проектах тысячи серверов. Для управления такими системы созданы специализированные программы, которые следят за логами на всех машинах, скачивают их, складывают в заточенные под логи базы данных и предоставляют удобный способ поиска по ним.

Здесь тоже есть несколько путей. Можно воспользоваться готовыми решениями, такими как DataDog Logging, либо устанавливать и настраивать все самостоятельно через, например, ELK Stack

Источник

Сообщения каких уровней мы увидим задав уровень info

Логирование в Java

Хотя правильнее было бы говорить наверное журналирование/протоколирование и вести журнал/протокол соответственно.

Но так никто никогда не говорит, конечно ¯\(ツ)

Поэтому «логи всякие нужны, логи всякие важны».

Все ли нужно логировать?

Если вы вдруг залогируете в общий файл-лога пароль и логин пользователя, то никто такому рад не будет, что подводит нас к мысли, что логировать надо тоже с умом.

Т.е возникает требование управления информацией, которая нам нужна в данный момент, а также форматом ее вывода.

При этом, логично, что изменения этого формата и того, что мы хотим видеть в логе не должны требовать перекомпиляции всего проекта или изменения кода.

Уровень логирования Описание
ALL Все сообщения
TRACE Сообщение для более точной отладки
DEBUG Дебаг-сообщение, для отладки
INFO Обычное сообщение
WARN Предупреждение, не фатально, но что-то не идеально
ERROR Ошибка
FATAL Фатальная ошибка, дело совсем плохо
OFF Без сообщения

Если проиллюстрировать это:

log level

Принципы и понятия

Логер создается с помощью фабрики и на этапе создания ему присваивается имя. Имя может быть любым, но по стандарту имя должно быть сопряжено с именем класса, в котором вы собираетесь что-то логировать:

Почему так рекомендуется делать?

Получается выстраивается следующая иерархия логеров:

И каждому логеру можно выставить свой уровень. Установленный логгеру уровень вывода распространяется на все его дочерние логгеры, для которых явно не выставлен уровень.

При этом во главе иерархии логеров всегда стоит некотрый дефолтный рутовый(корневой) логер.

Поэтому у всех логеров будет уровень логирования, даже если явно мы не прописали для ru.aarexer.example.SomeClass его, то он унаследуется от рутового.

Вопрос:

Логер Назначенный уровень
root INFO
ru Не назначен
ru.aarexer DEBUG
ru.aarexer.example Не назначен

Какой у какого логера будет уровень логирования?

Ответ:

Вспоминаем, что, если уровень логирования не назначен для логера, то он унаследует его от родительского, смотрим на иерархию:

Logger Назначенный уровень Уровень, который будет
root Все сообщения INFO
ru Не назначен INFO
ru.aarexer DEBUG DEBUG
ru.aarexer.example Не назначен DEBUG

Это событие по сути состоит из двух полей:

Аппендер – это та точка, куда события приходят в конечном итоге. Это может быть файл, БД, консоль, сокет и т.д.

У одного логгера может быть несколько аппендеров, а к одному аппендеру может быть привязано несколько логгеров.

Логеры при этому наследуют от родительских не только уровни логирования, но и аппендеры.

Например, если к root-логгеру привязан аппендер A1, а к логгеру ru.aarexer – A2, то вывод в логгер ru.aarexer попадет в A2 и A1, а вывод в ru – только в A1.

Вопрос:

Пусть у нас есть несколько аппендеров и логеров

Logger Appender
root А1
ru.aarexer А2
ru.aarexer.example.SomeClass А3

В какой аппендер попадет лог-сообщение:

Ответ:

Это говорит о том, что логер-наследник будет свои события передавать логеру-родителю.

Смотрим на иерархию:

Из всего вышесказанного делаем вывод, что событие «hello» с уровнем Level.INFO попадет во все три аппендера.

Но такое наследование аппендеров можно отключить через конфигурацию, для этого стоит посмотреть в сторону выставления флага additivity=»false» на логгерах.

Т.е как лог-сообщения будут отформативарованы, соответственно тут у каждой библиотеки свой набор доступных форматов.

Библиотеки логирования в Java

Однако он не отвечает всем тем требованиям, которые мы сформулировали выше, поэтому рассмотрим альтернативы.

Наиболее популярные библиотеки логирования в Java :

И поэтому появились еще две библиотеки:

Это самая первая библиотека логирования, появилась еще в 1999 году.

Поддерживает большое количество способов вывода логов: от консоли и файла до записи в БД.

Благодаря подобной иерархии лишнее отсекается и поэтому логер работает быстро.

dont think

Проект сейчас не развивается и по сути заброшен, с версией Java 9 уже не совместим.

Вклад log4j в мир логирования настолько велик, что многие идеи были взяты в библиотеки логирования для других языков.

jul fine

Чувствуете насколько все переосложнено?

Так как стандартных средств форматирования логов недостаточно, то все сводилось к тому, что писались свои. Это при том, что log4j предоставлял больший функционал, работал как минимум не медленнее и в целом себя чувствовал хорошо.

Уровни логгирования у JCL совпадают с log4j, а в случае взаимодействия с JUL происходит следующее сопоставление:

JCL JUL
ALL Все сообщения
TRACE Level.FINEST
DEBUG Level.FINE
INFO Level.INFO
WARN Level.WARNING
ERROR Level.SEVERE
FATAL Level.SEVERE
OFF Без сообщения

С уверенностю можно сказать сейчас, что в эту сторону даже смотреть не стоит. Пациент мертв.

Лицензия Apache License Version 2.0
Последняя версия 1.2
Дата выпуска последней версии июль 2014

Но добавили много нового, парочка из них:

Правда перестали поддерживать properties конфигурации и конфигурации от log4j на xml надо было переписывать заново.

Лицензия Apache License Version 2.0
Последняя версия 2.11.2
Дата выпуска последней версии февраль 2019
Лицензия MIT License
Последняя версия 2.0.0-alpha0
Дата выпуска последней версии июнь 2019

При этом, logback не является частью Apache или еще какой-то компании и независим.

Лицензия EPL/LGPL 2.1
Последняя версия 1.3.0-alpha4
Дата выпуска последней версии февраль 2018

Так как из адаптеров это по сути единственный выбор, да и встречается slf4j все чаще, то стоит рассмотреть его устройство.

Вопрос:

Ответ:

Вроде все проблемы решены, пусть и такими радикальными способоами.

log hell

Таким образом, чтобы работать со Spring получается надо сделать CLASSPATH подобным образом:

Если конфигурация сделана программно, то bridge не будет работать.

logger final

Бесконтрольно подтягиваемые транзитивные зависимости библиотек, которые вы используете в своем проекте, рано или поздно принесут какие-то свои библиотеки логирования, отчего могут открыться врата прямиком в ад.

При этом, если вы разрабатываете библиотеку, то:

Очень важно также не забывать о том, что такое логирование и для чего оно нужно.

Поэтому нельзя скатываться в бесмысленные записи в лог, вывод личных данных и так далее.

Думайте о том что вы пишите в лог!

Источник

Оцените статью
Мебель
Adblock
detector