I'm using @Timed
in Spring Boot app for collecting metrics from methods and it works:
@Timed(percentiles = {0.95, 0.99}, histogram = true, extraTags = {"slice", "client"})
Since I'm using this annotation in the different places I decided to create custom annotation TimedExtended
:
import io.micrometer.core.annotation.Timed;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Timed(percentiles = {0.95, 0.99}, histogram = true, extraTags = {"slice", "client"})
public @interface TimedExtended {
}
But this new one doesn't work, metrics are not being sent to Influx. Do you have idea what should be done for fixing it?
If you’re using a custom annotation that wraps @Timed
(a meta-annotation), such as @TimedExtended
, the pointcut from io.micrometer.core.aop.TimedAspect
"execution (@io.micrometer.core.annotation.Timed * .(..))" won't match it directly. This is because the execution expression looks only for methods explicitly annotated with @Timed
, and it won’t recognise methods annotated with @TimedExtended
.
For solving this problem I created my own Aspect, took as a base io.micrometer.core.aop.TimedAspect
:
@Aspect
public class TimedExtendedAspect {
...
@Around("execution (@com.test.metrics.TimedExtended * *.*(..))")
@Nullable
public Object timedMethod(ProceedingJoinPoint pjp) throws Throwable {
if (shouldSkip.test(pjp)) {
return pjp.proceed();
}
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
TimedExtended timed = method.getAnnotation(TimedExtended.class);
if (timed == null) {
method = pjp.getTarget().getClass().getMethod(method.getName(), method.getParameterTypes());
timed = method.getAnnotation(TimedExtended.class);
}
return perform(pjp, timed, method);
}
...
}
Also I modified my annotation in the next way:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface TimedExtended {
String value() default "";
boolean longTask() default false;
String description() default "";
String[] extraTags() default {"slice", "client"};
boolean histogram() default true;
double[] percentiles() default {0.95, 0.99};
}
Last step - create bean for new Aspect:
@Bean
TimedExtendedAspect timedExtendedAspect(InfluxMeterRegistry influxMeterRegistry) {
return new TimedExtendedAspect(influxMeterRegistry);
}