Search code examples
springspring-webclient

Dynamic metric tagging with Spring WebClient


Trying to migrate some code from a RestTemplate to Webclient. The old code was wrapping a timer for metric collection around the RestTemplate call, and was adding two additional custom tags that are based on the request input.

We're creating a WebClient and adding the MetricsWebCLientFilterFunction to the builder as a filter. I've also seen the DefaultWebClientExchangeTagsProvider. The issue is that the only mechanism I've seen to apply tags is on that builder. We don't want to create a new WebClient on every request from the builder, and I'm not seeing a way to add tags to an individual webclient get/options/post.

Is there a mechanism to add tagging to individual metrics on the actual webclient get or are we limited to creating a builder every single time?

For context, we're trying to log client id and another custom identifier that isn't part of the URL pattern for the call.

The only idea I've had so far was adding an HTTP header and then creating a custom WebClientExchangeTagsProvider that would add the tag as the request comes in. The problem is that we don't want these headers going out to the external vendor services we're calling.

We're using Spring Boot 2.5.4 and it's a spring MVC app we'd like to migrate to webflux eventually.


Solution

  • There isn't a mechanism to post custom tags per request once a WebClient is created. However, one can do a pattern like this

    val metricFilter = MetricWebClientFilterFunction(meterRegistry), CustomTagProvider(customValString), "metric-name", AutoTimer.ENABLED)
    webClient.mutate().filter(metricFilter).build().get() ...
    

    Then create a custom metric class

    class CustomTagProvider(private val customValString: String) : DefaultWebClientExchangeTagProvider() {
        override fun tags(request: ClientRequest, response: ClientRespose, throwable: Throwable): Iterable<Tag> {
            val custom: Tag.of("custom", customValString)
            val tags: MutableList<Tag> = mutableListOf(custom)
            tags.addAll(super.tags(request, response, throwable))
            return tags
        }
    }