Что я хотел бы сделать, это следующее: Отображение статистики вызовов (в основном количество вызовов и среднее время вызова) через JMX. Проблема в том, что я хотел бы сделать это с поддержкой AspectJ (чтобы автоматически вычислить его для моих классов реализации).Программная публикация статистики вызовов с помощью JMX
То, что я создал это JmxBean:
public class JmxStatistics implements Serializable {
private final String name;
private long errorCount;
private long errorCallTime;
private long successCount;
private long successCallTime;
public JmxStatistics(String name) {
this.name = name;
}
public synchronized long getCallCount() {
return errorCount + successCount;
}
public synchronized long getAvgCallTimeInMillisecs() {
return (errorCallTime + successCallTime)/getCallCount();
}
public synchronized long getAvgSuccessfulCallTimeInMillisecs() {
return (errorCallTime + successCallTime)/successCount;
}
public synchronized long getAvgFailedCallTimeInMillisecs() {
return (errorCallTime + successCallTime)/errorCount;
}
public synchronized void increaseErrorCallTime(long sumCallTime) {
this.errorCallTime += sumCallTime;
}
public synchronized void increaseSuccessCallTime(long sumCallTime) {
this.successCallTime += sumCallTime;
}
public synchronized long getErrorCount() {
return errorCount;
}
public synchronized void incrementErrorCount() {
this.errorCount++;
}
public synchronized long getSuccessCount() {
return successCount;
}
public synchronized void incrementSuccessCount() {
this.successCount++;
}
@Override
public String toString() {
return name + "{" + "callCount=" + getCallCount()
+ " (s: " + successCount + ",e:" + errorCount + "); "
+ "avgCallTime=" + getAvgCallTimeInMillisecs() + "ms "
+ "(" + getAvgSuccessfulCallTimeInMillisecs() + "ms;e:" + getAvgFailedCallTimeInMillisecs() + "ms)" + "}";
}
Точка АОП обертывание:
public Object wrap(ProceedingJoinPoint joinPoint) throws Throwable {
JmxStatistics jmxs = store.getStatisticsBean(joinPoint);
long start = System.currentTimeMillis();
Object result;
try {
result = joinPoint.proceed();
} catch (Throwable t) {
long runtime = System.currentTimeMillis() - start;
jmxs.incrementErrorCount();
jmxs.increaseErrorCallTime(runtime);
throw t;
}
long runtime = System.currentTimeMillis() - start;
jmxs.incrementSuccessCount();
jmxs.increaseSuccessCallTime(runtime);
return result;
}
И магазин для раскрытия всех (программно созданных) JMX бобов:
public class JmxStatisticsStore {
private final HashMap<String, JmxStatistics> jmxBeans = new HashMap<>();
public HashMap<String, JmxStatistics> getJmxBeans() {
return jmxBeans;
}
JmxStatistics getStatisticsBean(ProceedingJoinPoint joinPoint) {
String id = joinPoint.getTarget().getClass().toString() + "." + joinPoint.getSignature().getName();
if (!jmxBeans.containsKey(id)) {
synchronized (jmxBeans) {
if (!jmxBeans.containsKey(id)) {
JmxStatistics jmxStatistics = new JmxStatistics(id);
jmxBeans.put(id, jmxStatistics);
}
}
}
return jmxBeans.get(id);
}
}
Я хотел бы использовать Spring AOP и MBeanExporter для этого. Моя конфигурация выглядит следующим образом:
<bean id="jmxStatisticsStore" class="package.JmxStatisticsStore"/>
<bean id="jmxAspect" class="package.AspectJJmxCalculator" />
<aop:config>
<aop:aspect id="jmxAspectId" ref="jmxAspect">
<aop:pointcut id="pointCutAround"
expression="execution(* jmx.tester..*.*(..))" />
<aop:around method="wrap" pointcut-ref="pointCutAround" />
</aop:aspect>
</aop:config>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="beans">
<map>
<entry key="bean:name=callStatistics" value-ref="jmxStatisticsStore"/>
</map>
</property>
</bean>
В настоящее время я пытаюсь запустить его в котом (пакет jmx.tester пружинный компонент, который я использую в веб-приложение). Webapp работает правильно, а с JConsole я могу подключиться к серверу. На сервере, под бобами, я могу видеть компонент callStatistics с атрибутом HashMap.
До тех пор, пока я не сделаю звонок, hashmap пуст (что хорошо) (в поле «Значение» он показывает {}) После того как я сделаю звонок (так что hashmap больше не пуст) Значение становится Недоступно, и если я пытаюсь вызвать метод getJmxBeans через JMX, я получаю следующее исключение:
Problem invoking getJmxBeans: java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: package.JmxStatistics (no security manager: RMI class loader disabled)
EDIT: Я хотел бы видеть, что вызовы для различных идентификаторов показывают, как отдельные атрибуты JMX ,
Есть ли способ сделать то, что я хочу достичь? Thx
Хммм ... будет проверить это позже, если это лучше, чем наше текущее решение – SzaboAdam