tools & libs/로깅

[logging] logback 설정 및 사용

  • -
반응형

이번 글에서는 logback을 이용해서 로깅하는 방법에 대해 살펴보자.

https://logback.qos.ch/

 

Logback Home

Logback Project Logback is intended as a successor to the popular log4j project, picking up where log4j 1.x leaves off. Logback's architecture is quite generic so as to apply under different circumstances. At present time, logback is divided into three mod

logback.qos.ch

초기 logging은 log4j가 주도했다. log4j를 개선해서 logback이 나왔고 가장 최근에 log4j2가 등장했다. 2023.4월 현재 spring boot의 기본 logging framework는 logback이다.

 

설정

 

의존성 등록

logback을 사용하기 위해서 mvnrepository에서 logback-classic을 검색해서 pom.xml에 추가해 주자.

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.4.11</version>
</dependency>

기본 <scope> 값이 test로 되어있는데 일반 소스 영역에서도 사용할 필요가 있기 때문에 scope를 삭제하자.

참고로 logback은 사용하는 JDK 버전에 따라 적용할 수 있는 lib 버전이 다름으로 버전 선정에 주의가 필요하다.(https://logback.qos.ch/download.html)

STABLE version (ACTIVELY DEVELOPED) The current actively developed version of logback supporting Java EE (java.* namespace) is 1.3.6. It requires SLF4J version 2.0.4 and JDK 8. The current actively developed version of logback supporting Jakarta EE (jakarta.* namespace) is 1.4.6. It requires SLF4J version 2.0.4 and JDK 11.

바야흐로 apache에서 제공되는 프로젝트 발로 패키지부터 많은 변화가 있을 것 같다.

 

로그 작성

이제 간단한 로깅을 남기고 어떻게 동작하는지 살펴보자.

package com.quietjun.maven;

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

// @Slf4j
public class LogTest {
    private static final Logger log = LoggerFactory.getLogger(LogTest.class);

    public static void logtest(){
        log.trace("trace: {}", "trace");
        log.debug("debug: {}", "debug");
        log.info("info: {}", "info");
        log.warn("warn: {}", "warn");
        log.error("error: {}", "error");
    }
}

 

Slf4j 기반의 Logger를 사용하기 위해서는 먼저 Logger 객체를 얻어온 후 trace부터 error까지 메서드를 이용해서 로그를 남긴다. Lombok의 @Slf4j를 사용하면 Logger를 얻는 코드를 자동으로 삽입해 준다.

위 코드를 실행해 보면 logback의 기본 설정에 의해 아래와 같은 로그가 콘솔에 출력된다.

20:55:21.344 [main] DEBUG com.doding.mvntest.Main -- debug: debug
20:55:21.345 [main] INFO com.doding.mvntest.Main -- info: info
20:55:21.345 [main] WARN com.doding.mvntest.Main -- warn: warn
20:55:21.345 [main] ERROR com.doding.mvntest.Main -- error: error

이상한 일이다. 코드에서는 trace 레벨부터 작성되어있는데 trace 부터만 출력되고 있다. 이 로그를 커스터마이징 해보자.

 

로그 커스터마이징

 

설정 파일 배치

logging framework가 잘 동작하려면 "어떻게 로깅해라"는 설정이 필요하다. 각각의 logging framework 마다 이 설정 파일의 이름은 다르다.

  • logback: logback.xml
  • log4j 2.x: log4j2.xml

파일 이름은 각각 다르지만 파일의 클래스 패스에 있으면 된다. 일반적으로 src/main/resources에 작성한다.

 

logback.xml 파일 설정

https://logback.qos.ch/manual/configuration.html#automaticConf 하단의 코드를 참조하여 logback.xml 파일을 src/main/resources에 생성해 보자.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>

<configuration>
  <import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
  <import class="ch.qos.logback.core.ConsoleAppender"/>

  <appender name="STDOUT" class="ConsoleAppender">
    <encoder class="PatternLayoutEncoder">
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="STDOUT"/>
  </root>
</configuration>

위 설정 파일은 기본 로깅 포맷을 위한 내용이기도 하다.

 

로그 레벨 설정

로그에는 level이 있고 이 level에 대한 설정을 담당하는 부분이 <root level="debug"> 부분이다. 즉 현재는 우리 프로젝트에서는 debug 이상의 로그만 보겠다는 의도이다. (따라서 trace 출력되지 않았다.) level을 info로 변경해서 실행해 보자.

21:04:08.484 [main] INFO  com.doding.mvntest.Main -- info: info
21:04:08.485 [main] WARN  com.doding.mvntest.Main -- warn: warn
21:04:08.485 [main] ERROR com.doding.mvntest.Main -- error: error

아까와는 달리 info부터만 출력되는 것을 확인할 수 있다. 이를 통해서 개발 시에는 level을 trace로 설정해서 모든 로그를 보고 운영 시에는 info로 설정해서 필요한 로그만 볼 수 있다.

그런데 만약 우리가 사용하는 다른 라이브러리에서도 trace, debug 메시지를 뿜어내고 있다면 어떻게 될까?

우리는 외부 라이브러리의 로깅에는 사실 관심이 없기 때문에 그들의 level은 좀 올려줄 필요가 있다.이런 경우 <logger> 태그를 이용한다. <logger>의 name 속성에 package를 설정하고 level에 로그 레벨을 설정하면 해당 package에서 출력되는 로그만 별도로 레벨이 설정된다.

<!-- org.springframework에서 나오는 로그는 info 부터 표시 -->
<logger name="org.springframework" level="info"></logger>
<!-- 프로젝트의 기본 log level은 trace -->
<root level="trace">
	<appender-ref ref="STDOUT" />
</root>

이제 개발 시에는 root의 level을 trace로 하고 운영 시에는 info로 만들어주면 깔끔히 로그를 관리할 수 있게 되었다.

 

appender 구성

 

appender

 현재 사용된 appender는 ConsoleAppender로 로그를 콘솔에 출력하는 역할을 수행한다. appender는 encoder를 하위 태그로 갇는데 이 정보를 이용하여 OutputStream을 구성한다.  <pattern>은 어떤 형태로 출력할 것인지 layout을 구성한다.

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  <encoder>
    <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n</pattern>
  </encoder>
</appender>

appender의 name은 <root> 내부에서 appender-ref를 통해 참조된다. 

<root level="trace">
  <appender-ref ref="STDOUT" />
</root>

 

layout

layout은 appender의 <pattern> 태그에 대한 설정으로 로그를 어떤 포맷으로 보여줄 것인가에 대한 부분이다. layout에는 아주 다양한 옵션이 제공되지만 필요한 것만 쓰면 되고 한번 만들어두면 변경할 일은 거의 없다. 

여기서는 다음처럼 패턴을 수정해보자.

<pattern>%highlight(%d{HH:mm:ss} [%-5p] %c{1}.%M.%L - %m%n)</pattern>

 

패턴 약어 의미 예시
%highlight   로그의 레벨에 따라서 ANSI 컬러를 이용해서 강조해준다.  
%d{HH:mm:ss}   로그 출력 시간으로 시:분:초 17:21:35
%-5level %-5p 로그의 레벨을 앞에서 부터 최소 5글자로 출력 DEBUG
%logger{n} %c{n} 로그가 출력되는 클래스를 패키지 이름과 함께 n글자까지 출력
출력할 내용이 n을 넘어가면 패키지를 앞에서 부터 한 글자로 줄임
com.doding.mvntest.LogTest
c.d.m.LogTest
%method %M 로그가 출력되는 메서드 이름 logTest
%line %L 로그가 출력된 소스코드의 라인 번호 1
%msg %m 메시지 출력 message
%n   개행 문자  

 

Appender 추가하기

 

RollingFileAppender 추가하기

장기간 동작하는 시스템을 로깅하기 위해 로그를 파일에 출력하도록 RollingFileAppender를 추가해 보자. RollingFileAppender는 로그를 파일에 출력하면서 일자별로 로그 파일을 남기고 일정 기간이 지나면 오래된 순서로 삭제시켜 준다.

기본 코드는 공식 사이트에 잘 나와있으므로 코드를 분석하기만 해보자.

https://logback.qos.ch/manual/appenders.html#RollingFileAppender

 

Chapter 4: Appenders

There is so much to tell about the Western country in that day that it is hard to know where to start. One thing sets off a hundred others. The problem is to decide which one to tell first. —JOHN STEINBECK, East of Eden Chapter 4: Appenders What is an Ap

logback.qos.ch

코드에 대한 설명은 간단히 주석으로 대체한다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>

<configuration>
    <import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder" />
    <import class="ch.qos.logback.core.ConsoleAppender" />
    <import class="ch.qos.logback.core.rolling.RollingFileAppender" />
    <import class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" />

    <appender name="STDOUT" class="ConsoleAppender">
        <encoder class="PatternLayoutEncoder">
            <pattern>%highlight(%d{HH:mm:ss} [%-5level] %logger{36} - %msg%n)</pattern>
        </encoder>
    </appender>
    <appender name="FILE" class="RollingFileAppender">
        <file>logFile.log</file>
        <rollingPolicy class="TimeBasedRollingPolicy">
            <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>
        </rollingPolicy>
        <encoder class="PatternLayoutEncoder">
            <pattern>%-4relative [%thread] %-5level %logger{35} -%kvp- %msg%n</pattern>
        </encoder>
    </appender>

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

이제 다시 한번 로그를 남겨보면 프로젝트 루트 경로에 logs라는 폴더가 생기고 logFile.log라는 파일이 생성된 것을 확인할 수 있다. 이처럼 logging framework를 사용하면 복잡한 IO에 대한 작업 없이 손쉽게 파일 로그를 생성할 수 있다.

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.