perf4j @Profiled 注释不起作用

发布于 2024-10-25 06:40:20 字数 1510 浏览 4 评论 0原文

我已经通过 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;
    }
}

我错过了什么吗?

I have gone thru the below link from perf4J site and have done same to same: http://perf4j.codehaus.org/devguide.html#Using_Spring_AOP_to_Integrate_Timing_Aspects

Added the following in my spring.xml.

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

In class WscClientBase I have the following method with @Profiled annotation.

@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;
    }
}

I dont see the perf4j TimingLogger statements in the application log. However if I use it obtrusively (without annotation) as below, I see the log statements successfully.

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;
    }
}

Am I missing something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

盛夏已如深秋| 2024-11-01 06:40:31

将配置放在下面的“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"/>

put config below in your "servlet-context-config.xml" .have fun!

    <aop:aspectj-autoproxy/>
    <bean id="timingAspect" class="org.perf4j.log4j.aop.TimingAspect"/>
    <bean id="wscClientBase" class="com.xyz.csa.core.common.WscClientBase"/>
你如我软肋 2024-11-01 06:40:31

对于遇到此类问题的人,他们可以检查 Spring 日志(级别信息)中是否没有类似的消息“不符合所有 BeanPostProcessors 的处理条件(例如:不符合自动代理的条件)”。

For people who have this type of problem they can check that there is not in spring logs (level info), messages like it " is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)".

杀手六號 2024-11-01 06:40:30

这里我有两种方法让 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 项目,可能需要添加更多依赖项,例如 spring-aop、aopalliance...这些看起来包含在 spring-boot-starter-parent

1 中。 Java配置

这是最简单的方法并且大部分有效,但我发现不知何故不适用于 spring-data JpaRepository 方法。它只提供org.perf4j.log4j.aop.TimingAspect bean并进行aspectj自动代理。与上面其他人提供的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;
    }
}

Here I have two ways to make perf4j @Profiled work on spring boot project.
Precondition is adding below dependencies

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

For normal spring project, probably need to add little more dependencies like spring-aop, aopalliance... those looks included in spring-boot-starter-parent

1. Java Configuration

This is simplest way and mostly works, but I found that somehow not working on spring-data JpaRepository method. It just provides org.perf4j.log4j.aop.TimingAspect bean and do aspectj autoproxing. Same way like xml configuration provided by other people above

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

2. Provide Your own Aspect

In this way, the @Profiled annotated spring-data repository interface methods also work fine. But the downside of this is ignoring the tag given in @Profiled(tag='some tag') and using the joinPoint method name as tag.

@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;
    }
}
雪化雨蝶 2024-11-01 06:40:30

它无法工作的原因是分析方法位于 Spring-bean 的父类中。我可以通过查看您的 bean 名称来判断:WscClientBase。我假设这是一个基类,其中有许多子类。

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

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

“使用代理时,您应该应用<>”注释仅用于
具有公众可见性的方法。如果您确实注释了 protected、private
或带有这些注释的包可见方法,不会引发错误,
但带注释的方法没有展示配置的缓存
设置。如果需要,请考虑使用 AspectJ(见下文)
在非公共方法更改字节码本身时对其进行注释。”

而下面……

“Spring 建议您仅注释具体类(并且
具体类的方法)与 @Cache* 注释
,相反
来注释接口。你当然可以放置@Cache*
接口(或接口方法)上的注释,但这有效
仅当您使用基于接口时才如您所期望的那样
代理。 Java 注释不是继承自的事实
接口意味着如果您使用基于类的代理
(proxy-target-class="true") 或基于编织的方面 (
mode="aspectj"),则缓存设置无法被识别
代理和编织基础设施,并且该对象不会
封装在缓存代理中,这绝对是糟糕的。”

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

The reason why it could not work is that the profiled method is in the parent class of the Spring-bean. I can tell it by looking at your bean name: WscClientBase. I assume that this is base class from which you have many children classes.

After some research time I found very important note in Spring documentation about @Transactional and @Cacheable.

In both cases they say things like this:

“When using proxies, you should apply the <> annotations only to
methods with public visibility. If you do annotate protected, private
or package-visible methods with these annotations, no error is raised,
but the annotated method does not exhibit the configured caching
settings. Consider the use of AspectJ (see below) if you need to
annotate non-public methods as it changes the bytecode itself.”

And below…

