Debug logging of RestTemplate/RestOperations on Spring Framework [Kotlin/Java]

This article shows debug logging of RestTemplate/RestOperations.

🐠 Set DEBUG to log level for RestTemplate

Set DEBUG to log level for RestTemplate with src/main/resources/application.yml.

org.springframework.web.client.RestTemplate: DEBUG

🎳 Add logging process to Request/Response

This is a sample code for adding logging process to Request/Response by ClientHttpRequestInterceptor.

Implement ClientHttpRequestInterceptor Interface

This is a sample code of implemented ClientHttpRequestInterceptor interface. Please create app/util/RestTemplateLoggingInterceptor.kt and add the following code.

import org.slf4j.LoggerFactory
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpRequest
import org.springframework.http.HttpStatus
import org.springframework.http.client.*
import org.springframework.lang.Nullable
import org.springframework.util.StreamUtils

class RestTemplateLoggingInterceptor : ClientHttpRequestInterceptor {
private val log = LoggerFactory.getLogger(

override fun intercept(request: HttpRequest, body: ByteArray, execution: ClientHttpRequestExecution): ClientHttpResponse {
// Show request object"RestTemplate Request: URI={}, Headers={}, Body={}",

// Fetch response
val response = BufferingClientHttpResponseWrapper(execution.execute(request, body))

// load response object
val inputStringBuilder = StringBuilder()
val bufferedReader = BufferedReader(InputStreamReader(response.body, "UTF-8"))
var line: String? = bufferedReader.readLine()
while (line != null) {
line = bufferedReader.readLine()

// Show response object"RestTemplate Response: StatusCode={} {}, Headers={}, Body={}",

return response

private class BufferingClientHttpResponseWrapper internal constructor(private val response: ClientHttpResponse) : ClientHttpResponse {
override fun getHeaders(): HttpHeaders {
return this.response.headers

override fun getStatusCode(): HttpStatus {
return this.response.statusCode

override fun getRawStatusCode(): Int {
return this.response.rawStatusCode

override fun close() {

override fun getStatusText(): String {
return this.response.statusText

override fun getBody(): InputStream {
if (this.body == null) {
this.body = StreamUtils.copyToByteArray(this.response.body)

return ByteArrayInputStream(this.body)

private var body: ByteArray? = null

Load the above Interceptor

Load the Interceptor created earlier.

import app.util.RestTemplateLoggingInterceptor
import org.springframework.context.annotation.Configuration
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.context.annotation.Bean
import org.springframework.web.client.RestOperations

class RestOperationsConfig {
fun restOperations(): RestOperations {
return RestTemplateBuilder().additionalInterceptors(RestTemplateLoggingInterceptor()).build()

Logging sample

After then you can see request/response information in your log.

level:INFO  RestTemplate Request: URI=, Headers={Accept=[text/plain, application/json, application/*+json, */*], Content-Length=[0]}, Body=
level:INFO RestTemplate Response: StatusCode=200 OK, Headers={Accept-Ranges=[bytes], Cache-Control=[max-age=604800], Content-Type=[text/html], Date=[Wed, 09 May 2018 08:23:02 GMT], Expires=[Wed, 16 May 2018 08:23:02 GMT], Last-Modified=[Fri, 09 Aug 2013 23:54:35 GMT], Body=\n\n\n

🍮 References

🖥 Recommended VPS Service

VULTR provides high performance cloud compute environment for you. Vultr has 15 data-centers strategically placed around the globe, you can use a VPS with 512 MB memory for just $ 2.5 / month ($ 0.004 / hour). In addition, Vultr is up to 4 times faster than the competition, so please check it => Check Benchmark Results!!