使用 Spring 引导和 AOP 进行性能记录
Performance Logging with Spring Boot and AOP
我正在尝试基于此 post 实现性能日志记录:http://www.baeldung.com/spring-performance-logging. I'd like to log each controller endpoint and every database request. If you would like to see the full project, you can find it here。当我到达端点时,没有任何记录。在拦截器中放置一个断点 class 它也不会停止。我已经将包的日志记录设置为跟踪级别。我错过了什么?我相信这与 @PointCut
有关,但在查看文档后我相信我是正确的。
拦截器
public class PerformanceMonitorInterceptor extends AbstractMonitoringInterceptor
{
@Override
protected Object invokeUnderTrace(MethodInvocation methodInvocation, Log log) throws Throwable
{
String name = createInvocationTraceName(methodInvocation);
StopWatch stopWatch = new StopWatch();
stopWatch.start();
log.trace(String.format("Method %s execution start at %s", name, LocalDateTime.now()));
try
{
return methodInvocation.proceed();
}
finally
{
stopWatch.stop();
log.trace(String.format("Method %s execution took %dms (%s)", name,
stopWatch.getTotalTimeMillis(), DurationFormatUtils
.formatDurationWords(stopWatch.getTotalTimeMillis(), true, true)));
}
}
}
配置
@Configuration
@EnableAspectJAutoProxy
@Aspect
public class ContactControllerPerfLogConfig
{
@Bean
public PerformanceMonitorInterceptor performanceMonitorInterceptor()
{
return new PerformanceMonitorInterceptor();
}
// Any public method on the ContactController
@Pointcut("execution(public * org.example.phonebookexample.app.contact.ContactController.*(..))")
public void contactControllerMonitor()
{
}
@Bean
public Advisor contactControllerMonitorAdvisor(
PerformanceMonitorInterceptor performanceMonitorInterceptor)
{
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("org.example.phonebookexample.app.contact.ContactControllerPerfLogConfig.contactControllerMonitor()");
return new DefaultPointcutAdvisor(pointcut, performanceMonitorInterceptor);
}
}
AbstractTraceInterceptor
实现了 MethodInterceptor
并且其 invoke()
方法实现如下:
public Object invoke(MethodInvocation invocation) throws Throwable {
Log logger = getLoggerForInvocation(invocation);
if (isInterceptorEnabled(invocation, logger)) {
return invokeUnderTrace(invocation, logger);
}
else {
return invocation.proceed();
}
}
因此需要将拦截器 class 的记录器设置为 TRACE
。对于基本 PerformanceMonitorInterceptor
,那将是 org.springframework.aop.interceptor.PerformanceMonitorInterceptor
。由于您已经编写了自己的拦截器,因此您必须为自己的 class 设置日志记录级别。
查看 JamonPerformanceMonitorInterceptor
的替代方法示例,如果需要,可以跟踪所有调用,而不管日志级别如何。
为了完整起见,我还将post一个xml配置示例,因为涉及到AOP时,Spring java配置不是这样的与 xml 配置相比优雅:
<bean id="performanceMonitorInterceptor" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>
<aop:config>
<aop:pointcut id="contactControllerMonitor" expression="execution(public * org.example.phonebookexample.app.contact.ContactController.*(..))" />
<aop:advisor id="contactControllerMonitorAdvisor" pointcut-ref="contactControllerMonitor" advice-ref="performanceMonitorInterceptor"/>
</aop:config>
此配置可以导入到您的 java 配置中,如下所示:
@ImportResource("classpath:/aop-config.xml")
public class MainConfig { ... }
如果您要自定义它,我一直不明白 AbstractTraceInterceptor
的重要性。
我总觉得代码对我来说太多了,如果您已经有 @Aspect
,可以通过一个简单的 @Around
建议来实现。
@Around("execution(* com..*.*(..))")
public Object logStartAndEnd(ProceedingJoinPoint pjp) throws Throwable{
long startTime = System.currentTimeMillis();
String className = pjp.getTarget().getClass().getCanonicalName();
String methodName = pjp.getSignature().getName();
log.info("started method : " + className+"."+methodName);
Object obj;
try {
obj = pjp.proceed();
log.info("finished method : " + className+"."+methodName);
return obj;
} catch (Throwable e) {
throw e;
}finally {
log.info("Method "+className+"."+methodName+" execution lasted:"+((System.currentTimeMillis() - startTime )/1000f)+" seconds");
}
}
我正在尝试基于此 post 实现性能日志记录:http://www.baeldung.com/spring-performance-logging. I'd like to log each controller endpoint and every database request. If you would like to see the full project, you can find it here。当我到达端点时,没有任何记录。在拦截器中放置一个断点 class 它也不会停止。我已经将包的日志记录设置为跟踪级别。我错过了什么?我相信这与 @PointCut
有关,但在查看文档后我相信我是正确的。
拦截器
public class PerformanceMonitorInterceptor extends AbstractMonitoringInterceptor
{
@Override
protected Object invokeUnderTrace(MethodInvocation methodInvocation, Log log) throws Throwable
{
String name = createInvocationTraceName(methodInvocation);
StopWatch stopWatch = new StopWatch();
stopWatch.start();
log.trace(String.format("Method %s execution start at %s", name, LocalDateTime.now()));
try
{
return methodInvocation.proceed();
}
finally
{
stopWatch.stop();
log.trace(String.format("Method %s execution took %dms (%s)", name,
stopWatch.getTotalTimeMillis(), DurationFormatUtils
.formatDurationWords(stopWatch.getTotalTimeMillis(), true, true)));
}
}
}
配置
@Configuration
@EnableAspectJAutoProxy
@Aspect
public class ContactControllerPerfLogConfig
{
@Bean
public PerformanceMonitorInterceptor performanceMonitorInterceptor()
{
return new PerformanceMonitorInterceptor();
}
// Any public method on the ContactController
@Pointcut("execution(public * org.example.phonebookexample.app.contact.ContactController.*(..))")
public void contactControllerMonitor()
{
}
@Bean
public Advisor contactControllerMonitorAdvisor(
PerformanceMonitorInterceptor performanceMonitorInterceptor)
{
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("org.example.phonebookexample.app.contact.ContactControllerPerfLogConfig.contactControllerMonitor()");
return new DefaultPointcutAdvisor(pointcut, performanceMonitorInterceptor);
}
}
AbstractTraceInterceptor
实现了 MethodInterceptor
并且其 invoke()
方法实现如下:
public Object invoke(MethodInvocation invocation) throws Throwable {
Log logger = getLoggerForInvocation(invocation);
if (isInterceptorEnabled(invocation, logger)) {
return invokeUnderTrace(invocation, logger);
}
else {
return invocation.proceed();
}
}
因此需要将拦截器 class 的记录器设置为 TRACE
。对于基本 PerformanceMonitorInterceptor
,那将是 org.springframework.aop.interceptor.PerformanceMonitorInterceptor
。由于您已经编写了自己的拦截器,因此您必须为自己的 class 设置日志记录级别。
查看 JamonPerformanceMonitorInterceptor
的替代方法示例,如果需要,可以跟踪所有调用,而不管日志级别如何。
为了完整起见,我还将post一个xml配置示例,因为涉及到AOP时,Spring java配置不是这样的与 xml 配置相比优雅:
<bean id="performanceMonitorInterceptor" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>
<aop:config>
<aop:pointcut id="contactControllerMonitor" expression="execution(public * org.example.phonebookexample.app.contact.ContactController.*(..))" />
<aop:advisor id="contactControllerMonitorAdvisor" pointcut-ref="contactControllerMonitor" advice-ref="performanceMonitorInterceptor"/>
</aop:config>
此配置可以导入到您的 java 配置中,如下所示:
@ImportResource("classpath:/aop-config.xml")
public class MainConfig { ... }
如果您要自定义它,我一直不明白 AbstractTraceInterceptor
的重要性。
我总觉得代码对我来说太多了,如果您已经有 @Aspect
,可以通过一个简单的 @Around
建议来实现。
@Around("execution(* com..*.*(..))")
public Object logStartAndEnd(ProceedingJoinPoint pjp) throws Throwable{
long startTime = System.currentTimeMillis();
String className = pjp.getTarget().getClass().getCanonicalName();
String methodName = pjp.getSignature().getName();
log.info("started method : " + className+"."+methodName);
Object obj;
try {
obj = pjp.proceed();
log.info("finished method : " + className+"."+methodName);
return obj;
} catch (Throwable e) {
throw e;
}finally {
log.info("Method "+className+"."+methodName+" execution lasted:"+((System.currentTimeMillis() - startTime )/1000f)+" seconds");
}
}