“Spring recommends that you only annotate concrete classes (and
methods of concrete classes) with the @Cache* annotation
, as opposed
to annotating interfaces. You certainly can place the @Cache*
annotation on an interface (or an interface method), but this works
only as you would expect it to if you are using interface-based
proxies. The fact that Java annotations are not inherited from
interfaces means that if you are using class-based proxies
(proxy-target-class="true") or the weaving-based aspect (
mode="aspectj"), then the caching settings are not recognized by the
proxying and weaving infrastructure, and the object will not be
wrapped in a caching proxy, which would be decidedly bad.”

I assume that @Profiled use similar weaving mechanism therefore you can't put @Profiled on any method in parent classes.
As a matter of fact I had similar issue in my application: I had @Profiled and @Cacheable in parent class and none of those worked: I didn't see any records in my Perf4J log and cache wasn't updated. When I moved @Profiled into methods of children-classes I started seeing the records in the perf4j.log.

谈场末日恋爱 2024-11-01 06:40:29

尝试在 内添加 <aop:include name="timingAspect"/>

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

Try adding <aop:include name="timingAspect"/> inside the <aop:aspectj-autoproxy/>.

Can you also confirm that you are invoking sendMessage on an object that is retrieved from the spring application context (using getBean or injected as a dependency).

猛虎独行 2024-11-01 06:40:28

Perf4j

这是一个应用程序的性能分析和检查插件。可以使用spring AOP与spring集成。它创建一个日志文件,提供给解析器来分析和生成相关信息。默认可以提供平均值、均值、标准差。
有关更多一般信息,请查看http://perf4j.codehaus.org/index.html

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

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

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

本文档的主要目的是通过设置了解 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.创建您自己的 logback.xml,它将被 perf4j 隐式使用
logback.xml 的内容将为

<configuration>
    <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>

    <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>

    <!-- 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。在您的 spring 配置文件中,您需要添加aspectj 标签,该标签将启用perf4j 的@Profiled 注释。

(注意:什么是@Profiled注释?:您将将此标签添加到所有
从 spring 实例调用或使用的所有类中的方法
依赖注入。该对象基本上应该是 spring 上下文
注册并且该方法应该由被注册的对象调用
在 spring 上下文中注册。我花了一天的时间思考为什么我的方法
没有记录然后我意识到我测试的对象不是一部分
Spring 上下文。

好的,您需要添加到 spring 配置 xml 的代码是

<!-- 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.好了,现在你已经设置好了所有东西,剩下的就是测试类,它将启动 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 控制台附加程序在控制台上显示一行。

Perf4j 日志上的监控命令:

用于生成性能统计信息 在您的记录器路径上执行

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 注释集成。

Perf4j

This is a performance analysis and checking plugin for application. It can be integrated with spring using spring AOP. It creates a log file that is give to a parser to analyse and produce relevant information. It can provide average,mean, std deviation by default.
For more general information please check http://perf4j.codehaus.org/index.html

How to setup Perf4j.
For normal setup you just need to add perf4j jar and create StopWatch instance for every code sniplet you want to monitor.

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

This will create perf4j monitor and you will get logg information on the console.

Main purpose of this documentation is to have a setup by setup understanding of integrating perf4j with spring.

1.Add all of the below Jar files.

   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

Make sure you have all these jars in your classpath along with spring libraries.

2.create your own logback.xml that will be used by perf4j implicitly
the content of the logback.xml will be

<configuration>
    <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>

    <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>

    <!-- 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.In your spring configuration file you need to add aspectj tag that will enable @Profiled annotation of perf4j.

(Note: What is @Profiled annotation?: you will add this tag to all the
methods in all the classes that are called from spring instance or use
dependency injection. The object basically should be spring context
registered and the method should be invoked by the object that are
registered in spring context. I wasted one day thinking why my method
was not logged then I realized that the object I tested was not part
of spring context.

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.Create the Test class that will implement @Profiled annotation.

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 now you have setup every thing just thing remains is test class that will start spring context and with it load 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();
}

I hope by following these setups you should be able to perf4j console appender to display one line on console.

Perf4j Monitoring command on the log:

For Generating Performance statistical information execute on you logger path

java -jar perf4j-0.9.16.jar myLogger.log

For Generating Graphs

java -jar perf4j-0.9.16.jar --graph perfGraphs.out myLogger.log

I hope this tutorial helps you to integrated Spring, perf4j, logback with Profiled annotation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文