Стоит ли использовать slf4j с log4j2
Я не могу решить, использовать ли slf4j или нет с log4j2. Судя по сообщениям в Интернете, похоже, что это не повлияет на производительность, но действительно ли это необходимо.
Также эти пункты правят в пользу log4j2:
- SLF4J заставляет ваше приложение регистрировать строки. Log4j 2 API поддерживает запись любого CharSequence, если вы хотите записать текст, но также поддерживает запись любого объекта как есть.
- Log4j 2 API предлагает поддержку для регистрации объектов сообщений, лямбда-выражений Java 8 и ведения журналов без мусора (он избегает создания массивов vararg и избегает создания строк при регистрации объектов CharSequence).
2 ответа
Идем дальше: программируйте на API log4j2 вместо slf4j
Это безопасно: API Log4j2 предлагает те же гарантии, что и slf4j - и даже больше.
Теперь, когда сам Log4j2 разделен на API и модуль реализации, использование SLF4J больше не имеет смысла.
Да, это хорошая инженерная практика, чтобы держать ваши варианты открытыми. Возможно, вы захотите перейти к другой реализации ведения журнала позже.
В течение последних 10 лет создание такой гибкости в вашем приложении означало использование API-оболочки, такого как SLF4J. Эта гибкость не предоставляется бесплатно: недостатком этого подхода является то, что ваше приложение не может использовать более богатый набор функций базовой библиотеки журналов.
Log4j2 предлагает решение, которое не требует, чтобы ваше приложение ограничивалось наименьшим общим знаменателем.
Выпускной клапан: log4j-to-slf4j
Log4j2 включает в себя log4j-to-slf4j
Мостовой модуль. Любое приложение, закодированное с использованием API Log4j2, может в любой момент переключить поддержку реализации на любую реализацию, совместимую с slf4j.
Как уже упоминалось в этом вопросе, использование Log4j2 API напрямую предлагает больше функциональности и имеет некоторые нефункциональные преимущества по сравнению с использованием API-оболочки, такого как slf4j:
- API сообщений
- Лямбды для ленивых
- Журнал любого объекта, а не только строки
- Без мусора: избегайте создания varargs или строк, где это возможно
- CloseableThreadContext автоматически удаляет элементы из MDC, когда вы закончите с ними
(См. 10 функций API Log4j2, недоступных в SLF4J для получения дополнительной информации.)
Приложения могут безопасно использовать эти богатые функции API Log4j2, не будучи привязанными к собственной реализации ядра Log4j2.
SLF4J по-прежнему является вашим предохранительным клапаном, но это не означает, что ваше приложение должно больше кодировать против API SLF4J.
Раскрытие информации: я помогаю в Log4j2.
Обновление: Кажется, есть некоторая путаница, что программирование для API Log4j2 каким-то образом вводит "фасад для фасада". В этом отношении нет разницы между API Log4j2 и SLF4J.
Оба API требуют 2 зависимостей при использовании собственной реализации и 4 зависимости для не собственной реализации. SLF4J и Log4j2 API идентичны в этом отношении. Например:
Есть немало соображений, которые делают ведение журнала «более сложным, чем кажется на первый взгляд» (отсюда многолетние ожесточенные бои!).
Разделение проблем
В конце дня код «отправляет данные журнала», и эти данные «где-то попадают». Но где он окажется, зависит от цели, для которой он собирается. Сильно усложняет картину тот факт, что современное программное обеспечение состоит из различных компонентов, и все они потенциально нуждаются в регистрации.
Рассмотрим наихудший случай: все компоненты используют
System.out#println(String)
. По крайней мере, все операторы находятся в порядке выполнения, но может быть непросто определить, какой компонент генерирует каждую часть вывода. А некоторые компоненты могут быть слишком подробными для контекста, в котором они используются.
Давайте рассмотрим следующий наихудший случай: все компоненты принимают собственные меры для управления своим поведением в журнале и местом назначения. Администратору, возможно, придется настроить десятки систем журналов для одного программного обеспечения. Теперь операторы журнала не вместе и не в порядке. Надеюсь, у всех у них есть последовательная стратегия с отметками времени!
Мы хотели бы что-то среднее: что-то, посредством чего код может сказать «записать это», а администратор может контролировать, где он заканчивается.
Чрезмерно краткая история
Введите Log4J v1, который решает проблему с понятиями «уровни», «дополнения», «фильтры», «макеты» и «контексты» ... концептуальную архитектуру, поддерживаемую иерархическим «пространством имен регистратора» (включая способ естественного использования вне пространств имен пакетов Java), а также механизм конфигурации для легкого управления.
Все было хорошо ... пока все компоненты программного обеспечения основывались на одной и той же версии! Было время, когда эти вещи менялись. Основной вклад SLF4J состоял в том, чтобы «закрепить» эти концепции в стабильный API с точки зрения разработчика компонентов, без ущерба для возможностей администратора выполнять свою часть работы. Библиотеки могут полагаться на «фасад» SLF4J, ожидая, что они будут обращаться к «реализации» всего за несколько вызовов вниз по стеку. Администраторы могли выбрать то, что им подходит, чтобы объединить журналы в связную запись, которая им важна.
(Это еще более сложно, когда ваше программное обеспечение работает в контейнере, и у контейнера есть свои собственные потребности в журналировании, и вы даже не то же самое приложение, которое работает в контейнере ... Журнал Tomcat JULI - используется для его собственного внутреннего журналирования - `` уходит с дороги '' приложений, работающих в подконтекстах загрузчика классов.)
Загадочно презирая работу SLF4J, Java Community Process решил реализовать почти такую же концептуальную архитектуру, но с меньшей гибкостью в деталях. Однако, будучи по сути частью семантического богатства SLF4J, было легко сделать SLF4J фасадом для
j.u.l
.
Ведение журнала Apache Commons Util, вероятно, было не очень необходимо. Собственный Logback Ceki представил функции управления, которых у Log4J v1 в то время не было, - не в последнюю очередь являясь реализацией SLF4J и решающей все эти очень реальные головные боли с загрузчиком классов, но также предоставляя грамотную реализацию с некоторыми привлекательными функциями для администратора.
Ведение журнала для разных ситуаций
Но ведение журнала выполняется в самых разных контекстах. Преобразование этих сообщений в сверхмедленный ввод-вывод без чрезмерной блокировки потока и без необходимости платить за вычисление сообщения журнала, если оно не требуется, и создание согласованных журналов в многопоточном контексте ... все это имеет значение. (Вот почему
java.util.logging
не часто используется!).
Иногда требуемые оптимизации влияют на концептуальную архитектуру, которая, в свою очередь, должна влиять на API на стороне разработчика. Например, возможности, предоставляемые закрытием, определенно ускорят работу, если сообщение журнала окажется заблокированным из-за фильтрации. Для использования этой функции необходимо рассмотреть SLF4J.next или какой-либо другой API, и Log4J2 не нужно исключать из этого решения. Поскольку часть API является концептуальным надмножеством того, что предлагается SLF4J, легко сделать ее фасадом для SLF4J и тех реализаций, которые находятся под ним ... или более прямым мостом к тому, что предпочитает администратор.
Для разработчика приложений это действительно не имеет значения, если в конечном итоге администратор выбирает одно средство ведения журнала, и все компоненты могут выполнять выход из него. Если средство может принимать сообщения через SLF4J и Log4J2-the-API, это прекрасно. Log4J2-the-implementation делает именно это. Вы можете съесть свой пирог и съесть его: ваше приложение может пользоваться возможностями, предлагаемыми Log4J2-the-API, при этом по-прежнему используя библиотеки, которые адекватно обслуживаются SLF4J. Если администратор презирает реализацию Log4J2-the-реализации (хотя трудно понять, почему они это сделали, с любого угла), то они могут использовать все, что уже поддерживает SLF4J, не дожидаясь, пока эта реализация ведения журнала поддерживает Log4J2-the-API. Вы можете съесть свой пирог.
Для разработчиков библиотек это больше проблема. Безопасный путь - SLF4J из-за его широкого распространения. Если ведение журнала имеет решающее значение для успеха вашей библиотеки ... особенно, если оно многопоточное, создание операторов журнала может быть дорогостоящим, и, возможно, лучше отказаться от обработки, если они в конечном итоге не будут использованы, если есть большой объем операторов журнала для обработки, производительность имеет решающее значение, и ваши пользователи, вероятно, оценят преимущества Log4J2-the-implementation, а затем сделают Log4J2. Но вы также не крадете возможности у своих пользователей, оставаясь с SLF4J. Администратор может по-прежнему использовать Log4J-the-implmenation, если пожелает.
Суть
Если вам нужны функции, предоставляемые Log4J2, воспользуйтесь ими. Если они вам не нужны, SLF4J - это зрелый, стабильный интерфейс с большой поддержкой. SLF4J остается важной частью инфраструктуры с открытым исходным кодом. Ceki оказал сообществу большую услугу, взамен приложив много усилий.
Но в конечном итоге преобладают богатые API, поддерживаемые грамотными реализациями. Сегодняшняя стабильность - это завтрашний застой. Процесс доработки продолжается. Не нужно выходить из автобуса, если он едет туда, куда вы хотите.