Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 자바
- transaction
- 김영한
- 스프링 핵심 기능
- pointcut
- http
- spring
- JDBC
- Android
- java
- Greedy
- 그리디
- JPQL
- QueryDSL
- 백준
- kotlin
- Servlet
- jpa
- db
- 인프런
- Spring Boot
- Proxy
- Exception
- springdatajpa
- AOP
- Thymeleaf
- SpringBoot
- 스프링 핵심 원리
- 스프링
- 알고리즘
Archives
- Today
- Total
개발자되기 프로젝트
로그 추적기 v1 - 프로토 타입 본문
- 애플리케이션의 모든 로직에 직접 로그를 남겨도 되지만, 그것보다는 더 효율적인 개발 방법이 필요하다.
- 특히 트랜잭션ID와 깊이를 표현하는 방법은 기존 정보를 이어 받아야 하기 때문에
- 단순히 로그만 남긴다고 해결할 수 있는 것은 아니다.
- 요구사항에 맞추어 애플리케이션에 효과적으로 로그를 남기기 위한 로그 추적기를 개발해보자.
- 먼저 프로토타입 버전을 개발해보자.
- 아마 코드를 모두 작성하고 테스트 코드까지 실행해보아야 어떤 것을 하는지 감이 올 것이다.
- 먼저 로그 추적기를 위한 기반 데이터를 가지고 있는 TraceId , TraceStatus 클래스를 만들어보자.
1. TraceId
- 로그 추적기는 트랜잭션ID와 깊이를 표현하는 방법이 필요하다.
- 트랜잭션ID와 깊이를 표현하는 level을 묶어서 TraceId 라는 개념을 만듦.
- TraceId 는 단순히 id (트랜잭션ID)와 level 정보를 함께 가지고 있다.
public class TraceId {
private String id;
private int level;
public TraceId() {
this.id = creatId();
this.level = 0;
}
private TraceId(String id, int level){
this.id = id;
this.level= level;
}
private String creatId() {
return UUID.randomUUID().toString().substring(0,8); //앞에 9자리만 사용
}
//다음 level에 해당하는 traceId를 미리 만들어둠. id
public TraceId creatNextId(){
return new TraceId(id, level+1);
}
public TraceId creatPreviousId(){
return new TraceId(id, level-1);
}
public boolean isFirstLevel(){
return level == 0;
}
public String getId() {
return id;
}
public int getLevel() {
return level;
}
}
[796bccd9] OrderController.request() //트랜잭션ID:796bccd9, level:0
[796bccd9] |-->OrderService.orderItem() //트랜잭션ID:796bccd9, level:1
[796bccd9] | |-->OrderRepository.save()//트랜잭션ID:796bccd9, level:2
2. TraceStatus
로그를 시작하면 끝이 있어야 한다.
[796bccd9] OrderController.request() //로그 시작
[796bccd9] OrderController.request() time=1016ms //로그 종료
- TraceStatus 는 로그를 시작할 때의 상태 정보를 가지고 있다.
- 이 상태 정보는 로그를 종료할 때 사용된다.
- traceId : 내부에 트랜잭션ID와 level을 가지고 있다.
- startTimeMs : 로그 시작시간이다. 로그 종료시 이 시작 시간을 기준으로 시작~종료까지 전체 수행
시간을 구할 수 있다. - message : 시작시 사용한 메시지이다. 이후 로그 종료시에도 이 메시지를 사용해서 출력한다.
- TraceId , TraceStatus 를 사용해서 실제 로그를 생성하고, 처리하는 기능을 개발해보자.
@Slf4j
@Component
public class HelloTraceV1 {
private static final String START_PREFIX = "-->";
private static final String COMPLETE_PREFIX = "<--";
private static final String EX_PREFIX = "<X-";
public TraceStatus begin(String message){
TraceId traceId = new TraceId();
Long startTimeMs = System.currentTimeMillis();
log.info("[{}] {}{}", traceId.getId(), addSpace(START_PREFIX, traceId.getLevel()), message);
return new TraceStatus(traceId, startTimeMs, message);
}
public void end(TraceStatus status){
complete(status, null);
}
public void exception(TraceStatus status, Exception e){
complete(status, e);
}
private void complete(TraceStatus status, Exception e){
Long stopTimeMs = System.currentTimeMillis();
long resultTimeMs = stopTimeMs - status.getStartTimeMs();
TraceId traceId = status.getTraceId();
if (e == null){
log.info("[{}] {}{} time={}ms", traceId.getId(), addSpace(COMPLETE_PREFIX, traceId.getLevel()), status.getMessage());
}else {
log.info("[{}] {}{} time={}ms ex={}", traceId.getId(), addSpace(EX_PREFIX, traceId.getLevel()), status.getMessage(), resultTimeMs, 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();
}
}
공개 메서드
- 로그 추적기에서 사용되는 공개 메서드는 다음 3가지이다.
- begin(..)
- end(..)
- exception(..)
- TraceStatus begin(String message)
- 로그를 시작한다.
- 로그 메시지를 파라미터로 받아서 시작 로그를 출력한다.
- 응답 결과로 현재 로그의 상태인 TraceStatus 를 반환한다.
- void end(TraceStatus status)
- 로그를 정상 종료한다.
- 파라미터로 시작 로그의 상태( TraceStatus )를 전달 받는다. 이 값을 활용해서 실행 시간을 계산하고,
- 종료시에도 시작할 때와 동일한 로그 메시지를 출력할 수 있다.
- 정상 흐름에서 호출한다.
- void exception(TraceStatus status, Exception e)
- 로그를 예외 상황으로 종료한다.
- TraceStatus , Exception 정보를 함께 전달 받아서 실행시간, 예외 정보를 포함한 결과 로그를
- 출력한다.
- 예외가 발생했을 때 호출한다.
비공개 메서드
- complete(TraceStatus status, Exception e)
- end() , exception() , 의 요청 흐름을 한곳에서 편리하게 처리한다.
- 실행 시간을 측정하고 로그를 남긴다.
- String addSpace(String prefix, int level) : 다음과 같은 결과를 출력한다.
- prefix: -->
- level 0:
- level 1: |-->
- level 2: | |-->
- prefix: <--
- level 0:
- level 1: |<--
- level 2: | |<--
- prefix: <Xlevel
- 0:
- level 1: |<Xlevel
- 2: | |<X-
3. Test
class HelloTraceV1Test {
@Test
void begin_end(){
HelloTraceV1 trace = new HelloTraceV1();
TraceStatus status = trace.begin("hello");
trace.end(status);
}
@Test
void begin_exception(){
HelloTraceV1 trace = new HelloTraceV1();
TraceStatus status = trace.begin("hello");
trace.exception(status, new IllegalStateException());
}
}
23:28:35.666 [main] INFO hello.advanced.hellotrace.HelloTraceV1 - [159b8312] hello
23:28:35.673 [main] INFO hello.advanced.hellotrace.HelloTraceV1 - [159b8312] hello time=10ms ex=java.lang.IllegalStateException
23:28:35.684 [main] INFO hello.advanced.hellotrace.HelloTraceV1 - [e8a1d122] hello
23:28:35.684 [main] INFO hello.advanced.hellotrace.HelloTraceV1 - [e8a1d122] hello time=0ms
4. GitHub :211118 Log Tracer V1
'인프런 > [인프런] 스프링 핵심 원리 - 고급' 카테고리의 다른 글
로그 추적기 V2 - 적용 (0) | 2021.11.20 |
---|---|
로그 추적기 V2 - 파라미터로 동기화 개발 (0) | 2021.11.20 |
로그 추적기 V1 - 적용 (0) | 2021.11.19 |
로그 추적기 - 요구사항 분석 (0) | 2021.11.18 |
예제 프로젝트 - v0 (0) | 2021.11.18 |
Comments