Feign has out of box logging mechanism and it can be achieved through simple steps.

If you are using spring-cloud-starter-feign

Feign using Slf4jLogger for logging.Feign logging documentation

As per doc, the below logging levels are available to configure,

  • NONE - No logging (DEFAULT).
  • BASIC - Log only the request method and URL and the response status code and execution time.
  • HEADERS - Log the basic information along with request and response headers.
  • FULL - Log the headers, body, and metadata for both requests and responses.

Injecting the Logger.Level bean is enough.

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.BASIC;
    }

OR

If you prefer using configuration properties to configured all @FeignClient, you can create configuration properties with default feign name.

feign:
  client:
    config:
      default:
        loggerLevel: basic

of if you are using a newer version (Spring Boot 3) the config will be like:

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            loggerLevel: full

If you are using 'io.github.openfeign:feign-core'

If you are constructing the Feign builder then you can mention logLevel(Level.BASIC) as

Feign.builder()
    .logger(new Slf4jLogger())
    .logLevel(Level.BASIC)
    .target(SomeFeignClient.class, url);

We have the flexibility to customize the logging message

The default feign request and response logging

Request logging

Resopnse logging

we can customize the feign request, response logging pattern by overriding Logger#logRequest and Logger#logAndRebufferResponse methods. In the following example, we have customized request logging pattern

log(configKey, "---> %s %s HTTP/1.1 (%s-byte body) ", request.httpMethod().name(), request.url(), bodyLength);

and response logging pattern

log(configKey, "<--- %s %s HTTP/1.1 %s (%sms) ", request.httpMethod().name(), request.url(), status, elapsedTime);

The Full example is


import feign.Logger;
import feign.Request;
import feign.Response;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

import static feign.Logger.Level.HEADERS;

@Slf4j
public class CustomFeignRequestLogging extends Logger {

    @Override
    protected void logRequest(String configKey, Level logLevel, Request request) {

        if (logLevel.ordinal() >= HEADERS.ordinal()) {
            super.logRequest(configKey, logLevel, request);
        } else {
            int bodyLength = 0;
            if (request.requestBody().asBytes() != null) {
                bodyLength = request.requestBody().asBytes().length;
            }
            log(configKey, "---> %s %s HTTP/1.1 (%s-byte body) ", request.httpMethod().name(), request.url(), bodyLength);
        }
    }

    @Override
    protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response, long elapsedTime)
            throws IOException {
        if (logLevel.ordinal() >= HEADERS.ordinal()) {
            return super.logAndRebufferResponse(configKey, logLevel, response, elapsedTime);
        } else {
            int status = response.status();
            Request request = response.request();
            log(configKey, "<--- %s %s HTTP/1.1 %s (%sms) ", request.httpMethod().name(), request.url(), status, elapsedTime);
            return response;   
        }        
    }


    @Override
    protected void log(String configKey, String format, Object... args) {
        log.debug(format(configKey, format, args));
    }

    protected String format(String configKey, String format, Object... args) {
        return String.format(methodTag(configKey) + format, args);
    }
}

NOTE: Request payload can be easily logged through

String bodyText =
              request.charset() != null ? new String(request.body(), request.charset()) : null;

but be careful writing the response payload after you are reading the input stream Util.toByteArray(response.body().asInputStream()) then you have to construct the response again like response.toBuilder().body(bodyData).build(). Otherwise, you will end up with the expection. The reason is response streams are read and always closed before returning, thats why the method is named as logAndRebufferResponse

How to use the custom CustomFeignRequestLogging?

If you are building feign client using just 'io.github.openfeign:feign-core'

Feign.builder()
     .logger(new CustomFeignRequestLogging())
     .logLevel(feign.Logger.Level.BASIC);

If you are using 'org.springframework.cloud:spring-cloud-starter-openfeign'

@Configuration
public class FeignLoggingConfiguration {

    @Bean
    public CustomFeignRequestLogging customFeignRequestLogging() {
        return new CustomFeignRequestLogging();
    }

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.BASIC;
    }
}

Answer from Prasanth Rajendran on Stack Overflow
Top answer
1 of 6
83

Feign has out of box logging mechanism and it can be achieved through simple steps.

If you are using spring-cloud-starter-feign

Feign using Slf4jLogger for logging.Feign logging documentation

As per doc, the below logging levels are available to configure,

  • NONE - No logging (DEFAULT).
  • BASIC - Log only the request method and URL and the response status code and execution time.
  • HEADERS - Log the basic information along with request and response headers.
  • FULL - Log the headers, body, and metadata for both requests and responses.

