From 3d49ea2375fd53780965657d43709a0bc24355bc Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Fri, 18 Apr 2025 03:42:25 +0900 Subject: [PATCH 01/15] :sparkles: add : make log data dto classes --- .../common/log/model/HttpRequestLogInfo.java | 34 ++++++++++++++++++ .../common/log/model/MethodEndLogInfo.java | 22 ++++++++++++ .../common/log/model/MethodStartLogInfo.java | 35 +++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 src/main/java/org/runimo/runimo/common/log/model/HttpRequestLogInfo.java create mode 100644 src/main/java/org/runimo/runimo/common/log/model/MethodEndLogInfo.java create mode 100644 src/main/java/org/runimo/runimo/common/log/model/MethodStartLogInfo.java diff --git a/src/main/java/org/runimo/runimo/common/log/model/HttpRequestLogInfo.java b/src/main/java/org/runimo/runimo/common/log/model/HttpRequestLogInfo.java new file mode 100644 index 00000000..1b933ff1 --- /dev/null +++ b/src/main/java/org/runimo/runimo/common/log/model/HttpRequestLogInfo.java @@ -0,0 +1,34 @@ +package org.runimo.runimo.common.log.model; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; +import lombok.AccessLevel; +import lombok.Builder; + +@Builder(access = AccessLevel.PRIVATE) +public record HttpRequestLogInfo( + String requestMethod, + String uri, + Map queryParams +) { + + public static HttpRequestLogInfo of(HttpServletRequest request) { + String queryString = request.getQueryString(); + StringTokenizer st = new StringTokenizer(queryString, "&"); + Map queryParams = new HashMap<>(); + while (st.hasMoreTokens()) { + String[] keyVal = st.nextToken().split("="); + queryParams.put(keyVal[0], keyVal[1]); + // TODO : null 이면?? 1. query 변수 자체가 안붙어있음 2. 변수는 붙어있는 데 값이 없음 + } + + return HttpRequestLogInfo.builder() + .requestMethod(request.getMethod()) + .uri(request.getRequestURI()) + .queryParams(queryParams) + .build(); + } + +} diff --git a/src/main/java/org/runimo/runimo/common/log/model/MethodEndLogInfo.java b/src/main/java/org/runimo/runimo/common/log/model/MethodEndLogInfo.java new file mode 100644 index 00000000..abdc81c6 --- /dev/null +++ b/src/main/java/org/runimo/runimo/common/log/model/MethodEndLogInfo.java @@ -0,0 +1,22 @@ +package org.runimo.runimo.common.log.model; + +import lombok.AccessLevel; +import lombok.Builder; +import org.aspectj.lang.JoinPoint; + +@Builder(access = AccessLevel.PRIVATE) +public record MethodEndLogInfo( + String methodName, + long elapsedTimeMillis, + String returnData +) { + + public static MethodEndLogInfo of(JoinPoint joinPoint, long elapsedTimeMillis, + Object returnData) { + return MethodEndLogInfo.builder() + .methodName(joinPoint.getSignature().getName()) + .elapsedTimeMillis(elapsedTimeMillis) + .returnData(returnData.toString()) + .build(); + } +} diff --git a/src/main/java/org/runimo/runimo/common/log/model/MethodStartLogInfo.java b/src/main/java/org/runimo/runimo/common/log/model/MethodStartLogInfo.java new file mode 100644 index 00000000..e7c35459 --- /dev/null +++ b/src/main/java/org/runimo/runimo/common/log/model/MethodStartLogInfo.java @@ -0,0 +1,35 @@ +package org.runimo.runimo.common.log.model; + +import java.util.HashMap; +import java.util.Map; +import lombok.AccessLevel; +import lombok.Builder; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.reflect.MethodSignature; + +@Builder(access = AccessLevel.PRIVATE) +public record MethodStartLogInfo( + String methodName, + boolean authenticated, + String userId, + Map params +) { + + public static MethodStartLogInfo of(JoinPoint joinPoint, boolean authenticated, String userId) { + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + String[] parameterNames = methodSignature.getParameterNames(); + Object[] parameterValues = joinPoint.getArgs(); + + Map params = new HashMap<>(); + for (int i = 0; i < parameterNames.length; i++) { + params.put(parameterNames[i], parameterValues[i].toString()); + } + + return MethodStartLogInfo.builder() + .methodName(joinPoint.getSignature().getName()) + .authenticated(authenticated) + .userId(userId) + .params(params) + .build(); + } +} From c0aa504bbaf0fdf9d25163c61d9a799f6fa62d19 Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Fri, 18 Apr 2025 03:42:53 +0900 Subject: [PATCH 02/15] :sparkles: add : make ServiceLog annotation --- .../org/runimo/runimo/common/log/ServiceLog.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/java/org/runimo/runimo/common/log/ServiceLog.java diff --git a/src/main/java/org/runimo/runimo/common/log/ServiceLog.java b/src/main/java/org/runimo/runimo/common/log/ServiceLog.java new file mode 100644 index 00000000..40bdcd8c --- /dev/null +++ b/src/main/java/org/runimo/runimo/common/log/ServiceLog.java @@ -0,0 +1,12 @@ +package org.runimo.runimo.common.log; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface ServiceLog { + +} From e70c5732bc1f6bc48856f054b2911d4c7edab53e Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Fri, 18 Apr 2025 03:43:09 +0900 Subject: [PATCH 03/15] :sparkles: add : make LogMessageFormatter --- .../common/log/LogMessageFormatter.java | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java diff --git a/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java b/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java new file mode 100644 index 00000000..85b760de --- /dev/null +++ b/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java @@ -0,0 +1,100 @@ +package org.runimo.runimo.common.log; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import org.runimo.runimo.common.log.model.HttpRequestLogInfo; +import org.runimo.runimo.common.log.model.MethodEndLogInfo; +import org.runimo.runimo.common.log.model.MethodStartLogInfo; +import org.springframework.stereotype.Component; + +@Component +public class LogMessageFormatter { // TODO : 중복코드 리팩토링 + + public String toHttpRequestLogMessage(HttpRequestLogInfo logInfo) { + String queryParamString = convertMapToLogFormatString(logInfo.queryParams(), + new StringBuilder()).toString(); + + Map logs = new LinkedHashMap<>(); + logs.put("method", logInfo.requestMethod()); + logs.put("uri", logInfo.uri()); + logs.put("query_params", queryParamString); + logs.put("time", getCurrentTime()); + + StringBuilder sb = new StringBuilder(); + sb.append("HTTP_REQUEST "); + + convertMapToLogFormatString(logs, sb); + + return sb.toString(); + } + + + public String toMethodStartLogMessage(MethodStartLogInfo logInfo) { + String paramString = convertMapToLogFormatString(logInfo.params(), + new StringBuilder()).toString(); + + Map logs = new LinkedHashMap<>(); + logs.put("name", logInfo.methodName()); + logs.put("authenticated", String.valueOf(logInfo.authenticated())); + logs.put("userId", logInfo.userId()); + logs.put("params", paramString); + logs.put("time", getCurrentTime()); + + StringBuilder sb = new StringBuilder(); + sb.append("METHOD_CALL "); + + convertMapToLogFormatString(logs, sb); + + return sb.toString(); + } + + public String toMethodEndLogMessage(MethodEndLogInfo logInfo) { + Map logs = new LinkedHashMap<>(); + logs.put("name", logInfo.methodName()); + logs.put("elapsed_time", logInfo.elapsedTimeMillis() + "ms"); + logs.put("return", logInfo.returnData()); + logs.put("time", getCurrentTime()); + + StringBuilder sb = new StringBuilder(); + sb.append("METHOD_END "); + + convertMapToLogFormatString(logs, sb); + + return sb.toString(); + } + + private StringBuilder convertMapToLogFormatString(Map infoMap, + StringBuilder sb) { + sb.append("["); + + Iterator> it = infoMap.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + sb.append(convertCamelCaseToSnakeCase(entry.getKey())); + sb.append("="); + sb.append(entry.getValue()); + + if (it.hasNext()) { + sb.append(", "); + } + } + + sb.append("]"); + return sb; + } + + private String getCurrentTime() { + return ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")); + } + + private String convertCamelCaseToSnakeCase(String camelCase) { + return camelCase + .replaceAll("([A-Z])(?=[A-Z])", "$1_") + .replaceAll("([a-z])([A-Z])", "$1_$2") + .toLowerCase(); + } +} From 1f5b919af2073f6e708d359057659a8148cac770 Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Fri, 18 Apr 2025 03:43:42 +0900 Subject: [PATCH 04/15] :sparkles: add : add ToString annotation in response wrapper dtos --- .../java/org/runimo/runimo/common/response/ErrorResponse.java | 2 ++ src/main/java/org/runimo/runimo/common/response/Response.java | 2 ++ .../java/org/runimo/runimo/common/response/SuccessResponse.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/main/java/org/runimo/runimo/common/response/ErrorResponse.java b/src/main/java/org/runimo/runimo/common/response/ErrorResponse.java index 2b069934..379f6557 100644 --- a/src/main/java/org/runimo/runimo/common/response/ErrorResponse.java +++ b/src/main/java/org/runimo/runimo/common/response/ErrorResponse.java @@ -1,7 +1,9 @@ package org.runimo.runimo.common.response; +import lombok.ToString; import org.runimo.runimo.exceptions.code.CustomResponseCode; +@ToString public class ErrorResponse extends Response { private ErrorResponse(final String errorMessage, final String errorCode) { diff --git a/src/main/java/org/runimo/runimo/common/response/Response.java b/src/main/java/org/runimo/runimo/common/response/Response.java index 4e151c2c..fb63ae60 100644 --- a/src/main/java/org/runimo/runimo/common/response/Response.java +++ b/src/main/java/org/runimo/runimo/common/response/Response.java @@ -2,8 +2,10 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; +import lombok.ToString; import org.runimo.runimo.exceptions.code.CustomResponseCode; +@ToString @Getter public class Response { diff --git a/src/main/java/org/runimo/runimo/common/response/SuccessResponse.java b/src/main/java/org/runimo/runimo/common/response/SuccessResponse.java index 42f6e941..e5a7c1bc 100644 --- a/src/main/java/org/runimo/runimo/common/response/SuccessResponse.java +++ b/src/main/java/org/runimo/runimo/common/response/SuccessResponse.java @@ -1,8 +1,10 @@ package org.runimo.runimo.common.response; import lombok.Getter; +import lombok.ToString; import org.runimo.runimo.exceptions.code.CustomResponseCode; +@ToString @Getter public class SuccessResponse extends Response { From 29078be96c0dc1fd75ec49836a641656f3803f17 Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Fri, 18 Apr 2025 03:43:58 +0900 Subject: [PATCH 05/15] :sparkles: add : make LogAspect class --- .../runimo/runimo/common/log/LogAspect.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/main/java/org/runimo/runimo/common/log/LogAspect.java diff --git a/src/main/java/org/runimo/runimo/common/log/LogAspect.java b/src/main/java/org/runimo/runimo/common/log/LogAspect.java new file mode 100644 index 00000000..31a24bad --- /dev/null +++ b/src/main/java/org/runimo/runimo/common/log/LogAspect.java @@ -0,0 +1,83 @@ +package org.runimo.runimo.common.log; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.runimo.runimo.common.log.model.HttpRequestLogInfo; +import org.runimo.runimo.common.log.model.MethodEndLogInfo; +import org.runimo.runimo.common.log.model.MethodStartLogInfo; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +@Aspect +@Slf4j +@RequiredArgsConstructor +@Component +public class LogAspect { + + private final LogMessageFormatter logMessageFormatter; + + @Pointcut("execution(* org.runimo.runimo..controller.*Controller.*(..))") + private void controller() { + } + + @Pointcut("@annotation(org.runimo.runimo.common.log.ServiceLog)") + private void service() { + } + + @Before("controller()") + public void apiRequestLogger() { + ServletRequestAttributes attributes = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()); + if (attributes == null) { + log.info("ServletRequestAttributes is null"); + return; + } + + HttpServletRequest request = attributes.getRequest(); + HttpRequestLogInfo logInfo = HttpRequestLogInfo.of(request); + + log.info(logMessageFormatter.toHttpRequestLogMessage(logInfo)); + } + + @Around("controller() || service()") + public Object calledMethodLogger(ProceedingJoinPoint pjp) throws Throwable { + MethodStartLogInfo methodStartLogInfo = getMethodStartLogInfo(pjp); + log.info(logMessageFormatter.toMethodStartLogMessage(methodStartLogInfo)); + + long startTime = getCurrentTimeMillis(); + Object proceedReturn = pjp.proceed(); + long endTime = getCurrentTimeMillis(); + + MethodEndLogInfo methodEndLogInfo = MethodEndLogInfo.of(pjp, endTime - startTime, + proceedReturn); + log.info(logMessageFormatter.toMethodEndLogMessage(methodEndLogInfo)); + + return proceedReturn; + } + + private static MethodStartLogInfo getMethodStartLogInfo(ProceedingJoinPoint pjp) { + MethodStartLogInfo methodStartLogInfo; + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication != null) { + methodStartLogInfo = MethodStartLogInfo.of(pjp, true, authentication.getName()); + } else { + methodStartLogInfo = MethodStartLogInfo.of(pjp, false, null); + } + + return methodStartLogInfo; + } + + private long getCurrentTimeMillis() { + return System.currentTimeMillis(); + } + +} From 4057f4de49f7868824d8edf4eca43968e5e32997 Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Sun, 20 Apr 2025 23:33:01 +0900 Subject: [PATCH 06/15] :recycle: refactor : split LogAspect class to log about HttpRequest and Method --- .../common/log/HttpRequestLogAspect.java | 46 +++++++++++++++++++ .../{LogAspect.java => MethodLogAspect.java} | 22 +-------- 2 files changed, 48 insertions(+), 20 deletions(-) create mode 100644 src/main/java/org/runimo/runimo/common/log/HttpRequestLogAspect.java rename src/main/java/org/runimo/runimo/common/log/{LogAspect.java => MethodLogAspect.java} (76%) diff --git a/src/main/java/org/runimo/runimo/common/log/HttpRequestLogAspect.java b/src/main/java/org/runimo/runimo/common/log/HttpRequestLogAspect.java new file mode 100644 index 00000000..7202f6f1 --- /dev/null +++ b/src/main/java/org/runimo/runimo/common/log/HttpRequestLogAspect.java @@ -0,0 +1,46 @@ +package org.runimo.runimo.common.log; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.runimo.runimo.common.log.model.HttpRequestLogInfo; +import org.runimo.runimo.common.log.model.MethodEndLogInfo; +import org.runimo.runimo.common.log.model.MethodStartLogInfo; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +@Aspect +@Slf4j +@RequiredArgsConstructor +@Component +public class HttpRequestLogAspect { + + private final LogMessageFormatter logMessageFormatter; + + @Pointcut("execution(* org.runimo.runimo..controller.*Controller.*(..))") + private void controller() { + } + + @Before("controller()") + public void apiRequestLogger() { + ServletRequestAttributes attributes = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()); + if (attributes == null) { + log.info("ServletRequestAttributes is null"); + return; + } + + HttpServletRequest request = attributes.getRequest(); + HttpRequestLogInfo logInfo = HttpRequestLogInfo.of(request); + + log.info(logMessageFormatter.toHttpRequestLogMessage(logInfo)); + } + +} diff --git a/src/main/java/org/runimo/runimo/common/log/LogAspect.java b/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java similarity index 76% rename from src/main/java/org/runimo/runimo/common/log/LogAspect.java rename to src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java index 31a24bad..05c96196 100644 --- a/src/main/java/org/runimo/runimo/common/log/LogAspect.java +++ b/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java @@ -21,33 +21,15 @@ @Slf4j @RequiredArgsConstructor @Component -public class LogAspect { +public class MethodLogAspect { private final LogMessageFormatter logMessageFormatter; - @Pointcut("execution(* org.runimo.runimo..controller.*Controller.*(..))") - private void controller() { - } - @Pointcut("@annotation(org.runimo.runimo.common.log.ServiceLog)") private void service() { } - @Before("controller()") - public void apiRequestLogger() { - ServletRequestAttributes attributes = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()); - if (attributes == null) { - log.info("ServletRequestAttributes is null"); - return; - } - - HttpServletRequest request = attributes.getRequest(); - HttpRequestLogInfo logInfo = HttpRequestLogInfo.of(request); - - log.info(logMessageFormatter.toHttpRequestLogMessage(logInfo)); - } - - @Around("controller() || service()") + @Around("service()") public Object calledMethodLogger(ProceedingJoinPoint pjp) throws Throwable { MethodStartLogInfo methodStartLogInfo = getMethodStartLogInfo(pjp); log.info(logMessageFormatter.toMethodStartLogMessage(methodStartLogInfo)); From 743b29fc3d67b83ecd81a8dedcb5e6dcaf4c19a7 Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Sun, 20 Apr 2025 23:52:17 +0900 Subject: [PATCH 07/15] :sparkles: modify : modify useage of ServiceLog annotation --- src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java | 2 +- src/main/java/org/runimo/runimo/common/log/ServiceLog.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java b/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java index 05c96196..190ed7f0 100644 --- a/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java +++ b/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java @@ -25,7 +25,7 @@ public class MethodLogAspect { private final LogMessageFormatter logMessageFormatter; - @Pointcut("@annotation(org.runimo.runimo.common.log.ServiceLog)") + @Pointcut("execution(* (@org.runimo.runimo.common.log.ServiceLog *).*(..))") private void service() { } diff --git a/src/main/java/org/runimo/runimo/common/log/ServiceLog.java b/src/main/java/org/runimo/runimo/common/log/ServiceLog.java index 40bdcd8c..1e22c048 100644 --- a/src/main/java/org/runimo/runimo/common/log/ServiceLog.java +++ b/src/main/java/org/runimo/runimo/common/log/ServiceLog.java @@ -6,6 +6,7 @@ import java.lang.annotation.Target; @Target(ElementType.METHOD) +@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface ServiceLog { From a8419c89e198dbc8021db0e35b2117a7bff64797 Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Sun, 20 Apr 2025 23:52:55 +0900 Subject: [PATCH 08/15] :bulb: comment : add java doc comment in ServiceLog and fix typo --- .../org/runimo/runimo/common/log/LogMessageFormatter.java | 2 +- src/main/java/org/runimo/runimo/common/log/ServiceLog.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java b/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java index 85b760de..31ce392c 100644 --- a/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java +++ b/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java @@ -40,7 +40,7 @@ public String toMethodStartLogMessage(MethodStartLogInfo logInfo) { Map logs = new LinkedHashMap<>(); logs.put("name", logInfo.methodName()); logs.put("authenticated", String.valueOf(logInfo.authenticated())); - logs.put("userId", logInfo.userId()); + logs.put("user_id", logInfo.userId()); logs.put("params", paramString); logs.put("time", getCurrentTime()); diff --git a/src/main/java/org/runimo/runimo/common/log/ServiceLog.java b/src/main/java/org/runimo/runimo/common/log/ServiceLog.java index 1e22c048..075ef71c 100644 --- a/src/main/java/org/runimo/runimo/common/log/ServiceLog.java +++ b/src/main/java/org/runimo/runimo/common/log/ServiceLog.java @@ -5,7 +5,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target(ElementType.METHOD) +/** + * 비즈니스 로그 기록 어노테이션 - 메서드 실행 시 메서드명, 인자 목록, 반환값, 소요시간 등의 정보를 로깅 + */ @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface ServiceLog { From af2d90a9a2e0f1c73d8b3b1922b85a83f04cfd56 Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Mon, 21 Apr 2025 00:44:03 +0900 Subject: [PATCH 09/15] :bug: fix : handle query param null situation in logging logic --- .../common/log/model/HttpRequestLogInfo.java | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/runimo/runimo/common/log/model/HttpRequestLogInfo.java b/src/main/java/org/runimo/runimo/common/log/model/HttpRequestLogInfo.java index 1b933ff1..ef8ebf40 100644 --- a/src/main/java/org/runimo/runimo/common/log/model/HttpRequestLogInfo.java +++ b/src/main/java/org/runimo/runimo/common/log/model/HttpRequestLogInfo.java @@ -1,6 +1,7 @@ package org.runimo.runimo.common.log.model; import jakarta.servlet.http.HttpServletRequest; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; @@ -16,13 +17,8 @@ public record HttpRequestLogInfo( public static HttpRequestLogInfo of(HttpServletRequest request) { String queryString = request.getQueryString(); - StringTokenizer st = new StringTokenizer(queryString, "&"); - Map queryParams = new HashMap<>(); - while (st.hasMoreTokens()) { - String[] keyVal = st.nextToken().split("="); - queryParams.put(keyVal[0], keyVal[1]); - // TODO : null 이면?? 1. query 변수 자체가 안붙어있음 2. 변수는 붙어있는 데 값이 없음 - } + + Map queryParams = getQueryParamMap(queryString); return HttpRequestLogInfo.builder() .requestMethod(request.getMethod()) @@ -31,4 +27,22 @@ public static HttpRequestLogInfo of(HttpServletRequest request) { .build(); } + private static Map getQueryParamMap(String queryString) { + if (queryString == null || queryString.isBlank()) { + return Collections.emptyMap(); + } + + Map queryParams = new HashMap<>(); + + String[] paramPairs = queryString.split("&"); + for (String paramPair : paramPairs) { + String[] keyVal = paramPair.split("=", 2); + + String val = keyVal.length < 2 ? "" : keyVal[1]; + queryParams.put(keyVal[0], val); + } + + return queryParams; + } + } From e9fd8c6b9efc65bfc45f341f498bf6d0a2664a34 Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Mon, 21 Apr 2025 01:43:49 +0900 Subject: [PATCH 10/15] :sparkles: update : add class name in method logging --- .../common/log/LogMessageFormatter.java | 4 +-- .../common/log/model/MethodEndLogInfo.java | 7 +++++ .../common/log/model/MethodStartLogInfo.java | 26 ++++++++++++++----- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java b/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java index 31ce392c..6fa0790d 100644 --- a/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java +++ b/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java @@ -38,7 +38,7 @@ public String toMethodStartLogMessage(MethodStartLogInfo logInfo) { new StringBuilder()).toString(); Map logs = new LinkedHashMap<>(); - logs.put("name", logInfo.methodName()); + logs.put("name", logInfo.className() + "." + logInfo.methodName()); logs.put("authenticated", String.valueOf(logInfo.authenticated())); logs.put("user_id", logInfo.userId()); logs.put("params", paramString); @@ -54,7 +54,7 @@ public String toMethodStartLogMessage(MethodStartLogInfo logInfo) { public String toMethodEndLogMessage(MethodEndLogInfo logInfo) { Map logs = new LinkedHashMap<>(); - logs.put("name", logInfo.methodName()); + logs.put("name", logInfo.className() + "." + logInfo.methodName()); logs.put("elapsed_time", logInfo.elapsedTimeMillis() + "ms"); logs.put("return", logInfo.returnData()); logs.put("time", getCurrentTime()); diff --git a/src/main/java/org/runimo/runimo/common/log/model/MethodEndLogInfo.java b/src/main/java/org/runimo/runimo/common/log/model/MethodEndLogInfo.java index abdc81c6..bfd0d8c6 100644 --- a/src/main/java/org/runimo/runimo/common/log/model/MethodEndLogInfo.java +++ b/src/main/java/org/runimo/runimo/common/log/model/MethodEndLogInfo.java @@ -6,6 +6,7 @@ @Builder(access = AccessLevel.PRIVATE) public record MethodEndLogInfo( + String className, String methodName, long elapsedTimeMillis, String returnData @@ -14,9 +15,15 @@ public record MethodEndLogInfo( public static MethodEndLogInfo of(JoinPoint joinPoint, long elapsedTimeMillis, Object returnData) { return MethodEndLogInfo.builder() + .className(getClassName(joinPoint)) .methodName(joinPoint.getSignature().getName()) .elapsedTimeMillis(elapsedTimeMillis) .returnData(returnData.toString()) .build(); } + + private static String getClassName(JoinPoint joinPoint) { + String classPath = joinPoint.getSignature().getDeclaringTypeName(); + return classPath.substring(classPath.lastIndexOf(".") + 1); + } } diff --git a/src/main/java/org/runimo/runimo/common/log/model/MethodStartLogInfo.java b/src/main/java/org/runimo/runimo/common/log/model/MethodStartLogInfo.java index e7c35459..e5a8ee6c 100644 --- a/src/main/java/org/runimo/runimo/common/log/model/MethodStartLogInfo.java +++ b/src/main/java/org/runimo/runimo/common/log/model/MethodStartLogInfo.java @@ -9,6 +9,7 @@ @Builder(access = AccessLevel.PRIVATE) public record MethodStartLogInfo( + String className, String methodName, boolean authenticated, String userId, @@ -16,6 +17,20 @@ public record MethodStartLogInfo( ) { public static MethodStartLogInfo of(JoinPoint joinPoint, boolean authenticated, String userId) { + String className = getClassName(joinPoint); + + Map params = getParamMap(joinPoint); + + return MethodStartLogInfo.builder() + .className(className) + .methodName(joinPoint.getSignature().getName()) + .authenticated(authenticated) + .userId(userId) + .params(params) + .build(); + } + + private static Map getParamMap(JoinPoint joinPoint) { MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); String[] parameterNames = methodSignature.getParameterNames(); Object[] parameterValues = joinPoint.getArgs(); @@ -24,12 +39,11 @@ public static MethodStartLogInfo of(JoinPoint joinPoint, boolean authenticated, for (int i = 0; i < parameterNames.length; i++) { params.put(parameterNames[i], parameterValues[i].toString()); } + return params; + } - return MethodStartLogInfo.builder() - .methodName(joinPoint.getSignature().getName()) - .authenticated(authenticated) - .userId(userId) - .params(params) - .build(); + private static String getClassName(JoinPoint joinPoint) { + String classPath = joinPoint.getSignature().getDeclaringTypeName(); + return classPath.substring(classPath.lastIndexOf(".") + 1); } } From 0efe2348457ed29d8196c1b6f5711b7b590c3686 Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Mon, 21 Apr 2025 01:47:51 +0900 Subject: [PATCH 11/15] :bug: fix : fix @ServiceLog target pointcut --- .../org/runimo/runimo/common/log/MethodLogAspect.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java b/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java index 190ed7f0..f634b07e 100644 --- a/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java +++ b/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java @@ -1,21 +1,16 @@ package org.runimo.runimo.common.log; -import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; -import org.runimo.runimo.common.log.model.HttpRequestLogInfo; import org.runimo.runimo.common.log.model.MethodEndLogInfo; import org.runimo.runimo.common.log.model.MethodStartLogInfo; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; @Aspect @Slf4j @@ -25,11 +20,11 @@ public class MethodLogAspect { private final LogMessageFormatter logMessageFormatter; - @Pointcut("execution(* (@org.runimo.runimo.common.log.ServiceLog *).*(..))") - private void service() { + @Pointcut("@within(org.runimo.runimo.common.log.ServiceLog) || @annotation(org.runimo.runimo.common.log.ServiceLog)") + private void annotatedClassAndMethod() { } - @Around("service()") + @Around("annotatedClassAndMethod()") public Object calledMethodLogger(ProceedingJoinPoint pjp) throws Throwable { MethodStartLogInfo methodStartLogInfo = getMethodStartLogInfo(pjp); log.info(logMessageFormatter.toMethodStartLogMessage(methodStartLogInfo)); From cd6b3afd89be637f8b7615c8191e2184eee90542 Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Mon, 21 Apr 2025 02:03:18 +0900 Subject: [PATCH 12/15] :bulb: log : add @ServiceLog in hatch api --- .../org/runimo/runimo/hatch/controller/HatchController.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/runimo/runimo/hatch/controller/HatchController.java b/src/main/java/org/runimo/runimo/hatch/controller/HatchController.java index 573c45e4..aa28db76 100644 --- a/src/main/java/org/runimo/runimo/hatch/controller/HatchController.java +++ b/src/main/java/org/runimo/runimo/hatch/controller/HatchController.java @@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import org.runimo.runimo.common.log.ServiceLog; import org.runimo.runimo.common.response.SuccessResponse; import org.runimo.runimo.hatch.service.dto.HatchEggResponse; import org.runimo.runimo.hatch.exception.HatchHttpResponseCode; @@ -23,6 +24,7 @@ public class HatchController { private final HatchUsecase hatchUsecase; + @ServiceLog @Operation(summary = "알 부화", description = "알을 부화합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "[HSH2011] 알 부화 성공"), From 35b55d0f1101362b01a08a3f8dc392bb81359243 Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Sat, 26 Apr 2025 02:34:47 +0900 Subject: [PATCH 13/15] :bug: fix : prevent NPE --- .../org/runimo/runimo/common/log/model/MethodEndLogInfo.java | 2 +- .../org/runimo/runimo/common/log/model/MethodStartLogInfo.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/runimo/runimo/common/log/model/MethodEndLogInfo.java b/src/main/java/org/runimo/runimo/common/log/model/MethodEndLogInfo.java index bfd0d8c6..bae58ce7 100644 --- a/src/main/java/org/runimo/runimo/common/log/model/MethodEndLogInfo.java +++ b/src/main/java/org/runimo/runimo/common/log/model/MethodEndLogInfo.java @@ -18,7 +18,7 @@ public static MethodEndLogInfo of(JoinPoint joinPoint, long elapsedTimeMillis, .className(getClassName(joinPoint)) .methodName(joinPoint.getSignature().getName()) .elapsedTimeMillis(elapsedTimeMillis) - .returnData(returnData.toString()) + .returnData(String.valueOf(returnData)) .build(); } diff --git a/src/main/java/org/runimo/runimo/common/log/model/MethodStartLogInfo.java b/src/main/java/org/runimo/runimo/common/log/model/MethodStartLogInfo.java index e5a8ee6c..4d24a1ab 100644 --- a/src/main/java/org/runimo/runimo/common/log/model/MethodStartLogInfo.java +++ b/src/main/java/org/runimo/runimo/common/log/model/MethodStartLogInfo.java @@ -37,7 +37,7 @@ private static Map getParamMap(JoinPoint joinPoint) { Map params = new HashMap<>(); for (int i = 0; i < parameterNames.length; i++) { - params.put(parameterNames[i], parameterValues[i].toString()); + params.put(parameterNames[i], String.valueOf(parameterValues[i])); } return params; } From d645292a4ad222060830100945f220bd52b87652 Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Sat, 26 Apr 2025 02:36:26 +0900 Subject: [PATCH 14/15] :bug: fix : catch Exception from proceeding joinPoint in MethodLogAspect --- .../runimo/runimo/common/log/LogMessageFormatter.java | 10 +++++++++- .../org/runimo/runimo/common/log/MethodLogAspect.java | 10 ++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java b/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java index 6fa0790d..c8ab24bb 100644 --- a/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java +++ b/src/main/java/org/runimo/runimo/common/log/LogMessageFormatter.java @@ -67,6 +67,14 @@ public String toMethodEndLogMessage(MethodEndLogInfo logInfo) { return sb.toString(); } + public String toMethodErrorLogMessage(Throwable ex) { + StringBuilder sb = new StringBuilder(); + sb.append("METHOD_EXCEPTION "); + sb.append(ex.getMessage()); + + return sb.toString(); + } + private StringBuilder convertMapToLogFormatString(Map infoMap, StringBuilder sb) { sb.append("["); @@ -88,7 +96,7 @@ private StringBuilder convertMapToLogFormatString(Map infoMap, } private String getCurrentTime() { - return ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")); + return ZonedDateTime.now().toString(); } private String convertCamelCaseToSnakeCase(String camelCase) { diff --git a/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java b/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java index f634b07e..912df7bd 100644 --- a/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java +++ b/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java @@ -30,8 +30,14 @@ public Object calledMethodLogger(ProceedingJoinPoint pjp) throws Throwable { log.info(logMessageFormatter.toMethodStartLogMessage(methodStartLogInfo)); long startTime = getCurrentTimeMillis(); - Object proceedReturn = pjp.proceed(); - long endTime = getCurrentTimeMillis(); + long endTime; + Object proceedReturn = null; + try { + proceedReturn = pjp.proceed(); + } catch (Throwable ex) { + log.info(logMessageFormatter.toMethodErrorLogMessage(ex)); + } + endTime = getCurrentTimeMillis(); MethodEndLogInfo methodEndLogInfo = MethodEndLogInfo.of(pjp, endTime - startTime, proceedReturn); From 2f01a02094a70d5d8e6ee41c9afc6464b4b1e083 Mon Sep 17 00:00:00 2001 From: jeeheaG Date: Sat, 26 Apr 2025 03:00:19 +0900 Subject: [PATCH 15/15] :bug: fix : change logging level typo --- src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java b/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java index 912df7bd..75da9bc8 100644 --- a/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java +++ b/src/main/java/org/runimo/runimo/common/log/MethodLogAspect.java @@ -35,7 +35,7 @@ public Object calledMethodLogger(ProceedingJoinPoint pjp) throws Throwable { try { proceedReturn = pjp.proceed(); } catch (Throwable ex) { - log.info(logMessageFormatter.toMethodErrorLogMessage(ex)); + log.error(logMessageFormatter.toMethodErrorLogMessage(ex)); } endTime = getCurrentTimeMillis();