如何在任意方法名称上使用的 @Timed 注释中包含方法参数
Posted
技术标签:
【中文标题】如何在任意方法名称上使用的 @Timed 注释中包含方法参数【英文标题】:How to include Method Parameters in @Timed annotation used on arbitrary method name 【发布时间】:2019-12-06 05:55:15 【问题描述】:在我的应用程序中,我有一个用例,我必须通过提供的参数值来监视方法。我必须将指标公开给 Prometheus 端点。但是,该函数是一个通用函数,并且被许多不同的类使用。我试图将方法参数中传递的值传递给@Timed,以便根据传递的参数值区分此函数将表现出的不同行为。
我尝试使用@Timed 注释,但无法让@Timed 注释将函数参数作为指标公开给Prometheus。
@Timed("getFooContent")
public void getFooContent(Arg1 arg1, Arg2 arg2)
//some code....
【问题讨论】:
【参考方案1】:我能够通过创建注释 @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;
【讨论】:
在添加自定义标签/标签时要非常小心,您可能会因保存指标而出现“内存中”限制异常。一个例子是使用 webclient 进行休息调用时的“uriVaraibles”限制/异常【参考方案2】:在您的配置类中添加以下 bean,然后尝试。
@Bean
public TimedAspect timedAspect(MeterRegistry registry)
return new TimedAspect(registry);
使用@EnableAspectJAutoProxy
注释配置类请通过此链接阅读http://micrometer.io/docs/concepts#_the_timed_annotation
【讨论】:
感谢分享。我能够通过创建注释'@Foo'来解决这个问题【参考方案3】:没有办法仅使用注释将参数包含在计时器的标签中。 Micrometer 为简单的用例提供注释,并在您需要更复杂的东西时建议使用编程方法。
您应该在计时器上使用record
方法并将您的代码包装在其中。
registry.timer("myclass.getFooContent", Tags.of("arg1", arg1)).record(() ->
//some code...
)
【讨论】:
谢谢!是否有任何其他库可以实现此功能?以上是关于如何在任意方法名称上使用的 @Timed 注释中包含方法参数的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法将 Micrometer @Timed 注释捕获到 Prometheus 指标存储/注册表中? [复制]