Система была недавно удалена и все еще использует старую версию log4j, и ее необходимо обновить до последней версии log4j. Однако после обновления я обнаружил, что библиотеки обработки журналов, связанные с Java, включают log4j, log4j2, slf4j и logback. На первый взгляд они действительно немного утомительны, так в чем же разница? Я, вероятно, немного знал об этом раньше и искал много соответствующей информации. Вот краткое изложение, я думаю, после прочтения вы станете в этом разбираться.
Студенты, которые использовали Log4J и LogBack, обязательно обнаружат, что концепции проектирования этих двух фреймворков очень похожи, а методы использования совершенно одинаковы. На самом деле автором этих двух фреймворков является один человек, Чеки Гюльджю, российский программист.
Первоначально Log4J представлял собой платформу ведения журналов, разработанную на основе Java. После периода разработки автор Чеки Гюльджю передал Log4j в Apache Software Foundation, сделав его подпроектом службы ведения журналов Apache. Благодаря отличной производительности Log4J впоследствии были созданы подфреймворки, поддерживающие C, C++, C#, Perl, Python, Ruby и другие языки.
Однако великие программисты, похоже, обладают большей индивидуальностью. Чеки Гюльджю решил не участвовать в разработке и сопровождении Log4J из-за недовольства тем, как Apache управляет Log4J. После «ухода» Чеки Гюльджю начал заново и разработал фреймворк LogBack (SLF4J был разработан вместе с LogBack). LogBack исправил многие недостатки Log4J и значительно улучшил производительность. В то же время его использование почти такое же, как и у Log4J. Многие пользователи постепенно начали использовать LogBack.
Из-за влияния LogBack Log4J начал приходить в упадок. Наконец, в сентябре 2015 года Apache Software Foundation объявил, что Log4j больше не обслуживается, и рекомендовал обновить все связанные проекты до Log4j2. Log4J2 — это новая среда ведения журналов, разработанная Apache. Она устраняет многие недостатки Log4J, а также использует LogBack. Говорят, что она превосходит LogBack с точки зрения производительности. Подробно производительность проанализирую позже.
Полное имя SLF4J простое. Logging Facade for Java,slf4jдарежим фасадаТипичные применения,Итак, прежде чем говорить о slf4j,Мне нужно вкратце представить режим фасада.
Нижедарежим фасада Типичный процесс вызова,Суть в том, что внешняя связь с подсистемой должна осуществляться через единый объект внешнего вида, что упрощает использование подсистемы. На рисунке ниже клиенту не нужно напрямую вызывать несколько подсистем, ему достаточно общаться с единым фасадом.
Ядром шаблона фасада является Facade, который является объектом фасада, и ядром является несколько пунктов:
Прежде чем ответить на этот вопрос, давайте сначала посмотрим, как это сделать, если нам нужно использовать вышеуказанные платформы журналов для печати журналов. Конкретный код выглядит следующим образом:
// Для использования log4j требуется log4j.jar.
import org.apache.log4j.Logger;
Logger logger_log4j = Logger.getLogger(Test.class);
logger_log4j.info("Hello World!");
// Для использования log4j2 необходимы log4j-api.jar и log4j-core.jar.
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Logger logger_log4j2 = LogManager.getLogger(Test.class);
logger_log4j2.info("Hello World!");
// logback,нуждатьсяlogback-classic.jar、logback-core.jar
импортировать ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
Logger logger_logback = new LoggerContext().getLogger(Test.class);
logger_logback.info("Hello World!");
Из вышесказанного нетрудно увидеть, что использование разных платформ ведения журналов требует введения разных jar-пакетов и использования разных кодов для получения Logger. Если обновление проекта потребует замены другого фреймворка, то для получения нового Регистратора необходимо все изменить, что создаст огромную рабочую нагрузку.
На основании этого,Нам нужен интерфейс для унификации использования различных платформ ведения журналов, поэтому используется slf4j.
SLF4J, Simple Logging Facade для Java, не является конкретным решением для ведения журналов. Он обслуживает только различные системы ведения журналов. Согласно официальному заявлению, SLF4J — это простой фасад для систем журналирования, позволяющий конечным пользователям использовать ту систему журналирования, которую они хотят, при развертывании своих приложений.
Примечание. Аналогичный бревенчатый фасад - Jakarta Common. logging (JCL), основное отличие состоит в том, что SLF4J — это относительно новая платформа ведения журнала. Она более гибкая, имеет лучшую производительность и поддерживает больше реализаций ведения журнала. Кроме того, JCL динамически загружает структуру ведения журнала во время выполнения на основе classLoader, что может привести к возникновению ошибок. много смысла. Неожиданные проблемы безопасности, пожалуйста, обратитесь к обсуждению этого вопроса htt. ps://stackoverflow.com/questions/3222895/what-is-the-issue-with-the-runtime-discovery-algorithm-of-apache-commons-logging
Из приведенного выше введения мы знаем, что JCL и SLF4J являются фасадами журналов (Facade), а Log4J, Log4J2 и LogBack — это роли подсистемы (SunSystem), которая представляет собой конкретную структуру реализации журналов. Их отношения следующие: JUL — это реализация, предоставляемая самим JDK.
Самое большое преимущество использования бревенчатого фасада для представления бревенчатых компонентов.да:Отделите систему от конкретной структуры реализации журналов.
После использования slf4j при печати журналов мы можем использовать следующий метод:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Logger logger = LoggerFactory.getLogger(Test.class);
logger.info("Hello World!")
Возникает еще один вопрос: как slf4j решает, какой журнал фреймворка использовать и какие jar-пакеты вводить? Чиновник подготовил для нас следующую схему комбинированной структуры зависимостей:
Подводя итог, вот следующее:
Обратите внимание, что между log4j2 и log4j2 нет зависимости от jar. Для взаимодействия с log4j2 вам необходимо импортировать log4j-api.jar, log4j-core.jar и связующий пакет log4j-slf4j-impl.jar из log4j2.
Так называемый пакет моста реализует класс StaticLoggerBinder для подключения slf4j и платформы ведения журналов. Поскольку в log4j и log4j2 вначале не было класса StaticLoggerBinder, чтобы не менять структуру программы, мы могли только переписать новый jar для реализации StaticLoggerBinder. После того, как slf4j появился в журнале, StaticLoggerBinder был реализован в собственном jar-файле журнала, поэтому не было необходимости в связующем пакете.
Apache Log4j 2 — это обновленная версия Log4j(1), которая значительно улучшена по сравнению с его предшественником Log4j 1.x и logback. Помимо корректировок внутреннего дизайна, произошли серьезные обновления по следующим направлениям:
Log4j2 разделен на два модуля: API (log4j-api) и реализация (log4j-core). API и slf4j имеют один и тот же тип и относятся к абстракции/фасаду журнала, а часть реализации является ядром Log4j 2.
log4j2 имеет самую высокую производительность асинхронного ведения журналов среди существующих платформ ведения журналов в JAVA. Подробности см. в сравнительной таблице ниже:
log4j2 использует повторное использование строк и другие методы для достижения нулевого режима GC. Он также предоставляет MemoryMappedFileAppender для достижения чрезвычайно высокой производительности ввода-вывода, а API имеет более богатые функции форматирования параметров, чем slf4j.
После долгого разговора, как использовать Log4j2, я расскажу об этой части подробно.
Ниже в качестве примера используется конфигурация Maven.
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.2</version>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="LogToConsole" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="com.malaoshi" level="debug" additivity="false">
<AppenderRef ref="LogToConsole"/>
</Logger>
<Root level="error">
<AppenderRef ref="LogToConsole"/>
</Root>
</Loggers>
</Configuration>
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class HelloWorld {
private static final Logger logger = LogManager.getLogger(HelloWorld.class);
public static void main(String[] args) {
logger.debug("Hello from Log4j 2");
// in old days, we need to check the log level to increase performance
/*if (logger.isDebugEnabled()) {
logger.debug("{}", getNumber());
}*/
// with Java 8, we can do this, no need to check the log level
logger.debug("{}", () -> getNumber());
}
static int getNumber() {
return 5;
}
}
Вывод следующий:
19:12:25.337 [main] DEBUG com.malaoshi.HelloWorld - Hello from Log4j 2
19:12:25.340 [main] DEBUG com.malaoshi.HelloWorld - 5
Во-первых, позвольте мне показать вам относительно полный файл конфигурации. Он может показаться немного сложным. Не волнуйтесь, я тщательно проанализирую его позже.
<?xml version="1.0" encoding="UTF-8"?>
<!--Уровень журнала и сортировка по приоритетам: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configurationпозадиstatus,Это используется для настройки вывода информации внутри самого log4j2.,Нет необходимости устанавливать,Когда установлено отслеживание,ты увидишьlog4j2Различные внутренние подробные результаты-->
<!--monitorInterval:Log4jВозможность автоматического обнаружения измененных конфигураций. документипереконфигурировать себя,Установить интервал в секундах-->
<configuration status="WARN" monitorInterval="30">
<!--Сначала определите всеappender-->
<appenders>
<!--Конфигурация этой выходной консоли-->
<console name="Console" target="SYSTEM_OUT">
<!--Формат выходного журнала-->
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
</console>
<!--документраспечатаю всеинформация,Этот журнал будет автоматически очищаться при каждом запуске программы.,Определяется атрибутом добавления,Это тоже весьма полезно,Подходит для временного тестирования-->
<File name="log" fileName="log/test.log" append="false">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</File>
<!-- Это распечатает всю информацию и информацию ниже уровня.,Каждый раз, когда размер превышает размер,Тогда логи такого размера будут автоматически сохраняться в папках, созданных по годам и месяцам, и сжиматься.,как архив-->
<RollingFile name="RollingFileInfo" fileName="${sys:user.home}/logs/info.log"
filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
<!--Консоль выводит толькоlevelи информация вышележащего уровня(onMatch),Остальные отклоняются напрямую(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
<RollingFile name="RollingFileWarn" fileName="${sys:user.home}/logs/warn.log"
filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<!-- Если атрибут DefaultRolloverStrategy не установлен, по умолчанию в одной папке может быть не более 7 файлов, а здесь установлено 20. -->
<DefaultRolloverStrategy max="20"/>
</RollingFile>
<RollingFile name="RollingFileError" fileName="${sys:user.home}/logs/error.log"
filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
</appenders>
<!--затем определитеlogger,Только приложения, в которых определен и введен регистратор.,appenderвступит в силу-->
<loggers>
<!--отфильтроватьspringиmybatisкакой-то бесполезныйDEBUGинформация-->
<logger name="org.springframework" level="INFO"></logger>
<logger name="org.mybatis" level="INFO"></logger>
<root level="all">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</configuration>
Давайте внимательно разберем этот конфигурационный файл для всех:
1. Корневой узел
Конфигурация имеет два свойства: статус и интервал мониторинга, а также два подузла: Appenders и Loggers (что указывает на то, что можно определить несколько Appenders и Loggers).
2. Узел «Приложения»
Узел Appenders, распространенными подузлами являются: Console, RollingFile, File.
Консольный узелИспользуется для определения вывода на консольAppender。
Файловый узелИспользуется для определения вывода в указанное местодокументизAppender。
RollingФайловый узелИспользуется для определения автоматическогоудалитьстарое создает новоеAppender。
TimeBasedTriggeringPolicy: подузел «Политики», стратегия прокрутки на основе времени, атрибут интервала используется для указания частоты прокрутки, значение по умолчанию — 1 час. modulate=true используется для настройки времени: например, сейчас 3 часа ночи, а интервал равен 4, затем первая прокрутка в 4 утра, затем 8 утра, 12 утра... вместо 7 утра. SizeBasedTriggeringPolicy: подузел «Политики», политика смены значений на основе указанного размера файла. Атрибут размера используется для определения размера каждого файла журнала.
3. Loggers
Узел Loggers, общие подузлы: Root и Logger.
Корневой узелИспользуется для указания корневого журнала проекта.,Если Logger не указан отдельно,Тогда вывод корневого журнала будет использоваться по умолчанию.
Узел регистратораИспользуется для индивидуального указания формата журнала.,Например, вам необходимо указать разные уровни журналирования для классов в указанном пакете.
4. Уровень журнала
Всего существует 8 уровней, от низкого до высокого: Все < Trace < Debug < Info < Warn < Error < Fatal < OFF。
Программа будет печатать журналы выше или равные установленному уровню. Чем выше установлен уровень журнала, тем меньше журналов будет распечатано.
В этой части представлены несколько часто используемых конфигураций, которые можно использовать непосредственно в проекте, изменив имя пакета.
1. Вывод логов на консоль
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="DEBUG">
<Appenders>
<Console name="LogToConsole" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<!-- avoid duplicated logs with additivity=false -->
<Logger name="com.mkyong" level="debug" additivity="false">
<AppenderRef ref="LogToConsole"/>
</Logger>
<Root level="error">
<AppenderRef ref="LogToConsole"/>
</Root>
</Loggers>
</Configuration>
2. Вывод журнала в файл.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="DEBUG">
<Appenders>
<Console name="LogToConsole" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<File name="LogToFile" fileName="logs/app.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Logger name="com.malaoshi" level="debug" additivity="false">
<AppenderRef ref="LogToFile"/>
<AppenderRef ref="LogToConsole"/>
</Logger>
<Logger name="org.springframework.boot" level="error" additivity="false">
<AppenderRef ref="LogToConsole"/>
</Logger>
<Root level="error">
<AppenderRef ref="LogToFile"/>
<AppenderRef ref="LogToConsole"/>
</Root>
</Loggers>
</Configuration>
3. Вывод в файл и поочередное создание новых файлов журналов.
<Configuration status="DEBUG">
<Appenders>
<Console name="LogToConsole" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<RollingFile name="LogToRollingFile" fileName="logs/app.log"
filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="10 MB"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<!-- avoid duplicated logs with additivity=false -->
<Logger name="com.malaoshi" level="debug" additivity="false">
<AppenderRef ref="LogToRollingFile"/>
</Logger>
<Root level="error">
<AppenderRef ref="LogToConsole"/>
</Root>
</Loggers>
</Configuration>
Выше приведено все содержимое. Прочитав его, вы поймете взаимосвязь между различными платформами журналов и то, как использовать эти структуры журналов в проектах.
ссылка: