perf4j @Профилированная аннотация не работает
Я перешел по приведенной ниже ссылке с сайта perf4J и сделал то же самое с тем же: http://perf4j.codehaus.org/devguide.html
Добавил следующее в мой 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 ответов
Perf4j Это плагин для анализа производительности и проверки приложения. Он может быть интегрирован с пружиной с помощью пружины AOP. Он создает файл журнала, который передается анализатору для анализа и выдачи соответствующей информации. Это может обеспечить среднее, среднее, стандартное отклонение по умолчанию. Для получения более общей информации, пожалуйста, проверьте http://perf4j.codehaus.org/index.html
Как настроить Perf4j. Для нормальной настройки вам просто нужно добавить perf4j jar и создать экземпляр StopWatch для каждого фрагмента кода, который вы хотите отслеживать.
StopWatch stopWatch= new StopWatch(“snipletTagName”)
…
//{your code sniplet}
…
stopwatch.stop();
Это создаст монитор perf4j, и вы получите информацию о входе в систему на консоли.
Основная цель этой документации - получить настройку с пониманием интеграции perf4j с пружиной.
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
Убедитесь, что у вас есть все эти фляги на вашем пути к классу вместе с библиотекой Spring. 2. создайте свой собственный logback.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, который включит аннотацию @Profiled для perf4j.
**> (Примечание: что такое аннотация @Profiled?: вы добавите этот тег ко всем
методы во всех классах, которые вызываются из экземпляра 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. Создайте класс Test, который будет реализовывать аннотацию @Profiled.
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 appender.
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.
Попробуйте добавить < aop:include name="timingAspect"/>
внутри <aop:aspectj-autoproxy/>
,
Можете ли вы также подтвердить, что вы вызываете sendMessage для объекта, который извлекается из контекста весеннего приложения (используя getBean или внедряется как зависимость).
Здесь у меня есть два способа заставить perf4j @Profiled работать над проектом весенней загрузки. Условием является добавление ниже зависимостей
"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. Он просто предоставляет bean- компонент org.perf4j.log4j.aop.TimingAspect и выполняет автоматическую прокси-функцию aspectj. Точно так же, как конфигурация xml, предоставленная другими людьми выше
@Configuration
@EnableAspectJAutoProxy
public class PerformanceConfig {
@Bean
public TimingAspect timingAspect() {
return new TimingAspect();
}
}
2. Предоставьте свой собственный аспект
Таким образом, методы интерфейса аннотированного источника данных в аннотации @Profiled также работают нормально. Но недостатком этого является игнорирование тега, указанного в @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;
}
}
Поместите конфигурацию ниже в ваш "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"/>
Для людей, у которых есть этот тип проблемы, они могут проверить, что в журналах пружин нет (информация об уровне), такие сообщения "не могут обрабатываться всеми BeanPostProcessors (например, не имеют права на автоматическое проксирование)".
Причина, по которой он не может работать, заключается в том, что профилированный метод находится в родительском классе Spring-bean-компонента. Я могу сказать это, посмотрев на ваше имя бина: WscClientBase. Я предполагаю, что это базовый класс, из которого у вас много детских классов.
После некоторого времени исследования я нашел очень важную заметку в документации Spring о @Transactional и @Cacheable.
- http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/transaction.html. Проверьте блок "Видимость метода и @Transactional".
- http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html. Проверьте "Видимость метода и аннотации кеша"
В обоих случаях они говорят такие вещи:
"При использовании прокси вы должны применять аннотации<> только к методам с публичной видимостью. Если вы аннотируете защищенные, закрытые или видимые пакетами методы с этими аннотациями, ошибка не возникает, но аннотированный метод не отображает настроенные параметры кэширования. Рассмотрите возможность использования AspectJ (см. Ниже), если вам нужно аннотировать непубличные методы, так как он изменяет сам байт-код ".
И ниже…
"Spring рекомендует аннотировать @ Cache * только конкретные классы (и методы конкретных классов), а не аннотировать интерфейсы. Вы, конечно, можете разместить аннотацию @ Cache * на интерфейсе (или методе интерфейса), но это работает только так, как вы ожидаете, если вы используете прокси на основе интерфейса. Тот факт, что аннотации Java не наследуются от интерфейсов, означает, что если вы используете прокси на основе классов (proxy-target-class="true") или аспект на основе ткачества ( mode="aspectj"), то параметры кэширования не распознается инфраструктурой прокси и ткачества, и объект не будет обернут в кеширующий прокси, что было бы явно плохо ".
Я предполагаю, что @Profiled использует похожий механизм ткачества, поэтому вы не можете поместить @Profiled ни в какой метод родительских классов. На самом деле у меня была похожая проблема в моем приложении: у меня были @Profiled и @Cacheable в родительском классе, и ни одна из них не работала: я не видел никаких записей в моем журнале Perf4J, и кэш не обновлялся. Когда я переместил @Profiled в методы дочерних классов, я начал видеть записи в perf4j.log.