Spring-boot: Controller annotated with @Timed and active TimedAspect clashes with WebMvcMetricsFilter

Created on 15 Nov 2018  路  11Comments  路  Source: spring-projects/spring-boot

tl;dr
A demo can be found here:

https://github.com/AndreasKl/micrometerunexpectedbehaviour

When the controller is called an unhandled exception is raised, by WebMvcMetricsFilter as org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter#stop tries to register the same meter with different tags as already registered by the TimedAspect. There is afais no way to disable the behaviour of WebMvcMetricsFilter for this aspect.

To generate prometheus percentiles via micrometer for my controllers I added @Timed("some_name") to a few methods. Unluckily this caused issues in WebMvcMetricsFilter which we use to monitor our status codes.

java.lang.IllegalArgumentException: 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].

blocked bug

Most helpful comment

I also noticed if you have a REST response with an object being returned in the response, you get two distinct JSON bodies: https://github.com/abracadv8/micrometerunexpectedbehaviour

The below method should simply return {"response":"test"} but it returns that along with the Micrometer/Prometheus exception message in separate sets of JSON.

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

All 11 comments

Thanks for the sample. I've reproduced the problem.

I think the tags added by WebMvcMetricsFilter are more useful than those created by TimedAspect so, ideally, we'd like WebMvcMetricsFilter to win. That would require TimedAspect to realise that something else is already handling the @Timed annotation and it should ignore it. That would require a change in Micrometer.

@jkschneider what would you recommend here?

@wilkinsona a way to disable this behaviour in WebMvcMetricsFilter would help us, I could provide a PR if you think this could be helpful for others.

Maybe you could also propose a name for the config setting.

That sounds like a good fallback, but I don't want to add such an option until we know that it's needed. In the meantime, you can disable WebMvcMetricsFilter entirely by excluding org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration. It's broader than just disabling its support for @Timed but it will avoid the problem described here.

@wilkinsona Unfortunately I use the metrics generated by WebMvcMetricsFilter (http_server_requests et. al). I currently mitigate this by creating my own WebMvcMetricsFilter implementation that does not scan for @Timed.

@jkschneider Please see my comment above. Do you have any recommendations?

Ping @jkschneider. We're a bit stuck here. Do you have any suggestions please?

@wilkinsona Only thing I can think of is to have a variant of TimedAspect that specifically excludes WebMvc/WebFlux annotated methods as well. Any other ideas?

I found the same problem. When using

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

WebMvcMetricsFilterand LongTaskTimingHandlerInterceptor will all take effect.
They conflict with each other.

Fortunately, io.micrometer.core.aop.TimedAspect is not enabled by default, unless manually enabled.
My understanding is that this means belonging to a user-defined operation.

LongTaskTimingHandlerInterceptor default tag keys specified is [method, uri]
TimedAspect default tag keys specified is[class, exception, method]
WebMvcMetricsFilter default tag keys specified is [exception, method, outcome, status, uri]

Thanks.

I also noticed if you have a REST response with an object being returned in the response, you get two distinct JSON bodies: https://github.com/abracadv8/micrometerunexpectedbehaviour

The below method should simply return {"response":"test"} but it returns that along with the Micrometer/Prometheus exception message in separate sets of JSON.

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

That sounds like a good fallback, but I don't want to add such an option until we know that it's needed. In the meantime, you can disable WebMvcMetricsFilter entirely by excluding org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration. It's broader than just disabling its support for @Timed but it will avoid the problem described here.

Ok, as I understand the problem is not resolved, I updated version of micrometer to new, but no result.
How to disable this one org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration. ?
OK, I found the right way:

@SpringBootApplication(exclude = WebMvcMetricsAutoConfiguration.class)

FYI in Micrometer 1.6.0 we will no longer hard fail on these tag clashes, though the problem still exists. Just leaving it up to the user to determine how they want to deal with it. See https://github.com/micrometer-metrics/micrometer/issues/2068

Was this page helpful?
0 / 5 - 0 ratings