[스프링 핵심원리 - 고급편 ] 로그 추적기 v1

JEONG SUJIN·2023년 2월 11일
0

스프링부트 기본

목록 보기
8/15

OrderControllerV1.java

v1패키지 생성 후 OrderControllerV1 파일 생성

package study.advanced.app.v1;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;
import study.advanced.trace.TraceStatus;
import study.advanced.trace.hellotrace.HelloTraceV1;

@RestController
@RequiredArgsConstructor
public class OrderControllerV1 {

	private final OrderServiceV1 orderService;
	private final HelloTraceV1 trace;
	
	@GetMapping("/v1/request") //요청이 오면 아래 메서드가 호출
	public String request(String itemId) {
		
		TraceStatus status = null;
		
		//예외가 되더라도 로그가 되게끔 try처리
		try {
	    status = trace.begin("OrderController.request()");
		orderService.orderItem(itemId);
		trace.end(status);
		return "ok";
		
		}catch (Exception e) {	
			trace.exception(status, e);
			throw e; // 예외를꼭 다시 던져주어야 한다. 
		}	
	}
}
  • HelloTraceV1 trace : HelloTraceV1을 주입 받는다.
    참고로 HelloTraceV1어노테이션을 가지고 있기 때문에 컴포넌트 스캔의 대상이 된다.
    따라서 자동으로 스프링 빈으로 등록된다.

  • trace.begin("OrderController.request()") : 로그를 시작할 때 메시지 이름으로 컨트롤러 이름 + 메서드 이름을 주었다. 이렇게 하면 어떤 컨트롤러와 메서드가 호출되었는지 로그로 편리하게 확인할 수 있다.

  • 단순하게 trace.begin(), trace.end() 코드 두 줄만 적용하면 될 줄 알았지만 예외처리까지 처리해야 하므로 try, catch 코드가 추가된다.

  • begin() 의 결과 값으로 받은 TraceStatus status 값을 end(), exception()에 넘겨야 한다. 결국 try, catch 블록 모두에게 이 값을 넘겨야 한다. 따라서 try상위에 TraceStatus status 코드를 선언해야 한다. 만약 try안에서 TraceStatus status 를 선언하면 try 블록안에서만 해당 변수가 유효하기 때문에 catch 블록에 넘길 수 없다.

  • throw e : 예외를 꼭 다시 던져주어야 한다. 그렇지 않으면 여기서 예외를 먹어버리고, 이후에 정상 흐름으로 동작한다. 로그는 애플리케이션에 흐름에 영향을 주면 안된다. 로그 때문에 예외가 사라지면 안된다.

예외처리 발생 로그 처리 잘 된다.

OrderServiceV1.java

package study.advanced.app.v1;

import org.springframework.stereotype.Service;

import lombok.RequiredArgsConstructor;
import study.advanced.trace.TraceStatus;
import study.advanced.trace.hellotrace.HelloTraceV1;

@Service
@RequiredArgsConstructor
public class OrderServiceV1 {

	private final OrderRepositoryV1 orderRepository;
	private final HelloTraceV1 trace;

	 public void orderItem(String itemId) {
		
		TraceStatus status = null;

		// 예외가 되더라도 로그가 되게끔 try처리
		try {
			status = trace.begin("OrderService.orderItem()");
			orderRepository.save(itemId);
			trace.end(status);
			

		} catch (Exception e) {
			trace.exception(status, e);
			throw e; 
		}
		
	}

}

OrderRepositoryV1.java

package study.advanced.app.v1;

import org.springframework.stereotype.Repository;

import lombok.RequiredArgsConstructor;
import study.advanced.trace.TraceStatus;
import study.advanced.trace.hellotrace.HelloTraceV1;

@Repository
@RequiredArgsConstructor
public class OrderRepositoryV1 {

	private final HelloTraceV1 trace;
	
	
	public void save(String itemId) {
		
		TraceStatus status = null;
		
		try {
			status = trace.begin("OrderRepository.save()");
			//저장로직
			if(itemId.equals("ex")) {
				throw new IllegalStateException("예외발생");
			}
			//상품저장에 1초
			sleep(1000);
			trace.end(status);
			
		}catch(Exception e) {
			trace.exception(status, e);
			throw e;
		}
	
		
	}

	private void sleep(int millis) {
		try {
			Thread.sleep(millis);
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
	
}

정상처리 됐을 때 로그처리

예외처리로 로그처리

HelloTraceV1 덕분에 직접 로그를 하나하나 남기는 것보다는 편하게 여러가지 로그를 남길 수 있다.
하지만 로그를 남기기 위한 코드가 너무 복잡하지만 일단 나중에 정리하는걸로

남은문제

  • 메서드 호출의 깊이 표현
  • HTTP 요청을 구분
    • Http요청 단위로 특정 ID를 남겨서 어떤 HTTP 요청에서 시작된 것인지 명확하게 구분이 가능해야 함.
    • 트랜잭션 ID (DB트랜잭션 X)

아직 구현하지 못한 요구사항은 메서드 호출의 깊이를 표현하고 같은 HTTP요쳥이면 같은 트랜잭션 ID를 남기는 것.
이 기능은 직전 로그의 깊이와 트랜잭션 ID가 무엇인지 알아야 할 수 있는 일

예를 들어서 OrderController.request()에서 로그를 남길때 어떤 깊이와 어떤 트랜잭션 ID를 사용했는지를 그 다음에 로그를 남기는 OrderService.orderItem()에서 로그를 남길 때 알아야한다.
결국 현재 로그의 상태정보인 트랜잭션ID 와 level이 다음으로 전달되어야 한다.
로그에 대한 Context 정보가 필요하다.

profile
기록하기

0개의 댓글