-
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.
- Loading branch information
Showing
49 changed files
with
1,074 additions
and
127 deletions.
There are no files selected for viewing
Submodule secrets
updated
from f362f7 to 870d47
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
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
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
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
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
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
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
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,26 @@ | ||
import type { Discussion } from '@/types'; | ||
import { develupAPIClient } from './clients/develupClient'; | ||
import { PATH } from './paths'; | ||
|
||
export const getDiscussions = async (mission = 'all', hashTag = 'all'): Promise<Discussion[]> => { | ||
const { data } = await develupAPIClient.get<{ data: Discussion[] }>(PATH.discussions, { | ||
mission, | ||
hashTag, | ||
}); | ||
|
||
return data; | ||
}; | ||
|
||
export const postDiscussionSubmit = async (payload: { | ||
title: string; | ||
content: string; | ||
missionId?: number; | ||
hashTagIds: number[]; | ||
}): Promise<Discussion> => { | ||
const { data } = await develupAPIClient.post<{ data: Discussion }>( | ||
PATH.submitDiscussion, | ||
payload, | ||
); | ||
|
||
return data; | ||
}; |
Oops, something went wrong.