728x90
반응형
SMALL
Logging Trace V2
목차
TraceV2
V2에서는 beginSync()
메서드를 호출하여 TraceId
값을 일관적으로 사용할 수 있도록 동기화하고 depth
를 설정해준다.
@Slf4j
@Component
public class TraceV2 {
private static final String START_PREFIX = "-->";
private static final String END_PREFIX = "<--";
private static final String EXCEPTION_PREFIX = "<X-";
public TraceStatus begin(String message) {
TraceId traceId = new TraceId();
Long startTime = System.currentTimeMillis();
log.info("[{}] {}{}", traceId, addSpace(START_PREFIX, traceId.getLevel()), message);
return new TraceStatus(traceId, startTime, message);
}
public TraceStatus beginSync(TraceId beforeTraceId, String message) {
TraceId traceId = beforeTraceId.createNextId();
long startTime = System.currentTimeMillis();
log.info("[{}] {}{}", traceId, addSpace(START_PREFIX, traceId.getLevel()), message);
return new TraceStatus(traceId, startTime, message);
}
public void end(TraceStatus traceStatus) {
complete(traceStatus, null);
}
public void exception(TraceStatus status, Exception e) {
complete(status, e);
}
private void complete(TraceStatus traceStatus, Exception e) {
Long stopMills = System.currentTimeMillis();
long resultMillls = stopMills - traceStatus.getStartTime();
TraceId traceId = traceStatus.getTraceId();
if (e == null) {
log.info("[{}] {}{} time={}ms", traceId.getTraceId(), addSpace(END_PREFIX, traceId.getLevel()), traceStatus.getMessage(), resultMillls);
} else {
log.info("[{}] {}{} time={}ms, ex={}", traceId.getTraceId(), addSpace(EXCEPTION_PREFIX, traceId.getLevel()), traceStatus.getMessage(), resultMillls, e.toString());
}
}
private static String addSpace(String prefix, int level) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < level; i++) {
sb.append((i == level - 1) ? "|" + prefix : "| ");
}
return sb.toString();
}
}
TraceId에서 추가된 메서드
public TraceId createNextId() {
return new TraceId(traceId, level + 1);
}
Test
이전과 다른 점은 각 레이어에서 생성된 TraceId
값을 다음 레이어로 전달해준다는 점이다.
Controller
@RestController
@RequiredArgsConstructor
@Slf4j
@RequestMapping("/api/v1/user")
public class UserController {
private final UserService userService;
private final TraceV2 trace;
@GetMapping
public String create(@RequestParam String name) {
TraceStatus status = trace.begin("UserController.create()");
String answer = null;
try {
answer = userService.create(status.getTraceId(), name);
trace.end(status);
} catch (Exception e) {
trace.exception(status, e);
throw e;
}
return answer;
}
}
Service
보시다시피 TraceV2
에서는 Controller
에서 넘겨받은 TraceId
를 동기화하여 TraceStatus
를 생성하는 코드를 확인할 수 있다.
@Service
@RequiredArgsConstructor
@Slf4j
public class UserService {
private final UserRepository userRepository;
private final TraceV2 trace;
public String create(TraceId traceId, String name) {
TraceStatus status = trace.beginSync(traceId, "UserService.create()");
try {
if (name.equals("ex")) {
throw new IllegalStateException("예외 발생");
}
Users createdUser = Users.builder()
.username(name)
.build();
userRepository.save(createdUser);
trace.end(status);
return "created";
} catch (IllegalStateException e) {
trace.exception(status, e);
throw e;
}
}
}
결과
depth
에 대한 level
설정을 해줬기에 Service
로 들어가면 level
이 1 증가하고 로그도 Prefix
와 함께 출력되는 것을 확인할 수 있다.
2024-12-25T18:49:15.387+09:00 INFO 3087 --- [nio-8080-exec-2] c.e.loggingtest.global.trace.TraceV2 : [72235a4a] UserController.create()
2024-12-25T18:49:15.387+09:00 INFO 3087 --- [nio-8080-exec-2] c.e.loggingtest.global.trace.TraceV2 : [72235a4a] |-->UserService.create()
2024-12-25T18:49:15.425+09:00 INFO 3087 --- [nio-8080-exec-2] c.e.loggingtest.global.trace.TraceV2 : [72235a4a] |<--UserService.create() time=38ms
2024-12-25T18:49:15.425+09:00 INFO 3087 --- [nio-8080-exec-2] c.e.loggingtest.global.trace.TraceV2 : [72235a4a] UserController.create() time=38ms
문제점
하지만 코드와 설명을 보면서도 느꼈겠지만 유지보수에 매우 어려우며 이미 구현한 서비스의 파라미터를 모두 변경해야 한다는 어려움이 있다.
이러한 동기화 문제 및 유지 보수에 어려운 문제점들을 디자인 패턴을 사용해서 해결해보려고 한다.

reference
스프링 핵심 원리 - 고급편 강의 | 김영한 - 인프런
김영한 | 스프링의 핵심 원리와 고급 기술들을 깊이있게 학습하고, 스프링을 자신있게 사용할 수 있습니다., 핵심 디자인 패턴, 쓰레드 로컬, 스프링 AOP스프링의 3가지 핵심 고급 개념 이해하기
www.inflearn.com
728x90
반응형
SMALL
'Spring > Logging' 카테고리의 다른 글
[Logging] 로그 출력을 효율적으로 생성 및 추적하기 6편 - Proxy (1) | 2025.01.06 |
---|---|
[Logging] 로그 출력을 효율적으로 생성 및 추적하기 5편 - Template Method (1) | 2025.01.06 |
[Logging] 로그 출력을 효율적으로 생성 및 추적하기 4편 ThreadLocal사용기 (0) | 2025.01.06 |
[Logging] 로그 출력을 효율적으로 생성 및 추적하기 3편 (1) | 2024.12.26 |
[Logging] 로그 출력을 효율적으로 생성 및 추적하기 1편 (0) | 2024.12.25 |