현재 재직중인 회사에서는 레거시 프로젝트의 기술부채가 심각하여 로그를 쌓고 있지만 해당 로그를 잘 활용하여 찾기는 어렵게되어 있다.
이에 내가 주로 작업하는 파트너 리소스에 traceId 를 생성하여 빠르게 로그를 추적하고자 한다.
이전에 다녔던 회사중 한곳은 쿠버네티스 환경의 모든 리소스의 로그가 트레이스 단위로 추적이 가능한 환경이 였는데 현재 회사에서는 기술부채로 인하여 새로운 시스템 도입이 어려운 상황이다.
이에 현재 내가 담당하고 주로 작업을 진행하는 파트너리소스에 접근하는 호출들에 대하여 요청 아이디를 생성하기로 했다. 내가 담당하는 부분말고도 다른부분도 모두 적용하여 trace를 생성하면 좋겠지만 일단 해당 리소스에만 작업하기로 한다.
일단 내가 원하는이상적인 방법은 spring cloud sleuth와 zipkin을 통하여 흩어 져 있는 리소스를 모두 취합하고
trace추적 및 span 단위 작업 등을 확인하는 이상적인 구조..
아래는 2가지 기능들의 참조 사이트 이다.
https://docs.spring.io/spring-cloud-sleuth/docs/2.2.x-SNAPSHOT/reference/html/
Spring Cloud Sleuth
Spring Cloud Sleuth automatically instruments all your Spring applications, so you should not have to do anything to activate it. The instrumentation is added by using a variety of technologies according to the stack that is available. For example, for a s
docs.spring.io
OpenZipkin · A distributed tracing system
Zipkin Zipkin is a distributed tracing system. It helps gather timing data needed to troubleshoot latency problems in service architectures. Features include both the collection and lookup of this data. If you have a trace ID in a log file, you can jump di
zipkin.io
일단 급한대로 다른 방법이 없는지 찾아보니 MDC((Mapped Diagnostic Contex) 라는 게 있어 이를 활용하기로 했다.
MDC는 로깅 프레임워크에서 사용되는 기능이며 현재 실행중인 컨텍스트(혹은 쓰레드)에 메타 정보를 넣고 관리할 수 있는 공간입니다.
각각의 로그 메시지에 대한 컨텍스트 정보를 추가하여 제공하고, 로그 메시지를 보다 구체적이고 유용하게 만들어줍니다.
내부적으로 쓰레드 로컬을 사용하며 Map 형태로 되어있어, Key Value 형태로 값을 보관하고 꺼낼 수 있어 관리에 용이합니다.
- 즉 스레드 단위로 관리되는 Map을 사용합니다.
MDC를 사용하면 로깅 프레임워크에서 제공하는 로그 출력 형식에 특정 데이터를 쉽게 추가할 수 있습니다.
주로 다음과 같은 정보를 MDC에 설정하여 사용합니다:
- 요청 ID: 각각의 웹 요청이나 작업에 대해 고유한 식별자를 설정
- 세션 ID: 사용자 세션을 식별하기 위한 정보를 설정
- 사용자 정보: 현재 사용자의 ID, 이름 등과 같은 정보를 설정
- 트랜잭션 ID: 트랜잭션 처리에 대한 고유한 식별자를 설정
- 로깅 수준: 특정 로그 메시지에 대한 로깅 수준을 설정
MDC는 주로 다중 스레드 환경에서 스레드 로컬 (ThreadLocal) 변수를 사용하여 각각의 스레드에 대해 독립적인 MDC 값을 설정하고 사용할 수 있습니다. 이를 통해 멀티스레드 환경에서도 로그 메시지에 대한 정확한 컨텍스트 정보를 유지할 수 있습니다.
예를 들어, 웹 애플리케이션에서 각각의 HTTP 요청에 대해 고유한 요청 ID를 MDC에 설정하면, 해당 요청과 관련된 모든 로그 메시지에 자동으로 요청 ID가 포함됩니다. 이를 통해 로그 메시지를 필터링하거나 추적하는 등의 작업을 보다 쉽게 수행할 수 있습니다.
MDC는 Java에서는 로깅 프레임워크인 SLF4J (Simple Logging Facade for Java)와 함께 사용됩니다.
실제 적용 코드
일단 요청이 들어오는 시점에 최초로 MDC 요청아이디와 스레드 아이디를 달아주고자 doFilter를 활용했다.
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MDCRequestFilter 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());
MDC.put("thread_id", Thread.currentThread().getName());
chain.doFilter(request, response);
MDC.clear();
}
}
logback 에서는 추가된 요청 아이디와 스레드 아이드를 추가해준다.
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>[%d{yyyy.MM.dd HH:mm:ss.SSS}] - [%-5level] - [%X{request_id}] - [%logger{5}] - [%X{thread_id}] [%method:%line] - %msg%n</pattern>
</layout>
</appender>
실제 생성된 로그
생각보다 간단하게 적용 되었다. 현재 내용에는 빠져 있지만 completeFuture 비동기 처리 시 요청 아이디를 찾지 못하여 해당 값은 추가 처리를 통하여 처리하였다.
추가로 멀티 쓰레드 처리 시 추가 설정및 확인이 필요하다.
'코드 > dev' 카테고리의 다른 글
spring Rest Docs (0) | 2024.03.03 |
---|---|
Spring boot MongoDB transaction (0) | 2024.02.28 |
NoHttpResponseException 해결 방법 (2) | 2024.02.26 |
Hikari pool맥스 사이즈 문제 (1) | 2024.02.26 |
form 요청 PATCH , PUT, DELETE는 불가능한 이유 (2) | 2024.02.26 |