Концепция фреймворка ведения журнала
Функция журнала состоит в том, чтобы отслеживать и записывать информацию о работе нашей программы.Мы можем использовать журнал, чтобы быстро найти проблему, а также отследить и проанализировать ее.
уровень журнала
Прежде всего, вам нужно знать, для чего нужен уровень журнала.Когда вы запускаете различные способы, уровень журнала определяет, какая информация должна быть выведена в соответствии с тем, как вы работаете, и установленным вами уровнем печати журнала.
Положения: журнал будет печатать только установленный приоритет и контент с более высоким приоритетом, чем он сам.
Приоритет уровня журнала: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL
- ВЫКЛЮЧЕННЫЙ:
- ФАТАЛЬНО:
- ОШИБКА:
- ПРЕДУПРЕЖДАТЬ:
- ИНФОРМАЦИЯ:
- ОТЛАЖИВАТЬ:
- СЛЕД:
- ВСЕ:
Общие фреймворки ведения журналов
Jul: Java Util Logging
Платформа журналов Sun, собственная структура журналов, имеет то преимущество, что она очень проста в использовании и может использоваться непосредственно в JDK. Однако функция JDKLog слишком проста, не поддерживает отображение заполнителей и имеет плохую масштабируемость, поэтому сейчас ею мало кто пользуется. Пример:
import java.util.logging.Logger;
/****
** JDKLog Demo
**/
public class JDKLog
{
public static void main( String[] args )
{
Logger logger = Logger.getLogger("JDKLog");
logger.info("Hello World.");
}
}
Log4j
Инфраструктура ведения журнала Apache имеет несколько уровней ведения журнала (DEBUG/INFO/WARN/ERROR), которые могут записывать журналы разных уровней журналов отдельно, что значительно облегчает просмотр журналов.
- импортировать пакет зависимостей
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
- log4j.properties
### 设置###
log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
Log4J2
Обновленная версия Log4j, версия 2.x претерпела некоторые апгрейды в архитектуре, также претерпели некоторые изменения конфигурационные файлы.
- импортировать пакет зависимостей
<!-- Log4J -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.2</version>
</dependency>
Примечание. Пути пакетов зависимостей для log4j и log4j2 различаются, что специально установлено разработчиком, чтобы различать log4j и log4j2.
- Добавьте файл конфигурации log4j2.xml и поместите его в каталог ресурсов:
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="error">
<!-- 先定义所有的appender -->
<appenders>
<!-- 这个输出控制台的配置 -->
<Console name="Console" target="SYSTEM_OUT">
<!-- 控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
<ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>
<!-- 这个都知道是输出日志的格式 -->
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</Console>
<!-- 文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用 -->
<!-- append为TRUE表示消息增加到指定文件中,false表示消息覆盖指定的文件内容,默认值是true -->
<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>
<!-- 添加过滤器ThresholdFilter,可以有选择的输出某个级别以上的类别 onMatch="ACCEPT" onMismatch="DENY"意思是匹配就接受,否则直接拒绝 -->
<File name="ERROR" fileName="logs/error.log">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
</File>
<!-- 这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 -->
<RollingFile name="RollingFile" fileName="logs/web.log"
filePattern="logs/$${date:yyyy-MM}/web-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
<SizeBasedTriggeringPolicy size="2MB"/>
</RollingFile>
</appenders>
<!-- 然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
<loggers>
<!-- 建立一个默认的root的logger -->
<root level="trace">
<appender-ref ref="RollingFile"/>
<appender-ref ref="Console"/>
<appender-ref ref="ERROR" />
<appender-ref ref="log"/>
</root>
</loggers>
</configuration>
Commons Logging
Фасад журнала поддерживает динамическую загрузку реализации компонентов журнала во время выполнения. То есть в коде приложения вам нужно только вызвать общий интерфейс ведения журнала, а базовой реализацией может быть log4j или Java Util Logging.
Slf4J
Лагерь, противоположный Commons Logging, это интерфейс, а реализация — Logback.
Logback
Реализация Slf4J.
Сравнение механизмов реализации Commons Logging и Slf4j
- Механизм реализации ведения журнала Commons: ведение журнала Commons использует собственный ClassLoader для поиска и загрузки конкретных локальных реализаций с помощью механизма динамического поиска во время работы программы. Подробные политики см. в файле org.apache.commons.logging.impl.LogFactoryImpl.java в пакете commons-logging-*.jar. Поскольку разные подключаемые модули OSGi используют независимые загрузчики классов, этот механизм OSGI гарантирует, что подключаемые модули не зависят друг от друга, и его механизм ограничивает нормальное использование ведения журналов общих ресурсов в OSGi.
- Механизм реализации Slf4j: Slf4j статически привязывает локальную библиотеку LOG во время компиляции, поэтому ее можно нормально использовать в OSGi. Это поиск org.slf4j.impl.StaticLoggerBinder в пути к классам, а затем в этом классе выполняется связывание.
Если в проекте выбран фреймворк логирования
-
Механизм реализации Slf4j определяет, что Slf4j имеет меньше ограничений и более широкий диапазон использования. Поскольку Slf4j статически связывает локальную библиотеку LOG во время компиляции, он более универсален, чем ведение журнала Commons.
-
Logback имеет лучшую производительность. Logback утверждает, что производительность некоторых ключевых операций, таких как определение того, следует ли регистрировать оператор журнала, была значительно улучшена. Эта операция занимает 3 наносекунды в Logback и 30 наносекунд в Log4J. LogBack также создает регистраторы быстрее: 13 мс по сравнению с 23 мс в Log4J. Более того, для извлечения существующего регистратора требуется всего 94 наносекунды по сравнению с 2234 наносекундами для Log4J, что сокращает время до 1/23. Улучшение производительности по сравнению с JUL также значительно.
-
Commons Logging имеет более высокие накладные расходы Чтобы уменьшить накладные расходы на сбор информации журнала при создании Commons Logging, обычная практика такова:
if(log.isDebugEnabled()){
log.debug("User name: " +
user.getName() + " buy goods id :" + good.getId());
}
В лагере Slf4j вы просто делаете:
log.debug("User name:{} ,buy goods id :{}", user.getName(),good.getId());
Другими словами, slf4j помещает накладные расходы на журнал сборки после того, как подтвердит необходимость отображения этого журнала, уменьшает накладные расходы памяти и чашки, использует заполнители, а код становится более кратким.
- Документация по журналу бесплатна. Вся документация Logback полностью предоставляется бесплатно, в отличие от Log4J, который предоставляет только часть бесплатной документации и требует от пользователей покупки платной документации.
Как использовать Slf4J в своем проекте
Мост между Slf4J и другими журналами
имя пакета jar | иллюстрировать |
---|---|
slf4j-log4j12-1.7.13.jar | Для версии моста log4j1.2 вам необходимо добавить log4j.jar в путь к классам. |
slf4j-jdk14-1.7.13.jar | Мост к java.util.logging, собственной среде ведения журналов JDK. |
slf4j-nop-1.7.13.jar | Мост NOP, молча отбрасывающий все журналы. |
slf4j-simple-1.7.13.jar | Мост с простой реализацией, который выводит все события в System.err, печатаются только сообщения INFO и выше, что может быть полезно в небольших приложениях. |
slf4j-jcl-1.7.13.jar | Мост для ведения журналов Jakarta Commons Этот мост делегирует все журналы SLF4j в JCL. |
logback-classic-1.0.13.jar(requires logback-core-1.0.13.jar) | Нативная реализация slf4j, logback напрямую реализует интерфейс slf4j, поэтому использование slf4j в сочетании с logback также означает меньшие затраты памяти и вычислительных ресурсов. |
Конкретный метод доступа выглядит следующим образом:
Как соединить устаревшие API
При использовании разных фреймворков фреймворки, интегрированные другими, могут отличаться. Например, Spring Framework интегрирует ведение журнала Commons, а XSocket полагается на ведение журнала Java Util. Теперь нам нужно решить проблему, заключающуюся в том, что разные компоненты логов в разных фреймворках объединяются в Slf4J. SLF4J передаст журнал конкретному инструменту реализации журнала в соответствии с связующим. Slf4J поставляется с несколькими модулями моста, которые могут перенаправлять log4j, JCL и API в java.util.logging на Slf4J.
Устаревшая схема сопряжения API
имя пакета jar | эффект |
---|---|
log4j-over-slf4j-version.jar | перенаправить log4j на slf4j |
jcl-over-slf4j-version.jar | Перенаправить Simple Logger в журнал общих ресурсов на slf4j |
jul-to-slf4j-version.jar | Перенаправить ведение журнала Java Util на slf4j |
См. следующий рисунок для мостового метода:
Вопросы, требующие внимания при использовании моста slf4j
При использовании моста slf4j обратите внимание на то, чтобы избежать образования бесконечного цикла.В пакете jar, от которого зависит проект, не должно быть следующих ситуаций:
Условия для нескольких пакетов журналов для формирования бесконечного цикла | причина |
---|---|
И log4j-over-slf4j.jar, и slf4j-log4j12.jar существуют. | Все вызовы журналирования делегируются log4j из-за наличия slf4j-log4j12.jar. Однако из-за одновременного существования log4j-over-slf4j.jar все вызовы log4j API будут делегированы соответствующему эквивалентному slf4j, поэтому существование log4j-over-slf4j.jar и slf4j-log4j12.jar при этом будет образовываться бесконечный цикл |
И jul-to-slf4j.jar, и slf4j-jdk14.jar существуют | Из-за существования файла slf4j-jdk14.jar все вызовы журнала будут делегированы журналу jdk. Однако из-за одновременного существования jul-to-slf4j.jar все вызовы jul API будут делегированы соответствующему эквиваленту slf4j, поэтому сосуществование jul-to-slf4j.jar и slf4j-jdk14. jar образует бесконечный цикл. |