Это старая версия документа!
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!");
Библиотека «logback-core» содержит следующие классы:
«Logback-classic» расширяет перечень:
Журнал отладки конфигурации:
<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
Файловые аппендеры
<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>
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) Запись в лог");