Perf4j @ Profiled annotation does not work

I followed the link below from perf4J and did the same: http://perf4j.codehaus.org/devguide.html#Using_Spring_AOP_to_Integrate_Timing_Aspects

In my spring.xml the following is added.

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

In the WscClientBase class, 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 do not see perf4j TimingLogger instructions in the application log. However, if I use it obsessively (without annotation), as shown below, I see successful magazine statements.

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

Did I miss something?

+6
spring spring-aop seam log4j perf4j
source share
6 answers

Perf4j This is a performance analysis and plugin test for the application. It can be integrated with spring using spring AOP. It creates a log file that gives the parser the analysis and obtaining the relevant information. By default, this can lead to an average, average std. For more general information, please check http://perf4j.codehaus.org/index.html

How to configure Perf4j. For normal setup, you just need to add the perf4j jar and create a StopWatch instance for each sniplet code that you want to control.

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

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

The main purpose of this documentation is to set the configuration by establishing an understanding of perf4j integrating with spring.

1. Add the entire Jar file.

  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 this jar in your class path along with the spring library. 2.Create your own logback.xml, which will be used by perf4j implicitly the contents of logback.xml will be

 <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. In your spring configuration file, you need to add the aspectj tag, which will allow @Profiled to annotate perf4j.

**> (Note: what is @Profiled annotation: you add this tag to all

in all classes called from a spring instance or using dependency injection. The object should basically be the spring context, and the method should be called by the object that is registered in the spring context. Once I spent money thinking about why my method was not registered, then I realized that the object I tested was not part of the 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 a Test class that will implement the @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 configure everything that remains, remains a test class that will launch the spring context and load perf4j with it.

 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, following these settings, you can transfer the console appender to display a single line on the console.

Perf4j Monitoring command in the log To generate performance statistics, log in your path java -jar perf4j-0.9.16.jar myLogger.log

To generate graphs java -jar perf4j-0.9.16.jar --graph perfGraphs.out myLogger.log

Hope this tutorial helps you integrate Spring, perf4j, logback with profiled annotation.

+9
source share

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

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

+2
source share

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

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

For a regular spring project, you probably need to add a little more dependencies such as spring-aop, aallalliance ... those included in spring-boot-starter-parent

1. Java configuration

This is the easiest way and basically works, but I found that somehow it doesn't work on the spring -data JpaRepository method. It just provides org.perf4j.log4j.aop.TimingAspect bean and does aspectj autoproxing. Same way as xml configuration provided by other people above

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

2. Provide your own aspect

Thus, the @Profiled handlers of the annotated spring-data repository also work fine. But the disadvantage of this is ignoring the tag specified in @Profiled (tag = 'some tag') and using the joinPoint method name as the 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; } } 
+1
source share

The reason it cannot work is because the profiled method is in the Spring's parent class, the bean. I can say this by looking at your bean: WscClientBase name. I assume this is a base class from which you have many child classes.

After some research time, I found a very important note in the Spring documentation on @Transactional and @Cacheable.

In both cases, they say things like this:

"When using a proxy, you should use annotations <> only for methods with public visibility. If you annotate protected, private or visible packages with these annotations, an error does not occur, but the annotated method does not show configured caching Settings. Consider using AspectJ (see Below) if you need to annotate non-public methods as it modifies the bytecode itself. "

And below ...

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

I assume that @Profiled uses a similar weaving mechanism, so you cannot put @Profiled on any method in parent classes. Actually, I had a similar problem in my application: I had @Profiled and @Cacheable in the parent class, and none of them worked: I did not see any entries in my Perf4J log, and the cache was not updated. When I moved @Profiled to the methods of the child classes, I started to see entries in the perf4j.log file.

0
source share

put the configuration below in your 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"/> 
0
source share

For people who have problems of this type, they can check if there are any spring (level information) in the logs, such messages as "cannot be processed by all BeanPostProcessors (for example: proxying)".

0
source share

All Articles