Как включить параметры метода в аннотацию @Timed, используемую для произвольного имени метода

В моем приложении есть сценарий использования, в котором я должен отслеживать метод по значению аргумента, который он предоставляет. Я должен показать метрики конечной точке Прометея. Однако эта функция является общей и используется многими различными классами. Я пытаюсь получить значение, переданное в параметре метода, в @Timed, чтобы различать различные варианты поведения, которые эта функция будет демонстрировать, основываясь на переданном значении параметра.

Я попытался использовать аннотацию @Timed, но не смог получить аннотацию @Timed, чтобы выставить параметр функции в качестве метрики для Прометея.

@Timed("getFooContent")
public void getFooContent(Arg1 arg1, Arg2 arg2) {
    //some code.... 
}

4 ответа

Я смог понять это, создав аннотацию @Foo а затем добавляем эту аннотацию к параметру моей функции:

@Timed("getFooContent")
public void getFooContent(@Foo Arg1 arg1, Arg2 arg2) {
 //some code.... 
}

Ниже приведен мой класс временной конфигурации:

@Configuration
@SuppressWarnings("unchecked")
public class TimedConfiguration {
 public static final String NOT_AVAILABLE = "N/A";
  Function<ProceedingJoinPoint, Iterable<Tag>> tagsBasedOnJoinPoint;
  @Bean
  public TimedAspect timedAspect(MeterRegistry registry) {
    tagsBasedOnJoinPoint = pjp ->
        Tags.of("class", pjp.getStaticPart().getSignature().getDeclaringTypeName(),
            "method", pjp.getStaticPart().getSignature().getName(),
            "parameter_1", getArguments(pjp));
    return new TimedAspect(registry, tagsBasedOnJoinPoint);
  }


private String getArguments(ProceedingJoinPoint pjp) {
    Object[] args = pjp.getArgs();
    String className = pjp.getStaticPart().getSignature().getDeclaringTypeName();
    if(className.contains("com.example.foo")) { //Resstricting to only certain packages starting with com.example.foo
      MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
      Method method = methodSignature.getMethod();
      Annotation[][] annotations = method.getParameterAnnotations();
      int index = -1;
      for(int i = 0; i < annotations.length; i++) {
        Annotation[] annotationsArr = annotations[i];
        for(Annotation annotation: annotationsArr) {
          if(annotation.annotationType().getName().equals(Foo.class.getName())) {
            index = i;
            break;
          }
        }
      }
      if(index >= 0) {
        List parameterValues = new ArrayList((List)args[index]);
        if(CollectionUtils.isNotEmpty(parameterValues) && parameterValues.get(0) instanceof Byte) {
          Collections.sort(parameterValues); //Sorting the paratemer values as per my use case
          return String.valueOf(parameterValues.stream().collect(Collectors.toSet()));
        }
      }  
    }
    return NOT_AVAILABLE;
  }

Я решил это с помощью этой конфигурации TimedAspect, которую я нашел в PoC в проблеме микрометра github: https://github.com/jonatan-ivanov/micrometer-tags/blob/master/src/main/java/com/example/micrometertags/MetricsConfig.java

      @Configuration
public class MetricsConfig {
@Bean
public TimedAspect timedAspect(MeterRegistry meterRegistry) {
    return new TimedAspect(meterRegistry, this::tagFactory);
}

private Iterable<Tag> tagFactory(ProceedingJoinPoint pjp) {
    return Tags.of(
        "class", pjp.getStaticPart().getSignature().getDeclaringTypeName(),
        "method", pjp.getStaticPart().getSignature().getName()
    )
    .and(getParameterTags(pjp))
    .and(ExtraTagsPropagation.getTagsAndReset());
}

private Iterable<Tag> getParameterTags(ProceedingJoinPoint pjp) {
    Set<Tag> tags = new HashSet<>();

    Method method = ((MethodSignature) pjp.getSignature()).getMethod();
    Parameter[] parameters = method.getParameters();
    for (int i = 0; i < parameters.length; i++) {
        for (Annotation annotation : parameters[i].getAnnotations()) {
            if (annotation instanceof ExtraTag) {
                ExtraTag extraTag = (ExtraTag) annotation;
                tags.add(Tag.of(extraTag.value(), String.valueOf(pjp.getArgs()[i])));
            }
        }
    }

    return tags;
}

}

Нет способа включить параметры в теги таймера, используя только аннотацию. Микрометр предоставляет аннотацию для простых случаев использования и рекомендует использовать программный подход, когда вам нужно что-то более сложное.

Вы должны использовать record метод по таймеру и заверните ваш код в это.

registry.timer("myclass.getFooContent", Tags.of("arg1", arg1)).record(() -> {
  //some code...
})

Добавьте этот bean-компонент в свой класс конфигурации и попробуйте.

@Bean
public TimedAspect timedAspect(MeterRegistry registry) {
    return new TimedAspect(registry);
}

Аннотируйте класс конфигурации с помощью @EnableAspectJAutoProxy

Пожалуйста, прочтите эту ссылку http://micrometer.io/docs/concepts

Другие вопросы по тегам