MetricsAspectsAutoConfiguration introduced in Spring boot v3.2.0 breaks existing metrics configured by Spring.
Micrometer maintainers have been discussing about the issue here: https://github.com/micrometer-metrics/micrometer/issues/780
Metrics will be registered/counted twice, and in case of Prometheus only one metric will ultimately be reported.
In our case this caused the disappearance of Spring http.server.requests metrics in favor of a metric with default tags created by TimedAspect (if a name is defined for the metric e.g. @Timed('MyMetricName')).
The issues they mentioned should likely be handled by Spring boot if spring-boot enables TimedAspect by default.
The workaround suggested there is the strategy I would suggest to fix this bug, but maybe a more general solution exists to reduce confusion.
@Bean
@ConditionalOnMissingBean
TimedAspect timedAspect(MeterRegistry registry,
ObjectProvider<MeterTagAnnotationHandler> meterTagAnnotationHandler) {
TimedAspect timedAspect = new TimedAspect(registry, this::skipControllers);
meterTagAnnotationHandler.ifAvailable(timedAspect::setMeterTagAnnotationHandler);
return timedAspect;
}
private boolean skipControllers(ProceedingJoinPoint pjp){
Class targetClass = pjp.getTarget().getClass();
return (targetClass.isAnnotationPresent(RestController.class) || targetClass.isAnnotationPresent(Controller.class));
}
Comment From: mhalbritter
I just annotated a controller method with @Timed and my Prometheus shows up both metrics (the timed one and the http.server.requests one`).
If you'd like us to spend some time investigating, please take the time to provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.
Comment From: baeyenwo
@mhalbritter https://github.com/baeyenwo/spring-boot-3-metric-issue - this project contains a test demonstrating the issue.
Edit: This demonstrates the issue with re-used @Time annotation between Spring and micrometer, but I'm unsure it shows the issue with the latest spring-boot specifically as downgrading does not resolve it. I'll try and update it later, for today this was all the time I had available to check.
Comment From: mhalbritter
I can reproduce it, but only using Jersey. With WebMVC and Webflux it works. In your sample,
tutorials0(no@Timed) generates ahttp_metrictutorials1(@Timed) generates ahttp_metric and a custom onetutorials2(@Timed(value = "tutorials2")) generates nohttp_metric, but a custom one
Comment From: mhalbritter
MetricsRequestEventListener is what creates the metrics in the Jersey case. This class is from the Micrometer project, so this looks like a bug in their code. Could you please open an issue on their tracker and reference this issue? Thanks!