perf4j @Profiled注释不起作用

时间:2011-03-24 04:20:21

标签: spring log4j seam spring-aop perf4j

我已通过perf4J网站的以下链接,并完成相同的操作:http://perf4j.codehaus.org/devguide.html#Using_Spring_AOP_to_Integrate_Timing_Aspects

在spring.xml中添加了以下内容。

<aop:aspectj-autoproxy/>
<bean id="timingAspect" class="org.perf4j.log4j.aop.TimingAspect"/>
<bean id="wscClientBase" class="com.xyz.csa.core.common.WscClientBase"/>

在WscClientBase类中,我使用 @Profiled 注释获得以下方法。

@Profiled(tag = "SOAPCALLTEST")
public Object sendMessage(Object message) {
    String msg = message.toString();
    if (msg.indexOf(' ') > 1) {
        msg = msg.substring(1, msg.indexOf(' '));
    }
    try {
        Object ret = marshalSendAndReceive(message);
        return ret;
    } catch (RuntimeException ex) {
        throw ex;
    }
}

我在应用程序日志中没有看到perf4j TimingLogger语句。但是,如果我如下所示使用它(没有注释),我会成功地看到日志语句。

public Object sendMessage(Object message) {
    String msg = message.toString();
    if (msg.indexOf(' ') > 1) {
        msg = msg.substring(1, msg.indexOf(' '));
    }
    StopWatch stopWatch = new Slf4JStopWatch();
    try {
        Object ret = marshalSendAndReceive(message);
        stopWatch.stop("PERF_SUCCESS_TAG", msg);
        return ret;
    } catch (RuntimeException ex) {
        stopWatch.stop("PERF_FAILURE_TAG", msg);
        throw ex;
    }
}

我错过了什么吗?

6 个答案:

答案 0 :(得分:9)

<强>的Perf4 这是一个应用程序的性能分析和检查插件。它可以使用弹簧AOP与弹簧集成。它创建一个日志文件,供分析人员分析和生成相关信息。默认情况下,它可以提供平均值,平均值,标准偏差。 有关更多一般信息,请查看http://perf4j.codehaus.org/index.html

如何设置Perf4j。 对于正常设置,您只需添加perf4j jar并为要监视的每个代码片段创建StopWatch实例。

StopWatch stopWatch= new StopWatch(“snipletTagName”)
…
//{your code sniplet}
…
stopwatch.stop();

这将创建perf4j监视器,您将在控制台上获取logg信息。

本文档的主要目的是通过设置理解将perf4j与spring集成来进行设置。

1.添加所有Jar文件。

 1. perf4j-0.9.16-slf4jonly.jar
    2.aspectjweaver-1.6.12.jar
    3.aopalliance-1.0.jar
    4.commons-logging-1.1.1.jar
    5.logback-classic-1.0.7.jar
    6.logback-core-1.0.7.jar
    7.slf4j-api-1.7.1.jar
    8.perf4j-0.9.16.jar
    9.aspectjrt-1.6.1.jar
    10.commons-jexl-1.1.jar
    11.asm-1.5.3.jar
    12.cglib-2.1_3.jar

确保在类路径中包含所有这个jar以及spring库。 2.创建你自己的backback.xml,它将由perf4j隐式使用 logback.xml的内容将是

<configuration>

    <appender name="CoalescingStatistics"
        class="org.perf4j.logback.AsyncCoalescingStatisticsAppender">
        <param name="TimeSlice" value="1" />        
        <appender-ref ref="perf4jFileAppender" />       
    </appender>

    <appender name="RootConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%date %-5level [%thread] %logger{36} [%file:%line] %msg%n
            </pattern>
        </layout>
    </appender>

    <appender name="perf4jFileAppender"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>logs/perf4j.log</File>
        <encoder>
            <Pattern>%date %-5level [%thread] %logger{36} [%file:%line] %msg%n
            </Pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>logs/perf4j.%d{yyyy-MM-dd}.log</FileNamePattern>
        </rollingPolicy>
    </appender>

    <!-- Loggers -->
    <!-- The Perf4J logger. Note that org.perf4j.TimingLogger is the value of 
        the org.perf4j.StopWatch.DEFAULT_LOGGER_NAME constant. Also, note that additivity 
        is set to false, which is usually what is desired - this means that timing 
        statements will only be sent to this logger and NOT to upstream loggers. -->
    <logger name="org.perf4j.TimingLogger" additivity="false">
        <level value="DEBUG" />
        <appender-ref ref="CoalescingStatistics" />
        <appender-ref ref="perf4jFileAppender" />
        <appender-ref ref="RootConsoleAppender" />
    </logger>
</configuration>

3.在弹簧配置文件中,您需要添加aspectj标签,以启用perf4j的@Profiled注释。

