-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* fix: 기본 설정을 가져와서 같은 로그가 중복으로 찍히는 오류 수정 * feat: 로그 포맷 변경 * feat: HTTP 요청 및 응답 로깅 구현 * fix: 로그 출력 작업 이후 MDC를 초기화하도록 수정 MDC는 스레드에 저장되는데, 스레드 풀링에 의해 스레드를 재사용할 때 이전 MDC가 남아있지 않도록 초기화하는 것 * feat: Trace-Id를 응답 헤더에 추가 * refactor: 필요 없는 static 키워드 삭제 * fix: 쿼리 스트링이 없을 경우 아예 출력하지 않도록 수정 * fix: Json 형태의 데이터는 이쁘게 출력하도록 변경 * fix: 오타 수정 * fix: 로그 포맷 수정 * chore: 로그가 여러 줄로 나뉘지 않도록 수정
- Loading branch information
Showing
2 changed files
with
158 additions
and
3 deletions.
There are no files selected for viewing
154 changes: 154 additions & 0 deletions
154
backend/src/main/java/develup/api/logging/LoggingFilter.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,154 @@ | ||
package develup.api.logging; | ||
|
||
import java.io.IOException; | ||
import java.util.Collections; | ||
import java.util.UUID; | ||
import java.util.stream.Collectors; | ||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.databind.ObjectWriter; | ||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.slf4j.MDC; | ||
import org.springframework.core.annotation.Order; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
import org.springframework.web.util.ContentCachingRequestWrapper; | ||
import org.springframework.web.util.ContentCachingResponseWrapper; | ||
|
||
@Component | ||
@Order(1) | ||
public class LoggingFilter extends OncePerRequestFilter { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(LoggingFilter.class); | ||
|
||
private final ObjectMapper objectMapper; | ||
|
||
public LoggingFilter(ObjectMapper objectMapper) { | ||
this.objectMapper = objectMapper; | ||
} | ||
|
||
@Override | ||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { | ||
saveTraceId(request); | ||
|
||
ContentCachingRequestWrapper cachedRequest = new ContentCachingRequestWrapper(request); | ||
ContentCachingResponseWrapper cachedResponse = new ContentCachingResponseWrapper(response); | ||
|
||
saveRequestBody(cachedRequest); | ||
|
||
filterChain.doFilter(cachedRequest, cachedResponse); | ||
|
||
saveRequestMethod(cachedRequest); | ||
saveRequestUri(cachedRequest); | ||
saveQueryString(cachedRequest); | ||
saveRequestHeader(cachedRequest); | ||
printRequestLog(); | ||
|
||
addTraceIdToResponse(cachedResponse); | ||
saveResponseBody(cachedResponse); | ||
cachedResponse.copyBodyToResponse(); | ||
saveResponseHeader(cachedResponse); | ||
printResponseLog(); | ||
MDC.clear(); | ||
} | ||
|
||
private void saveTraceId(HttpServletRequest request) { | ||
String header = request.getHeader("X-Request-ID"); | ||
if (header == null || header.isBlank()) { | ||
header = UUID.randomUUID().toString(); | ||
} | ||
MDC.put("traceId", header); | ||
} | ||
|
||
private void saveRequestBody(ContentCachingRequestWrapper cachedRequest) { | ||
String content = cachedRequest.getContentAsString(); | ||
String prettyJsonString = toPrettyJsonString(content); | ||
MDC.put("requestBody", prettyJsonString); | ||
} | ||
|
||
private String toPrettyJsonString(String jsonString) { | ||
try { | ||
Object json = objectMapper.readValue(jsonString, Object.class); | ||
ObjectWriter writer = objectMapper.writerWithDefaultPrettyPrinter(); | ||
return writer.writeValueAsString(json); | ||
} catch (JsonProcessingException e) { | ||
return jsonString; | ||
} | ||
} | ||
|
||
private void saveRequestMethod(ContentCachingRequestWrapper cachedRequest) { | ||
MDC.put("method", cachedRequest.getMethod()); | ||
} | ||
|
||
private void saveRequestUri(ContentCachingRequestWrapper cachedRequest) { | ||
MDC.put("requestUri", cachedRequest.getRequestURI()); | ||
} | ||
|
||
private void saveQueryString(ContentCachingRequestWrapper cachedRequest) { | ||
String queryString = "?" + cachedRequest.getQueryString(); | ||
if (queryString.equals("?null")) { | ||
queryString = ""; | ||
} | ||
MDC.put("queryString", queryString); | ||
} | ||
|
||
private void saveRequestHeader(HttpServletRequest request) { | ||
String headers = Collections.list(request.getHeaderNames()) | ||
.stream() | ||
.map(headerName -> headerName + " : " + request.getHeader(headerName)) | ||
.collect(Collectors.joining("\n")); | ||
MDC.put("requestHeaders", headers); | ||
} | ||
|
||
private void addTraceIdToResponse(HttpServletResponse response) { | ||
response.addHeader("Trace-Id", MDC.get("traceId")); | ||
} | ||
|
||
private void saveResponseBody(ContentCachingResponseWrapper cachedResponse) { | ||
String content = new String(cachedResponse.getContentAsByteArray()); | ||
MDC.put("responseBody", toPrettyJsonString(content)); | ||
} | ||
|
||
private void saveResponseHeader(ContentCachingResponseWrapper cachedResponse) { | ||
String responseHeader = cachedResponse.getHeaderNames() | ||
.stream() | ||
.map(headerName -> headerName + " : " + cachedResponse.getHeader(headerName)) | ||
.collect(Collectors.joining("\n")); | ||
MDC.put("responseHeader", responseHeader); | ||
} | ||
|
||
private void printRequestLog() { | ||
String template = """ | ||
Request | ||
{} {}{} | ||
Headers : | ||
{} | ||
Content : | ||
{} | ||
"""; | ||
log.info( | ||
template, | ||
MDC.get("method"), | ||
MDC.get("requestUri"), | ||
MDC.get("queryString"), | ||
MDC.get("requestHeaders"), | ||
MDC.get("requestBody") | ||
); | ||
} | ||
|
||
private void printResponseLog() { | ||
String responseLogTemplate = """ | ||
Response | ||
Headers : | ||
{} | ||
Content : | ||
{} | ||
"""; | ||
log.info(responseLogTemplate, MDC.get("responseHeader"), MDC.get("responseBody")); | ||
} | ||
} |
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