在我的应用程序中,我有一个用例,必须通过提供的参数值监视方法。我必须将指标暴露于Prometheus端点。但是,该函数是一个常见的函数,并由许多不同类别使用。我试图将方法传递到方法参数中 @timed中,以区分不同行为,此函数将根据传递的参数值展示。
我尝试使用@Timed注释,但无法获得@Timed注释将功能参数视为Prometheus的指标。
@Timed("getFooContent")
public void getFooContent(Arg1 arg1, Arg2 arg2) {
//some code....
}
我能够通过创建注释@Foo
来弄清楚这一点,然后将此注释添加到我函数的参数:
@Timed("getFooContent")
public void getFooContent(@Foo Arg1 arg1, Arg2 arg2) {
//some code....
}
以下是我的定时配置 class>
@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;
}
i使用我在千分尺github问题中的POC中发现的时间表配置解决了它:https://github.com/jonatan-ivanov/micrometer-tags/blob/master/src/src/main/java/java/com/com/example/micrometertertags/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#_the_timed_annotation