From a8952b94285fc76e188a5de3a4146eb2592dd3a2 Mon Sep 17 00:00:00 2001 From: mikekks Date: Thu, 13 Feb 2025 15:28:36 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[UNI-139]=20refactor:=20=EB=A1=9C=EA=B9=85?= =?UTF-8?q?=20=EB=A9=94=EC=84=B8=EC=A7=80=20=EA=B0=80=EB=8F=85=EC=84=B1=20?= =?UTF-8?q?=EC=A2=8B=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/logging/ExecutionLoggingAop.java | 130 +++++++++++------- 1 file changed, 80 insertions(+), 50 deletions(-) diff --git a/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java b/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java index 48c0898..8eb0a97 100644 --- a/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java +++ b/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java @@ -1,9 +1,8 @@ package com.softeer5.uniro_backend.common.logging; -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; +import java.util.Arrays; import java.util.Enumeration; -import java.util.Objects; +import java.util.List; import java.util.UUID; import org.aspectj.lang.ProceedingJoinPoint; @@ -30,10 +29,8 @@ public class ExecutionLoggingAop { @Around("execution(* com.softeer5.uniro_backend..*(..)) " + "&& !within(com.softeer5.uniro_backend.common..*) " - + "&& !within(com.softeer5.uniro_backend.resolver..*) " - ) + + "&& !within(com.softeer5.uniro_backend.resolver..*)") public Object logExecutionTrace(ProceedingJoinPoint pjp) throws Throwable { - // 요청에서 userId 가져오기 (ThreadLocal 사용) String userId = userIdThreadLocal.get(); if (userId == null) { userId = UUID.randomUUID().toString().substring(0, 12); @@ -41,76 +38,109 @@ public Object logExecutionTrace(ProceedingJoinPoint pjp) throws Throwable { } Object target = pjp.getTarget(); - Annotation[] declaredAnnotations = target.getClass().getDeclaredAnnotations(); + boolean isController = isRestController(target); String className = pjp.getSignature().getDeclaringType().getSimpleName(); String methodName = pjp.getSignature().getName(); String task = className + "." + methodName; - for(Annotation annotation : declaredAnnotations){ - if(annotation instanceof RestController){ - logHttpRequest(userId); - - HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest(); - RequestMethod httpMethod = RequestMethod.valueOf(request.getMethod()); - - log.info(""); - log.info("🚨 [ userId = {} ] {} Start", userId, className); - log.info("[ userId = {} ] [Call Method] {}: {}", userId, httpMethod, task); - } + if (isController) { + logHttpRequest(userId); } + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); + log.info("✅ [ userId = {} Start] [Call Method] {}: {}", userId, request.getMethod(), task); - Object[] paramArgs = pjp.getArgs(); - for (Object object : paramArgs) { - if (Objects.nonNull(object)) { - log.info("[Parameter] {} {}", object.getClass().getSimpleName(), object); - - String packageName = object.getClass().getPackage().getName(); - if (packageName.contains("java")) { - break; - } - - Field[] fields = object.getClass().getDeclaredFields(); - for (Field field : fields) { - field.setAccessible(true); - 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()); - } - } - } + try{ + logParameters(pjp.getArgs()); + } + catch (Exception e){ + // 로깅 중에 발생한 에러는 무시하고 로깅을 계속 진행 + log.error("🚨🚨🚨 [ userId = {} ] {} 메서드 파라미터 로깅 중 에러 발생 : {} 🚨🚨🚨", userId, task, e.getMessage()); } + log.info(""); StopWatch sw = new StopWatch(); sw.start(); - Object result = null; + Object result; try { result = pjp.proceed(); } catch (Exception e) { log.warn("[ERROR] [ userId = {} ] {} 메서드 예외 발생 : {}", userId, task, e.getMessage()); throw e; } finally { - // Controller 클래스일 때만 ThreadLocal 값 삭제 - for(Annotation annotation : declaredAnnotations){ - if(annotation instanceof RestController){ - userIdThreadLocal.remove(); - } + if (isController) { + userIdThreadLocal.remove(); } } sw.stop(); - long executionTime = sw.getTotalTimeMillis(); - - log.info("[ExecutionTime] {} --> {} (ms)", task, executionTime); - log.info("🚨 [ userId = {} ] {} End", userId, className); - log.info(""); + log.info("[ExecutionTime] {} --> {} (ms)", task, sw.getTotalTimeMillis()); + log.info("🚨 [ userId = {} ] {} End\n", userId, className); return result; } + private boolean isRestController(Object target) { + return Arrays.stream(target.getClass().getDeclaredAnnotations()) + .anyMatch(RestController.class::isInstance); + } + + private void logParameters(Object[] args) { + StringBuilder parametersLogMessage = new StringBuilder(); + + Arrays.stream(args) + .forEach(arg -> logCommonTest(arg, "[Parameter]", parametersLogMessage, 0)); + + log.info("\n{}", parametersLogMessage.toString()); + } + + private void logCommonTest(Object arg, String requestType, StringBuilder logMessage, int depth) { + String indent = " ".repeat(depth); // depth 수준에 따른 들여쓰기 + + if (arg == null) { + logMessage.append(indent).append(requestType).append(" null\n"); + return; + } + + if (arg instanceof List) { + logMessage.append(indent).append(requestType).append(" ").append(arg.getClass().getSimpleName()).append("\n"); + List list = (List) arg; + for (int i = 0; i < list.size(); i++) { + logCommonTest(list.get(i), "[List Element " + i + "] ", logMessage, depth + 1); + } + } else if (isCustomDto(arg)) { + logMessage.append(indent).append(requestType).append("DTO: ").append(arg.getClass().getSimpleName()).append("\n"); + logObjectFields(arg, logMessage, depth + 1); + } else if (isEntity(arg)) { + logMessage.append(indent).append(requestType).append(arg.getClass().getSimpleName()).append(" : ").append("\n"); + logObjectFields(arg, logMessage, depth + 1); + } + else { + logMessage.append(indent).append(requestType).append(" ").append(arg.getClass().getSimpleName()).append(": ").append(arg).append("\n"); + } + } + + private void logObjectFields(Object object, StringBuilder logMessage, int depth) { + String indent = " ".repeat(depth); // depth 기반 들여쓰기 + Arrays.stream(object.getClass().getDeclaredFields()).forEach(field -> { + try { + field.setAccessible(true); + Object value = field.get(object); + logCommonTest(value, "[Field] " + field.getName(), logMessage, depth + 1); + } catch (IllegalAccessException e) { + logMessage.append(indent).append("[Field Access Error] Cannot access field: ").append(field.getName()).append("\n"); + } + }); + } + + private boolean isCustomDto(Object arg) { + return arg.getClass().getName().contains("dto"); // 패키지 명에 "dto" 포함 여부로 DTO 판단 (적절히 변경 가능) + } + + private boolean isEntity(Object arg) { + return arg.getClass().getName().contains("entity"); // 패키지 명에 "dto" 포함 여부로 DTO 판단 (적절히 변경 가능) + } private void logHttpRequest(String userId) { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); From 5b359ad53c9300ddaf011f50cf94200c41a131f5 Mon Sep 17 00:00:00 2001 From: mikekks Date: Thu, 13 Feb 2025 15:52:50 +0900 Subject: [PATCH 2/4] =?UTF-8?q?[UNI-139]=20chore:=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/logging/ExecutionLoggingAop.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java b/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java index 8eb0a97..4316070 100644 --- a/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java +++ b/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java @@ -11,7 +11,6 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; import org.springframework.util.StopWatch; -import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; @@ -90,12 +89,12 @@ private void logParameters(Object[] args) { StringBuilder parametersLogMessage = new StringBuilder(); Arrays.stream(args) - .forEach(arg -> logCommonTest(arg, "[Parameter]", parametersLogMessage, 0)); + .forEach(arg -> logDetail(arg, "[Parameter]", parametersLogMessage, 0)); log.info("\n{}", parametersLogMessage.toString()); } - private void logCommonTest(Object arg, String requestType, StringBuilder logMessage, int depth) { + private void logDetail(Object arg, String requestType, StringBuilder logMessage, int depth) { String indent = " ".repeat(depth); // depth 수준에 따른 들여쓰기 if (arg == null) { @@ -107,7 +106,7 @@ private void logCommonTest(Object arg, String requestType, StringBuilder logMess logMessage.append(indent).append(requestType).append(" ").append(arg.getClass().getSimpleName()).append("\n"); List list = (List) arg; for (int i = 0; i < list.size(); i++) { - logCommonTest(list.get(i), "[List Element " + i + "] ", logMessage, depth + 1); + logDetail(list.get(i), "[List Element " + i + "] ", logMessage, depth + 1); } } else if (isCustomDto(arg)) { logMessage.append(indent).append(requestType).append("DTO: ").append(arg.getClass().getSimpleName()).append("\n"); @@ -127,7 +126,7 @@ private void logObjectFields(Object object, StringBuilder logMessage, int depth) try { field.setAccessible(true); Object value = field.get(object); - logCommonTest(value, "[Field] " + field.getName(), logMessage, depth + 1); + logDetail(value, "[Field] " + field.getName(), logMessage, depth + 1); } catch (IllegalAccessException e) { logMessage.append(indent).append("[Field Access Error] Cannot access field: ").append(field.getName()).append("\n"); } From 3c90162807d2963cce5fd6d399a8307a8767c97b Mon Sep 17 00:00:00 2001 From: mikekks Date: Thu, 13 Feb 2025 15:54:13 +0900 Subject: [PATCH 3/4] =?UTF-8?q?[UNI-139]=20chore:=20resolver=20=EB=82=B4?= =?UTF-8?q?=EC=9A=A9=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../uniro_backend/common/logging/ExecutionLoggingAop.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java b/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java index 4316070..325880e 100644 --- a/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java +++ b/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java @@ -28,7 +28,7 @@ public class ExecutionLoggingAop { @Around("execution(* com.softeer5.uniro_backend..*(..)) " + "&& !within(com.softeer5.uniro_backend.common..*) " - + "&& !within(com.softeer5.uniro_backend.resolver..*)") + ) public Object logExecutionTrace(ProceedingJoinPoint pjp) throws Throwable { String userId = userIdThreadLocal.get(); if (userId == null) { From 43cee381e020904de7f3b0ba97f914e3523f3fe9 Mon Sep 17 00:00:00 2001 From: mikekks Date: Thu, 13 Feb 2025 16:01:21 +0900 Subject: [PATCH 4/4] =?UTF-8?q?[UNI-139]=20refactor:=20ArgType=20enum=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EB=B6=84=EA=B8=B0=EB=AC=B8=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../uniro_backend/common/logging/ArgType.java | 34 ++++++++++ .../common/logging/ExecutionLoggingAop.java | 65 +++++++++++-------- 2 files changed, 71 insertions(+), 28 deletions(-) create mode 100644 uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ArgType.java diff --git a/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ArgType.java b/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ArgType.java new file mode 100644 index 0000000..ceed19e --- /dev/null +++ b/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ArgType.java @@ -0,0 +1,34 @@ +package com.softeer5.uniro_backend.common.logging; + +import java.util.List; + +public enum ArgType { + NULL, + LIST, + CUSTOM_DTO, + ENTITY, + OTHER; + + public static ArgType getArgType(Object arg) { + if (arg == null) { + return NULL; + } else if (arg instanceof List) { + return LIST; + } else if (isCustomDto(arg)) { + return CUSTOM_DTO; + } else if (isEntity(arg)) { + return ENTITY; + } else { + return OTHER; + } + } + + private static boolean isCustomDto(Object arg) { + return arg.getClass().getName().contains("dto"); + } + + private static boolean isEntity(Object arg) { + return arg.getClass().getName().contains("entity"); + } +} + diff --git a/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java b/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java index 325880e..4a28c89 100644 --- a/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java +++ b/uniro_backend/src/main/java/com/softeer5/uniro_backend/common/logging/ExecutionLoggingAop.java @@ -96,27 +96,44 @@ private void logParameters(Object[] args) { private void logDetail(Object arg, String requestType, StringBuilder logMessage, int depth) { String indent = " ".repeat(depth); // depth 수준에 따른 들여쓰기 - - if (arg == null) { - logMessage.append(indent).append(requestType).append(" null\n"); - return; - } - - if (arg instanceof List) { - logMessage.append(indent).append(requestType).append(" ").append(arg.getClass().getSimpleName()).append("\n"); - List list = (List) arg; - for (int i = 0; i < list.size(); i++) { - logDetail(list.get(i), "[List Element " + i + "] ", logMessage, depth + 1); + ArgType argType = ArgType.getArgType(arg); + + switch (argType) { + case NULL -> logMessage.append(indent).append(requestType).append(" null\n"); + case LIST -> { + logMessage.append(indent) + .append(requestType) + .append(" ") + .append(arg.getClass().getSimpleName()) + .append("\n"); + List list = (List)arg; + for (int i = 0; i < list.size(); i++) { + logDetail(list.get(i), "[List Element " + i + "] ", logMessage, depth + 1); + } } - } else if (isCustomDto(arg)) { - logMessage.append(indent).append(requestType).append("DTO: ").append(arg.getClass().getSimpleName()).append("\n"); - logObjectFields(arg, logMessage, depth + 1); - } else if (isEntity(arg)) { - logMessage.append(indent).append(requestType).append(arg.getClass().getSimpleName()).append(" : ").append("\n"); - logObjectFields(arg, logMessage, depth + 1); - } - else { - logMessage.append(indent).append(requestType).append(" ").append(arg.getClass().getSimpleName()).append(": ").append(arg).append("\n"); + case CUSTOM_DTO -> { + logMessage.append(indent) + .append(requestType) + .append("DTO: ") + .append(arg.getClass().getSimpleName()) + .append("\n"); + logObjectFields(arg, logMessage, depth + 1); + } + case ENTITY -> { + logMessage.append(indent) + .append(requestType) + .append(arg.getClass().getSimpleName()) + .append(" : ") + .append("\n"); + logObjectFields(arg, logMessage, depth + 1); + } + default -> logMessage.append(indent) + .append(requestType) + .append(" ") + .append(arg.getClass().getSimpleName()) + .append(": ") + .append(arg) + .append("\n"); } } @@ -133,14 +150,6 @@ private void logObjectFields(Object object, StringBuilder logMessage, int depth) }); } - private boolean isCustomDto(Object arg) { - return arg.getClass().getName().contains("dto"); // 패키지 명에 "dto" 포함 여부로 DTO 판단 (적절히 변경 가능) - } - - private boolean isEntity(Object arg) { - return arg.getClass().getName().contains("entity"); // 패키지 명에 "dto" 포함 여부로 DTO 판단 (적절히 변경 가능) - } - private void logHttpRequest(String userId) { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();