[spring-projects/spring-boot]更轻松地配置微米谓词以与 TimedAspect 一起使用

2024-04-17 849 views
6

tl;dr 可以在此处找到演示:

https://github.com/AndreasKl/micrometerunexpectedbehaviour

当调用控制器时,会引发未处理的异常,因为WebMvcMetricsFilterasorg.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter#stop尝试使用已由 注册的不同标签注册相同的仪表TimedAspect。没有办法禁用WebMvcMetricsFilter这方面的行为。

为了通过千分尺为我的控制器生成普罗米修斯百分位数,我添加了@Timed("some_name")一些方法。不幸的是,这导致了WebMvcMetricsFilter我们用来监控状态代码的问题。

java.lang.IllegalArgumentException:Prometheus 要求所有同名的计量表具有相同的标签键集。已经存在一个包含标签键[类、异常、方法]的现有仪表。您尝试注册的仪表具有键 [异常、方法、结果、状态、uri]。

回答

5

感谢您提供样品。我已经重现了这个问题。

我认为添加的标签WebMvcMetricsFilter比创建的标签更有用TimedAspect,因此,理想情况下,我们希望WebMvcMetricsFilter获胜。这需要TimedAspect意识到其他东西已经在处理@Timed注释并且应该忽略它。这需要改变千分尺。

@jkschneider 你会在这里推荐什么?

6

@wilkinsona 一种禁用此行为的方法WebMvcMetricsFilter会对我们有所帮助,如果您认为这对其他人有帮助,我可以提供 PR。

也许您还可以为配置设置提出一个名称。

1

这听起来像是一个很好的后备方案,但在我们知道需要它之前,我不想添加这样的选项。同时,您可以WebMvcMetricsFilter通过排除来完全禁用org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration。它比仅仅禁用其支持更广泛,@Timed但它将避免此处描述的问题。

9

WebMvcMetricsFilter@wilkinsona不幸的是我使用(http_server_requests等人)生成的指标。我目前通过创建自己的WebMvcMetricsFilter不扫描@Timed.

4

@jkschneider 请参阅我上面的评论。你有什么建议?

3

平@jkschneider。我们有点被困在这里。请问您有什么建议吗?

4

@wilkinsona我唯一能想到的是有一个 TimedAspect 的变体,它也专门排除 WebMvc/WebFlux 带注释的方法。还有其他想法吗?

4

我发现了同样的问题。使用时

@Timed(value = "metric_name", longTask = true)

WebMvcMetricsFilter并将LongTaskTimingHandlerInterceptor全部生效。他们互相冲突。

幸运的是,io.micrometer.core.aop.TimedAspect默认情况下不启用,除非手动启用。我的理解是,这意味着属于用户定义的操作。

LongTaskTimingHandlerInterceptor指定的默认标签键 指定的[method, uri] TimedAspect默认标签键 指定[class, exception, method] WebMvcMetricsFilter的默认标签键是[exception, method, outcome, status, uri]

谢谢。

6

我还注意到,如果您有一个 REST 响应,并且在响应中返回一个对象,您会得到两个不同的 JSON 主体:https://github.com/abracadv8/micrometerunexpectedbehaviour

下面的方法应该简单地返回{"response":"test"},但它会与单独的 JSON 集中的 Micrometer/Prometheus 异常消息一起返回。

$ curl -i -X GET  -H "Content-Type: application/json" 'http://localhost:8080/response'
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 28 Oct 2019 14:10:19 GMT

{"response":"test"}{"timestamp":"2019-10-28T14:10:19.181+0000","status":200,"error":"OK","message":"Prometheus requires that all meters with the same name have the same set of tag keys. There is already an existing meter containing tag keys [class, exception, method]. The meter you are attempting to register has keys [exception, method, outcome, status, uri].","path":"/response"}
0

好的,据我了解问题尚未解决,我将千分尺的版本更新为新版本,但没有结果。如何禁用这个org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration。 ?好的,我找到了正确的方法:

@SpringBootApplication(exclude = WebMvcMetricsAutoConfiguration.class)
7

避免冲突的另一个策略是过滤 REST 控制器重新注册的指标。我通常将所有 REST 控制器类命名为以 Controller 结尾。他们的 - 注释也@Timed反映了这个名称。简单的 bean 定义如下:

@Bean
public MeterFilter filterDuplicates() {
    return MeterFilter.deny(id -> id.getName().contains("Controller")
            && id.getTags().stream().noneMatch(t -> "status".equals(t.getKey())));
}

仅注册那些包含状态标签的控制器度量。 TimedAspect 不提供这样的标签。这样您就可以同时拥有两个世界:WebMVC 指标以及其他带有 的 Spring Bean @Timed

9

鉴于 Micrometer 1.7 中的变化,我想知道我们应该在这里做什么(如果有的话)来进一步改善这种情况。 Spring Boot 不会自动配置TimedAspectCountedAspect因此目前我们无法插入一个在活动时跳过@Controllers 和@RestControllers 控制器的谓词。WebMvcMetricsFilter

几个选项:

  1. 不执行任何操作并依赖用户遵循 Micrometer 的 javadoc 中的建议
  2. 在 Boot 中提供谓词作为公共 API。然后用户可以将其插入TimedAspectCountedAspect
  3. TimedAspect为和提供CountedAspect自动配置谓词的选择加入
7

我们决定人们应该遵循 Micrometer 的 javadoc 中的建议。

3

你好@abracadv8,我在 spring boot 2.2.4-RELEASE 中遇到了同样的问题,我通过添加主类解决了这个问题

@EnableAutoConfiguration(
        exclude = {
                CompositeMeterRegistryAutoConfiguration.class,
                DataSourcePoolMetricsAutoConfiguration.class,
                TomcatMetricsAutoConfiguration.class,
                SimpleMetricsExportAutoConfiguration.class,
                SystemMetricsAutoConfiguration.class})