Пиление через логгеры Java
Я знаю, о чем ты думаешь: «Это просто лесозаготовка!» Эта небольшая, но все же распространенная часть наших приложений предоставляет разработчикам, QA и специалистам по устранению неполадок информацию, помогающую в определении последовательности выполнения кода, проверке значений данных и проблемных точек в наших приложениях. Реальность такова, что без надежных реализаций регистрации мы бы потеряли значительный инструмент для устранения неполадок.
Варианты ведения журнала Java
- System.out / System.err
- java.util.logging (JUL)
- Apache Commons Jogging (также известный как Jakarta Commons Logging — JCL)
- Log4j
- SLF4J
- Logback
System.out & System.err
В первые дни (надеюсь, не сейчас) мы использовали старый System.out.println()метод регистрации. Мы бы быстро обнаружили, что их использование не хорошо.
Причины избегать System методов
- Мы не можем отключить в производстве, что влияет на производительность и может поставить под угрозу безопасность данных. О, у нас есть,
System.err.println()но все еще недостаточно хорошо - Мы не можем настроить, сколько или мало информации сообщается (уровни ведения журнала)
- В кластерной среде мы не можем настроить централизованное расположение для информации
- System.out работает плохо … см. Ведение журнала против производительности System.out
- Метаданные недоступны и должны быть закодированы для каждого System.out, что неизбежно не будет выполнено или, по крайней мере, будет очень противоречивым
*** НЕ ИСПОЛЬЗУЙТЕ System.out или System.err где-либо еще, никогда! ***
java.util.logging (JUL)
Java предоставляет опцию регистрации, которая является шагом вперед в регистрации. Тем не менее, он не получил широкого распространения, поскольку опоздал на вечеринку. Не многие платформы с открытым исходным кодом используют JUL. Как правило , вы найдете это com.sun или com.oracle проектов , таких как Джерси.
Log4j
Log4j — это проект Apache, который существует уже некоторое время и широко используется в проектах с открытым исходным кодом. Log4j предоставляет гибкую структуру ведения журналов, но немного устарела на данный момент.
SLF4j — логирование API
У нас есть много вариантов ведения журнала, и в наши проекты с открытым исходным кодом мы обычно включаем проекты, которые могут реализовывать JCL и JUL.
SLF4j ( Simple Logging Facade для Java ) предоставляет общий интерфейс ведения журнала для наших проектов. Большинство респектабельных проектов с открытым исходным кодом теперь используют SLF4j для конфигурируемости и гибкости при изменении реализации ведения журнала. Думайте о SLF4j как об общем интерфейсе (API) для нашего выбора реализации ведения журнала.
Весь наш код регистрации должен использовать один и тот же API SLF4j. Например:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
…
public class MyClass {
private static final Logger logger = LoggerFactory.getLogger(MyClass.class);
…
public void someMethod() {
logger.debug("something is happening");
}
}
Базовые зависимости Maven SLF4j
<properties>
<slf4j.version>1.7.5</slf4j.version>
<logback.version>1.0.11</logback.version>
</properties>
<dependencies>
<!-- SLF4J - logging api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Logback - logging impl -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>
Усовершенствованные зависимости Maven SLF4j
<properties>
<slf4j.version>1.7.5</slf4j.version>
<logback.version>1.0.11</logback.version>
</properties>
<dependencies>
<!-- SLF4J - logging api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Interceptor for Commons-logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Interceptor for java.util.logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Logback - logging impl -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>
Преимущества SLF4j
- Одна стратегия ведения журнала для всех
- Строковые заполнители
- logger.debug («Значение {} равно {}», myVar, myValue);
- Перехватчики
commons-logging- Включить
jcl-over-slf4jзависимость - Следует исключить
commons-loggingзависимости из проекта
- Включить
- Может перехватить
java.util.logging- Включить
jul-to-slf4jзависимость - Требуется регистрация классов в приложении
- См. Блог Best Practices Enterprise Spring
- Включить
- Может перехватить
System.out&System.err- Требуется в том числе зависимости
- Требуется регистрация классов в приложении
- См. Блог Best Practices Enterprise Spring
Logback — более разумное ведение журнала
Logback — это проект от создателя Log4j и SLF4j Чеки Гюльчу ( произносится как Джеки Гульджу ).
Первая статья для чтения: Logback: причины для переключения
Простой файл logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true" scan="true" scanPeriod="30 seconds">
<!-- Handle JUL -->
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<!-- To enable JMX Management -->
<jmxConfigurator/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-5level %logger{0} - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.gordondickens.demo" level="debug" />
<logger name="org.springframework.beans" level="trace" />
<root level="warn">
<appender-ref ref="console" />
</root>
</configuration>
File Appenders
Помимо консольного приложения есть File и RollingFile. В приложении Rolling File Appender предусмотрены параметры, основанные на времени и размере , с возможностью указания количества сохраняемых файлов и необязательного сжатия (zip).
См .: Logback Appenders
Говорит на родном SLF4j
Выше мы видели, что просто заменив Log4j на Logback, теперь у нас есть логирование через SLF4j. На самом деле, его зависимость меньше, так как мы больше не будем включать slf4j-log4j12 зависимость.
RESTful и протоколирование веб-доступа
Мы можем использовать logback-доступ для обеспечения регистрации доступа к серверу. Это может оказаться очень полезным при устранении неполадок веб-сервисов RESTful, а также для веб-приложений. В src/main/resources каталоге нашего приложения создайте файл logback-access.xml.
Logback-access.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${user.dir}/logs/app-access.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${user.dir}/logs/app-access.%d{yyyy-MM-dd}.log.zip</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>combined</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%n%n%fullRequest%n%n%fullResponse%n%n</pattern>
</encoder>
</appender>
<appender-ref ref="FILE" />
<appender-ref ref="STDOUT" />
</configuration>
web.xml
«TeeFilter» управляет регистрацией доступа. См. Http://logback.qos.ch/access.html
Необязательный «ViewStatusMessagesServlet» позволяет нам просматривать конфигурацию возврата через URL-адрес /logbackstatus. См. Http://logback.qos.ch/manual/configuration.html.
<filter> <filter-name>TeeFilter</filter-name> <filter-class>ch.qos.logback.access.servlet.TeeFilter</filter-class> </filter> <filter-mapping> <filter-name>TeeFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>ViewStatusMessages</servlet-name> <servlet-class>ch.qos.logback.classic.ViewStatusMessagesServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ViewStatusMessages</servlet-name> <url-pattern>/logbackStatus</url-pattern> </servlet-mapping>
Тестовая Конфигурация
В нашем проекте src/main/resources мы определяем logback.xml файл.
В нашем проекте src/test/resources мы определяем logback-test.xml файл.
Условная конфигурация
Logback использует Janino позволяя способность выполнять условную конфигурацию.
Янино Мавен Зависимость
<dependency> <groupId>org.codehaus.janino</groupId> <artifactId>janino</artifactId> <version>2.6.1</version> </dependency>
Условные операции
- boolean isDefined(String prop);
- boolean isNull(String prop);
- String p(String prop);
- String property(String prop);
Смотрите: PropertyWrapperForScripts JavaDoc
<if condition='isDefined("catalina.home")'>
<then>
<property name="log.dir" value="${catalina.home}"/>
</then>
<else>
<property name="log.dir" value="${user.dir}/logs"/>
</else>
</if>
Круто, что мы можем использовать профили среды Spring 3 spring.profiles.active. В приведенном ниже примере метод property() или p() возвращает String, поэтому мы можем использовать такие функции String, как contains().
<if condition='property("spring.profiles.active").contains("dev")'>
<then>
<property name="log.dir" value="${catalina.home}"/>
</then>
<else>
<property name="log.dir" value="${user.dir}/logs"/>
</else>
</if>
Примечание. Для тестирования с Maven через подключаемые модули Jetty или Tomcat ${user.dir} разрешается переход к исходному проекту.
Модульная конфигурация
Мы можем настроить несколько файлов конфигурации, эффективно сегментируя нашу конфигурацию. Мы могли бы использовать более подробную конфигурацию ведения журнала для тестирования и более консервативное ведение журнала для производства.
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true" scan="true" scanPeriod="5 seconds">
<property resource="logconfig/logback.properties"/>
<include resource="logconfig/headerconfig.xml"/>
<if condition='property("spring.profiles.active").contains("dev")'>
<then>
<include resource="logconfig/springbeans.xml"/>
<include resource="logconfig/hibernatefile.xml"/>
</then>
<else>
<include resource="logconfig/productionfile.xml"/>
</else>
</if>
<include resource="logconfig/consolelog.xml"/>
<root level="warn">
<appender-ref ref="console"/>
</root>
</configuration>
hibernatefile.xml
Включенные файлы используют внутри include тега.
<?xml version="1.0" encoding="UTF-8"?>
<included>
<appender name="hibernatefile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.dir}/${hibernate.logfile}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>${log.dir}/${hibernate.logfile}.%i.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>6</maxIndex>
</rollingPolicy>
<triggeringPolicy
class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>50MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%date %level - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.springframework.orm" level="debug">
<appender-ref ref="hibernatefile" />
</logger>
<logger name="org.springframework.jdbc" level="debug">
<appender-ref ref="hibernatefile" />
</logger>
<logger name="org.springframework.transaction" level="debug">
<appender-ref ref="hibernatefile" />
</logger>
<logger name="org.hibernate.ejb" level="debug">
<appender-ref ref="hibernatefile" />
</logger>
<logger name="org.hibernate.sql" level="debug">
<appender-ref ref="hibernatefile" />
</logger>
<logger name="org.hibernate.tool.hbm2ddl" level="debug">
<appender-ref ref="hibernatefile" />
</logger>
</included>
Резюме
- НЕ использовать
System.outилиSystem.err - Используйте заполнитель параметра SLF4j
{}вместо конкатенации строк, это устраняет необходимостьisDebugEnabled()обхода журнала отладки. - Всегда определяйте
Loggerкакprivate static final - Использование SLF4j и Logback обеспечивает гибкую, интеллектуальную регистрацию. У нас есть инструменты, которые предоставляют широкие возможности ведения журналов для разработки корпоративных приложений
- Logback говорит изначально с SLF4j
- Конфигурация Java и Groovy
- Условное ведение журнала
- Модульная конфигурация
- Регистрация доступа
- Фильтрация сообщений
- Сжатие свернутых файлов журнала
- Отбор аппендеров по атрибутам времени выполнения
Дальнейшее чтение
- http://logback.qos.ch
- http://www.slf4j.org
- http://logging.apache.org/log4j/1.2
- Ведение журнала против производительности System.out
- Блог Best Practices Enterprise Spring
- Janino
