Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document issues when using Spring FactoryBean and Spring Cloud OpenFeign Clients #1009

Closed
raul-avila-ph opened this issue Mar 27, 2024 · 8 comments
Assignees
Milestone

Comments

@raul-avila-ph
Copy link

Bug description

We found a problem where Micrometer tracing propagation stops working when a Feign client is injected to a Spring FactoryBean.

Steps to reproduce:

  1. Have Micrometer tracing enabled
  2. Configure a Feign client
  3. Create a service class that contains the Feign client as dependency
  4. Instantiate the service class through a Spring FactoryBean, not using stereotype annotations or bean declaration. This FactoryBean will need to have a reference to the Feign client, because it will be necessary to instantiate the service class created in step 3

We would expect Micrometer traces to continue working. With the setup explained above it stopped working.

Sample

We have created a small sample project reproducing the issue, it can be found here: https://github.com/raul-avila-ph/tracing-issue/

The project contains a single test that passes only when tracing is working properly. The code in master has the test failing, while you can see there is a branch called without-factory-bean that basically removes the FactoryBean and instantiates the service with @Service. The test in this branch works, so tracing is not broken under these conditions.

Please note that this problem occurs when Feign client is a transitive dependency of the Spring FactoryBean as well, we have just injected it directly in the sample code for simplicity.

@OlgaMaciaszek
Copy link
Collaborator

@jonatan-ivanov, could you take a look at this issue?

@jonatan-ivanov
Copy link
Member

jonatan-ivanov commented Jun 26, 2024

Thank you for the issue and extra thanks for providing a reproducer!
I looked into it and I think the issue is not related to Spring Cloud OpenFeign. When the app uses the FactoryBean, you can see lots of WARN events in the logs. One of them is saying something like this:

'observationRegistry' is not eligible for getting processed by all BeanPostProcessors

Exact event:

2024-06-26T12:45:18.772-07:00  WARN 86139 --- [demo] [           main] [                                                 ] trationDelegate$BeanPostProcessorChecker : Bean 'observationRegistry' of type [io.micrometer.observation.SimpleObservationRegistry] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [meterRegistryPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.

This is a problem since in Boot's auto-config ObservationRegistryPostProcessor is needed since it registers the handlers/filter/predicates/etc. to the registry using ObservationRegistryConfigurer.
In your case, since this is not happening, no ObservationHandler will be registered so nothing happens when an Observation is created (no metrics, no tracing, no context-propagation). You can check this with a debugger: either inject and ObservationRegistry to one of your components or put a breakpoint into MicrometerObservationCapability (OpenFeign's observability support), the registry has a config field which should have a list of handlers but that list is empty due to the post processor were not executed and register them. This issue might belong to Boot's or Framework's issue tracker.

I guess one workaround could be creating and configuring the registry on your own the same way Boot does (see ObservationAutoConfiguration) but without a post processor.

@OlgaMaciaszek
Copy link
Collaborator

Thanks @jonatan-ivanov. There was actually a bug in Spring Cloud Commons that caused bean postprocessing issues. @raul-avila-ph Please upgrade to Spring Cloud Commons 2023.0.2 and see if the issue has been resolved. If not, please follow the steps outlined by @jonatan-ivanov above.

@raul-avila-ph
Copy link
Author

Thanks for taking a look.

We tried upgrading Spring Cloud Commons to version 2023.0.2, but the problem persists.

We then tried the solution proposed by @jonatan-ivanov. This can be found in a separate branch in our project (https://github.com/raul-avila-ph/tracing-issue/tree/fix-observation-registry). This solves the problem, however we're not entirely happy with the workaround, because we can't replicate what the autoconfiguration does entirely, as the class ObservationHandlerGrouping is package private (see comment: https://github.com/raul-avila-ph/tracing-issue/blob/fe41dcfb19c2162d7ebd7488fb29ced3d2504a45/src/main/java/com/example/tracingissue/ObservationConfiguration.java#L34). We could create our own config class in a package org.springframework.boot.actuate.autoconfigure.observation as a workaround, but we don't really like to do this.

@OlgaMaciaszek
Copy link
Collaborator

@jonatan-ivanov could you please take a look?

@jonatan-ivanov
Copy link
Member

I guess the other thing you can do is copying that class (still not optimal) or asking the Boot team to make it public (still a hack/workaround).
I think the proper solution would be fixing what breaks the bean post processors but I don't think that issue lies in OpenFeign, probably somewhere else in Spring Cloud or Spring Framework?

@raul-avila-ph
Copy link
Author

Thanks for your response. Should I create the issue somewhere else? It'd be great to have this problem solved at some point, but I don't want to create unnecessary noise in other Spring projects.

@OlgaMaciaszek
Copy link
Collaborator

Thanks a lot @raul-avila-ph, @jonatan-ivanov. I have done some debugging to verify why there's an issue with the FactoryBean scenario. What happens is that the observationRegistry bean is created earlier then it should, i.e. without the FactoryBean its creation is triggered from org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization while in the one with the FactoryBean it's done from org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors, so a few steps to early; That happens because during registerBeanPostProcessor, the Framework looks for beans of type ApplicationContext and that includes instantiating any FactoryBeans, including MyFactoryBean and that triggers the instantiation of MyFeignClient which is way too early for the Feign Client to be instantiated correctly; instantiating Feign clients includes a call to org.springframework.cloud.context.named.NamedContextFactory#createContext that first registers Feign FactoryBean definitions and then refreshes the context (which will result in a lot of beans being created way too early, including observationRegistry).

To summarise, with the current programming model, there's no way to correctly create Feign client beans declared as fields in FactoryBeans and the real issue is that it's not been documented earlier, so I'm converting this one into a documentation issue.

@OlgaMaciaszek OlgaMaciaszek self-assigned this Jul 3, 2024
@OlgaMaciaszek OlgaMaciaszek added this to the 4.1.3 milestone Jul 3, 2024
@OlgaMaciaszek OlgaMaciaszek changed the title Micrometer tracing propagation not working when using Spring FactoryBean and Feign Document issues when using Spring FactoryBean and Feign Jul 3, 2024
@OlgaMaciaszek OlgaMaciaszek changed the title Document issues when using Spring FactoryBean and Feign Document issues when using Spring FactoryBean and Spring Cloud OpenFeign Clients Jul 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

No branches or pull requests

4 participants