Инструменты пользователя

Инструменты сайта


develop:java:logging

Это старая версия документа!


Логирование

Сведения

:!: Logback

Logback - одна из наиболее используемых библиотек ведения журнала, замена предшественника Log4j
Состоит из трех классов:
Logger:
Контекст для сообщений журнала. Класс с которым взаимодействуют приложения для создания сообщений

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

Layout:
Форматирование сообщений

Maven зависимости:(?)

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.3.5</version>
</dependency>
 
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.4</version>
    <scope>test</scope>
</dependency>
 
# И еще возможно это
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.3.5</version>
</dependency>

Минимальный пример:

# Файл logback.xml
<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>
 
  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

Файл программы:

public class Example {
 
    private static final Logger logger 
      = LoggerFactory.getLogger(Example.class);
 
    public static void main(String[] args) {
        logger.info("Example log from {}", Example.class.getSimpleName());
    }
}
 
  # Еще такой пример есть, пока неясно зачем приведение и что ето за класс
ch.qos.logback.classic.Logger logger = 
  (ch.qos.logback.classic.Logger)LoggerFactory.getLogger("com.baeldung.logback");
logger.debug("Hi there!");
:!: Уровни
  • TRACE — самый низкий уровень информации, в основном используемый для очень глубокой отладки кода, обычно не включаемый в производственные журналы.
  • DEBUG — информация низкого уровня, используемая для целей отладки, обычно не включаемая в производственные журналы.
  • INFO — серьезность журнала, содержащая информацию, например, о начавшейся или завершенной операции.
  • WARN – уровень журнала, информирующий о событии, которое может потребовать нашего внимания, но не является критическим и может быть ожидаемым.
  • ОШИБКА — уровень журнала, сообщающий об ошибке, ожидаемой или неожиданной, обычно означающей, что часть системы работает неправильно.

Библиотека «logback-core» содержит следующие классы:

  • ConsoleAppender — добавляет события журнала в System.out или System.err.
  • OutputStreamAppender — добавляет события журнала в java.io.Outputstream, предоставляя базовые услуги для других приложений.
  • FileAppender — добавляет события журнала в файл.
  • RollingFileAppender — добавляет события журнала в файл с возможностью автоматического переключения файлов.

«Logback-classic» расширяет перечень:

  • SocketAppender — добавляет события журнала в сокет
  • SSLSocketAppender — добавляет события журнала в сокет, используя безопасное соединение.
  • SMTPAppender — накапливает данные в пакетах и ​​отправляет содержимое пакета на указанный пользователем адрес электронной почты после наступления указанного пользователем события.
  • DBAppender — добавляет данные в таблицы базы данных
  • SyslogAppender — добавляет данные в место назначения, совместимое с Syslog.
  • SiftingAppender — приложение, которое может разделять ведение журнала в соответствии с заданным атрибутом времени выполнения.
  • AsyncAppender — асинхронно добавляет события журнала.

Конфигурация

:!: Конфигурация

Журнал отладки конфигурации:

<configuration debug="true">
  ...
</configuration>
 
  # Либо такой метод
<configuration>
    <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />  
    ...
</configuration>

Автоматическая перезагрузка конфигурации

<configuration scan="true">
  ...
</configuration>
 
  # По умолчанию 60 секунд, можно изменить
<configuration scan="true" scanPeriod="15 seconds">
  ...
</configuration>

Конфигурация логгеров

  # Уровень логирования можно задать каждому персонально
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <logger name="com.baeldung.logback" level="INFO" /> 
    <logger name="com.baeldung.logback.tests" level="WARN" /> 
    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
 
  # Далее использование:
Logger foobar = 
  (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.baeldung.foobar");
Logger logger = 
  (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.baeldung.logback");
Logger testslogger = 
  (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.baeldung.logback.tests");
 
foobar.debug("This is logged from foobar");
logger.debug("This is not logged from logger");
logger.info("This is logged from logger");
testslogger.info("This is not logged from tests");
testslogger.warn("This is logged from tests");

Переменные

<property name="LOG_DIR" value="/var/log/application" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>${LOG_DIR}/tests.log</file>
    <append>true</append>
    <encoder>
        <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
</appender>
 
  # Значение объявлено в первой строке, либо можно указать в аргументах запуска джарки (возможно и через переменные окружения, но это не точно)
$ java -DLOG_DIR=/var/log/application com.baeldung.logback.LogbackTests
:!: Appenders

Файловые аппендеры

<configuration debug="true">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type
             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
 
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>tests.log</file>
        <append>true</append>
        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>
 
    <logger name="com.baeldung.logback" level="INFO" /> 
    <logger name="com.baeldung.logback.tests" level="WARN"> 
        <appender-ref ref="FILE" /> 
    </logger> 
 
    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

Ротируемый аппендер

<property name="LOG_FILE" value="LogFile" />
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_FILE}.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!-- daily rollover -->
        <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern>
 
        <!-- keep 30 days' worth of history capped at 3GB total size -->
        <maxHistory>30</maxHistory>
        <totalSizeCap>3GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
        <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
</appender> 

Использование

:!: Приемы/детали
  # Параметризованные сообщения
  # фигурные скобки используют "toString()" при возможности/необходимости
log.debug("Current count is " + count);
log.debug("Current count is {}", count);
logger.debug("Going to divide {} by {}", 42, zero);
:!: Макеты

Например

<encoder>
    <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
  • %d{HH:mm:ss.SSS} – метка времени с часами, минутами, секундами и миллисекундами
  • [%thread] — имя потока, создающего сообщение журнала, заключенное в квадратные скобки.
  • %-5level — уровень события логирования, дополненный до 5 символов
  • %logger{36} – имя логгера , усеченное до 35 символов.
  • %msg%n — сообщения журнала, за которыми следует символ-разделитель строк, зависящий от платформы.

Перечень

:!: Итого

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

Есть вариант создавать свои логеры, но там нужно указывать класс, с которого идет обращения сообщения, из приложения, тобишь в приложении нужно создавать объект логера с таким же (или базовым) классом.
Вроде вариант, но базовый логер эти сообщения тоже перехватывает

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

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 
    <property name="LOGS" value="./logs" />
 
    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                %d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger{36}.%M - %msg%n
            </pattern>
        </encoder>
    </appender>
 
    <appender name="SystemLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGS}/system.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M - %msg%n</Pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- rollover daily and when the file reaches 10 MegaBytes -->
            <fileNamePattern>${LOGS}/archived/system_%d{yyyy-MM-dd}_%i.log.zip
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>50MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
    </appender>
 
    <appender name="ErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGS}/error.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M - %msg%n</Pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- rollover daily and when the file reaches 10 MegaBytes -->
            <fileNamePattern>${LOGS}/archived/error_%d{yyyy-MM-dd}_%i.log.zip
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>50MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
    </appender>
 
    <appender name="WebappLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGS}/webapp.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M - %msg%n</Pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- rollover daily and when the file reaches 10 MegaBytes -->
            <fileNamePattern>${LOGS}/archived/webapp_%d{yyyy-MM-dd}_%i.log.zip
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>50MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
    </appender>
 
    <logger name="com.baeldung.logback" level="INFO">
        <appender-ref ref="webapp" />
    </logger>
 
    <root level="info">
        <appender-ref ref="SystemLog" />
        <appender-ref ref="Console" />
        <appender-ref ref="ErrorLog"/>
    </root>
</configuration>
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private final Logger waLogger = LoggerFactory.getLogger("com.baeldung.logback");
 
    logger.info("Запись в лог");
    waLogger.info("(WA) Запись в лог");
develop/java/logging.1683215090.txt.gz · Последнее изменение: 2023/05/04 15:44 — admin