본문 바로가기
프레임워크/스프링

[Spring] 로그 추적기 프로토타입 개발

by so5663 2022. 10. 31.

김영한의 스프링 고급 강의를 복습하기 위해

 

 

HelloTraceV1

import hello.advanced.trace.TraceId;
import hello.advanced.trace.TraceStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@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(),
        resultTimeMs);
    	} 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: | |<--

테스트 코드 작성

import hello.advanced.trace.TraceStatus;
import org.junit.jupiter.api.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());
    }
}

 

begin_end() - 실행 로그

[41bbb3b7] hello [41bbb3b7] hello time=5ms

 

begin_exception() - 실행 로그

[898a3def] hello [898a3def] hello time=13ms ex=java.lang.IllegalStateException