如何在SpringBoot Actuator中自定义Metrics

5,572 阅读4分钟

从SpringBoot2.0开始,所有的指标metrics都采用MicroMeter的公共接口来实现,所以要在SpringBoot中创建自定义指标,需要先了解MicroMeter。

MicroMeter概念

1. 那什么是MicroMeter呢?

其实他是一组接口,类似于Slf4j提供了关于日志的统一接口一样,MicroMeter提供了一组关于监控指标统一的接口,有了这组接口,可以让使用者可以不再关心监控指标的底层实现,同时也可以更容易的切换不同的监控系统实现。

MicroMeter名词含义:MicroMeter - 千分尺(类似于游标卡尺)或者是微米,可以认为是度量长度最小单位的工具。这里,Meter(米)就是长度系统里的一个指标单位,那么MicroMeter可以理解为是长度指标系统里最小的单位(微米)或者度量工具(千分尺)。在MicroMeter里,指标Metric被称为Meter。

2. 基本概念

一个指标的组成部分:时间 + 一组维度 + 一组数值

时间通常是采集时间,可由采集方产生

维度:由维度名:维度值组成,其中维度值是有限集合,这也是维度与数值的区别。例如,维度名为性别,则维度值有{男,女},维度名为HttpStatus,则维度值是http状态码,例如404,500等。

数值:也是由数值名与数值组成,其中数值名通常取名要直观,例如计数count,最大值max等等

3. 基本组成

在MicroMeter的世界里,主要有Registry、Meter组成,其中Meter下又有Measurement与Statistics组成。

Registry: 就是保存Meter以及相关信息的仓库,不同的监控系统实现者会提供不同的Registry,来实现各自的规范。

Meter:对应着每一个指标,其内部有一组Measurement(度量)组成,每一个Measurement(度量)由有统计名称(Statistics)和数值(value)组成。

常见的Meter有Counter(计数),Gauge(数值),Timer(一段时间内的统计)。

4. 基本操作

a. 注册指标Meter:根据监控指标的不同,创建不同的Meter类型,例如创建Counter:

Counter counter = Counter
    .builder("http.requests.counter") //指标名字
    .baseUnit("beans") // optional
    .description("a description of what this counter does") // optional
    .tags("region", "test") // optional
    .register(registry);

b. 记录数值

counter.increment()
//或者 先从regitry获取指标再计数
registry.counter("http.requests.counter").increment()

SpringBoot Actuator

上面说了在MicroMeter里如何创建一个指标,那么假如现在有了这个指标Meter,那它又是如何在SpringBoot中被获取然后输出结果的呢?

题外话:其实SpringBoot Actuator内提供了丰富的production-ready的功能,除了监控指标外,还提供了例如健康检查HealthCheck、HttpTracing、Auditing等功能,详细请参考官方文档:docs.spring.io/spring-boot…

1. 如何输出结果

在Actuator中,不单单是监控指标,所有的信息输出都是通过Endpoint方式来实现的,这个Endpoint同时也是注解,有点类似于Controller。但为什么不叫Controller要重新定义一个Endpoint注解呢?那是因为,Controller用户Spring MVC只提供Http的访问方式,但对于系统信息内的输出,除了采用http的方式外,很多时候采用的是JMX的技术,所以为了同时支持这两种方式,Spring提供了Endpoint这个注解。关于这个注解怎么使用,以及Actuator对它的权限控制,可以参考官方文档关于Endpoints这个章节的介绍。docs.spring.io/spring-boot…

所以,为了能够输出指标数据,Actuator也提供了一个默认Endpoint,MetricsEndpoint。看源码可知,主要有两个只读方法(被ReadOperation注解):listNames和metric。分别是列举所有的指标名字和输出对应指标的数值信息。分别对应的url为:/actuator/metrics/ 和/actuator/metrics/{metric-name}。

2. 如何将MicroMeter的指标与Actuator绑定

从上面我们已经知道Actuator是可以输出指标的,那么如何让Actuator知道我们新建了一个指标呢?

一个简单的方式是实现MeterBinder这个接口,Actuator会对每一个MeterBinder类型的bean注入MeterRegitry,详细源码参见:MeterRegistryConfigurer。

自定义Meter的方式可以参考http.server.requests这个指标实现,主要包含的class有:TomcatMetrics、TomcatMetricsBinder、WebMvcMetricsFilter。

下面是一个自定义Meter的Demo:

public class CustomCacheMetrics implements MeterBinder {

  public CustomCacheMetrics() {
    log.info("custom cache metrics");
  }

  @Override
  public void bindTo(MeterRegistry registry) {
    Gauge.builder("redis.queue.failed", () -> getFailedCount())
        .baseUnit("次数")
        .description("redis queue failed size count")
        .register(registry);
    Gauge.builder("redis.queue.tohandle", () -> getToHandleCount())
        .baseUnit("次数")
        .description("redis queue to handle size count")
        .register(registry);
  }

  private Number getFailedCount() {
    return System.currentTimeMillis()/1000;
  }

  private Number getToHandleCount() {
    return System.currentTimeMillis();
  }
}

最后把这个class在configuration内配置成bean即可,然后访问/actuator/metrics/redis.queue.failed即能获取结果。

参考:

spring.io/blog/2018/0…

micrometer.io/docs/concep…

docs.spring.io/spring-boot…