Springboot 로그 설정(Logback)

 

Summry

로그 라이브러리는 Logback, Log4J, Log4J2 등등 수 많은 라이브러리가 있는데 스프링 부트에서 이것들을 통합해서 인터페이스로 제공하는 것이 바로 SLF4J 라이브러리다.

본 문서에서는 Logback 적용 및 사용 방법을 정리한다.

send me email if you have any questions.


Logback이란?

  • Logback이란 Log4J를 기반으로 개발된 자바 오픈소스 로깅 라이브러리이다.
  • 스프링 부트의 기본으로 설정되어 있어서 사용시 별도로 라이브러리를 추가하지 않아도 된다.
  • log4j에 비해 약 10배 정도 빠른 퍼포먼스, 메모리 효율성 증대를 보여준다.

※ 출시순서 : log4j -> logback -> log4j2

Logback 특징

  • 로그에 특정레벨을 설정할 수 있다. (Trace -> Debug -> Info -> Warn -> Error)
  • 실제 운영과 테스트 상황에서 각각 다른 출력 레벨을 설정하여 로그를 확인할 수 있다.
  • 출력 형식(form)에 대해 설정할 수 있다.
  • 설정 파일을 일정 시간마다 스캔하여 어플리케이션 중단 없이 설정 변경이 가능하다.
  • 별도의 프로그램 없이 자체적으로 로그 압축을 지원한다.
  • 로그 보관 기간을 설정할 수 있다.

Log Level

  1. ERROR : 로직 수행 중에 오류가 발생한 경우, 시스템적으로 심각한 문제가 발생하여 작동이 불가한 경우
  2. WARN : 시스템 에러의 원인이 될 수 있는 경고 레벨, 처리 가능한 사항
  3. INFO : 상태변경과 같은 정보성 메시지
  4. DEBUG : 어플리케이션의 디버깅을 위한 메시지 레벨
  5. TRACE : DEBUG 레벨보다 더 디테일한 메시지를 표현하기 위한 레벨

※ 설정한 레벨보다 하위 레벨의 로그는 출력하지 않는다. 예를 들어 로그 레벨을 INFO로 설정하면 TRACE, DEBUG 레벨은 출력되지 않는다.

Logback 구성

appender

Log의 형태 및 어디에 출력할지 설정하기 위한 영역이다.

대표적인 Appender는 아래와 같다.

  1. ConsoleAppender : 콘솔에 로그를 출력
  2. FileAppender : 파일에 로그를 저장
  3. RollingFileAppender : 여러 개의 파일을 순회하며 로그를 저장
  4. SMTPAppender : 로그를 메일로 보냄
  5. DBAppender : 데이터베이스에 로그를 저장

실제로는 1,3번을 많이 사용하게 된다.

<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
  <!-- ThresholdFilter - 임계값보다 낮은 레벨의 경우 이벤트는 거부 -->
  <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
    <level>INFO</level>
  </filter>
  <encoder>
    <pattern>${LOG_PATTERN}</pattern>
  </encoder>
</appender>

위의 코드는 ConsoleAppender의 예시이다.

encoder

Appender 내에 포함되는 항목이며, pattern을 사용하여 원하는 형식으로 로그를 표현할 수 있다.

<encoder>
  <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger{30} %msg%n</pattern>
</encoder>

Log Pattern

  • %logger: 패키지 포함 클래스 정보
  • %logger{0}: 패키지를 제외한 클래스 이름만 출력
  • %logger{length}: Logger name을 축약할 수 있음. {length}는 최대 자리 수, ex)logger{35}
  • %-5level: 로그 레벨, -5는 출력의 고정폭 값(5글자), 로깅레벨이i nfo일 경우 빈칸 하나 추가
  • ${PID:-}: 프로세스 아이디
  • %d: 로그 기록시간 출력
  • %p: 로깅 레벨 출력
  • %F: 로깅이 발생한 프로그램 파일명 출력
  • %M: 로깅일 발생한 메소드의 명 출력
  • %line: 로깅이 발생한 호출지의 라인
  • %L: 로깅이 발생한 호출지의 라인
  • %thread: 현재 Thread 명
  • %t: 로깅이 발생한 Thread 명
  • %c: 로깅이 발생한 카테고리
  • %C: 로깅이 발생한 클래스 명 (%C{2}는 somePackage.SomeClass 가 출력됨)
  • %m: 로그 메시지
  • %msg: - 로그 메시지 (=%message)
  • %n: 줄바꿈(new line)
  • %%: %를 출력
  • %r : 애플리케이션 시작 이후부터 로깅이 발생한 시점까지의 시간(ms)
  • %d{yyyy-MM-dd-HH:mm:ss}: %d는 date를 의미하며 중괄호에 들어간 문자열은 dateformat을 의미. 따라서 [2022-08-05 02:16:11]과 같은 날짜가 로그에 출력됨.

root

설정한 Appender를 참조하여 로그의 레벨을 설정할 수 있다.

<root level="INFO">
  <appender-ref ref="console" />
</root>

