[응용] 1. 로그 추적기 생성

kiwonkim·2021년 11월 25일
0

[ 강의 내용 ]

인프런 김영한 강사님의 스프링 핵심 원리 - 고급편을 정리할 예정입니다. 해당 강의는 스레드-로컬과 스프링의 디자인 패턴, AOP의 원리 및 개념에 대한 강의입니다.

[ 로그 추적기 구현준비 ]

구현 목표

위와같이 동작하는 로그추적기를 생성하는 것이 목표이다.

  • 모든 클래스에서 로그추적기 객체를 주입받는다.
  • 모든 Public 메서드의 호출과 응답 정보를 로그로 출력한다.
  • 정상 흐름과 예외 흐름을 구분해서 예외시 예외 정보를 남겨야한다.
  • 로그추적기는 어플리케이션 동작 흐름에 영향을 주면 안된다다.
  • 메서드 호출 깊이를 |-> 로 표현해야한다.
  • HTTP 요청을 구분해서 별도의 ID를 부여해야 한다.

TraceId

public class TraceId {
    private String id; // [796bccd9]
    private int level; // |--> 몇단계 호출인지.
}

TraceId 객체이다. UUID 를 자른 id와 몇단계 호출인지 저장하는 level 필드를 갖는다.

TraceStatus

public class TraceStatus {

    private TraceId traceId; // id와 level
    private Long startTimeMs; // 시작시간
    private String message; // OrderController.request() 같은 메시지
}

TraceStatus 객체이다. TraceId 와 시작시간, 출력용 메시지를 갖는다.


[ 로그 추적기 구현 - 파라미터 사용 ]

이제 TraceId 와 TraceStatus 를 활용해서 로그추적기 객체를 생성해보겠다. 로그 추적기 객체는 begin, end, exception 등의 메서드를 갖는다.

begin

메서드의 메인 로직 전에 호출할 메서드이다. begin 은 호출 깊이가 0인 메서드에서만 실행된다. 다음 호출된 메서드에서는 동일한 Id 를 갖도록 해야하기 때문이다. 생성한 Id 와 message 를 출력한다.

beginSync

begin 과 마찬가지로 메서드 시작시 호출할 메서드이다. 대신 상위 메서드에서 생성한 TraceId 를 파라미터로 받는다. 동일한 Id를 갖으므로 TraceId 의 level 만 1을 증가시켜서 사용한다. Id 와 message를 출력한다.

end

메서드의 메인 로직이 끝나고 정상적으로 종료되었을 경우 호출하는 메서드이다. complete 를 호출한다.

exception

메서드에서 예외가 발생해 비정상 종료되었을 경우 호출하는 메서드이다. complete 를 호출한다.

complete

메서드 종료시 공통적으로 호출하는 메서드이다. 정상 종료시 현재 level 에서 id, 소요시간, 메시지를 출력한다. 비정상 종료시 동일한 정보와 추가로 예외를 출력한다.


[ 로그 추적기 적용 - 파라미터 사용 ]

Controller, Service, Repository 에서 스프링빈으로 등록해놓은 로그추적기 객체를 주입받아 사용한다.

Controller

요청이 들어오면 매핑된 핸들러가 실행된다. 즉 최초로 실행되는 메서드이므로 레벨이 0이다. 따라서 begin 으로 새로 TraceId 를 생성한다. 다음 호출되는 메서드와는 Id, Level 을 공유해야하기에 생성한 traceId 를 넘겨준다.
예외 발생시 trace.exception 을 실행해줘야 하므로 try catch 로 구분한다. 이때 catch 에서 로그 추적기가 예외를 처리한 것으로 간주되어 정상흐름에 영향을 주므로 다시 예외를 던져준다.

Service

컨트롤러가 넘겨준 traceId를 파라미터로 사용한다. 동일하게 try catch 를 쓰며 repository 에게 다시 traceId 를 넘겨준다.

Repository

서비스가 넘겨준 traceId를 사용하며 try catch 를 사용한다.

출력결과

레벨이 0인 컨트롤러 메서드만 traceId 를 생성하고, 호출되는 메서드들인 서비스, 리포지토리에서는 traceId 를 파라미터로 받아 사용하므로 동기화가 되어서 정상적으로 결과가 수행된다.

파라미터 동기화의 한계

하나의 요청에 Id와 Level 을 동기화하기 위해 파라미터로 넘겨주는 방식을 채택했다.
그런데 모든 메서드에 traceId 를 파라미터로 받도록 수정해야 하며, 컨트롤러에서 traceId 를 생성하고 다른곳에서는 파라미터로 받아 사용하므로 컨트롤러에서 메서드를 호출하는 경우가 아니면 traceId 가 없어 에러가 발생한다.
즉 모든 메서드에 traceId 를 파라미터로 하는 것은 너무 비효율적이다.

0개의 댓글