You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AOP统计Logger.error()调用次数,Prometheus计数器未递增排查

问题排查:AOP结合Prometheus统计Logger.error()调用次数不生效

核心问题分析

当前代码存在两个关键问题导致计数器不递增:

1. 切点表达式使用错误

你用了execution(void org.slf4j.Logger.error(..)),但Spring AOP的execution切点匹配的是方法在目标类上的执行逻辑,而org.slf4j.Logger是接口,实际运行时LoggerFactory返回的是具体日志框架(如Logback)的实现类实例,且我们要拦截的是对Logger.error()方法的调用动作,不是方法内部的执行,应该改用AspectJ原生的call()切点:

@Pointcut("call(void org.slf4j.Logger.error(..)) && within(com.mypackage.controller.DummyController)")
public void errorMethodExecution() {
}

2. Spring AOP默认不支持call()切点

Spring AOP默认基于动态代理,仅支持有限的切点类型(如execution、within、annotation等),call()是AspectJ原生切点,需要启用**AspectJ加载时织入(LTW)**才能生效:

  • 在pom.xml中添加AspectJ依赖:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>
  • 在Spring Boot启动类上添加@EnableLoadTimeWeaving注解:
@SpringBootApplication
@EnableLoadTimeWeaving
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

修改后的完整AOP代码

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ErrorLogCounterAspect {

    private final Counter errorLogCounter;

    @Autowired
    public ErrorLogCounterAspect(MeterRegistry meterRegistry) {
        this.errorLogCounter = Counter
                .builder("log.error.calls")
                .description("Total number of org.slf4j.Logger.error() calls")
                .register(meterRegistry);
    }

    @Pointcut("call(void org.slf4j.Logger.error(..)) && (within(com.mypackage.controller..*) || within(com.mypackage.service..*) || within(com.mypackage.repository..*))")
    public void errorMethodCall() {
    }

    @After("errorMethodCall()")
    public void countLogErrorCalls(JoinPoint joinPoint) {
        errorLogCounter.increment();
    }
}

额外优化点

  • 扩展切点的within范围,覆盖控制器、服务、仓库等所有需要统计的包(如示例中的com.mypackage.controller..*表示controller包及其子包)
  • 可以为计数器添加标签(如tag("class", joinPoint.getTarget().getClass().getSimpleName())),区分不同类的错误日志调用情况

内容的提问来源于stack exchange,提问作者Sachin Mankotia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 22:17:12