Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 로그 출력용 AOP 구현 #430

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package org.sopt.makers.crew.main.global.aop;

import jakarta.servlet.http.HttpServletRequest;

import java.lang.reflect.Field;
import java.util.Objects;
import lombok.extern.log4j.Log4j2;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.Profile;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
Expand All @@ -15,56 +15,84 @@
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.log4j.Log4j2;

@Aspect
@Component
@Log4j2
@Profile("!test")
public class ExecutionLoggingAop {

// 모든 패키지 내의 controller package에 존재하는 클래스
@Around("execution(* org.sopt.makers.crew..*Controller.*(..))")
public Object logExecutionTrace(ProceedingJoinPoint pjp) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
RequestMethod httpMethod = RequestMethod.valueOf(request.getMethod());
/**
* @implNote : 일부 클래스를 제외하고, 모든 클래스의 메서드의 시작과 끝을 로깅한다.
* @implNote : 제외 클래스 - global 패키지, config 관련 패키지, Test 클래스
* */
@Around("execution(* org.sopt.makers.crew.main..*(..)) "
+ "&& !within(org.sopt.makers.crew.main.global..*) "
+ "&& !within(org.sopt.makers.crew.main.external.s3.config..*)"
)
public Object logExecutionTrace(ProceedingJoinPoint pjp) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
RequestMethod httpMethod = RequestMethod.valueOf(request.getMethod());

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Object userId = authentication.getPrincipal().toString();

String className = pjp.getSignature().getDeclaringType().getSimpleName();
String methodName = pjp.getSignature().getName();
String task = className + "." + methodName;

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Object userId = authentication.getPrincipal().toString();
log.info("");
log.info("🚨 {} Start", className);
log.info("[Call Method] " + httpMethod + ": " + task + " | Request userId=" + userId);

String className = pjp.getSignature().getDeclaringType().getSimpleName();
String methodName = pjp.getSignature().getName();
String task = className + "." + methodName;
Object[] paramArgs = pjp.getArgs();
for (Object object : paramArgs) {
if (Objects.nonNull(object)) {
log.info("[Parameter] {} {}", object.getClass().getSimpleName(), object);

log.info("[Call Method] " + httpMethod.toString() + ": " + task + " | Request userId=" + userId);
String packageName = object.getClass().getPackage().getName();
if (packageName.contains("java")) {
break;
}

Object[] paramArgs = pjp.getArgs();
for (Object object : paramArgs) {
if (Objects.nonNull(object)) {
log.info("[parameter type] {}", object.getClass().getSimpleName());
log.info("[parameter value] {}", object);
}
}
Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true); // private 필드에도 접근 가능하도록 설정
try {
Object value = field.get(object); // 필드값 가져오기
log.info("[Field] {} = {}", field.getName(), value);
} catch (IllegalAccessException e) {
log.warn("[Field Access Error] Cannot access field: " + field.getName());
}
}
}
}

// 해당 클래스 처리 전의 시간
StopWatch sw = new StopWatch();
sw.start();
// 해당 클래스 처리 전의 시간
StopWatch sw = new StopWatch();
sw.start();

Object result = null;
Object result = null;

// 해당 클래스의 메소드 실행
try{
result = pjp.proceed();
}
catch (Exception e){
log.warn("[ERROR] " + task + " 메서드 예외 발생 : " + e.getMessage());
throw e;
}
// 해당 클래스의 메소드 실행
try {
result = pjp.proceed();
} catch (Exception e) {
log.warn("[ERROR] " + task + " 메서드 예외 발생 : " + e.getMessage());
throw e;
}

// 해당 클래스 처리 후의 시간
sw.stop();
long executionTime = sw.getTotalTimeMillis();
// 해당 클래스 처리 후의 시간
sw.stop();
long executionTime = sw.getTotalTimeMillis();

log.info("[ExecutionTime] " + task + " --> " + executionTime + " (ms)");
log.info("[ExecutionTime] " + task + " --> " + executionTime + " (ms)");
log.info("🚨 {} End", className);
log.info("");

return result;
}
return result;
}

}
Loading