如何跟踪基于Spring的Web应用程序中所有函数的进入和退出?

时间:2011-08-25 16:41:21

标签: java spring logging

在我现在使用的基于Spring的Web应用程序项目中,开发人员已经为每个函数编写了两个日志记录语句。一个将条目记录到函数中,另一个记录退出。我们的想法是追踪执行路径 - 至少是一个功能级别。

有没有办法在不乱丢整个代码库的情况下完成这些重复的语句?

要清楚,我们要记录所有函数,而不仅仅是Spring bean的公共方法。

2 个答案:

答案 0 :(得分:4)

您可以使用Spring AOP执行此操作。

Spring AOP允许您在方法调用之前和/或之后“拦截”方法调用并执行任意代码。您还可以检查这些方法的参数和返回值。

要实现您正在谈论的日志记录,您可以使用around advice执行此类操作:

  1. 拦截所有方法调用(或者最好只删除您感兴趣的方法调用)。
  2. 执行'before method'记录。
  3. 调用方法。
  4. 执行'after method'记录。
  5. 有关如何执行此操作的所有Spring详细信息都可以在提供的文档中找到。

答案 1 :(得分:0)

与尼古拉斯相同的想法。你可以使用Spring AOP来做到这一点。

我喜欢使用注释,因此逻辑在源代码中指定,而不是在方面的建议中。

定义注释

package aop;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Traceable {}

定义方面

package aop;
@Aspect
public class TraceableAspect {

    private final static AtomicLong Count = new AtomicLong(0);

    @Around("execution(* *(..)) && @annotation(aop.Traceable)")
    public Object aroundTraceableMethod(ProceedingJoinPoint pjp) throws Throwable {

        Logger logger = LoggerFactory.getLogger(pjp.getTarget().getClass());
        if (logger.isTraceEnabled()) {
            return executeWithTrace(pjp, logger, Count.incrementAndGet());
        }

        return pjp.proceed();
    }

    private Object executeWithTrace(ProceedingJoinPoint pjp, Logger logger, long id) throws Throwable {

        long start = System.currentTimeMillis();
        try {
            logger.trace(String.format("#### - #%d - Starting execution of method '%s'", id, pjp.toShortString()));
            return pjp.proceed();
        } catch (Throwable throwable) {
            logger.error(String.format("#### - #%d - Error while executing method '%s' : %s", id, pjp.toShortString(), throwable.toString()));
            throw throwable;
        } finally {
            if (logger.isTraceEnabled()) {
                logger.trace(String.format("#### - #%d - End of method '%s' (duration %s ms)", id, pjp.toShortString(), (System.currentTimeMillis() - start)));
            }
        }
    }    
}

使用Spring Boot项目中的方面

package project;
@Profile("with-trace-aop")
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class SecToolWebApplicationTraceableAspect extends aop.TraceableAspect {

    @PostConstruct
    public void init(){
        Logger logger = LoggerFactory.getLogger(this.getClass());
        logger.warn("###-AOP-### TraceableAspect initialized for this application");
    }
}

**控制器中的跟踪方法

package project;
@RestController
public class ModelController {

    @Traceable
    @RequestMapping(method = RequestMethod.GET, value = "/{date}")
    @ResponseBody
    public <Collection<TE> find(@PathVariable @DateTimeFormat(pattern = DateUtils.DATE_FORMAT) Date date) {
    ...
    }
}

重要当某个类与建议相关联时,不再调用所有“最终”方法。重要的是不要使用“最终”

因此,假设启用了TRACE模式日志,将跟踪方法“find”的每次调用

如果

,请注意这不起作用