自定义监控端点
# 13.3 自定义端点
在项目中,我们可能需要根据实际情况来自定义监控端点,特别是一些和业务相关的监控端点。
# 13.3.1 自定义健康监控端点
自定义健康监测的端点有两种方式:
- 继承 AbstractHealthIndicator 类;
- 实现 HealthIndicator 接口。
通过查看 HealthIndicator 接口源码,可以看到,系统内置的众多健康检测端点都是从 AbstractHealthIndicator 抽象类继承而来的。
在 spring-boot-actuator 项目的 application.yml 配置文件中添加 Actuator 健康监控总是显示详细信息配置。
# Actuator 端口配置
management:
endpoint:
health:
show-details: always
2
3
4
5
# 13.3.1.1 继承 AbstractHealthIndicator 类
创建一个监控端点类 CustomHealthEndPoint 继承 AbstractHealthIndicator 类。
在其中获取磁盘使用信息并输出监控信息。
package com.example.actuator.custom;
import java.io.File;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health.Builder;
import org.springframework.stereotype.Component;
/**
* 自定义监控示例,监控磁盘容量
* @author Kevin
*
*/
@Component("myHealth")
public class CustomHealthEndPoint extends AbstractHealthIndicator {
@Override
protected void doHealthCheck(Builder builder) throws Exception {
File[] rootFiles = File.listRoots();
if (rootFiles != null && rootFiles.length != 0) {
long total = 0, free = 0;
for (File file : rootFiles) {
total += file.getTotalSpace(); // 磁盘总量
free += file.getUsableSpace(); // 可用容量
}
long user = total - free; // 已用容量
double userRate = total == 0 ? 0 : ((double) user / total);// 磁盘利用率
builder.up()
.withDetail("磁盘总量", total) // 这里是你要显示的具体健康监测信息
.withDetail("可用容量", free)
.withDetail("利用率%", userRate * 100).build();
} else {
builder.down().build();
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
运行 Spring Boot 应用程序,访问监控监控端点http://localhost:8080/actuator/health (opens new window), 查看自定义监控端点输出的监控信息。
# 13.3.1.2 实现 HealthIndicator 接口
创建一个 AnotherCustomHealthEndPoint 类,实现 HealthIndicator 接口。实现public Health health()
方法,在其中生成一个随机数,然后根据这个随机数是否为零来输出健康状态。
package com.example.actuator.custom;
import java.util.Random;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component("anotherCustomHealthEndPoint")
public class AnotherCustomHealthEndPoint implements HealthIndicator {
@Override
public Health health() {
int errorCode = new Random().nextInt(5); // 定义一个错误代码 随机产生
if (errorCode != 0) {
return Health.down().withDetail("错误码:", errorCode).build();
} else {
return Health.up().withDetail("正确代码:", errorCode).build();
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
运行 Spring Boot 应用程序,访问监控监控端点http://localhost:8080/actuator/health (opens new window), 查看自定义监控端点输出的监控信息。
# 13.3.2 自定义 Metrics 端点
自定义 Metrics 是通过实现 MeterBinder 接口完成的。
新建一个 DiskspaceMetrics 类,实现 MeterBinder 接口,代码如下:
package com.example.actuator.custom;
import java.io.File;
import org.springframework.stereotype.Component;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.MeterBinder;
@Component("diskspaceMetrics")
public class DiskspaceMetrics implements MeterBinder {
private File rootFilePath;
public DiskspaceMetrics() {
this.rootFilePath = new File(".");
}
@Override
public void bindTo(MeterRegistry registry) {
Gauge.builder("磁盘已用容量", rootFilePath, File::getTotalSpace).register(registry);
Gauge.builder("磁盘剩余容量", rootFilePath, File::getFreeSpace).register(registry);
Gauge.builder("磁盘使用率", rootFilePath, c -> {
long totalDiskSpace = rootFilePath.getTotalSpace();
if (totalDiskSpace == 0) {
return 0.0;
}
long usedDiskSpace = totalDiskSpace - rootFilePath.getFreeSpace();
return (double) usedDiskSpace / totalDiskSpace * 100;
}).register(registry);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
运行 Spring Boot 应用程序,访问监控监控端点http://localhost:8080/actuator/metrics (opens new window), 查看自定义监控端点输出的监控信息。
# 13.3.3 完全自定义端点
我们也可以通过 Spring Boot 提供的 @Endpoint、 @ReadOperation、@WriteOperation、@DeleteOperation 注解完全自定义监控端点,例如和业务运行状态相关的端点。
创建一个 PersonEndpoint 类:
package com.example.actuator.custom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
import org.springframework.stereotype.Component;
@Endpoint(id = "person")
@Component
public class PersonEndpoint {
private final Map<String, Person> people = new HashMap<>();
PersonEndpoint() {
this.people.put("kevin", new Person("Kevin Zhang"));
this.people.put("roy", new Person("Roy Zhang"));
this.people.put("lily", new Person("Lily Huang"));
}
@ReadOperation
public List<Person> getAll() {
return new ArrayList<>(this.people.values());
}
@ReadOperation
public Person getPerson(@Selector String person) {
return this.people.get(person);
}
@WriteOperation
public void updatePerson(@Selector String name, String person) {
this.people.put(name, new Person(person));
}
public static class Person {
private String name;
Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
运行 Spring Boot 应用程序,访问监控监控端点http://localhost:8080/actuator/person (opens new window), 查看自定义监控端点输出的监控信息。
进一步访问http://localhost:8080/actuator/person/kevin (opens new window), 查看针对 kevin 用户的监控信息。
本小节示例项目代码:
https://github.com/gyzhang/SpringBootCourseCode/tree/master/spring-boot-actuator (opens new window)