728x90

Mapped Diagnostic Context

멀티 쓰레드 환경에서 로그가 뒤섞이는 문제를 해결하기 위해 사용할 수 있는 객체로

현재 실행 중인 쓰레드에 메타 정보를 넣고 관리하는 공간이다.

 

  • 내부적으로 쓰레드 로컬을 사용한다.
  • Map 형태로 구성되어 (키, 값) 형태로 값을 저장하고 사용할 수 있다.
  • 다양한 데이터를 저장해 구체적이고 유용한 로그 메시지를 제공할 수 있다.

 

주로 각각의 요청에 대한 로깅을 구분하기 위해 고유한 요청 ID를 설정하거나

사용자 정보, 세션, 트랜잭션, 로깅 수준 등을 설정한다.

 

 

MDC 사용

implementation 'org.springframework.boot:spring-boot-starter-logging'

 

위의 디펜던시를 추가하면 org.slf4j 패키지에 있는 MDC를 사용할 수 있다.

 

위에서 언급한 것처럼 Map 형태로 이루어져 있기 때문에 put, get, remove, clear 처럼

자바의 유틸 클래스에 있는 Map의 메서드와 다를게 없어서 사용에 어려움은 없다.

 

이제 MDC를 어디에서 설정해주는게 효율적인지를 생각해 봐야 하는데

요청에 대한 모든 로그를 남기려면 가장 처음에 접근하는 필터단에서 처리해주는게 효율적이다.

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MDCLoggingFilter implements Filter {

	@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        final UUID uuid = UUID.randomUUID();
        MDC.put("request_id", uuid.toString());
        chain.doFilter(request, response);
        MDC.clear();
    }
}

 

위와 같이 @Order 어노테이션을 사용해 filter 중에서도 가장 빠른 순서로 만들어준다.

 

랜덤으로 고유한 UUID를 만들어 MDC에 저장해주면 요청별로 고유 ID를 기록할 수 있게 되고

쓰레드 로컬 변수는 초기화하지 않으면 쓰레드풀에서 다시 꺼낼 때

이전 데이터가 남아있게 되어 doFilter가 끝난 후에는 MDC를 clear 해줘야 한다.

 

 

Logback 적용

<configuration>
    <appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>utf8</charset>
            <pattern>%date{HH:mm:ss.SSS, Asia/Seoul} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="CONSOLE_APPENDER" />
    </root>
</configuration>

 

위와 같이 설정하면 콘솔창에 로그가 출력되는 것을 확인할 수 있다.

 

AOP를 적용하여 번거로운 로깅 처리를 간단하게 할 수도 있고

Spring Cloud Sleuth와 Zipkin을 사용해 분산된 마이크로서비스 간의 로깅도 가능하다 하니

이 부분들도 학습하면서 언젠가 정리해보도록 하겠다.

+ Recent posts