介绍
Micrometer 为 Java 平台上的性能数据收集提供了一个通用的 API,应用程序只需要使用 Micrometer 的通用 API 来收集性能指标即可。Micrometer 会负责完成与不同监控系统的适配工作。这就使得切换监控系统变得很容易。Micrometer 还支持推送数据到多个不同的监控系统。
在Springboot 2.X中,除了通过业务代码的方式埋点,官方也提供了@Timed,@Counted注解实现。
遗憾的是,官方对于自定义的Tag只做了简单的适配,不能满足我们一些自定义的指标需求。为了满足项目需求,所以我们需要自定义注解来实现MicroMeter的埋点。
依赖
除了基础的springboot依赖以外,我们还需要引入aop的依赖和actuator。actuator默认是依赖了micrometer,并通过micrometer对外提供endpoint。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
实践
这里我们以micrometer常见的Timer指标为例,自定义@Timed注解
自定义注解
为了更好的拓展官方定义的指标,直接沿用了一些官方的定义。针对Tag指标,我们做了单独的处理。
@Timed
@Target({
ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Timed {
String value() default "";
boolean longTask() default false;
double[] percentiles() default {
};
boolean histogram() default false;
String description() default "";
}
@Tag
@Target({
ElementType.METHOD,ElementType.ANNOTATION_TYPE,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(value = Tags.class)
public @interface Tag {
String key();
String value();
}
@Tags
@Target({
ElementType.METHOD,ElementType.ANNOTATION_TYPE,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Tags {
Tag[] value();
}
类和接口
为了能支持自定义tag的解析,因此我们需要定义一个tag解析器。为了能更好的拓展,所以我们需要先定义一个接口
TagParser
public interface TagParser {
/**
* 获取tag解析器类型
* @return
*/
String getType();
/**
* tag解析
* @param tagDefinition tag定义
* @param args 参数,包含:入参,返回值
* @return
* @throws JsonProcessingException
*/
Tag parse(TagDefinition tagDefinition, Object[] args) throws JsonProcessingException;
}
AbstractDefaultTagParser
AbstractDefaultTagParser存放公共的属性和方法
public abstract class AbstractDefaultTagParser implements TagParser {
final static String POINT = ".";
final static String REGEX_POINT = "\\.";
final static String DEFAULT_TAG_VALUE = "None";
@Override
public String getType() {
return null;
}
@Override
public Tag parse(TagDefinition tagDefinition,Object[] args) throws JsonProcessingException {
return null;
}
Integer regexParam(String regexString) {
String reg = "[^0-9]";
//Pattern类的作用在于编译正则表达式后创建一个匹配模式.
Pattern pattern = Pattern.compile(reg);
//Matcher类使用Pattern实例提供的模式信息对正则表达式进行匹配
Matcher matcher = pattern.matcher(regexString);
return Integer.parseInt(matcher.replaceAll("").trim());
}
}
ArgTagParser
ArgTagParser 用于处理入参tag类型
public class ArgTagParser extends AbstractDefaultTagParser {
public final static String ARG_TAG_PARSER_TYPE = "ARG";
@Override
public String getType() {
return ARG_TAG_PARSER_TYPE;
}
@Override
public Tag parse(TagDefinition tagDefinition, Object[] args) throws JsonProcessingException {
if (null == args){
return Tag.of(tagDefinition.getKey(),DEFAULT_TAG_VALUE);
}
String value = tagDefinition.getValue