背景
一直在使用一款轻量级的APM监控工具:Javamelody。使用简单,监控数据还是挺多维度的,定期拉出来分析还是一件很有价值的事情。
但是Javamelody本身只对Http与Spring托管对象监控,还有很多我们自己的工具类或基础库没法监控起来。在阅读其部分源码后,写了一个扩展类,实现了监控项目的自定义操作。
话不多说,直接上代码:
代码
package net.bull.javamelody;//因MonitoringProxy类定义为了Package。此处的Package名称需要与net.bull.javamelody保持一置
import lombok.extern.slf4j.Slf4j;
import net.bull.javamelody.internal.model.Counter;
/**javamelody监控代理。在javamelody的基础上扩展部分监控项,用于一些自定义场景[或方法]的监控点。
* @author heshengchao
*/
@Slf4j
public class BusMonitorProxy {
/**默认Counter 都放到Spring下面
* @return
*/
public static Counter getCounter() {
return MonitoringProxy.getSpringCounter();
}
/** 自定义监控点
* @param monitorName 业务监控点名称
* @param call 回调函数
* @throws Exception
*/
public static void monitor(String monitorName,Function call) {
boolean systemError = false;//主要用于标记方法执行期间是否产生的异常。
try {
getCounter().bindContextIncludingCpu(monitorName);
call.call();
}catch (Throwable e) {
systemError = true;
throw new RuntimeException(e);
} finally {
getCounter().addRequestForCurrentContext(systemError);
}
}
/** 自定义监控点【执行完成后,需要将返回值】
* @param <T>
* @param monitorName 业务监控点名称
* @param call 回调函数
* @throws Exception
*/
public static <T> T monitorAndReturn(String monitorName,Callback<T> call) {
boolean systemError = false;
try {
getCounter().bindContextIncludingCpu(monitorName);
return call.call();
}catch (Throwable e) {
systemError = true;
throw new RuntimeException(e);
} finally {
getCounter().addRequestForCurrentContext(systemError);
}
}
/**不需要返回值的回调接口定义
* @author heshengchao
* @param <T>
*/
@FunctionalInterface
public static interface Function {
void call();
}
/**需要返回值的回调接口定义
* @author heshengchao
* @param <T>
*/
@FunctionalInterface
public static interface Callback<T> {
T call() ;
}
}
使用示例说明
import net.bull.javamelody.BusMonitorProxy;
public class BusMonitorProxyTest {
String url = "";
/** 验证直接监控方法 */
@Test
public void testMonitor() {
BusMonitorProxy.monitor("post.url(" + url + ")", () -> {
// do something.
});
}
/** 验证需要得到响应的监控 */
@Test
public void testMonitorAndReturn() {
boolean result = BusMonitorProxy.monitorAndReturn("post.url(" + url + ")", () -> {
// do something.
return true;
});
}
}