Динамическое маркирование метрик с помощью Spring WebClient

#spring #spring-webclient

Вопрос:

Пытаюсь перенести некоторый код из RestTemplate в Webclient. Старый код оборачивал таймер для сбора метрик вокруг вызова RestTemplate и добавлял два дополнительных пользовательских тега, основанных на вводе запроса.

Мы создаем веб-клиент и добавляем функцию Metricswebclientfilter в конструктор в качестве фильтра. Я также видел DefaultWebClientExchangeTagsProvider. Проблема в том, что единственный механизм, который я видел для применения тегов, находится в этом конструкторе. Мы не хотим создавать новый веб-клиент по каждому запросу от разработчика, и я не вижу способа добавить теги в отдельный веб-клиент get/options/post.

Существует ли механизм добавления тегов к отдельным метрикам в реальном веб-клиенте get или мы ограничиваемся созданием конструктора каждый раз?

Для контекста мы пытаемся зарегистрировать идентификатор клиента и другой пользовательский идентификатор, который не является частью шаблона URL-адреса для вызова.

Единственная идея, которая у меня была до сих пор, заключалась в добавлении заголовка HTTP, а затем создании пользовательского поставщика WebClientExchangeTagsProvider, который добавлял бы тег по мере поступления запроса. Проблема в том, что мы не хотим, чтобы эти заголовки отправлялись в службы внешних поставщиков, которым мы вызываем.

Мы используем Spring Boot 2.5.4, и это приложение spring MVC, которое мы хотели бы в конечном итоге перенести в webflux.

Ответ №1:

Нет механизма для публикации пользовательских тегов для каждого запроса после создания веб-клиента. Тем не менее, можно сделать такой шаблон

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

Затем создайте пользовательский класс метрик

 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
    }
}