spring-projects / spring-boot

Spring Boot
https://spring.io/projects/spring-boot
Apache License 2.0
74.54k stars 40.54k forks source link

Add bean id to Actuator (mappings) JSON data for functional routes #15230

Open BoykoAlex opened 5 years ago

BoykoAlex commented 5 years ago

STS team attempts to find a spot in the source code that declares routes using functional style using the JSON data from the Actuator.

Source code example:

public class VetsRouter {

    @Bean
    public RouterFunction<ServerResponse> route(VetsHandler vetsHandler) {
        return RouterFunctions
            .route(RequestPredicates.GET("/vets").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), vetsHandler::vets)
            .andRoute(RequestPredicates.GET("/vets.html"), vetsHandler::vetsHtml);
    }

    @Bean
    public RouterFunction<ServerResponse> moreRoute(VetsHandler vetsHandler) {
        return RouterFunctions
            .route(RequestPredicates.GET("/new-vets").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), vetsHandler::vets)
            .andRoute(RequestPredicates.GET("/new-vets.html"), vetsHandler::vetsHtml);
    }
}

The JSON data from the Actuator for /vets route:

          {
            "predicate": "((GET && /vets) && Accept: [text/plain])",
            "handler": "org.springframework.samples.petclinic.deviations.VetsRouter$$Lambda$868/443912630@369564bd",
            "details": {
              "handlerFunction": {
                "className": "org.springframework.samples.petclinic.deviations.VetsRouter$$Lambda$868/443912630"
              }
            }
          },

There are two pieces of data to help matching are predicate and handler The handler data should be most helpful in matching the proper place in the source. The matching place in the source code we think should be the route method declaration. Based on the handler's data we cannot match the route method unfortunately. The lambda with magic numbers is useless in this case.

It'd be great if the details object had something helpful to find the route method. Either method signature or perhaps the id of the corresponding RouterFunction bean. Seemed like getting the bean id into the JSON is doable (ApplicationContext.getBeansOfType(RouterFunction.class, true, true) gives an id -> bean object map, given a RouterFunction object should be easy to get the corresponding id ). Therefore the JSON would look like:

          {
            "predicate": "((GET && /vets) && Accept: [text/plain])",
            "handler": "org.springframework.samples.petclinic.deviations.VetsRouter$$Lambda$868/443912630@369564bd",
            "details": {
              "handlerFunction": {
                "className": "org.springframework.samples.petclinic.deviations.VetsRouter$$Lambda$868/443912630"
              },
              "bean": "route"
            }
          },
wilkinsona commented 5 years ago

Thanks for the suggestion. Unfortunately, I don't think it's possible to perform the RouterFunction -> Bean mapping as you have described.

Actuator is dealing with a DispatcherHandler which contains a single RouterFunctionMapping. It contains a single RouterFunction that isn't, itself, a bean. Typically, this composed RouterFunction is a composition of all of the application context's RouterFunction beans but this is an implementation detail that isn't exposed anywhere. We examine the composed function using a visitor. This provides us with access to each route (a request predicate and a handler function) but not to any information about the individual router functions.

In short, we would need some changes to be made in WebFlux.Fn to be able to support this. If you think this is worth pursuing, can you please open a Spring Framework issue and link to it here?

BoykoAlex commented 5 years ago

Somehow I missed e-mail notification with your reply... Indeed all rm functions are packed into a single one which actuator examines with a visitor... Raised: https://jira.spring.io/browse/SPR-17579

poutsma commented 5 years ago

I left a comment on the corresponding JIRA that explains how to get to a RouterFunction bean id, see https://jira.spring.io/browse/SPR-17579?focusedCommentId=164021&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-164021

BoykoAlex commented 5 years ago

@wilkinsona does Arjens suggestion help in getting to the bean id on the actuator side?

wilkinsona commented 5 years ago

Yes, I think it does.