**指(注意:什么是@Profiled注释?:您将此标记添加到所有

  

从spring实例或use中调用的所有类中的方法   依赖注入。该对象基本上应该是spring上下文   注册并且该方法应该由对象调用   在春天的背景下注册。有一天我浪费思考为什么我的方法   没有记录然后我意识到我测试的对象不是一部分   春天的背景。**

OK the code that you need to add to spring configuration xml is.

<!-- this is my spring-context.xml -->
<beans>
….
    <aop:aspectj-autoproxy>
        <aop:include name="timingAspect" />
    </aop:aspectj-autoproxy>

    <bean id="timingAspect" class="org.perf4j.slf4j.aop.TimingAspect" />

<!-- this is the class that will be registered with the spring and now we can get this class and call the method that we need to monitor-->
    <bean class="com.perf4jexample.Test" />
….
</beans>

4.创建将实现@Profiled注释的Test类。

public class Test {

    private String testVal;

    public Test() {
        // TODO Auto-generated constructor stub
    }

    @Profiled
    public void testing() {
        System.out.println("testt" );
    }

    public String getTestVal() {
        return testVal;
    }

    public void setTestVal(String testVal) {
        this.testVal = testVal;
    }
}

5.Ok现在你已经设置了所有东西,只剩下的是测试类,它将启动spring上下文并加载perf4j。

public class Test(){

public static void main(){
        AbstractApplicationContext context = new ClassPathXmlApplicationContext(
                "spring-context.xml");

        context.start();

        Test bean = context.getBean(Test.class);
        bean.testing();
}

我希望通过遵循这些设置,您应该能够在控制台上显示一行的perf4j控制台appender。

日志上的Perf4j Monitoring命令 对于生成性能统计信息在您的记录器路径上执行 java -jar perf4j-0.9.16.jar myLogger.log

用于生成图表 java -jar perf4j-0.9.16.jar --graph perfGraphs.out myLogger.log

我希望本教程可以帮助您将Spring,perf4j,logback与Profiled注释集成在一起。

答案 1 :(得分:2)

尝试在aop:include name="timingAspect"/>中添加&lt; <aop:aspectj-autoproxy/>

您是否还可以确认您正在从spring应用程序上下文中检索的对象上调用sendMessage(使用getBean或作为依赖项注入)。

答案 2 :(得分:1)

这里我有两种方法可以让perf4j @Profiled 在spring boot项目上工作。 前提条件是添加以下依赖项

"org.aspectj:aspectjweaver",
"org.perf4j:perf4j:0.9.16",
"commons-jexl:commons-jexl:1.1",
"cglib:cglib:3.2.1",

对于普通的春季项目,可能需要添加更多的依赖项,如spring-aop,aopalliance ......那些看起来包含在spring-boot-starter-parent

<强> 1。 Java配置

这是最简单的方法,并且大部分都有效,但我发现不知何故不使用spring-data JpaRepository方法。它只提供 org.perf4j.log4j.aop.TimingAspect bean并执行aspectj autoproxing。与上面其他人提供的xml配置相同

@Configuration
@EnableAspectJAutoProxy
public class PerformanceConfig {
    @Bean
    public TimingAspect timingAspect() {
        return new TimingAspect();
    }
}

<强> 2。提供您自己的方面

通过这种方式, @Profiled 带注释的spring-data存储库接口方法也可以正常工作。但缺点是忽略 @Profiled(tag ='some tag')中的标记,并使用joinPoint方法名作为标记。

@Aspect
@Component
public class PerformanceTracker {

    @Around(value="execution(@org.perf4j.aop.Profiled * com.mypackage..*(..))")
    public Object checkPerformance(ProceedingJoinPoint pjp) throws Throwable {
        StopWatch stopWatch = new Log4JStopWatch(pjp.getSignature().toShortString());
        Object result = pjp.proceed();
        stopWatch.stop();
        return result;
    }
}

答案 3 :(得分:0)

它无法工作的原因是profiled方法位于Spring-bean的父类中。我可以通过查看你的bean名称来告诉它:WscClientBase。我假设这是一个基类,你有很多子类。

经过一段时间的研究,我在Spring文档中发现了关于@Transactional和@Cacheable的非常重要的注意事项。

在这两种情况下,他们都会这样说:

  

“使用代理时,您应该应用&lt;&gt;注释仅限于   公众可见度的方法。如果你注释protected,私有   或带有这些注释的包可见方法,不会引发错误,   但带注释的方法不会显示已配置的缓存   设置。如果需要,请考虑使用AspectJ(见下文)   注释非公共方法,因为它改变了字节码本身。“

以下......

  

“Spring建议您仅注释具体类(和   使用@Cache * annotation 的具体类的方法,而不是   注释接口。你当然可以放置@Cache *   接口(或接口方法)上的注释,但这是有效的   只有在你使用基于接口的情况下才会如你所愿   代理。 Java注释不是从中继承的事实   接口意味着如果您使用基于类的代理   (proxy-target-class =&#34; true&#34;)或基于编织的方面(   mode =&#34; aspectj&#34;),然后无法识别缓存设置   代理和编织基础设施,而对象不会   包装在缓存代理中,这将是非常糟糕的。“

我认为@Profiled使用类似的编织机制,因此您不能将@Profiled放在父类中的任何方法上。 事实上,我在我的应用程序中遇到了类似的问题:我在父类中有@Profiled和@Cacheable,但没有一个工作:我没有看到我的Perf4J日志中的任何记录,并且缓存没有更新。当我将@Profiled移动到子类的方法时,我开始在perf4j.log中看到记录。

答案 4 :(得分:0)

将下面的配置放在“ servlet-context-config.xml ”中。好玩!

    <aop:aspectj-autoproxy/>
    <bean id="timingAspect" class="org.perf4j.log4j.aop.TimingAspect"/>
    <bean id="wscClientBase" class="com.xyz.csa.core.common.WscClientBase"/>

答案 5 :(得分:0)

对于遇到此类问题的人,他们可以检查春季日志中没有(级别信息),类似的消息&#34;不适合所有BeanPostProcessors处理(例如:不符合自动代理条件)&#34;。