【问题标题】:Add tags for Spring webclient default metrics为 Spring webclient 默认指标添加标签
【发布时间】:2021-11-16 05:22:34
【问题描述】:

我目前正在开发一个 Spring webflux 项目,该项目具有以下 Actuator、Micrometer 依赖项,

    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-registry-prometheus</artifactId>
    </dependency>
    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-core</artifactId>
    </dependency>

公开默认指标(包括 Spring webClient 指标)。我使用 Spring WebClient 调用了 4 个不同的端点。我想知道是否有一种方法可以为每个添加到默认指标的 Web 客户端调用添加特定标签。我在 /actuator/prometheus 端点暴露了一些指标,例如来自 Webclient 的 Histogram,如下所示,

http_client_requests_seconds_bucket{clientName="my-app.com",method="GET",outcome="SUCCESS",status="200",uri="/shops",le="0.001048576",} 0.0
http_client_requests_seconds_bucket{clientName="my-app.com",method="GET",outcome="SUCCESS",status="200",uri="/shops",le="0.002088576",} 1.0

在我的代码中,我想在 Webclient 调用中为上述所有指标添加一些额外的标签。比如这样的,

http_client_requests_seconds_bucket{clientName="my-app.com",method="GET",outcome="SUCCESS",status="200",uri="/shops",le="0.001048576",investor="A", version="v1"} 0.0
http_client_requests_seconds_bucket{clientName="my-app.com",method="GET",outcome="SUCCESS",status="200",uri="/shops",le="0.002088576",investor="A", version="v1"} 1.0

请注意我添加的 2 个自定义标签 investor="A", version="v1"。我正在寻找一些可能看起来像这样的代码,

@Autowire
private WebClient webclient; // Assume there is already a bean created for us

public Mono<String> getShopsList(String... extraTags) {
     return webclient.baseUrl("http://my-app.com")
         .build()
         .get()
         .uri("/shops")
         .tags(extraTags) // Some extra tags I want callers of the method to pass. Note there are only 4-5 methods that call "getShopsList()" method
         .retrieve() 
         .bodyToMono(String.class);
 }
 

有人可以帮助了解实现这一目标的最佳方法吗?

【问题讨论】:

    标签: spring spring-webflux spring-boot-actuator spring-webclient spring-micrometer


    【解决方案1】:

    这样做的预期方法是引入您的自定义标签提供程序:

    @Component
    public class CustomWebClientExchangeTagsProvider extends DefaultWebClientExchangeTagsProvider {
    
      public static final String VERSION_ATTRIBUTE = "custom.webclient.version";
      public static final String INVESTOR_ATTRIBUTE = "custom.webclient.investor";
    
      @Override
      public Iterable<Tag> tags(ClientRequest request, ClientResponse response, Throwable throwable) {
        Tag method = WebClientExchangeTags.method(request);
        Tag investor = getInvestorTag(request);
        Tag version = getVersionTag(request);
        return asList(method, investor, version, WebClientExchangeTags.status(response, throwable), WebClientExchangeTags.outcome(response));
      }
    
      private Tag getInvestorTag(ClientRequest request) {
        return request.attribute(INVESTOR_ATTRIBUTE)
            .map(name -> Tag.of("investor", (String) name))
            .orElse(WebClientExchangeTags.clientName(request));
      }
    
      private Tag getVersionTag(ClientRequest request) {
        return request.attribute(VERSION_ATTRIBUTE)
            .map(uri -> Tag.of("version", (String) uri))
            .orElse(WebClientExchangeTags.uri(request));
      }
    
    }
    

    您必须以这种方式检测您的自定义 Web 客户端:

    @Bean
    public WebClient webClient(MetricsWebClientCustomizer metricsCustomizer) {
        TcpClient timeoutClient = ...
        WebClient.Builder builder = WebClient.builder();
        metricsCustomizer.customize(builder);
        return ...;
    }
    

    最后,你需要像这样设置两个属性:

    return webClient.get()
            .uri(filePath)
            .attribute(INVESTOR_ATTRIBUTE, "A")
            .attribute(VERSION_ATTRIBUTE, "v1")
            .retrieve()
            .bodyToMono(String.class);
    

    示例结果:

    http_client_requests_seconds_count{investor="A",method="GET",outcome="CLIENT_ERROR",status="401",version="v1",} 1.0
    http_client_requests_seconds_sum{investor="A",method="GET",outcome="CLIENT_ERROR",status="401",version="v1",} 0.073818807
    

    编辑

    根据文档:

    S attributes(Consumer<Map<String,Object>> attributesConsumer)

    提供对迄今为止声明的每个属性的访问 添加、替换或删除值的可能性。

    是的,您可以使用它来添加多个属性。

    【讨论】:

    • 这行得通。谢谢。我想知道如何使用 webClient.attributes(Consumer>)。你能解释一下吗,这样我就可以在一个地图中传递多个属性
    • @justAnotherDev 编辑完成
    • 我尝试使用它,但它没有用。如果可以,请提供一个例子
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-04
    • 2016-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多