Java&Web

[Logging] Springboot에 Log4j2 설정하기

프로그래민 2020. 12. 29. 18:47
반응형

[Logging] slf4j, log4j, logback, log4j2

 

[Logging] slf4j, log4j, logback, log4j2

로그(log)는 소프트웨어의 이벤트를 기록하는 것으로써, 소프트웨어의 동작상태를 파악하고 문제가 발생했을 때 이 동작 파악을 통해서 소프트웨어의 문제를 찾아내고 해결하기 위해 디자인 되

minkwon4.tistory.com

 

Springboot는 기본 Java 로깅 프레임워크로 spring-boot-starter-web안에 spring-boot-starter-loggig의 logback이 포함되어 있지만 가장 최신에 나오고 성능이 좋은 log4j2를 Springboot 프로젝트에 설정을 해보았다. 다음과 같은 과정을 거쳐 설정을 진행했다.

log4j2 Dependency 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
          <dependency>    
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
 
        <!-- log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
                                                               

log4j2의 dependency를 추가해주기 위해 maven환경에서의 pom.xml에서 작업을 해주었다. 우선적으로 Springboot의 기본적으로 주어져있는 logback 라이브러리를 제외 시켜주고 log4j2를 추가시켜주었다.

 

log4j2.xml 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info" monitorInterval="30">
    <Properties>
        <Property name="BASE_DIR">./logs</Property>
        <Property name="LOG_FORMAT">[%date{yyyy-MM-dd HH:mm:ss}] %level %logger{36}(%file:%line) - %msg%n</Property>
    </Properties>
 
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT" follow="true">
            <PatternLayout pattern="${LOG_FORMAT}"/>
        </Console>
 
         <RollingFile name="File"
                     fileName="${BASE_DIR}/logfile.log"
                     filePattern="${BASE_DIR}/logfile.%d{yyyyMMdd}.log">
            <PatternLayout pattern="${LOG_FORMAT}"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
            </Policies>
            <DefaultRolloverStrategy>
                <Delete basePath="${BASE_DIR}">
                    <IfFileName glob="*.log"/>
                    <IfLastModified age="30d"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
    </Appenders>
 
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="File"/>
        </Root>
 
        <Logger name="com.pacakge.controller" level="DEBUG" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="File"/>
        </Logger>
    </Loggers>
</Configuration>
 
           

그 후 application.properties가 존재하는 main/resources에 다음과 같은 log4j2.xml 설정파일을 작성해주었다. Java 로깅 프레임워크의 설정파일(여기선 log4j2.xml)은 부분적으로는 다르지만 거의 대부분이 크게 아래와 같은 3가지 부분으로 구성되어있다.

요소 설명
Logger 출력할 메시지를 Appender에게 전달
Appender 전달된 로그를 어디에 출력할 것인지 결정(Console, File, JDBC등)
Layout 로그를 어떤 형식으로 출력할 것인지 결정

 

위의 log4j2.xml을 위에서 부터본다면 properties라는 태그에서는 log4j2.xml에서 사용할 변수를 설정해주었다. 이 부분에서 LOG_FORMAT이라는 것을 이용하여 출력할 로그에 대해 커스텀할 수 있도록 해주었는데, 아래와 같은 규칙을 가지고 있다.

패턴 설명
%c{숫자}, %logger{숫자} {숫자}에 적힌 만큼의 package depth와 함께 해당 로그를 쓰는 로거의 이름
%C, %class 해당 로그를 요청한 클래스 이름
%d, %date 해당 로그가 발생한 시간
%F, %file 해당 로그가 발생한 클래스 파일명
%l, %location 해당 로그가 발생한 클래스명.메소드명
%L, %line 해당 로그가 발생한 라인 번호
%m, %msg, %message 로그문에 전달된 메세지
%p, %level 로그 레벨(TRACE ~ FATAL)
%t, %thread 해당 로그가 발생한 스레드명
%r, %relative 로그 처리시간

 

그 다음 Appenders 태그에서 출력방식을 나누어주었다. 위에서는 콘솔에 출력해주는 ConsoleAppender와 설정한 조건에 따라 파일에 출력해주는 RollingFileAppender를 설정해주었다. 위의 RollingFileAppender를 자세히 보면 TimeBasedTriggeringPolicy를 이용하여 시간 단위로 로그를 저장하게 설정해두었고 yyyyMMdd라는 pattern을 이용하여  하루 단위로 저장하게 해두었다. 또한 DefaultRolloverStrategy를 이용하여 30일이 지나면 삭제를 하게 설정해두었다.

그 다음 Loggers 태그에서 Appender들을 적용해주었다. 일단 기본적으로 Root는 level을 INFO로 설정하고 console과 file 둘다 출력되도록하였다. 여기서 level을 INFO로 설정해주면 INFO 이상의 로그 level을 출력하도록 해놓은 것이다. 여기서는 INFO, WARN, ERROR, FATAL이 출력이 되도록 하였다. 또한, log4j2는 패키지 별로 상이하게 로그 레벨을 지정할 수 있기 때문에 logger 태그를 이용하여 설정해보았다. controller라는 package에선 DEBUG 이상의 로그 level을 출력되도록 하였다. 

 

Java에서 로그 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
@RequestMapping("/api")
public class ApiController {
    private static final Logger LOGGER = LogManager.getLogger(ApiController.class);
 
    @GetMapping
    public ResponseEntity<String> hello() {
        LOGGER.debug("Hello World");
        LOGGER.info("Hello World");
        LOGGER.warn("Hello World");
        return new ResponseEntity<String>("Hello World", HttpStatus.OK);
    }
}
                                        

설정한 로그를 Test하기 위해 다음과 같은 것을 작성하였다. 우선적으로 LOGGER를 하나 만들어 주었다. 이 Java 파일은 com.package.controller 라는 패키지 안에 존재하기때문에 앞선 설정한 Logger를 가져오도록 설계를 하였다. 그 후 실행시키고 다음과 같은 결과를 확인 할 수 있었다.

log4j2 Test 결과

 

다음 단계로 배포환경에 따라서 로그 출력을 다르게 설정(ex. 로컬에선 console, 서버에선 file)하려고 시도해보았다. 찾아본 결과 springProfile 이라는 태그를 이용하여 각 환경에 맞도록 적용할 수 있는 것을 알았다. 하지만, springProfile태그 같은 경우 logback에서는 사용할 수 있지만 log4j2에선 사용할 수 없었다. 그리하여 maven의 profile을 이용하여 log4j2.xml을 다르게 설정하는 방법을 적용하여 배포환겨에 따라 로그 출력을 나누도록 하였다.

 

출처
madplay.github.io/post/spring-boot-log4j2
www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte3:fdl:logging:log4j_2:%EC%84%A4%EC%A0%95_%ED%8C%8C%EC%9D%BC%EC%9D%84_%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94_%EB%B0%A9%EB%B2%95
velog.io/@bread_dd/Log4j-2-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-%EA%B0%9C%EB%85%90
반응형