Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop'
Browse files Browse the repository at this point in the history
# Conflicts:
#	build.gradle
  • Loading branch information
ChoiWonYu committed Oct 29, 2024
2 parents 467f952 + b2738a1 commit 2ed55af
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 80 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'

// json
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.1'

// sentry
implementation 'io.sentry:sentry-spring-boot-starter-jakarta:7.9.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(final String id) throws UsernameNotFoundException {
Member foundMember = memberService.findById(UUID.fromString(id));
return new CustomUserDetails(foundMember.getId(), foundMember.getRole());
return new CustomUserDetails(foundMember.getId(), foundMember.getRole(),
foundMember.getNickName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

public record CustomUserDetails(UUID id, Role role) implements UserDetails {
public record CustomUserDetails(UUID id, Role role, String nickName) implements UserDetails {

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.singletonList(new SimpleGrantedAuthority(role.name()));
}

public String getNickName() {
return nickName;
}

@Override
public String getPassword() {
return null;
Expand Down
186 changes: 109 additions & 77 deletions src/main/java/com/first/flash/global/aspect/LoggingAspect.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package com.first.flash.global.aspect;

import com.first.flash.global.util.AuthUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.first.flash.account.auth.application.dto.CustomUserDetails;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Objects;
import java.util.HashMap;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
Expand All @@ -23,92 +25,122 @@
@RequiredArgsConstructor
public class LoggingAspect {

@Before("com.first.flash.global.aspect.PointCuts.allController()")
public void doBeforeController() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();

log.info("======= Controller Start =======");
log.info("Request URI: {}", request.getRequestURI());
log.info("HTTP Method: {}", request.getMethod());
private final ObjectMapper objectMapper = new ObjectMapper();
private final ThreadLocal<Map<String, Object>> logContext = ThreadLocal.withInitial(
HashMap::new);

Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
log.info("Header: {} = {}", headerName, request.getHeader(headerName));
}
@PostConstruct
public void setUp() {
objectMapper.registerModule(new JavaTimeModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // ISO-8601 형식으로 출력
}

Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {
String parameterName = parameterNames.nextElement();
log.info("Parameter: {} = {}", parameterName, request.getParameter(parameterName));
}
@AfterReturning(pointcut = "execution(* com.first.flash.account.auth.application.CustomUserDetailsService.loadUserByUsername(..))", returning = "userDetails")
public void logUserDetails(final CustomUserDetails userDetails) {
Map<String, Object> logData = logContext.get();
logData.put("requester", userDetails.getNickName());
logContext.set(logData);
}

@Before("com.first.flash.global.aspect.PointCuts.verifiedControllers()")
public void doBeforeVerifiedController() {
log.info("user id: {}", AuthUtil.getId());
@Before("com.first.flash.global.aspect.PointCuts.allController()")
public void logRequestInfo(final JoinPoint joinPoint) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();

Map<String, Object> logData = logContext.get();
logData.put("request URI", request.getRequestURI());
logData.put("HTTP method", request.getMethod());
logContext.set(logData);
}

@AfterReturning(value = "com.first.flash.global.aspect.PointCuts.allController()", returning = "result")
public void afterReturnController(final Object result) {
if (result instanceof ResponseEntity<?> responseEntity) {
int statusCode = responseEntity.getStatusCode().value();
Object responseBody = responseEntity.getBody();
// @Before("com.first.flash.global.aspect.PointCuts.allService() || com.first.flash.global.aspect.PointCuts.allRepository()")
// public void logMethodDetails(final JoinPoint joinPoint) {
// if (log.isDebugEnabled()) {
// String key = generateLogKey(joinPoint);
//
// Map<String, Object> methodDetails = new HashMap<>();
// Object[] args = joinPoint.getArgs();
// if (args.length > 0) {
// methodDetails.put("params", args);
// } else {
// methodDetails.put("params", "no params");
// }
//
// updateLogContext(key, methodDetails);
// }
// }
//
// @AfterReturning(pointcut = "com.first.flash.global.aspect.PointCuts.allService() || com.first.flash.global.aspect.PointCuts.allRepository()", returning = "result")
// public void logMethodReturn(final JoinPoint joinPoint, final Object result) {
// if (log.isDebugEnabled()) {
// String key = generateLogKey(joinPoint);
//
// Map<String, Object> methodDetails = new HashMap<>();
// methodDetails.put("returnValue", result);
//
// updateLogContext(key, methodDetails);
// }
// }

@AfterReturning(pointcut = "com.first.flash.global.aspect.PointCuts.allController()", returning = "result")
public void logResponse(final Object result) {
Map<String, Object> logData = logContext.get();
logData.put("type", "log");

log.info("Response Status Code: {}", statusCode);
if (!Objects.isNull(responseBody)) {
log.info("Response Body: {}", responseBody);
} else {
log.info("no Response Body");
}
if (result instanceof ResponseEntity<?> responseEntity) {
logData.put("response status", responseEntity.getStatusCode().value());
logData.put("response body", responseEntity.getBody());
} else {
if (!Objects.isNull(result)) {
log.info("Response: {}", result);
} else {
log.info("no Response");
}
logData.put("response", result);
}
log.info("======= Controller End =======");
}

@Before("com.first.flash.global.aspect.PointCuts.allService() || com.first.flash.global.aspect.PointCuts.allRepository()")
public void doBefore(final JoinPoint joinPoint) {
Method method = getMethod(joinPoint);
String objectName = joinPoint.getTarget()
.getClass()
.getSimpleName();
log.info("======= {} Start =======", objectName);
log.info("method name = {}", method.getName());
Object[] args = joinPoint.getArgs();
if (Objects.isNull(args) || args.length == 0) {
log.info("no parameter");
return;
}
for (Object arg : args) {
if (Objects.isNull(arg)) {
continue;
}
log.info("parameter type = {}", arg.getClass().getSimpleName());
log.info("parameter value = {}", arg);
try {
log.info(objectMapper.writeValueAsString(logData));
} catch (Exception e) {
log.error("Error converting log to JSON", e);
} finally {
logContext.remove();
}
}

@AfterReturning(value = "com.first.flash.global.aspect.PointCuts.allService() || com.first.flash.global.aspect.PointCuts.allRepository()", returning = "result")
public void afterReturnLog(final JoinPoint joinPoint, final Object result) {
if (Objects.isNull(result)) {
return;
@AfterReturning(pointcut = "com.first.flash.global.aspect.PointCuts.allExceptionHandler()", returning = "exception")
public void logException(final Object exception) {
Map<String, Object> logData = logContext.get();
logData.put("type", "error");

if (exception instanceof ResponseEntity<?> exceptionResponse) {
logData.put("error status", exceptionResponse.getStatusCode().value());
logData.put("error body", exceptionResponse.getBody());
} else {
logData.put("error", exception);
}
log.info("return type = {}", result.getClass().getSimpleName());
log.info("return value = {}", result);
String objectName = joinPoint.getTarget()
.getClass()
.getSimpleName();
log.info("======= {} End =======", objectName);
}

private Method getMethod(final JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
return signature.getMethod();
try {
log.info(objectMapper.writeValueAsString(logData));
} catch (Exception e) {
log.error("Error converting log to JSON", e);
} finally {
logContext.remove();
}
}

// private String generateLogKey(final JoinPoint joinPoint) {
// MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// String className = joinPoint.getTarget().getClass().getSimpleName();
// String methodName = signature.getMethod().getName();
// return className + "." + methodName;
// }
//
// private void updateLogContext(final String key, final Map<String, Object> methodDetails) {
// Map<String, Object> logData = logContext.get();
//
// if (logData.containsKey(key)) {
// Map<String, Object> existingDetails = (Map<String, Object>) logData.get(key);
// existingDetails.putAll(methodDetails);
// logData.put(key, existingDetails);
// } else {
// logData.put(key, methodDetails);
// }
//
// logContext.set(logData);
// }
}
5 changes: 4 additions & 1 deletion src/main/java/com/first/flash/global/aspect/PointCuts.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ public void allService() {
public void allRepository() {
}

@Pointcut("execution(* com.first.flash..*ExceptionHandler.*(..))")
public void allExceptionHandler() {
}

@Pointcut("execution(* com.first.flash.climbing..*Controller.*(..))")
public void verifiedControllers() {

}
}

0 comments on commit 2ed55af

Please sign in to comment.