如何在代码中获取spring-boot-actuator的metrics指标数据?
编程式获取Spring Boot Actuator指标实现方案
Spring Boot Actuator暴露的所有指标,底层统一托管在Micrometer的MeterRegistry实例中,web端点本质只是对这个Bean里的数据做HTTP序列化输出,你完全可以直接注入这个Bean拉取全量指标,不需要走HTTP请求,也不需要依赖官方提供的micrometer-registry-xxxx适配组件。
前置依赖确认
只需要保证项目引入了基础的actuator依赖即可,不需要额外引入其他registry组件,也不需要配置web端点暴露规则(哪怕把所有web端点都关了,MeterRegistry依然会被Spring自动装配):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
核心实现代码
直接在自定义的指标发布组件中注入MeterRegistry,就可以按需拉取全量或指定指标,自行组装格式后推送到目标端:
import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Statistic; import org.springframework.stereotype.Component; import jakarta.annotation.Resource; import java.util.HashMap; import java.util.List; import java.util.Map; @Component public class CustomMetricsPusher { @Resource private MeterRegistry meterRegistry; /** * 拉取全量Actuator生成的指标 * 返回结构和/actuator/metrics端点返回的数据源完全一致 */ public List<Map<String, Object>> getAllMetrics() { return meterRegistry.getMeters().stream() .map(meter -> { Map<String, Object> metricItem = new HashMap<>(); // 指标名,例:jvm.memory.used、http.server.requests metricItem.put("name", meter.getId().getName()); // 指标维度标签,和web端点返回的tag完全对齐 metricItem.put("tags", meter.getId().getTags()); // 指标类型:GAUGE、COUNTER、TIMER、DISTRIBUTION_SUMMARY等 metricItem.put("type", meter.getId().getType().name()); // 指标具体测量值 Map<Statistic, Number> metricValues = new HashMap<>(); meter.measure().forEach(measure -> metricValues.put(measure.getStatistic(), measure.getValue()) ); metricItem.put("measurements", metricValues); return metricItem; }).toList(); } /** * 按名称精准查询单个指标 */ public Map<String, Object> getMetricByName(String metricName) { Meter targetMeter = meterRegistry.get(metricName).meter(); Map<String, Object> metricItem = new HashMap<>(); metricItem.put("name", targetMeter.getId().getName()); metricItem.put("tags", targetMeter.getId().getTags()); metricItem.put("type", targetMeter.getId().getType().name()); Map<Statistic, Number> metricValues = new HashMap<>(); targetMeter.measure().forEach(measure -> metricValues.put(measure.getStatistic(), measure.getValue()) ); metricItem.put("measurements", metricValues); return metricItem; } }
拿到指标数据后,你可以根据目标端的要求自定义序列化格式、推送频率、过滤规则,完全不需要受限于官方registry组件的适配逻辑。
补充说明
- 这种方式拿到的指标数据和web接口返回的内容100%同源,没有任何偏差,省去了本地HTTP调用的开销,性能更高
- 遍历指标时可以自定义过滤逻辑,比如只采集JVM、HTTP请求、数据库连接池相关的指标,灵活度远高于调用web接口
- 如果项目中已经存在多个
MeterRegistry实例(比如已经接入了Prometheus等监控组件),直接注入CompositeMeterRegistry即可,它会自动聚合所有注册表中的指标,不会出现漏采
内容的提问来源于stack exchange,提问作者codesup
相关产品推荐
相关产品推荐

