如何在用于任意方法名称的@Timed批注中包含方法参数

时间:2019-07-28 20:07:41

标签: spring-boot prometheus micrometer spring-micrometer prometheus-java

在我的应用程序中,我有一个用例,其中我必须通过提供的参数值来监视方法。我必须将指标公开给Prometheus端点。但是,该函数是一个通用函数,并且被许多不同的类使用。我试图获取传递给@Timed的方法参数中的值,以便根据传递的参数值来区分此函数将表现出的不同行为。

我尝试使用@Timed批注,但无法获取@Timed批注将函数参数作为Prometheus的度量标准。

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

3 个答案:

答案 0 :(得分:1)

没有一种仅使用注释将参数包含在计时器标签中的方法。千分尺为简单的用例提供注释,并在需要更复杂的内容时建议使用编程方法。

您应该在计时器上使用record方法,并将代码包装在其中。

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

答案 1 :(得分:0)

将此下面的bean添加到您的Configuration类中,然后尝试。

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

使用 @EnableAspectJAutoProxy

注释配置类

请通过此链接http://micrometer.io/docs/concepts#_the_timed_annotation

阅读

答案 2 :(得分:0)

我能够通过创建注释@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;
  }