• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

@AfterReturning에서 질문있습니다.

23.10.22 16:48 작성 23.10.22 16:57 수정 조회수 184

0

안녕하세요 강사님!

강사님께서 말씀해주신 AOP로 구현하면 좋은 기능을 실제 코드로 작성해봤습니다.

로그 트레이스기능에 매서드 종료가 1초 5초 10초가 될때 로그 레벨을 높여서 로그를 찍는 기능입니다.

    @Aspect
    @Slf4j
    static class LogTraceSelf {

        ThreadLocal<TraceStatus> trace = new ThreadLocal<>();

        private TraceStatus SynchronizedTrace(){
            TraceStatus traceStatus = trace.get();
            if (traceStatus == null) {
                trace.set(new TraceStatus());
                traceStatus = trace.get();
            }
            return traceStatus;
        }

        @Pointcut("@annotation(hello.aop.exam.annotation.Trace)")
        public void logTrace() {}

        @Before("logTrace()")
        public void doTrace(JoinPoint joinPoint) {
            TraceStatus traceStatus = SynchronizedTrace();
            traceStatus.begin(joinPoint.getSignature().getName());
        }

        @AfterReturning("logTrace()")
        public void doTraceSuccess(JoinPoint joinPoint) {
            TraceStatus traceStatus = SynchronizedTrace();
            long gap = traceStatus.end(joinPoint.getSignature().getName());
        }

        @AfterThrowing(value = "logTrace()", throwing = "ex")
        public void doTraceException(JoinPoint joinPoint, Exception ex) {
            TraceStatus traceStatus = SynchronizedTrace();
            traceStatus.end(joinPoint.getSignature().getName(),ex);
        }

    }

조인포인트 실행 권한이 필요없는 부가 기능이다보니

@Around 사용을 하지 않고 나누어서 처리를 하다보니 불필요한 코드가 더 증가하게되었습니다.

그리고 @Around와 다르게 어드바이스내 지역변수에 TraceStatus를 저장하고 사용할수 없기때문에

ThreadLoacal에 공유할 데이터와 본인이 가지고 있어야하는 timestamp도 저장했습니다.

@Slf4j
public class TraceStatus {

    private final String id;
    private int depth = 0;
    private Deque<Long> timeStampHolder = new ArrayDeque<>();
    private final int offsetInfoMs;
    private final int offsetWarningMs;
    private final int offsetErrorMs;

}

기능은 stack 자료구조를 활용해서 begin을 할때마다 timeStampHolder에 시작시간을 저장합니다.

end를 호출하면 pop으로 자신이 넣은 시작 시간을 꺼내서 시간을 계산하고 로그를 출력합니다.

기타 기능 메서드들은 강사님이 작성하신거와 유사해서 제외했습니다.

 

이제 소요된 시간이 1초, 5초, 10초가 걸릴 경우 info,warning,error로 출력하는 로그를 남기려고할때

  1. 어드바이스가 조건을 가지고 추가 기능을 만든다.

  2. 위 코드처럼 로그 트레이스 내에 저장하고 로그 트레이스 내부에서 출력하도록 한다.

  3. 경고 알림용 트레이스를 따로 만들고 상태를 전달한다.

제 생각은 트레이스에게 넘길경우 트레이스를 인터페이스로 만들어서 필요에 따라 다른 트레이스를 사용한다고 한다면 이 기능을 계속 구현해야 된다는 단점이 생길거 같습니다.
저라면 어드바이스에서 소요시간을 트레이스에게 받아서 추가 로직을 수행하려고 할거같습니다.

 

강사님께서 코드를 작성하신다면

어떤 포인트컷을 사용하셔서 구현하실건지,

그리고 애노테이션에서 넘어온 값을 가지고 어드바이스에서 처리하게 하시는지

아니면 로그 트레이스 내에서 처리하게 하실건지 그 이유가 궁금합니다.


 

 

 

답변 1

답변을 작성해보세요.

1

안녕하세요. kamser님

좋은 시도를 하고 계시네요 :) 저도 답변을 남겨드리면 좋겠지만 사실 이런 부분은 정답이 있다기 보다는 각각의 장단이 있기 때문에, 프로젝트 규모나 요구사항에 따라서 다를 것 같아요. 이런 경우 보통 단순한 방법으로 문제를 해결하고, 이후에 필요에 의해서 추상화나 더 복잡한 구조를 고민하는 것이 좋습니다.

그리고 죄송하지만 앞으로는 질문 안내에서 말씀드린 것처럼 강의 학습에 관련된 질문을 올려주시길 부탁드립니다.

저도 마음으로는 도움을 드리고 싶지만, 하루에도 수많은 분들이 질문을 올려주십니다. 그래서 강의 학습과 관련된 질문에 초점을 맞추는 것이 맞다 생각합니다. 다시한번 이해를 부탁드립니다.

kamser님의 프로필

kamser

질문자

2023.10.23

아닙니다. 덕분에 편하게 AOP에 대해서 공부하게 되었습니다.
정말 공식 문서를 보고 강의도 보니 이영한님이 강의를 안해주셨으면

AOP가 먼지도 모르고 사용했을거같네요 감사합니다 !