The application should log the following information without impacting a client, asynchronously(in a separate thread).
If we consume inputstream
in the filter, then it cant be consumed again by spring for json to object mapping. Somewhere during the input stream to object mapping, can we plug our logger?
Update:
We can write over logging code in a MessageConverter, but it doesnt seems to be a good idea.
public class MyMappingJackson2MessageConverter extends AbstractHttpMessageConverter<Object> {
...
protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
InputStream inputStream = inputMessage.getBody();
String requestBody = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
String method = request.getMethod();
String uri = request.getRequestURI();
LOGGER.debug("{} {}", method, uri);
LOGGER.debug("{}", requestBody);
return objectMapper.readValue(requestBody, clazz);
}
protected void writeInternal(Object o, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
String responseBody = objectMapper.writeValueAsString(o);
LOGGER.debug("{}", responseBody);
outputMessage.getBody().write(responseBody.getBytes(StandardCharsets.UTF_8));
}
}
Custom Request Logging Among the Spring request interceptors, one of the noteworthy interfaces is HandlerInterceptor, which we can use to log the incoming request by implementing the following methods: preHandle() – we execute this method before the actual controller service method.
Spring Boot uses Apache Commons Logging for internal logging but allows developers to configure the underlying log implementation. Various logging providers are supported through simple configuration. Spring Boot provides default configurations for Java Util Logging, Log4J2 and Logback.
If two simultaneous requests access a singleton bean, then the bean must be stateless (or at least synchronized to avoid problems). One way you can handle multiple requests is to have multiple physical servers. Each request can be given to a server that is free and it can serve it.
GitHub - zalando/logbook: An extensible Java library for HTTP request and response logging. Skip to content Toggle navigation. Product. Actions. Automate any workflow.
An answer from baeldung.com :
Spring provides a built-in solution to log payloads. We can use ready-made filters by plugging into Spring application using configuration. AbstractRequestLoggingFilter is a filter which provides basic functions of logging. Subclasses should override the
beforeRequest()
andafterRequest()
methods to perform the actual logging around the request. Spring framework provides following concrete implementation classes which can be used to log the incoming request. These are:
- CommonsRequestLoggingFilter
- ServletContextRequestLoggingFilter
Spring Boot application can be configured by adding a bean definition to enable request logging:
@Configuration public class RequestLoggingFilterConfig { @Bean public CommonsRequestLoggingFilter logFilter() { CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter(); filter.setIncludeQueryString(true); filter.setIncludePayload(true); filter.setMaxPayloadLength(10000); filter.setIncludeHeaders(false); filter.setAfterMessagePrefix("REQUEST DATA : "); return filter; } }
Also, this logging filter requires the log level be set to DEBUG. In
application.properties
putlogging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG
To make the logging asynchronous, we may use asynchronous appenders. Unfortunately it does not support logging response payloads. :(
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With