Today, I've stumbled over this issue:

https://github.com/micrometer-metrics/micrometer/issues/780

It seems that this happens not only when annotating controller methods with @Timed but also when annotating Spring Data repositories (and possibly other beans).

Is there some way for Spring Boot to prevent this?

Comment From: wilkinsona

Unfortunately, I don't think there's anything that Boot can do here as it doesn't have the necessary information to detect a double registration. To do so, it would have to:

  1. Detect @Timed on a method
  2. Detect that the TimedAspect is in play
  3. Know that the annotated method is also instrumented by the underlying framework

1 is possible. 2 is harder as it relies both on a TimedAspect bean and the necessary AOP machinery being in place. 3 is the real stumbling block as it isn't possible without coupling Boot more tightly than we would like to behavior in Spring MVC, Spring Data, etc.

If you've opted into using @Timed (or @Counted), you may also want to consider defining TimedAspect yourself with a predicate that performs your desired filtering, as described in this comment from @jonatan-ivanov.

Comment From: helpermethod

Hi @wilkinsona,

thanks for the detailed answer, that makes sense.

I've used the predicate workaround to solve this issue, but it took me quite a while to find out what the actual problem was. Maybe the metrics chapter @Timed usage should link to the workaround / give some hints. Wdyt?

Comment From: wilkinsona

Yes, I think we could add something to https://docs.spring.io/spring-boot/3.3/reference/actuator/metrics.html#actuator.metrics.supported.timed-annotation. Thanks for the suggestion.

Comment From: jonatan-ivanov

FWIW, I think by adding @Timed/@Observed/etc. to something that is already instrumented out of the box, (without disabling that instrumentation) you are explicitly asking for double instrumentation (built-in + annotation). Also, since annotating a controller method with @Timed/@Observed/etc. is technically not exactly the same (Spring Framework instruments these on the ServletFilter level), this "double instrumentation" could be a ~valid use-case if you want to distinguish between just the method call and the method call + Spring overhead.

Because of these, I think Boot should not do anything but making it easy to turn auto-instrumentation on/off (this is already happening).

@wilkinsona For the doc change, could you please also consider @Counted, @Observed, and @NewSpan next to @Timed?