-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[BBB-153] ✨Feat: 요청 및 응답 로그 데이터를 파일로 저장
user_id, request_body, response_body 등의 정보를 로그 파일로 저장
- Loading branch information
1 parent
d1734ec
commit 151598c
Showing
6 changed files
with
202 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ build/ | |
!**/src/main/**/build/ | ||
!**/src/test/**/build/ | ||
*.env | ||
/logs | ||
|
||
### IntelliJ IDEA ### | ||
.idea | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
...ternal-api/src/main/java/com/bombombom/devs/external/global/logging/ApiLoggingFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package com.bombombom.devs.external.global.logging; | ||
|
||
import com.bombombom.devs.external.global.logging.dto.ApiLogInfo; | ||
import com.bombombom.devs.security.AppUserDetails; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
import java.util.Optional; | ||
import java.util.UUID; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.slf4j.MDC; | ||
import org.springframework.core.Ordered; | ||
import org.springframework.core.annotation.Order; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
import org.springframework.web.util.ContentCachingRequestWrapper; | ||
import org.springframework.web.util.ContentCachingResponseWrapper; | ||
|
||
@Slf4j | ||
@Component | ||
@Order(Ordered.HIGHEST_PRECEDENCE) | ||
@RequiredArgsConstructor | ||
class ApiLoggingFilter extends OncePerRequestFilter { | ||
|
||
private final ObjectMapper objectMapper; | ||
|
||
@Override | ||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, | ||
FilterChain filterChain) throws IOException, ServletException { | ||
String requestId = Optional.ofNullable(request.getHeader("request_id")) | ||
.orElse(UUID.randomUUID().toString()); | ||
MDC.put("request_id", requestId); | ||
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request); | ||
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response); | ||
Long userId = getRequestUserId(); | ||
long start = System.currentTimeMillis(); | ||
try { | ||
filterChain.doFilter(requestWrapper, responseWrapper); | ||
long elapsedTime = System.currentTimeMillis() - start; | ||
ApiLogInfo apiLogInfo = ApiLogInfo.fromResult(requestWrapper, responseWrapper, userId, | ||
elapsedTime); | ||
log.info(objectMapper.writeValueAsString(apiLogInfo)); | ||
} catch (Throwable e) { | ||
ApiLogInfo apiLogInfo = ApiLogInfo.fromResult(requestWrapper, userId); | ||
log.info(objectMapper.writeValueAsString(apiLogInfo)); | ||
throw e; | ||
} finally { | ||
responseWrapper.copyBodyToResponse(); | ||
} | ||
MDC.clear(); | ||
} | ||
|
||
private Long getRequestUserId() { | ||
Long userId = null; | ||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | ||
if (authentication != null && authentication.isAuthenticated()) { | ||
Object principal = authentication.getPrincipal(); | ||
if (principal instanceof AppUserDetails) { | ||
userId = ((AppUserDetails) principal).getId(); | ||
} | ||
} | ||
return userId; | ||
} | ||
} |
92 changes: 92 additions & 0 deletions
92
...external-api/src/main/java/com/bombombom/devs/external/global/logging/dto/ApiLogInfo.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package com.bombombom.devs.external.global.logging.dto; | ||
|
||
import com.bombombom.devs.core.exception.ErrorCode; | ||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Collection; | ||
import java.util.Enumeration; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import lombok.Builder; | ||
import org.springframework.web.util.ContentCachingRequestWrapper; | ||
import org.springframework.web.util.ContentCachingResponseWrapper; | ||
|
||
@Builder | ||
public record ApiLogInfo( | ||
@JsonProperty(value = "http_method") String httpMethod, | ||
String uri, | ||
@JsonProperty(value = "user_id") Long userId, | ||
@JsonProperty(value = "request_header") Map<String, String> requestHeader, | ||
@JsonProperty(value = "response_header") Map<String, String> responseHeader, | ||
@JsonProperty(value = "request_body") String requestBody, | ||
@JsonProperty(value = "response_body") String responseBody, | ||
@JsonProperty(value = "client_ip") String clientIp, | ||
@JsonProperty(value = "elapsed_time") long elapsedTime | ||
) { | ||
|
||
public static ApiLogInfo fromResult(ContentCachingRequestWrapper request, | ||
ContentCachingResponseWrapper response, Long userId, long elapsedTime) throws IOException { | ||
String requestBody = new String(request.getContentAsByteArray(), StandardCharsets.UTF_8); | ||
String responseBody = new String(response.getContentAsByteArray(), | ||
StandardCharsets.UTF_8); | ||
return ApiLogInfo.builder() | ||
.httpMethod(request.getMethod()) | ||
.uri(request.getRequestURI()) | ||
.userId(userId) | ||
.requestHeader(getRequestHeader(request)) | ||
.responseHeader(getResponseHeader(response)) | ||
.requestBody(requestBody) | ||
.responseBody(responseBody) | ||
.clientIp(getClientIp(request)) | ||
.elapsedTime(elapsedTime) | ||
.build(); | ||
} | ||
|
||
public static ApiLogInfo fromResult(ContentCachingRequestWrapper request, Long userId) | ||
throws IOException { | ||
String requestBody = new String(request.getContentAsByteArray(), StandardCharsets.UTF_8); | ||
return ApiLogInfo.builder() | ||
.httpMethod(request.getMethod()) | ||
.uri(request.getRequestURI()) | ||
.userId(userId) | ||
.requestHeader(getRequestHeader(request)) | ||
.requestBody(requestBody) | ||
.responseBody(String.valueOf(ErrorCode.UNEXPECTED_EXCEPTION)) | ||
.clientIp(getClientIp(request)) | ||
.build(); | ||
} | ||
|
||
private static Map<String, String> getRequestHeader(HttpServletRequest request) { | ||
Map<String, String> requestHeaders = new HashMap<>(); | ||
Enumeration<String> headerNames = request.getHeaderNames(); | ||
while (headerNames.hasMoreElements()) { | ||
String headerName = headerNames.nextElement(); | ||
requestHeaders.put(headerName, request.getHeader(headerName)); | ||
} | ||
return requestHeaders; | ||
} | ||
|
||
private static Map<String, String> getResponseHeader(HttpServletResponse response) { | ||
Map<String, String> responseHeaders = new HashMap<>(); | ||
Collection<String> headerNames = response.getHeaderNames(); | ||
for (String headerName : headerNames) { | ||
responseHeaders.put(headerName, response.getHeader(headerName)); | ||
} | ||
return responseHeaders; | ||
} | ||
|
||
private static String getClientIp(HttpServletRequest request) { | ||
String clientIp; | ||
String xForwardedForHeader = request.getHeader("X-Forwarded-For"); | ||
if (xForwardedForHeader != null && !xForwardedForHeader.isEmpty()) { | ||
clientIp = xForwardedForHeader.split(",")[0]; | ||
} else { | ||
clientIp = request.getRemoteAddr(); | ||
} | ||
return clientIp; | ||
} | ||
|
||
} |
27 changes: 0 additions & 27 deletions
27
...api/src/main/java/com/bombombom/devs/external/global/logging/filter/MDCLoggingFilter.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters