当前位置: 代码网 > it编程>编程语言>Java > SpringBoot方法级耗时监控实现方案

SpringBoot方法级耗时监控实现方案

2026年08月07日 Java 我要评论
一、需求痛点线上应用常见问题:某些接口偶尔变慢,但日志看不出问题;方法调用次数不透明,性能瓶颈难找;线上出现失败/超时,但缺乏统计维度;想要监控,却不想引入重量级的apm方案。常见apm工具功能强大,

一、需求痛点

线上应用常见问题:

  • 某些接口偶尔变慢,但日志看不出问题;
  • 方法调用次数不透明,性能瓶颈难找;
  • 线上出现失败/超时,但缺乏统计维度;
  • 想要监控,却不想引入重量级的 apm 方案。

常见 apm 工具功能强大,但部署复杂、学习成本高,不适合中小团队或者单机项目。

那有没有可能,基于 springboot 实现一个轻量级耗时监控器,做到方法级监控 + 可视化统计 ?

二、功能目标

我们希望监控器能做到:

基础监控能力
• 方法调用次数:统计某方法被调用了多少次
• 耗时指标:平均耗时、最大耗时、最小耗时
• 成功/失败次数:区分正常与异常调用
• 多维排序:支持按调用次数、平均耗时、失败次数等维度排序

进阶功能
• 时间段过滤:选择时间范围(如最近 5 分钟、1 小时、1 天)查看数据
• 接口搜索:快速定位特定接口的性能数据
• 可视化控制台:实时展示接口调用统计

三、技术设计

1. 基于aop的耗时监控

1.1 添加依赖

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-aop</artifactid>
</dependency>

1.2 自定义监控注解

@target(elementtype.method)
@retention(retentionpolicy.runtime)
public @interface timemonitor {
    string value() default "";
    timeunit timeunit() default timeunit.milliseconds;
    boolean logresult() default false;
}

1.3 实现aop切面

@aspect
@component
@slf4j
public class executiontimeaspect {
    @around("@annotation(timemonitor)")
    public object monitorexecutiontime(proceedingjoinpoint joinpoint, 
                                     timemonitor timemonitor) throws throwable {
        long starttime = system.currenttimemillis();
        object result = null;
        try {
            result = joinpoint.proceed();
            return result;
        } finally {
            long endtime = system.currenttimemillis();
            long duration = endtime - starttime;
            long convertedduration = converttimeunit(duration, timemonitor.timeunit());
            logexecutiontime(joinpoint, timemonitor, convertedduration, result);
        }
    }
    private long converttimeunit(long duration, timeunit timeunit) {
        switch (timeunit) {
            case seconds: return duration / 1000;
            case microseconds: return duration * 1000;
            case nanoseconds: return duration * 1000000;
            default: return duration;
        }
    }
    private void logexecutiontime(proceedingjoinpoint joinpoint, timemonitor timemonitor, 
                                long duration, object result) {
        string methodname = joinpoint.getsignature().toshortstring();
        string message = string.format("方法 %s 执行耗时: %d %s", 
            methodname, duration, gettimeunitstring(timemonitor.timeunit()));
        if (timemonitor.logresult() && result != null) {
            message += string.format(" | 返回结果: %s", result.tostring());
        }
        log.info(message);
    }
    private string gettimeunitstring(timeunit timeunit) {
        switch (timeunit) {
            case seconds: return "s";
            case milliseconds: return "ms";
            case microseconds: return "μs";
            case nanoseconds: return "ns";
            default: return "ms";
        }
    }
}

1.4 使用示例

@service
public class userservice {
    @timemonitor(value = "用户查询", timeunit = timeunit.milliseconds, logresult = true)
    public user getuserbyid(long id) {
        // 业务逻辑
        return userrepository.findbyid(id).orelse(null);
    }
    @timemonitor("批量用户查询")
    public list<user> getusers(list<long> ids) {
        // 业务逻辑
        return userrepository.findallbyid(ids);
    }
}

2. 基于spring boot actuator的监控

2.1 添加依赖

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-actuator</artifactid>
</dependency>
<dependency>
    <groupid>io.micrometer</groupid>
    <artifactid>micrometer-core</artifactid>
</dependency>

2.2 配置metrics监控

@component
public class methodmetrics {
    private final meterregistry meterregistry;
    private final map<string, timer> timers = new concurrenthashmap<>();
    public methodmetrics(meterregistry meterregistry) {
        this.meterregistry = meterregistry;
    }
    public void recordexecutiontime(string methodname, long duration, timeunit unit) {
        timer timer = timers.computeifabsent(methodname, 
            key -> timer.builder("method.execution.time")
                       .tag("method", methodname)
                       .register(meterregistry));
        timer.record(duration, unit);
    }
    @eventlistener
    public void handlemethodexecutionevent(methodexecutionevent event) {
        recordexecutiontime(event.getmethodname(), 
                          event.getduration(), 
                          event.gettimeunit());
    }
}

3. 高级功能:统计和告警

3.1 监控统计类

@component
@slf4j
public class methodperformancemonitor {
    private final map<string, methodstats> statsmap = new concurrenthashmap<>();
    private final long warningthreshold;
    public methodperformancemonitor(@value("${monitor.warning-threshold:1000}") long warningthreshold) {
        this.warningthreshold = warningthreshold;
    }
    public void recordmethodexecution(string methodname, long duration) {
        methodstats stats = statsmap.computeifabsent(methodname, k -> new methodstats());
        stats.recordexecution(duration);
        // 超过阈值告警
        if (duration > warningthreshold) {
            log.warn("方法 {} 执行耗时 {}ms 超过阈值 {}ms", 
                    methodname, duration, warningthreshold);
        }
        // 定期输出统计信息
        if (stats.getexecutioncount() % 100 == 0) {
            log.info("方法 {} 统计: {}", methodname, stats.getstatssummary());
        }
    }
    @scheduled(fixedrate = 60000) // 每分钟输出一次汇总统计
    public void printsummary() {
        log.info("=== 方法执行耗时统计汇总 ===");
        statsmap.foreach((method, stats) -> {
            log.info("方法 {}: {}", method, stats.getstatssummary());
        });
    }
    @data
    public static class methodstats {
        private long executioncount;
        private long totaltime;
        private long maxtime;
        private long mintime = long.max_value;
        public void recordexecution(long duration) {
            executioncount++;
            totaltime += duration;
            maxtime = math.max(maxtime, duration);
            mintime = math.min(mintime, duration);
        }
        public double getaveragetime() {
            return executioncount == 0 ? 0 : (double) totaltime / executioncount;
        }
        public string getstatssummary() {
            return string.format("调用次数: %d, 平均耗时: %.2fms, 最大耗时: %dms, 最小耗时: %dms", 
                    executioncount, getaveragetime(), maxtime, mintime);
        }
    }
}

3.2 增强的aop切面

@aspect
@component
@slf4j
public class enhancedexecutiontimeaspect {
    private final methodperformancemonitor performancemonitor;
    public enhancedexecutiontimeaspect(methodperformancemonitor performancemonitor) {
        this.performancemonitor = performancemonitor;
    }
    @around("@annotation(timemonitor)")
    public object monitorexecutiontime(proceedingjoinpoint joinpoint, 
                                     timemonitor timemonitor) throws throwable {
        string methodname = getmethodname(joinpoint);
        long starttime = system.currenttimemillis();
        try {
            object result = joinpoint.proceed();
            return result;
        } catch (throwable throwable) {
            log.error("方法 {} 执行异常", methodname, throwable);
            throw throwable;
        } finally {
            long endtime = system.currenttimemillis();
            long duration = endtime - starttime;
            // 记录执行时间
            performancemonitor.recordmethodexecution(methodname, duration);
            // 记录详细日志
            if (log.isdebugenabled()) {
                log.debug("方法 {} 执行耗时: {}ms", methodname, duration);
            }
        }
    }
    private string getmethodname(proceedingjoinpoint joinpoint) {
        methodsignature signature = (methodsignature) joinpoint.getsignature();
        return signature.getdeclaringtype().getsimplename() + "." + signature.getname();
    }
}

4. 配置类

@configuration
@enableaspectjautoproxy
@enablescheduling
public class monitorconfig {
    @bean
    @conditionalonmissingbean
    public methodperformancemonitor methodperformancemonitor() {
        return new methodperformancemonitor(1000l);
    }
    @bean
    public enhancedexecutiontimeaspect enhancedexecutiontimeaspect(
            methodperformancemonitor performancemonitor) {
        return new enhancedexecutiontimeaspect(performancemonitor);
    }
}

5. 应用配置

# application.yml
monitor:
  warning-threshold: 500  # 告警阈值,单位ms
logging:
  level:
    com.yourpackage.monitor: debug
management:
  endpoints:
    web:
      exposure:
        include: metrics
  endpoint:
    metrics:
      enabled: true

四、使用方式

  1. 基本使用:在需要监控的方法上添加 @timemonitor 注解
  2. 自定义配置:通过注解参数调整时间单位和是否记录返回值
  3. 查看统计:系统会自动输出方法执行统计信息
  4. 监控告警:当方法执行时间超过阈值时会输出警告日志

以上就是springboot方法级耗时监控实现方案的详细内容,更多关于springboot方法级耗时监控的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com