You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Quarkus+Micrometer的RestClient添加自定义区分标签

为Quarkus RestClient添加专属监控标签

问题场景

使用Quarkus 2.13.3.Final版本,通过quarkus-micrometer-registry-prometheus实现指标监控。现有如下RestClient代码:

@ApplicationScoped
@RegisterRestClient(configKey = "foo-api")
interface FooClient {

    @GET
    @Path("/foo")
    fun findFoo(
        @QueryParam("foo") foo: String
    ): RestResponse
}

当前生成的Prometheus指标示例:

http_client_requests_seconds_count{clientName="foo.com",method="GET",outcome="SUCCESS",status="200",uri="/foo",} 30.0

存在的问题:多个调用同域名(foo.com/{thisVaries})的RestClient,指标的clientName均为foo.com,无法区分不同客户端;使用commonTag会给所有指标添加相同标签,无法满足需求。希望为每个客户端添加专属标签,让指标呈现如下形式:

http_client_requests_seconds_count{clientName="foo.com",method="GET",outcome="SUCCESS",status="200",uri="/foo",clientClass="AddressClient"} 30.0
http_client_requests_seconds_count{clientName="foo.com",method="GET",outcome="SUCCESS",status="200",uri="/foo",clientClass="NameClient"} 36.0

解决方案

方法1:通过配置为单个RestClient添加标签

无需编写代码,直接在application.properties中针对每个RestClient的配置key添加自定义标签:

# 针对foo-api配置的RestClient添加标签
quarkus.micrometer.binder.rest-client."foo-api".tags=clientClass=FooClient
# 针对另一个bar-api配置的RestClient添加标签
quarkus.micrometer.binder.rest-client."bar-api".tags=clientClass=BarClient

这种方式简单直接,适合标签值固定的场景。

方法2:自定义请求拦截器动态添加标签

创建一个ClientRequestFilter,在请求发起时为当前RestClient添加专属标签:

@RegisterProvider
@Priority(Priorities.USER)
class RestClientTagFilter : ClientRequestFilter {

    override fun filter(requestContext: ClientRequestContext) {
        // 获取当前RestClient的类名
        val clientClassName = requestContext.client.javaClass.simpleName
        // 获取当前监控实例并添加标签
        Observation.getCurrentObservation()?.apply {
            highCardinalityKeyValue("clientClass", clientClassName)
            // 若标签属于低基数维度,改用lowCardinalityKeyValue
            // lowCardinalityKeyValue("clientClass", clientClassName)
        }
    }
}

如果要让拦截器仅作用于特定RestClient,在对应的客户端接口上添加@RegisterProvider注解:

@ApplicationScoped
@RegisterRestClient(configKey = "foo-api")
@RegisterProvider(RestClientTagFilter::class)
interface FooClient {
    // 接口方法不变
}

若要全局生效,去掉接口上的@RegisterProvider即可。

方法3:自定义ObservationConvention全局修改标签

通过自定义RestClientObservationConvention替换默认实现,为所有RestClient自动添加专属标签:

@Singleton
class CustomRestClientObservationConvention : RestClientObservationConvention {

    override fun getLowCardinalityKeyValues(context: RestClientObservationContext): MutableList<KeyValue> {
        val defaultTags = super.getLowCardinalityKeyValues(context)
        // 添加客户端类名标签
        defaultTags.add(KeyValue.of("clientClass", context.client.javaClass.simpleName))
        return defaultTags
    }
}

Quarkus会自动发现并使用这个自定义实现,所有RestClient的监控指标都会带上clientClass标签。

内容的提问来源于stack exchange,提问作者Stepan Tuhacek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 17:20:26