依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置
spring:
application:
name: monitor
# 与监控相关的配置key都是以management开头
# 每一个端点就表示一个单独模块的功能,这些监控端点官网都有
# https://docs.spring.io/spring-boot/docs/2.7.18/reference/html/actuator.html#actuator.endpoints
# 端点的访问格式: http://localhost:8080/actuator/端点名称/端点子属性
# 显示所有暴露的端点: http://localhost:8080/actuator/
# 常用的端点
# 1. beans: spring中完整的bean列表
# 2. conditions: 自动装配的条件信息,匹配成功和不匹配的原因
# 3. configprops: 显示所有的@ConfigProperties
# 4. env: 暴露spring的环境对象
# 5. health: 显示应用程序运行状态(重要)
# 6. info: 应用程序信息
# 7. loggers: 显示和修改应用程序中的日志配置
# 8. metrics: 应用程序的指标信息(重要)
# 9. mappings: 显示所有RequestMapping列表
# 10. scheduledtasks: 显示应用程序中的定时任务
# 11. sessions: 允许从Spring Session支持的会话存储中检索和删除会话
# 12. shutdown: 使应用程序正常关闭,默认禁用
management:
endpoints:
# 默认开启所有端点,一般不会这样做,不太安全
enabled-by-default: true
# 以web的方式暴露端点信息,也就是http
web:
exposure:
include: '*'
# 方法端点的基本路径
base-path: /actuator
# 以jmx的方式暴露端点信息
# jmx:
# exposure:
# include: '*'
# 单独启用端点
endpoint:
# 这个健康信息我们可以进行自定义,自定义某个组件的健康信息,实现HealthIndicator接口
health:
enabled: true
# 显示健康的详细信息
show-details: always
# 这个应用信息我们可以进行自定义,实现InfoContributor接口
info:
enabled: true
# 开启info端点包含info开头的属性变量
info:
env:
enabled: true
# 通过info定义的配置属性,可以被监控的info端点获取到
info:
app-name: luck-springboot
version: 1.0
# 获取配置的规则@ 配置名称 @
maven: "@project.parent.version@"
自定义
// 自定义端点
@Endpoint(id = "luck")
@Slf4j
@Component
public class LuckEndpoint {
// 当访问http://localhost:8080/actuator/luck则会执行此方法
@ReadOperation
public Map<String, Object> getDockerInfo() {
return Map.of("info", "docker start");
}
// 通过jconsole可以调用这个操作,web不行
@WriteOperation
public void restartDocker() {
log.error("docker restart...");
}
}
// 自定义组件的健康信息
// http://localhost:8080/actuator/health
@Component
public class LuckHealthIndicator implements HealthIndicator {
@Autowired
private RedisService redisService;
@Component
static
class LuckInnerHealthIndicator extends AbstractHealthIndicator {
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
builder.status(Status.DOWN);
Map<String, String> details = Map.of("code", "501", "message", "服务挂了");
builder.withDetails(details);
}
}
@Override
public Health health() {
Health.Builder builder = new Health.Builder();
String luck = redisService.getValue("luck");
if (luck.equals("luck")) {
builder.status(Status.UP);
} else if (StrUtil.isNotEmpty(luck)) {
builder.status(Status.UNKNOWN);
} else if (luck != null) {
builder.status(Status.OUT_OF_SERVICE);
} else {
builder.status(Status.DOWN);
}
Map<String, String> details = Map.of("code", "505", "message", "状态不知道怎么样");
builder.withDetails(details);
return builder.build();
}
}
@Component
public class LuckInfoContributor implements InfoContributor {
@Override
public void contribute(Info.Builder builder) {
builder.withDetail("健康信息", "非常健康");
}
}
@Component
public class LuckMetrics {
@Autowired
@Lazy
private MeterRegistry meterRegistry;
private Counter counter;
@PostConstruct
public void init() {
// 新增一个监控指标
counter = meterRegistry.counter("luck.method.running.count");
}
public void insert() {
System.out.println("insert xxx");
counter.increment();
}
// 也可以通过这种方法新增指标
@Bean
MeterBinder size() {
return registry -> Gauge.builder("luck.size", () -> 10);
}
}