Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to log all the request-responses in spring rest?

The application should log the following information without impacting a client, asynchronously(in a separate thread).

  • Request HTTP Method and URI
  • Request Headers (Except the default)
  • Client's IP Address
  • Request Processing Time(In milliseconds)
  • Request Body
  • Response Body

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));
    }
}
like image 472
Nilesh Avatar asked Jan 17 '18 12:01

Nilesh


People also ask

How do you log HTTP request and response in spring boot?

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.

Which logging does Spring use?

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.

How do you handle multiple requests in Spring?

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.

What is Zalando logbook?

GitHub - zalando/logbook: An extensible Java library for HTTP request and response logging. Skip to content Toggle navigation. Product. Actions. Automate any workflow.


1 Answers

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() and afterRequest() 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 put

logging.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. :(

like image 159
Nilesh Avatar answered Sep 21 '22 05:09

Nilesh