Log

로그 구분 ID 추가 logback-spring.xml + Filter

땍땍 2024. 8. 12. 18:20

코드를 작성하고 테스트를 하거나 디버깅을 하는 과정에서 로그를 봐야하는 상황은 정말 많이 존재한다.

하지만 이러한 로그에는 구분을 위한 ID 값이 존재하지 않기에 특정 로그를 찾는데 어렵다는 문제점이 존재하였다.

이러한 사항 과정의 불편함을 줄이기 위해 각 로그 별로 특정 ID를 생성해 함께 출력하도록 하려 한다.

로그에 ID 값을 출력하기 위해서는 로그 포맷을 변경해주어야 하는데, 기본 설정의 경우 아래와 같은 형식으로 로그가 출력되고 있을 것이다.

 

포맷 변경을 위해서는 application.yml 에서 간단하게 처리할 수 있으나, 세부적인 설정이 불가하기에 이번에는 logback-spring.xml 을 통해 변경해보도록 하겠다.

logback-spring.xml 파일은 resources 아래에 생성해주면 된다.

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

  <appender name="UUID_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%green([%X{uuid}]) %cyan(%d{yyyy-MM-dd HH:mm:ss}) %highlight([%thread])
        %red(%-5level)
        %magenta(%logger{36}) %msg%n
      </pattern>
    </encoder>
  </appender>

  <root level="INFO">
    <appender-ref ref="UUID_CONSOLE"/>
  </root>
</configuration>

위와 같이 {uuid} 라는 변수를 포함하여 로그를 출력하도록 하였고, 별도의 처리 없이 로그를 확인해보면 아래와 같이 빈 값으로 출력이 되는 것을 확인할 수 있다.

 

이러한 변수는 각 로그 별 설정할 수 있기에 특정 상황/코드를 구분하여 설정할 수 있으나, 이번에는 하나의 요청이 왔을때 , Request 부터 Response 까지의 모든 로그를 하나의 ID로 표시하는 방식으로 구현해보겠다.

코드는 아래 블로그에서 구현한 로깅 코드에 UUID 값을 추가하는 과정만 추가되었기에, 로깅 코드 관련한 설명이 필요하다면 아래 글을 참조하면 되겠다.

https://taekt.tistory.com/12

@Slf4j
@Component
public class LogFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        RequestWrapper requestWrapper = new RequestWrapper(request);
        ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);

        final UUID uuid = UUID.randomUUID();

        MDC.put("uuid", uuid.toString());

        log.info("Request Body: " + getBody(requestWrapper.getInputStream()));

        filterChain.doFilter(requestWrapper, responseWrapper);

        log.info("Response Body : " + getBody(responseWrapper.getContentInputStream()));

        responseWrapper.copyBodyToResponse();
        MDC.clear();
    }

    public String getBody(InputStream is) throws IOException {
        byte[] content = StreamUtils.copyToByteArray(is);
        if (content.length == 0) {
            return null;
        }
        return new String(content, StandardCharsets.UTF_8);
    }
}

테스트1 이라는 값을 Post 했을 때, Request 부터 Response 까지 동일한 UUID를 가진 로그가 출력 되는 것을 확인할 수 있다.