如何为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
相关产品推荐
相关产品推荐