Logback 설정

  • Java Legacy, Spring의 경우에는 logback.xml 파일을 참조
  • Spring boot의 경우에는 logback-spring.xml 파일을 참조
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds"> <!-- logback 구현체가 설정을 확인하는 주기 -->
  <property name="LOG_PATH" value="D:\\test\\log"/>
  <property name="LOG_FILE_NAME" value="test"/>
  <property name="LOG_PATTERN" value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger{30} %msg%n"/>

  <!-- Appenders -->
  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <!-- ThresholdFilter - 임계값보다 낮은 레벨의 경우 이벤트는 거부 -->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>INFO</level>
    </filter>
    <encoder>
      <pattern>${LOG_PATTERN}</pattern>
    </encoder>
  </appender>

  <appender name="INFO_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>INFO</level>
    </filter>
    <file>{LOG_PATH}/${LOG_FILE_NAME}.log</file>
    <append>true</append>

    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <!-- .gz, .zip 등을 넣으면 자동 일자별 로그파일 압축 -->
      <fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}_INFO_LOG.%d{yyyy-MM-dd-HH-mm}.%i.log</fileNamePattern>

      <!-- 파일당 최고 용량 kb, mb, gb -->
      <maxFileSize>10MB</maxFileSize>

      <!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거-->
      <maxHistory>30</maxHistory>
    </rollingPolicy>

    <!-- 출력패턴 설정-->
    <encoder>
      <pattern>${LOG_PATTERN}</pattern>
    </encoder>
  </appender>

  <!-- TRACE > DEBUG > INFO > WARN > ERROR > OFF -->
  <!-- Root Logger -->
  <root level="INFO">
    <appender-ref ref="console" />
    <appender-ref ref="INFO_LOG" />
  </root>
</configuration>

위의 코드는 Logback 설정 예시이다. 입맛에 바꾸어 사용하면 된다.

<configuration scan="true" scanPeriod="30 seconds"> <!-- logback 구현체가 설정을 확인하는 주기 -->

Logback의 특징 중에 설정 파일을 일정 시간마다 스캔하여 어플리케이션 중단 없이 설정 변경이 가능하다는 것이 있었는데 이것이 그 스캔 주기를 설정하는 부분이다.

 <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  <!-- .gz, .zip 등을 넣으면 자동 일자별 로그파일 압축 -->
  <fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}_INFO_LOG.%d{yyyy-MM-dd-HH-mm}.%i.log</fileNamePattern>

  <!-- 파일당 최고 용량 kb, mb, gb -->
  <maxFileSize>10MB</maxFileSize>

  <!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거-->
  <maxHistory>30</maxHistory>
</rollingPolicy>

rollingPolicy란 rollover 발생 시 RollingFileAppender의 행동이다.

SizeAndTimeBasedRollingPolicy는 파일의 크기까지 고려한 TimeBasedPolicy를 상속한 RollingPolicy이다. 이 policy는 fileNamePattern에서 %i와 %d가 필수적인 토큰인데 maxFileSize 태그가 각각의 로그파일이 가질 수 있는 최대 크기를 제한하여 활성화 된 로그파일의 크기가 maxFileSize에 다다르면 %i 토큰이 index로 작용하여 다음 로그 파일의 이름을 결정한다.

그림1

위의 이미지를 보면 8월 5일 1시 31분에 해당하는 파일이 0~14까지 있는 것을 볼 수 있다.
%d{yyyy-MM-dd-HH-mm}.%i 분 단위로 rollover하며 maxFileSize를 50KB로 설정하여 50KB를 초과할 시 %i가 index 역할을 하여 다음 로그파일에 저장한다.

로그 찍어보기

로그 선언하여 사용

@RequiredArgsConstructor
@RequestMapping("/test")
@RestController
@Slf4j
public class testController {
  // 1번 선언 방법
  private final Logger LOGGER = LoggerFactory.getLogger(getClass());

  // 2번 선언 방법
  private static final Logger log = LoggerFactory.getLogger(testController.class)
  @PostMapping("log-test")
  public void logTest() {
    log.trace("Trace Log");
    log.debug("Debug Log");
    log.info("Info Log");
    log.warn("Warn Log");
    log.error("Error Log");
    LOGGER.trace("Trace Log");
    LOGGER.debug("Debug Log");
    LOGGER.info("Info Log");
    LOGGER.warn("Warn Log");
    LOGGER.error("Error Log");
  }
}

어노테이션 사용

lombok을 사용하면 로그 선언을 자동으로 해주어 바로 사용할 수 있다.

@RequiredArgsConstructor
@RequestMapping("/test")
@RestController
@Slf4j
public class testController {
  @PostMapping("log-test")
  public void logTest() {
    log.trace("Trace Log");
    log.debug("Debug Log");
    log.info("Info Log");
    log.warn("Warn Log");
    log.error("Error Log");
  }
}

Reference

[Java] 간단한 로깅(Logging) 사용 방법 - cornarong
[스프링부트 (5)] Spring Boot 로그 설정(1) Logback - 갓대희
[Logging] Logback이란? - 검프
Logback - 4. Appenders (2). RollingFileAppender - 긍.응.성
로깅 프레임워크 Logback 적용하기 [ 스프링 부트 (Spring Boot) ] - 어라운드허브 스튜디오