背景
统计某些接口的rt情况
RTMetrics
import cn.nvriot.platform.geocoding.infra.utils.HistogramSnapshotUtil;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.search.Search;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class RTMetrics {
@Autowired
MeterRegistry meterRegistry;
public void geoRt(Long cost) {
Timer.builder("geoRT")
.description("geo api req/res time cost")
.publishPercentileHistogram()
.publishPercentiles(0.5, 0.90, 0.95, 0.99)
.serviceLevelObjectives(Duration.ofMillis(50),
Duration.ofMillis(100),
Duration.ofMillis(200),
Duration.ofSeconds(1),
Duration.ofSeconds(5))
.minimumExpectedValue(Duration.ofMillis(10))
.maximumExpectedValue(Duration.ofSeconds(5))
.distributionStatisticExpiry(Duration.ofMinutes(5))
.register(this.meterRegistry)
.record(cost, TimeUnit.MILLISECONDS);
}
public void lbsRt(Long cost) {
Timer.builder("lbsRT")
.description("lbs api req/res time cost")
.publishPercentileHistogram()
.publishPercentiles(0.5, 0.90, 0.95, 0.99)
.serviceLevelObjectives(Duration.ofMillis(50),
Duration.ofMillis(100),
Duration.ofMillis(200),
Duration.ofSeconds(1),
Duration.ofSeconds(5))
.minimumExpectedValue(Duration.ofMillis(10))
.maximumExpectedValue(Duration.ofSeconds(5))
.distributionStatisticExpiry(Duration.ofMinutes(5))
.register(this.meterRegistry)
.record(cost, TimeUnit.MILLISECONDS);
}
/**
* cron 表达式,每隔1分钟执行一次
*/
@Scheduled(cron = "0 */1 * * * ?")
public void print() {
Search.in(meterRegistry).name(p -> "geoRT".equals(p) || "lbsRT".equals(p)).meters().forEach(each -> {
StringBuilder builder = new StringBuilder();
builder.append("name:")
.append(each.getId().getName())
.append(",type:").append(each.getId().getType())
.append(",value:").append(each.measure())
.append(",takeSnapshot:").append(HistogramSnapshotUtil.format(((Timer) each).takeSnapshot(), TimeUnit.MILLISECONDS));
log.info("RT Statistic: [{}] ", builder);
});
}
}
HistogramSnapshotUtil
import io.micrometer.core.instrument.distribution.HistogramSnapshot;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* @author wxl
*/
public class HistogramSnapshotUtil {
public static String format(HistogramSnapshot snapshot, TimeUnit timeUnit) {
final StringBuilder buf = new StringBuilder();
buf.append("HistogramSnapshot{count=");
buf.append(snapshot.count());
buf.append(", total=");
buf.append(snapshot.total(timeUnit));
buf.append(", mean=");
buf.append(snapshot.mean(timeUnit));
buf.append(", max=");
buf.append(snapshot.max(timeUnit));
if (snapshot.percentileValues().length > 0) {
buf.append(", percentileValues=");
buf.append(Arrays.stream(snapshot.percentileValues()).map(s -> format(s, timeUnit)).collect(Collectors.joining()));
}
if (snapshot.histogramCounts().length > 0) {
buf.append(", histogramCounts=");
buf.append(Arrays.stream(snapshot.histogramCounts()).map(s -> format(s, timeUnit)).collect(Collectors.joining()));
}
buf.append('}');
return buf.toString();
}
public static String format(io.micrometer.core.instrument.distribution.ValueAtPercentile percentile, TimeUnit unit) {
return "(" + percentile.value(unit) + " at " + percentile.percentile() * 100 + "%)";
}
public static String format(io.micrometer.core.instrument.distribution.CountAtBucket percentile, TimeUnit unit) {
return "(" + percentile.count() + " at " + percentile.bucket(unit) + ')';
}
}
打印日志
2023-11-21 17:18:00.014 INFO [scheduling-1] xx RT Statistic: [name:lbsRT,type:TIMER,value:[
Measurement{statistic='COUNT', value=12.0}, # 总请求次数
Measurement{statistic='TOTAL_TIME', value=0.408}, # 总消耗时间 单位s
Measurement{statistic='MAX', value=0.324}], # 最大的请求消耗时间 单位s
takeSnapshot:
HistogramSnapshot{count=12, total=408.0, mean=34.0, max=324.0, # 基本统计 单位毫秒
percentileValues=(6.815744 at 50.0%)(11.79648 at 90.0%)(335.282176 at 95.0%)(335.282176 at 99.0%), # 单位毫秒,p99等指标
histogramCounts=(11.0 at 50.0)(11.0 at 100.0)(11.0 at 200.0)(12.0 at 1000.0)(12.0 at 5000.0)}] # 单位毫秒 , 耗时分布情况