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.
🌐
Mayukh Datta
thecoducer.com › 2023 › 03 › custom-logger-configuration-for-feign-clients
Custom Logger Configuration for Feign Clients · Mayukh Datta
March 26, 2023 - @Slf4j @Configuration public class ... blank to prevent it * from logging the request. We will log both the request and the response * in the logAndRebufferResponse method....
🌐
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.
🌐
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.
🌐
Medium
medium.com › @somarouthu.sivaprasads › spring-cloud-feign-858c225e2341
Spring Cloud Feign. Logging: | by SivaprasadS | Medium
March 15, 2019 - logging.level.com.ssp.microservices.springcloudfeign.feignClients.DummyRestApiClient = DEBUG · Custom Request and Response Logging: 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 ?
🌐
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 - 2022-07-25 14:16:06.217 INFO 1057053 --- [Executor] me.bvn13.openfeign.logger.NormalizedFeignLogger : normalized feign request {AuthApi#login(LoginRequestDto)=[AuthApi#login] }: [ ---> POST https://example.com/api/v1/login HTTP/1.1 Content-Length: 23 Content-Type: application/json user-agent: bvn13 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4464.5 Safari/537.36 {"phone":"123456789"} ---> END HTTP (21-byte body) ] has response [ <--- UNKNOWN 200 (411ms) cache-control: no-cache cf-cache-status: DYNAMIC cf-ray: 73047b41ffd2fa4c-AMS content-type: applicati
🌐
Mingliang
mingliang.me › blog › rest-client-logging-in-spring-boot
Rest client logging in spring boot - You Will Never Walk Alone
July 23, 2019 - logging.level.project.user.UserClient: DEBUG 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.
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 - 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.
🌐
Javacodemonk
javacodemonk.com › feign-client-logging-and-connection-timeout-spring-boot-60b8826d
Feign Client Logging and connection timeout
July 14, 2020 - 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.
🌐
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:
🌐
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/ HT...
Author: OpenFeign
🌐
O'Reilly
oreilly.com › library › view › mastering-spring-boot › 9781787127562 › 43853f02-3bf6-4c2f-8661-e94899a05cdd.xhtml
Feign logging - Mastering Spring Boot 2.0 [Book]
May 31, 2018 - A logger is created for each Feign client. The log level can be changed by setting the logging.level.project.user.UserClient property in the configuration property. Let's see the following application.yml configuration file: ... BASIC: This level of log responds to the request method and URL and the response status code and execution time
Author: Dinesh Rajput
Published: 2018
Pages: 390
🌐
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 - FULL also logs body content and the rest of the request and response details. You can set the Feign log level in a configuration class and then apply that configuration to a specific client:
🌐
GitHub
github.com › OpenFeign › feign › issues › 874
Log details as one message · Issue #874 · OpenFeign/feign
January 11, 2019 - tl;dr: Call log() only once for each request and response? I'm using feign.client.config.default.loggerLevel: full to log payload of an application deployed to Cloud Foundry in a dev/test environment. In Cloud Foundry, every line of log to stdout is treated as an independent log-event and sent to a log-drain.
Author: OpenFeign
🌐
OneUptime
oneuptime.com › home › blog › how to implement custom feign interceptors
How to Implement Custom Feign Interceptors
January 30, 2026 - For complete logging including responses, configure Feign's built-in logger.
🌐
GitHub
github.com › OpenFeign › feign › blob › master › core › src › main › java › feign › Logger.java
feign/core/src/main/java/feign/Logger.java at master · OpenFeign/feign
* Override to log requests and responses using your own implementation. Messages will be http · * request and response text. * * @param configKey value of {@link Feign#configKey(Class, java.lang.reflect.Method)} * @param format {@link java.util.Formatter format string} * @param args arguments applied to {@code format} */ protected abstract void log(String configKey, String format, Object...
🌐
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.
🌐
Wick
blog.wick.technology › sensible-feign
Sensible feign client configuration | Wick Technology Blog
This requires you to do two things: set the loggerLevel for your feign config in your application.yml and set the logging level of the feign client class to DEBUG. logger.level: root: INFO com.example.clients.InvoiceClient: DEBUG feign: client: config: default: loggerLevel: basic · You can set loggerLevel to full if you want to see headers and response bodies in the logs too...
🌐
GitHub
github.com › asventetsky › logging-feign
GitHub - asventetsky/logging-feign: Configurable logging for Feign (Java HTTP client)
Implementation of feign.Logger with one-log-message request/response. Request and response messages would be look like this:
Author: asventetsky