Search code examples
javaspringrestspring-mvcspring-cloud-sleuth

Accessing Parameters mapped by @RequestMapping for Tracing


I am currently working on a monitoring application using Spring Cloud Sleuth. Currently I try to collect as much information about my requests as possible.

To keep the approach as scalable as possible I use GenericFilterBeans and HandlerInterceptorAdapter to access information from the requests sent to the REST-API.

I am struggling with getting parameters of a REST-call where the parameters are mapped from the URL like in the following code snippet:

  @RequestMapping(
            value = {"/{service}/{route_id}/book", "/accounting-core-service/{service}/{route_id}/book"},
            method = RequestMethod.GET)
    @ResponseBody
    public ModelAndView book(@PathVariable(value="service") String serviceName,
                             @PathVariable(value = "route_id") int routeId,
                             HttpServletResponse response) {
    /*Do something*/
}

The question is not, whether it is good practice or not to write it like so. The question is whether there is an approach similar to Filter or Interceptor (or the proper use of them) to access those parameters.

A requirement is, that it can be applied easily to an application by adding very few lines of code. Annotating every Method call manually or manually inserting the code to write the parameters into the trace from within the method is not feasible for me.

If you need more information feel free to ask. I will provide you with all information you need to help me with my problem.


Solution

  • Although not officially supported (as it's not written in the reference documentation), Spring MVC holds that information as request attributes.

    You could create your own HandlerInterceptor, ordered right after the Sleuth one, and get that information from the request like this:

    // "/{service}/{route_id}/book"
    String matchingPattern = (String) request
                        .getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
    // "service" => "fooService", "route_id" => "42"
    Map<String, String> templateVariables = (Map<String, String>) request
                        .getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
    

    Note, the template variables are already decoded at that point, which is probably what you want anyway.