Injecting the Logger.Level bean is enough.

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.BASIC;
    }

OR

If you prefer using configuration properties to configured all @FeignClient, you can create configuration properties with default feign name.

feign:
  client:
    config:
      default:
        loggerLevel: basic

of if you are using a newer version (Spring Boot 3) the config will be like:

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            loggerLevel: full

If you are using 'io.github.openfeign:feign-core'

If you are constructing the Feign builder then you can mention logLevel(Level.BASIC) as

Feign.builder()
    .logger(new Slf4jLogger())
    .logLevel(Level.BASIC)
    .target(SomeFeignClient.class, url);

We have the flexibility to customize the logging message

The default feign request and response logging

Request logging

Resopnse logging

we can customize the feign request, response logging pattern by overriding Logger#logRequest and Logger#logAndRebufferResponse methods. In the following example, we have customized request logging pattern

log(configKey, "---> %s %s HTTP/1.1 (%s-byte body) ", request.httpMethod().name(), request.url(), bodyLength);

and response logging pattern

log(configKey, "<--- %s %s HTTP/1.1 %s (%sms) ", request.httpMethod().name(), request.url(), status, elapsedTime);

The Full example is


import feign.Logger;
import feign.Request;
import feign.Response;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

import static feign.Logger.Level.HEADERS;

@Slf4j
public class CustomFeignRequestLogging extends Logger {

    @Override
    protected void logRequest(String configKey, Level logLevel, Request request) {

        if (logLevel.ordinal() >= HEADERS.ordinal()) {
            super.logRequest(configKey, logLevel, request);
        } else {
            int bodyLength = 0;
            if (request.requestBody().asBytes() != null) {
                bodyLength = request.requestBody().asBytes().length;
            }
            log(configKey, "---> %s %s HTTP/1.1 (%s-byte body) ", request.httpMethod().name(), request.url(), bodyLength);
        }
    }

    @Override
    protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response, long elapsedTime)
            throws IOException {
        if (logLevel.ordinal() >= HEADERS.ordinal()) {
            return super.logAndRebufferResponse(configKey, logLevel, response, elapsedTime);
        } else {
            int status = response.status();
            Request request = response.request();
            log(configKey, "<--- %s %s HTTP/1.1 %s (%sms) ", request.httpMethod().name(), request.url(), status, elapsedTime);
            return response;   
        }        
    }


    @Override
    protected void log(String configKey, String format, Object... args) {
        log.debug(format(configKey, format, args));
    }

    protected String format(String configKey, String format, Object... args) {
        return String.format(methodTag(configKey) + format, args);
    }
}

NOTE: Request payload can be easily logged through

String bodyText =
              request.charset() != null ? new String(request.body(), request.charset()) : null;

but be careful writing the response payload after you are reading the input stream Util.toByteArray(response.body().asInputStream()) then you have to construct the response again like response.toBuilder().body(bodyData).build(). Otherwise, you will end up with the expection. The reason is response streams are read and always closed before returning, thats why the method is named as logAndRebufferResponse

How to use the custom CustomFeignRequestLogging?

If you are building feign client using just 'io.github.openfeign:feign-core'

Feign.builder()
     .logger(new CustomFeignRequestLogging())
     .logLevel(feign.Logger.Level.BASIC);

If you are using 'org.springframework.cloud:spring-cloud-starter-openfeign'

@Configuration
public class FeignLoggingConfiguration {

    @Bean
    public CustomFeignRequestLogging customFeignRequestLogging() {
        return new CustomFeignRequestLogging();
    }

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.BASIC;
    }
}

2 of 6
13

The accepted answer did not work for me until I added the following settings to my application.yml file:

logging:
  level:
    com:
      mypackage1:
        mysubackage1:
          mysubpackage2: DEBUG
🌐
Baeldung
baeldung.com › home › spring › spring boot › feign logging configuration
Feign Logging Configuration | Baeldung
February 26, 2025 - In the first part of the log, we can see the request logged; The URL endpoint with his HTTP GET method. In this case, as it is a GET request, we don’t have a request body. The second part contains the response. It shows the headers and the body of the response. In this short tutorial, we have looked at the Feign client ...
Discussions

