Post thumbnail

Logger는 사드세요... 제발: SLF4J와 Logback

· by 박승재

자바의 로깅(Logging) 라이브러리로는 Log4j 등 다양한 종류가 있지만, 현재 가장 좋은 조합SLF4J+Logback이라고 생각합니다.

SLF4JSimple Logging Facade for Java의 약자로 라이브러리 인터페이스 역할이며,

Logback이 실질적인 로깅 라이브러리 구현체로,

SLF4J는 Logback를 사용하기 쉽게 포장하는 역할을 합니다.

LogbackLog4j v1을 포크(Fork)해서 개발한 버전으로, 통상 Log4j라 불리는 Log4j v2와 다릅니다.

참고: Reasons to prefer logback over log4j 1.x

참고: Log4j, LogBack 정리

설치

이 글에서는 Gradle을 이용해 라이브러리 종속성을 추가할 것입니다.

dependencies {
    implementation 'ch.qos.logback:logback-classic:1.4.1'
    implementation 'org.slf4j:slf4j-api:2.0.3'
}

Java 11 버전 이상이면 Logback 1.4를 사용하면 됩니다.

사용

package org.example;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger("org.example.Main");
        logger.debug("Hello world.");
    }
}

SLF4J는 클래스 별로 Logger를 사용합니다.

이름을 통해 어디에서 오류가 발생했는지 추적할 수 있습니다.

> Task :compileJava
> Task :processResources NO-SOURCE
> Task :classes

> Task :Main.main()
21:16:58.694 [main] DEBUG org.example.Main - Hello world.
package org.example;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger("org.example.Main");
        int newT = 15;
        int oldT = 16;
        logger.debug("Temperature set to {}. Old value was {}.", newT, oldT);
        logger.atDebug().log("Temperature set to {}. Old value was {}.", newT, oldT);
    }
}

.debug.atDebug().log와 동일합니다.

설정

Logback에서는 로그의 출력 형식을 지정할 수 있습니다.

resources/logback.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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>

콘솔 출력과 동시에 파일에 로그를 기록할 수 있습니다.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>logFile.log</file>
        <encoder>
            <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
        </encoder>
    </appender>

    <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="FILE" />
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

RollingFileAppender를 이용하면 로그파일이 너무 커지지 않도록 나눌 수 있습니다.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logFile.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>
        </rollingPolicy>

        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="FILE" />
    </root>
</configuration>

30일/3GB 단위로 로그파일을 분리하는 설정입니다.

RollingFileAppender<prudent>true</prudent>를 넣으면 파일을 저장할 때 lock을 겁니다.

참고: Logback 으로 쉽고 편리하게 로그 관리를 해볼까요?

참고: The logback manual