Last active
February 8, 2021 08:01
-
-
Save yusufcakal/c593d8d92619559675ee90b38f932459 to your computer and use it in GitHub Desktop.
Helps you easy to tracing logs to request and response via Spring
This file contains hidden or 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
logging: | |
pattern: | |
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} %clr([%thread]){magenta} %yellow([%X{requestId}]) %highlight(%-5level) %cyan(%-40.40logger{40}) - %msg %n" |
This file contains hidden or 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
import com.dolap.settlement.model.request.CreateSettlementRequest; | |
import com.dolap.settlement.model.response.GetSettlementResponse; | |
import com.fasterxml.jackson.core.type.TypeReference; | |
import com.fasterxml.jackson.databind.ObjectMapper; | |
import org.apache.commons.lang3.tuple.ImmutablePair; | |
import org.apache.logging.log4j.util.Strings; | |
import org.slf4j.MDC; | |
import org.springframework.core.ParameterizedTypeReference; | |
import org.springframework.http.HttpMethod; | |
import org.springframework.stereotype.Component; | |
import org.springframework.web.filter.OncePerRequestFilter; | |
import org.springframework.web.util.ContentCachingRequestWrapper; | |
import org.springframework.web.util.ContentCachingResponseWrapper; | |
import javax.servlet.FilterChain; | |
import javax.servlet.ServletException; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import java.io.IOException; | |
import java.lang.reflect.Type; | |
import java.nio.charset.StandardCharsets; | |
import java.util.HashMap; | |
import java.util.Map; | |
import java.util.UUID; | |
@Component | |
public class LoggingFilter extends OncePerRequestFilter { | |
private static final Map<String, HttpMethod> EXCLUDED_LOGGING_ENDPOINT = new HashMap<>() {{ | |
put("/actuator/health", HttpMethod.GET); | |
}}; | |
private static final Map<String, Map.Entry<HttpMethod, Object>> MASKABLE_DATA_OF_REQUEST_ENDPOINTS = new HashMap<>() {{ | |
put("/settlement/create", new ImmutablePair<>(HttpMethod.POST, CreateSettlementRequest.class)); | |
}}; | |
private static final Map<String, Map.Entry<HttpMethod, Object>> MASKABLE_DATA_OF_RESPONSE_ENDPOINTS = new HashMap<>() {{ | |
put("/settlement/", new ImmutablePair<>(HttpMethod.GET, GetSettlementResponse.class)); | |
}}; | |
private final ObjectMapper objectMapper; | |
public LoggingFilter(ObjectMapper objectMapper) { | |
this.objectMapper = objectMapper; | |
} | |
@Override | |
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { | |
for (String uri : EXCLUDED_LOGGING_ENDPOINT.keySet()) { | |
if (uri.equals(request.getRequestURI()) && EXCLUDED_LOGGING_ENDPOINT.get(uri).toString().equals(request.getMethod())) { | |
return; | |
} | |
} | |
MDC.put("requestId", "Correlation ID: " + UUID.randomUUID().toString()); | |
String method = request.getMethod(); | |
String endpoint = request.getRequestURL().toString(); | |
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request); | |
ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response); | |
filterChain.doFilter(wrappedRequest, wrappedResponse); | |
String requestBody = getContentAsString(wrappedRequest.getContentAsByteArray()); | |
String responseBody = getContentAsString(wrappedResponse.getContentAsByteArray()); | |
for (String url : MASKABLE_DATA_OF_REQUEST_ENDPOINTS.keySet()) { | |
if (request.getRequestURI().equals(url) && request.getMethod().equals(MASKABLE_DATA_OF_REQUEST_ENDPOINTS.get(url).getKey().toString())) { | |
Object object = MASKABLE_DATA_OF_REQUEST_ENDPOINTS.get(url).getValue(); | |
Object o = objectMapper.readValue(requestBody, convertToTypeReference(ParameterizedTypeReference.forType((Type) object))); | |
logger.info("Request: " + method + " - " + endpoint + "\n" + o.toString()); | |
} else { | |
logger.info("Request: " + method + " - " + endpoint + "\n" + requestBody); | |
} | |
} | |
for (String url : MASKABLE_DATA_OF_RESPONSE_ENDPOINTS.keySet()) { | |
if (request.getRequestURI().equals(url) && request.getMethod().equals(MASKABLE_DATA_OF_RESPONSE_ENDPOINTS.get(url).getKey().toString())) { | |
Object object = MASKABLE_DATA_OF_RESPONSE_ENDPOINTS.get(url).getValue(); | |
Object o = objectMapper.readValue(responseBody, convertToTypeReference(ParameterizedTypeReference.forType((Type) object))); | |
logger.info("Response: " + "\n" + o.toString()); | |
} else { | |
logger.info("Response: " + "\n" + responseBody); | |
} | |
} | |
wrappedResponse.copyBodyToResponse(); | |
} | |
private String getContentAsString(byte[] bytes) { | |
return (bytes != null && bytes.length > 0) ? new String(bytes, 0, bytes.length, StandardCharsets.UTF_8) : Strings.EMPTY; | |
} | |
private <T> TypeReference<T> convertToTypeReference(ParameterizedTypeReference<T> parameterizedTypeReference) { | |
return new TypeReference<T>() { | |
public Type getType() { | |
return parameterizedTypeReference.getType(); | |
} | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment