Micrometer的_seconds系列指标生成位置及自定义扩展咨询
Micrometer指标生成位置与自定义扩展指南
一、标准分位数指标的生成位置
你贴的这种带_bucket、_count、_sum的指标,是Micrometer里Timer类型指标的默认输出格式(对应Prometheus exporter的输出)。核心生成逻辑分布在这些类中:
io.micrometer.core.instrument.Timer:Timer的核心接口,定义了分位数、计数、总耗时的统计逻辑io.micrometer.prometheus.PrometheusMeterRegistry:Prometheus导出器的核心类,负责把Timer的统计数据格式化成你看到的文本行格式
简单来说,当你在代码里创建并使用Timer(比如调用Timer.start()或record()方法),Micrometer的核心统计模块会自动累积分位数、请求计数、总耗时数据,最后由Prometheus注册表将这些数据转换为指定的指标格式输出。
二、扩展自定义指标(均值、吞吐量)
要新增metric_name_seconds_mean和metric_name_seconds_throughput,可以通过两种实用方式实现:
方式1:基于现有Timer数据计算
直接复用Timer已统计的count()和totalTime()数据,快速计算均值和吞吐量:
// 假设已创建并注册了目标Timer Timer timer = Timer.builder("metric_name") .tags("key", "value") .register(meterRegistry); // 注册均值指标:总耗时/请求数 Gauge.builder("metric_name_seconds_mean", timer, t -> t.totalTime(TimeUnit.SECONDS) / t.count()) .tags(timer.getId().getTags()) .register(meterRegistry); // 注册吞吐量指标:单位时间内的请求数(示例用FunctionCounter统计累计请求数,Prometheus侧可通过rate函数计算瞬时吞吐量) FunctionCounter.builder("metric_name_seconds_throughput", timer, Timer::count) .tags(timer.getId().getTags()) .register(meterRegistry);
这种方式无需额外埋点,适合快速扩展基础衍生指标。
方式2:自定义统计逻辑(灵活适配特殊场景)
如果需要自定义统计窗口或特殊计算规则,可以实现自己的统计类:
class CustomTimerStats { private final AtomicLong requestCount = new AtomicLong(0); private final DoubleAdder totalElapsedSeconds = new DoubleAdder(); private final Instant startTime = Instant.now(); // 埋点时调用,记录单次请求耗时 public void record(double elapsedSeconds) { requestCount.incrementAndGet(); totalElapsedSeconds.add(elapsedSeconds); } // 向注册表注册自定义指标 public void register(MeterRegistry registry, String metricName, Iterable<Tag> tags) { // 注册均值指标 Gauge.builder(metricName + "_seconds_mean", this, stats -> { long count = stats.requestCount.get(); return count == 0 ? 0 : stats.totalElapsedSeconds.sum() / count; }) .tags(tags) .register(registry); // 注册吞吐量指标:累计请求数/运行时长(也可自定义滑动窗口) Gauge.builder(metricName + "_seconds_throughput", this, stats -> { long elapsedSeconds = Duration.between(startTime, Instant.now()).getSeconds(); return elapsedSeconds == 0 ? 0 : stats.requestCount.get() / (double) elapsedSeconds; }) .tags(tags) .register(registry); } } // 使用示例 CustomTimerStats customStats = new CustomTimerStats(); customStats.register(meterRegistry, "metric_name", Tags.of("key", "value")); // 业务埋点 customStats.record(0.256);
注意事项
- 自定义指标命名需符合Prometheus规范:小写字母、下划线分隔,避免特殊字符
- Spring Boot环境下,
MeterRegistry实例会自动注入,直接使用即可 - 注册指标前可通过
meterRegistry.find(metricName).tags(tags).gauge()检查是否已存在,避免重复注册
内容的提问来源于stack exchange,提问作者John Warestone
相关产品推荐
相关产品推荐

