前言
本文来分析GaugeService的实现,其类图如下:
解析
GaugeService
GaugeService–> 1个可以用来提交1个被命名的duble值为了存储和分析的服务.任意的统计和分析需要留给其他人去做,但是最终还是需要被该接口的实现所控制.举例说明:这个值可能是通过1个定时任务提交的,并且保存在后端的直方图中以进行比较。或者 可以是一个传感器值的简单测量(比如温度读数)以原始形式传递给监测系统.
其只声明了1个方法,如下:
// 设置给定的测量值 void submit(String metricName, double value);
DefaultGaugeService
DefaultGaugeService实现了GaugeService接口.该类是JDK1.8之前默认装配的
其字段,构造器如下:
// 此时注入的是InMemoryMetricRepository private final MetricWriter writer; // key-->metricName,value-->加入前缀后的metricName private final ConcurrentHashMap<String, String> names = new ConcurrentHashMap<String, String>(); public DefaultGaugeService(MetricWriter writer) { this.writer = writer; }
submit 实现如下:
public void submit(String metricName, double value) { this.writer.set(new Metric<Double>(wrap(metricName), value)); }
尝试为传入的metricName加上前缀.代码如下:
private String wrap(String metricName) { // 1. 如果缓存中有的话,则直接返回对应的值 String cached = this.names.get(metricName); if (cached != null) { return cached; } // 2. 如果传入的metricName是gauge或者histogram或者timer开头的则直接返回 if (metricName.startsWith("gauge") || metricName.startsWith("histogram") || metricName.startsWith("timer")) { return metricName; } // 3. 为metricName 加上gauge.的前缀,放入到names缓存中,然后进行返回 String name = "gauge." + metricName; this.names.put(metricName, name); return name; }
- 如果缓存中有的话,则直接返回对应的值
- 如果传入的metricName是gauge或者histogram或者timer开头的则直接返回
- 为metricName 加上gauge.的前缀,放入到names缓存中,然后进行返回
- 实例化Metric
- 加入到InMemoryMetricRepository中.
GaugeBuffer
GaugeBuffer实现了Buffer接口,代码如下:
public class GaugeBuffer extends Buffer<Double> {
private volatile double value;
public GaugeBuffer(long timestamp) {
super(timestamp);
this.value = 0;
}
@Override
public Double getValue() {
return this.value;
}
public void setValue(double value) {
this.value = value;
}
}
GaugeBuffers
GaugeBuffers继承自Buffers,泛型参数为GaugeBuffer.该类是1.8以后默认装配的.
createBuffer,直接实例化了1个GaugeBuffer,时间戳为当前时间,值为0.实现如下:
protected GaugeBuffer createBuffer() { return new GaugeBuffer(0L); }
此外,还声明了1个set方法–> 对给定名字的GaugeBuffer设置值.代码如下:
public void set(final String name, final double value) { doWith(name, new Consumer<GaugeBuffer>() { @Override public void accept(GaugeBuffer buffer) { buffer.setTimestamp(System.currentTimeMillis()); buffer.setValue(value); } }); }
- 从父类中的buffers获得给定名字所对应的GaugeBuffer,如果不存在,则创建1个
- 将GaugeBuffer中的时间戳设为当前时间,并设置给定的值
使用案例
新建GaugeController.代码如下:
package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.metrics.GaugeService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class GaugeController { @Autowired private GaugeService gaugeService; @RequestMapping("/test-gauge") public String testGauge() { long start = System.currentTimeMillis(); try { Thread.sleep(5000); } catch (InterruptedException e) { } gaugeService.submit("test-gauge.use", System.currentTimeMillis()-start); return "操作成功"; } }
我们访问如下链接后 http://127.0.0.1:8080/test-gauge 后,访问 http://127.0.0.1:8080/metrics,即可发现gauge.test-gauge.use对应的统计次数约为5005.如下:
auge.test-gauge.use: 5005