Search code examples
spring-cloudhystrixnetflix-feignfeign

How to log the reason that hystrix fallback method invoked


I am creating a REST client using Fiegn. I have got my calls working, but I want to log the exception whitch tigger the fallback method invoked.
Code like this:

public interface FooService {
    Foo queryFoo(Integer fooId);
}

public interface FooServiceFallback implements FooService {
    @Override
    Foo queryFoo(Integer fooId) {
        return new Foo();
    }
}

@Configuration
public class FooServiceConfiguration {
    @Bean
    public FooService() {
        return HystrixFeign.builder().[...].target(FooService.class, "http://xxx", FooServiceFallback.class);
    }
}

The fallback method can be invoked when exception occurs, but noting is logged.

How to log the exception which trigger the fallback method invoked?
Like connectionTimeoutException.


Solution

  • Fallback method can take an extra argument of type Throwable, which will indicate the cause.

    For example if your method is like this

    @HystrixCommand(fallbackMethod = "fallbackMethod")
    public String mainMethod(String s) {
     .....
    }
    

    Your fallback method can be like this

    public String fallbackMethod(String s) {
         ......
    }
    

    or

    public String fallbackMethod(String s, Throwable throwable) {
         //log the cause using throwable instance
         ......
    }
    

    In your case use the second one.

    EDIT:

    If you are using HystrixFeign, this is how you do it. You should make use of FallbackFactory

    @Component
    public class FooServiceFallbackFactory implements FallbackFactory<FooService> {
    
        @Override
        public FooService create(Throwable throwable) {
            return new FooServiceFallback(throwable);
        }
    
    }
    

    Your fallback class would look like

    @Component
    public class FooServiceFallback implements FooService {
    
       private final Throwable cause;
    
       public FooServiceFallback(Throwable cause) {
          this.cause = cause;
       }
    
       @Override
       Foo queryFoo(Integer fooId) {
           //You have access to cause now, which will have the real exception thrown
       }
    
    }
    

    Also you need to change a bit of your configuration class

    @Configuration
    public class FooServiceConfiguration {
        @Bean
        public FooService() {
            return HystrixFeign.builder().[...].target(FooService.class, "http://xxx", FooServiceFallbackFactory.class);
        }
    }