如何通过Micrometer/Prometheus获取已记录的方法执行时间指标
可行方案实现指南
前提注意
Spring AOP默认无法拦截private方法,你当前标记@Timed的process方法如果是private的,注解实际不会生效。建议将方法改为public,或者启用AspectJ编织(需额外引入AspectJ依赖并在启动类添加@EnableAspectJAutoProxy(proxyTargetClass = true))。
步骤1:配置执行阈值
在application.properties或application.yml中添加阈值配置:
# 单位:毫秒,可根据需求调整 data.processing.time-threshold=500
方案一:实时监控单次执行耗时并对比阈值
该方案会在每次process方法执行后,计算实际耗时并与阈值对比,将"超过阈值的次数"作为新指标上报Prometheus。
1.1 实现监控组件
@Component public class ProcessingTimeMonitor { private final long timeThresholdMs; private final Counter thresholdExceededCounter; public ProcessingTimeMonitor(MeterRegistry meterRegistry, @Value("${data.processing.time-threshold}") long timeThresholdMs) { this.timeThresholdMs = timeThresholdMs; // 注册自定义计数器,记录超过阈值的次数 this.thresholdExceededCounter = meterRegistry.counter("data.processing.time.threshold.exceeded"); } public long getTimeThresholdMs() { return timeThresholdMs; } public void recordThresholdExceed() { thresholdExceededCounter.increment(); } }
1.2 自定义切面拦截方法
@Aspect @Component public class ProcessingTimeAspect { private final ProcessingTimeMonitor monitor; public ProcessingTimeAspect(ProcessingTimeMonitor monitor) { this.monitor = monitor; } // 替换为你的process方法所在类的全路径 @Around("execution(* com.yourpackage.YourClass.process(..))") public Object trackProcessingTime(ProceedingJoinPoint joinPoint) throws Throwable { long startTime = System.currentTimeMillis(); try { return joinPoint.proceed(); } finally { long elapsedTime = System.currentTimeMillis() - startTime; // 对比阈值,超过则计数 if (elapsedTime > monitor.getTimeThresholdMs()) { monitor.recordThresholdExceed(); } } } }
方案二:定时检查统计指标与阈值对比
如果你关注的是方法执行时间的统计值(如平均值、最大值),可以定时从MeterRegistry中读取@Timed生成的Timer指标,与阈值对比后上报状态指标。
2.1 实现定时检查组件
@Component public class TimedMetricChecker { private final MeterRegistry meterRegistry; private final long timeThresholdMs; private final Gauge thresholdExceededGauge; public TimedMetricChecker(MeterRegistry meterRegistry, @Value("${data.processing.time-threshold}") long timeThresholdMs) { this.meterRegistry = meterRegistry; this.timeThresholdMs = timeThresholdMs; // 注册Gauge指标,1表示超过阈值,0表示未超过 this.thresholdExceededGauge = Gauge.builder("data.processing.time.threshold.exceeded.gauge", () -> 0.0) .register(meterRegistry); } // 每分钟执行一次检查,可调整频率 @Scheduled(fixedRate = 60000) public void checkThresholdAgainstStats() { // 从注册表中获取@Timed生成的Timer指标 Timer timer = meterRegistry.find("data.processing.time").timer(); if (timer == null) { return; } // 读取统计的平均耗时(单位:毫秒),也可改用max()获取最大值 double avgTimeMs = timer.mean(TimeUnit.MILLISECONDS); // 更新Gauge状态 thresholdExceededGauge.set(avgTimeMs > timeThresholdMs ? 1.0 : 0.0); } }
最后配置验证
确保Actuator的Prometheus端点已开启,在配置文件中添加:
management.endpoints.web.exposure.include=prometheus management.metrics.export.prometheus.enabled=true
启动应用后,访问/actuator/prometheus即可看到自定义的阈值相关指标,Prometheus可正常抓取这些数据。
内容的提问来源于stack exchange,提问作者agingcabbage32
相关产品推荐
相关产品推荐

