0

I am trying to pretty print my restTemplate request and response in pretty print JSON format in the log file using below:

public static RestTemplate createNewRestTemplateWithLogging() {
        ClientHttpRequestInterceptor interceptor = new RestLoggingInterceptor();
        List<ClientHttpRequestInterceptor> interceptorList = new ArrayList<ClientHttpRequestInterceptor>();
        RestTemplate restTemplate = new RestTemplate();
        interceptorList.add(interceptor);
        restTemplate.setInterceptors(interceptorList);
        restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
        return restTemplate;
        
    }

The log4j2.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <RollingFile name="rest_messages_file_appender" fileName="servers/AdminServer/logs/abc.log"
            filePattern="servers/AdminServer/logs/abc-%i.log.gz">
            <LevelRangeFilter maxLevel="INFO" />
            <PatternLayout>
                <Pattern>%d{DEFAULT} %-5p [%c{1}] [%X{hostName}] [%X{transactionId}]
                    [%X{uuid}|%X{username}|%X{caseNum}]:
                    %replace{%msg}{(\r|\n|\r\n)+}{}%n</Pattern>
            </PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="10MB" />
            </Policies>
            <DefaultRolloverStrategy max="30" />
        </RollingFile>
        <Console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout pattern="%m%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Logger
            name="com.accenture.apsp.architecture.rest.log.interceptor.RestLoggingInterceptor"
            level="INFO" additivity="false">
            <AppenderRef ref="rest_messages_file_appender" />
        </Logger>
        <Root level="INFO">
            <AppenderRef ref="rest_messages_file_appender" />
            <AppenderRef ref="STDOUT"/>
        </Root>
    </Loggers>
</Configuration> 

I used tag as well but still its not working.

It is displaying as below for any JSON:

Outbound Message----------------------------Direction: OUTAddress: http://apsp-opa:7017/opa/determinations-server/batch/auth?grant_type=client_credentials&client_id=rulescompuser&client_secret=Welcome@99Headers: [Accept:"application/json, application/*+json", Content-Type:"application/json", Content-Length:"2"]Total Time (ms): 14Request Time: 2021-06-23 06:56:05,613Request Payload: {}Response Time: 2021-06-23 06:56:05,627Response Payload: {"access_token":"f541be05-580e-123c-c43a-ca4e0ee567bc","token_type":"Bearer","expires_in":1800}----------------------------

Is there a way/pattern to print a formatted JSON for Response Payload in log4j2.xml .

/**
 * 
 * @param response
 * @param wsLoggingContext
 */
public void logResponse(ClientHttpResponse response, LoggingContext wsLoggingContext) {
    try {
        wsLoggingContext.setResponseTime(new Date());
        wsLoggingContext.setResponseJson(StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
    
    } catch (Exception e) {
        REST_LOGGER.info("Error occured while logging" + e);
    }
}

How can we pretty print the request and response payload.

Sanu
  • 1
  • 2

1 Answers1

0

If I understand the log4j documentation, this part of the pattern his wrong %replace{%msg}{(\r|\n|\r\n)+}{} Here you are replacing every line break with nothing.

Then you could:

  • leave the message (don't do replacement)
  • write %replace{%msg}{(\r|\n)+}{\r\n} If you have problem with line breaks.

Or maybe is your json that is not pretty formated at first.

If you are using it, spring have this property:

spring.jackson.serialization.indent_output = true

But if you don't, you can try to follow the advice from these posts:

Mohicane
  • 302
  • 2
  • 15
  • I had tried that, in this case also, the request payload is getting formatted, but the response payload from postForEntity() is still not printing correctly. – Sanu Jun 24 '21 at 08:26
  • {"cases":[{"@id":12345678,"isMultiMonth":true,"thecaserequiresanffmoutboundmessage":null,"programs":[{"@id":6545,"programType":"Medicaid","programCurrentBenefitMonth":"2021-06-08","programGetsNOA":true,"programNoaProcessingDate":"2021-06-24","programCaseId":1.00032277E9,"programsCurrentEdbcId":67895,"programsedbcs":[{"@id":123,"isTheCurrentEDBC":true,"programsedbcsbudgets":[{"@id":456,"programsedbcsbudgetspeople":[{"@id":789,"programsedbcsbudgetspersonsindividualaidcodeactions":[]}]} – Sanu Jun 24 '21 at 08:27
  • I found another solution. I've edited my anwer. – Mohicane Jun 24 '21 at 09:52
  • Its not working...Actually the JSON response coming from RestTemplate is directly getting printed in the logs and hence is not printing properly. Is there any way of formatting that ? – Sanu Jun 24 '21 at 10:46
  • I add some links to my answer – Mohicane Jun 24 '21 at 12:04
  • These links are for pretty printing in java code. For my scenario, the response getting from 3rd party from postForEntity() method, the Response Payload in RestLoggingInterceptor Outbound message is printing in blocks.....the reuqest json we are pretty printing and then sending to rest template, and that is why it is getting printed properly, but the response payload is not. – Sanu Jun 25 '21 at 07:03
  • Is there a way we can format that response payload – Sanu Jun 25 '21 at 07:03
  • Ok... I try to understand but maybe some code is missing. Are you responsible of the log (i.e. is your code doing something like LOG.log(Level.INFO, "message")) ? – Mohicane Jun 25 '21 at 07:19
  • No, In our code , nothing is happening. We have used RestLoggingInterceptor. We are just passing a jsonString as input to postForEntity. That is printed in correct format in the log file. But the response entity returned from restTemplate, the response payload is printed in block and in proper JSON format. – Sanu Jun 25 '21 at 09:31
  • Sorry but I find nothing. The only clues could give you is: Try to debug and find the location of the logger that printed the response outbound. Then you'll be able to check what is log and if the String is pretty printed (so you'll have to find the good configuration of the logger) or not (then it'll be difficult to pretty print the json string, but maybe not impossible threw log4j configuration and replace or by override some class and change the log) – Mohicane Jun 25 '21 at 12:03
  • The code to set response json for rest template in RestLoggingInterceptor class is below: public void logResponse(ClientHttpResponse response, LoggingContext wsLoggingContext) { try { wsLoggingContext.setResponseTime(new Date()); wsLoggingContext.setResponseJson(StreamUtils.copyToString(response.getBody(), Charset.defaultCharset())); } catch (Exception e) { REST_LOGGER.info("Error occured while logging" + e); } } this needs to be formatted – Sanu Jun 27 '21 at 15:06
  • Have you control response.getBody in order to know if it's allready not pretty printed? If the body is correctly formated, then the problem comes from log4j and you have to find the good configuration (maybe check files that configure the REST_LOGGER and find a way to ovverride it) – Mohicane Jun 29 '21 at 07:09