Tracing context is lost while logging request body
I have created a simple REST controller ... controller makes a call to an external service using a Reactive Feign client version 3.3.0. When invoking an external service, the trace is lost when logging the request body.... More on github.com
🌐 github.com
0
September 8, 2023
Log HTTP body, not headers
It could be useful to allow logging of HTTP body but not headers. In some cases, headers contains restricted / confidential information such as usernames, passwords, tokens, so you don't want t... More on github.com
🌐 github.com
2
December 19, 2022
Log details as one message
As I see in the code, Feign logs every detail separately on a new line: https://github.com/OpenFeign/feign/blob/master/core/src/main/java/feign/Logger.java#L46 More on github.com
🌐 github.com
5
January 11, 2019
Log request (and response) in single batch
Having a single log per request/response means having a single document for request, another for response. That would be much easier to follow. ... feign-12Issues that are related to the next major releaseIssues that are related to the next major releaseproposalProposed Specification or API ... More on github.com
🌐 github.com
4
August 8, 2019
🌐
Mayukh Datta
thecoducer.com › 2023 › 03 › custom-logger-configuration-for-feign-clients
Custom Logger Configuration for Feign Clients · Mayukh Datta
March 26, 2023 - */ } @Override protected Response logAndRebufferResponse( String configKey, Level logLevel, Response response, long elapsedTime) { int status = response.status(); Request request = response.request(); String responseString = ""; Response clonedResponse = response.toBuilder().build(); if (Objects.nonNull(response.body())) { try { byte[] bodyData = Util.toByteArray(response.body().asInputStream()); Response.Body responseBodyCopy = response.toBuilder().body(bodyData).build().body(); clonedResponse = response.toBuilder().body(responseBodyCopy).build(); responseString = StringUtil.toString(response
🌐
Apps Developer Blog
appsdeveloperblog.com › home › spring framework › spring cloud › feign client logging
Feign Client Logging - Apps Developer Blog
November 9, 2022 - The default logger level of Feign Client is NONE. So if you want to see something meaningful appear in your console, update the default logger level from NONE to one of these options: BASIC, Log only the request method and URL and the response status code and execution time. HEADERS, Log the basic information along with request and response headers. FULL, Log the headers, body, and metadata for requests and responses.
🌐
Spring Cloud
cloud.spring.io › spring-cloud-openfeign › 2.2.x › reference › html
Spring Cloud OpenFeign
The Logger.Level object that you may configure per client, tells Feign how much to log. Choices are: NONE, No logging (DEFAULT). BASIC, Log only the request method and URL and the response status code and execution time. HEADERS, Log the basic information along with request and response headers. FULL, Log the headers, body, and metadata for both requests and responses.
🌐
Medium
medium.com › @somarouthu.sivaprasads › spring-cloud-feign-858c225e2341
Spring Cloud Feign. Logging: | by SivaprasadS | Medium
March 15, 2019 - class CustomFeignLogger extends Slf4jLogger { @Override protected void logRequest(String configKey, Level logLevel, Request request) { FeignRequest feignRequest = new FeignRequest(); feignRequest.setMethod(request.method()); feignRequest.setUrl(request.url()); if (logLevel.ordinal() >= Level.HEADERS.ordinal()) { for (String field : request.headers().keySet()) { for (String value : valuesOrEmpty(request.headers(), field)) { feignRequest.addHeader(field, value); } } if (request.body() != null && logLevel.ordinal() >= Level.FULL.ordinal()) { feignRequest.setBody(request.charset() != null ?
🌐
Getdocs
spring.getdocs.org › en-US › spring-cloud-docs › spring-cloud-openfeign › spring-cloud-feign › feign-logging.html
Untitled :: Spring Docs
The Logger.Level object that you may configure per client, tells Feign how much to log. Choices are: NONE, No logging (DEFAULT). BASIC, Log only the request method and URL and the response status code and execution time. HEADERS, Log the basic information along with request and response headers. FULL, Log the headers, body, and metadata for both requests and responses.
🌐
Medium
bvn13.medium.com › normalized-logger-for-openfeign-8727b4e5d776
Normalized Logger for OpenFeign. Standard Feign logger provides the only… | by Vyacheslav Boyko | Medium
August 12, 2022 - ‘Normalized Logger’ is intended to combine all log entries related to one request-reply communication into one log entry. ... Request: a. request headers — every header is put into separated entry b. requst body — at separated entry · Response: a. response headers — separately b. response body — at separated entry as well · 2022-07-25 14:12:43.572 DEBUG 1032530 --- [Executor] feign.Logger : [AuthApi#login] ---> POST https://example.com/api/v1/login HTTP/1.1 2022-07-25 14:12:43.573 DEBUG 1032530 --- [Executor] feign.Logger : [AuthApi#login] Content-Length: 23 2022-07-25 14:12:43.5
Find elsewhere
🌐
Medium
medium.com › @reetesh043 › handling-logging-in-spring-boot-feignclient-a-complete-guide-0831676b8526
Handling Logging in Spring Boot FeignClient: A Complete Guide | by Reetesh Kumar | Medium
August 5, 2025 - This post shows you how to enable and customize FeignClient logging in Spring Boot, with working code snippets and configuration examples. Feign abstracts away HTTP calls. That’s great for cleaner code. But it also means you don’t see raw HTTP requests or responses unless you explicitly log them.
🌐
Mingliang
mingliang.me › blog › rest-client-logging-in-spring-boot
Rest client logging in spring boot - You Will Never Walk Alone
July 23, 2019 - Choices are: NONE, No logging (DEFAULT). BASIC, Log only the request method and URL and the response status code and execution time. HEADERS, Log the basic information along with request and response headers. FULL, Log the headers, body, and metadata for both requests and responses.
🌐
Javacodemonk
javacodemonk.com › feign-client-logging-and-connection-timeout-spring-boot-60b8826d
Feign Client Logging and connection timeout
July 14, 2020 - we will cover how to enable network ... by feign Clients in Spring Boot applications. Feign provides the following logging levels for debugging/troubleshooting purpose: ... No logging. This is the default behaviour. ... Log only the request method and URL and the response status code and execution time. ... Log the basic information along with request and response headers. ... Log the headers, body, and metadata ...
🌐
GitHub
github.com › PlaytikaOSS › feign-reactive › issues › 623
Tracing context is lost while logging request body · Issue #623 · PlaytikaOSS/feign-reactive
September 8, 2023 - I have created a simple REST controller ... controller makes a call to an external service using a Reactive Feign client version 3.3.0. When invoking an external service, the trace is lost when logging the request body....
Author: PlaytikaOSS
🌐
GitHub
github.com › OpenFeign › feign › issues › 1888
Log HTTP body, not headers · Issue #1888 · OpenFeign/feign
December 19, 2022 - In some cases, headers contains restricted / confidential information such as usernames, passwords, tokens, so you don't want to write them to logs. Whilst HTTP body could contribute useful information. Actually feign.Logger doesn't have a feign.Logger.Level allowing to configure logging of HTTP body but not headers.
Author: OpenFeign
🌐
Poznachowski
blog.poznachowski.pl › posts › feign-slf4j-logger
Feign Slf4j Logger you wish you had // It's SOAP's Fault...
August 17, 2021 - When it comes to Feign and logging its requests and responses, it provides Logger - an abstraction layer with dedicated set of log Levels:
🌐
Baeldung
baeldung.com › home › spring › spring cloud › handling feign get requests with a body
Handling Feign GET Requests With a Body | Baeldung
December 3, 2025 - By default, Feign and Spring MVC don’t allow a body in a GET request, and any attempt to send one is either ignored before the request is sent.
🌐
GitHub
github.com › OpenFeign › feign › issues › 874
Log details as one message · Issue #874 · OpenFeign/feign
January 11, 2019 - As I see in the code, Feign logs every detail separately on a new line: https://github.com/OpenFeign/feign/blob/master/core/src/main/java/feign/Logger.java#L46
Author: OpenFeign
🌐
Medium
medium.com › @AlexanderObregon › navigating-client-server-communication-with-springs-feignclient-annotation-70376157cefd
Navigating Client-Server Communication with Spring’s @FeignClient Annotation
March 30, 2026 - BASIC logs the request method, URL, response status, and timing. HEADERS adds request and response headers. FULL also logs body content and the rest of the request and response details.
🌐
GitHub
github.com › OpenFeign › feign › issues › 1035
Log request (and response) in single batch · Issue #1035 · OpenFeign/feign
August 8, 2019 - Feign's Logger is logging once per request / response line item. For example, JavaLogger will log the following request / response pair by invoking java.util.logging.Logger 7 times: [SendsStuff#login] ---> POST http://localhost:61113/ HTTP/1.1 ...
Author: OpenFeign
🌐
GitHub
github.com › OpenFeign › feign › issues › 598
How to log the server name which the request was sent to? · Issue #598 · OpenFeign/feign
November 3, 2017 - c.l.l.r.service.FooFeignClient ... {"name":"John"} c.l.l.r.service.FooFeignClient : [FooFeignClient#bar] ---> END HTTP (15-byte body) c.l.l.r.service.FooFeignClient : [FooFeignClient#ba...
Author: OpenFeign