[Logging] 로그 출력을 효율적으로 생성 및 추적하기 2편

2024. 12. 25. 19:24·Spring/Logging
728x90
반응형
SMALL

 

Logging Trace V2

목차

  • TraceV2
  • TraceId에서 추가된 메서드
  • Test
    • Controller
    • Service
  • 결과
  • 문제점

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


https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B3%A0%EA%B8%89%ED%8E%B8

 

스프링 핵심 원리 - 고급편 강의 | 김영한 - 인프런

김영한 | 스프링의 핵심 원리와 고급 기술들을 깊이있게 학습하고, 스프링을 자신있게 사용할 수 있습니다., 핵심 디자인 패턴, 쓰레드 로컬, 스프링 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
'Spring/Logging' 카테고리의 다른 글
  • [Logging] 로그 출력을 효율적으로 생성 및 추적하기 5편 - Template Method
  • [Logging] 로그 출력을 효율적으로 생성 및 추적하기 4편 ThreadLocal사용기
  • [Logging] 로그 출력을 효율적으로 생성 및 추적하기 3편
  • [Logging] 로그 출력을 효율적으로 생성 및 추적하기 1편
공부하고 기억하는 공간
공부하고 기억하는 공간
IT 비전공자로 시작하여 훌륭한 개발자가 되기 위해 공부하고 있는 공간입니다. 틀린 내용이나 부족한 부분이 있으면 댓글로 알려주세요 바로 수정하겠습니다.
IT - railroadIT 비전공자로 시작하여 훌륭한 개발자가 되기 위해 공부하고 있는 공간입니다. 틀린 내용이나 부족한 부분이 있으면 댓글로 알려주세요 바로 수정하겠습니다.
    250x250
  • 공부하고 기억하는 공간
    IT - railroad
    공부하고 기억하는 공간
  • 전체
    오늘
    어제
    • 분류 전체보기 (317) N
      • 면접 준비 (38) N
        • OS (6)
        • Spring Security (0)
        • Java (3) N
        • DB (10) N
        • Network (3)
      • ElasticSearch (2)
      • Kafka (4)
      • Spring (22)
        • Spring Cloud (7)
        • Security6 (5)
        • JPA (12)
        • 프로젝트 리팩토링 회고록 (4)
        • Logging (8)
        • Batch (2)
      • Redis (17)
        • Redis 개념 (8)
        • Redis 채팅 (5)
        • Redis 읽기쓰기 전략 (1)
      • AWS (11)
      • 리눅스 (29)
        • 리눅스 마스터 2급 (5)
        • 네트워크(기초) (7)
        • 리눅스의 이해 (6)
        • 리눅스의 설치 (2)
        • 리눅스 운영 및 관리 (6)
      • JAVA-기초 (16)
        • JAVA기본 (11)
        • Design Pattern (5)
      • JSP (27)
        • JSP 기본 개념 (10)
        • JSP (1)
      • SQL (1)
      • TIL (36)
      • 문제 풀이 (2)
        • Programmers (9)
        • 백준 문제풀이 (28)
      • JavaScript (10)
      • HTML (17)
      • Ngrinder (1)
        • Ngrinder 문서 정리 (1)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      리눅스
      JSP
      Springframework
      자바
      java
      Til
      jsp request
      리눅스마스터2급정리
      프로그래머스
      springsecurity
      자바 알고리즘
      자바기초
      백준
      jsp기초
      redis 채팅
      레디스
      Spring Data Redis
      리눅스마스터2급
      CSS
      spring redis
      자바 면접질문
      JavaScript
      자바스크립트
      자바 반복문
      redis
      JS
      스프링프레임워크
      Spring
      HTML
      자바 면접
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    공부하고 기억하는 공간
    [Logging] 로그 출력을 효율적으로 생성 및 추적하기 2편

    개인정보

    • 티스토리 홈
    • 포럼
    • 로그인
    상단으로

    티스토리툴바

    단축키

    내 블로그

    내 블로그 - 관리자 홈 전환
    Q
    Q
    새 글 쓰기
    W
    W

    블로그 게시글

    글 수정 (권한 있는 경우)
    E
    E
    댓글 영역으로 이동
    C
    C

    모든 영역

    이 페이지의 URL 복사
    S
    S
    맨 위로 이동
    T
    T
    티스토리 홈 이동
    H
    H
    단축키 안내
    Shift + /
    ⇧ + /

    * 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.