mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
add spring stat support
This commit is contained in:
@@ -7,6 +7,7 @@ import java.util.Map;
|
||||
|
||||
import com.alibaba.druid.stat.DruidStatManagerFacade;
|
||||
import com.alibaba.druid.support.http.stat.WebAppStatManager;
|
||||
import com.alibaba.druid.support.spring.stat.SpringStatManager;
|
||||
import com.alibaba.druid.util.MapComparator;
|
||||
import com.alibaba.druid.util.StringUtils;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
@@ -90,10 +91,19 @@ public class JSONDruidStatService {
|
||||
if (url.startsWith("/websession.json")) {
|
||||
return returnJSONResult(RESULT_CODE_SUCCESS, getWebSessionStatDataList(parameters));
|
||||
}
|
||||
|
||||
if (url.startsWith("/spring.json")) {
|
||||
return returnJSONResult(RESULT_CODE_SUCCESS, getSpringStatDataList(parameters));
|
||||
}
|
||||
|
||||
return returnJSONResult(RESULT_CODE_ERROR, "Do not support this request, please contact with administrator.");
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> getSpringStatDataList(Map<String, String> parameters) {
|
||||
List<Map<String, Object>> array = SpringStatManager.getInstance().getMethodStatData();
|
||||
return comparatorOrderBy(array, parameters);
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> getWebURIStatDataList(Map<String, String> parameters) {
|
||||
List<Map<String, Object>> array = WebAppStatManager.getInstance().getURIStatData();
|
||||
return comparatorOrderBy(array, parameters);
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.alibaba.druid.support.http.stat.WebRequestStat;
|
||||
import com.alibaba.druid.support.http.stat.WebSessionStat;
|
||||
import com.alibaba.druid.support.logging.Log;
|
||||
import com.alibaba.druid.support.logging.LogFactory;
|
||||
import com.alibaba.druid.support.spring.stat.SpringMethodStat;
|
||||
import com.alibaba.druid.util.DruidWebUtils;
|
||||
import com.alibaba.druid.util.PatternMatcher;
|
||||
import com.alibaba.druid.util.ServletPathMatcher;
|
||||
@@ -264,49 +265,79 @@ public class WebStatFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void addUpdateCount(int updateCount) {
|
||||
WebRequestStat localStat = WebRequestStat.current();
|
||||
if (localStat != null) {
|
||||
localStat.addJdbcUpdateCount(updateCount);
|
||||
WebRequestStat reqStat = WebRequestStat.current();
|
||||
if (reqStat != null) {
|
||||
reqStat.addJdbcUpdateCount(updateCount);
|
||||
}
|
||||
|
||||
SpringMethodStat springMethodStat = SpringMethodStat.current();
|
||||
if (springMethodStat != null) {
|
||||
springMethodStat.addJdbcUpdateCount(updateCount);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFetchRowCount(int fetchRowCount) {
|
||||
WebRequestStat localStat = WebRequestStat.current();
|
||||
if (localStat != null) {
|
||||
localStat.addJdbcFetchRowCount(fetchRowCount);
|
||||
WebRequestStat reqStat = WebRequestStat.current();
|
||||
if (reqStat != null) {
|
||||
reqStat.addJdbcFetchRowCount(fetchRowCount);
|
||||
}
|
||||
|
||||
SpringMethodStat springMethodStat = SpringMethodStat.current();
|
||||
if (springMethodStat != null) {
|
||||
springMethodStat.addJdbcFetchRowCount(fetchRowCount);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeBefore(String sql, boolean inTransaction) {
|
||||
WebRequestStat localStat = WebRequestStat.current();
|
||||
if (localStat != null) {
|
||||
localStat.incrementJdbcExecuteCount();
|
||||
WebRequestStat reqStat = WebRequestStat.current();
|
||||
if (reqStat != null) {
|
||||
reqStat.incrementJdbcExecuteCount();
|
||||
}
|
||||
|
||||
SpringMethodStat springMethodStat = SpringMethodStat.current();
|
||||
if (springMethodStat != null) {
|
||||
springMethodStat.incrementJdbcExecuteCount();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeAfter(String sql, long nanoSpan, Throwable error) {
|
||||
WebRequestStat localStat = WebRequestStat.current();
|
||||
if (localStat != null) {
|
||||
localStat.addJdbcExecuteNano(nanoSpan);
|
||||
public void executeAfter(String sql, long nanos, Throwable error) {
|
||||
WebRequestStat reqStat = WebRequestStat.current();
|
||||
if (reqStat != null) {
|
||||
reqStat.addJdbcExecuteTimeNano(nanos);
|
||||
}
|
||||
|
||||
SpringMethodStat springMethodStat = SpringMethodStat.current();
|
||||
if (springMethodStat != null) {
|
||||
springMethodStat.addJdbcExecuteTimeNano(nanos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() {
|
||||
WebRequestStat localStat = WebRequestStat.current();
|
||||
if (localStat != null) {
|
||||
localStat.incrementJdbcCommitCount();
|
||||
WebRequestStat reqStat = WebRequestStat.current();
|
||||
if (reqStat != null) {
|
||||
reqStat.incrementJdbcCommitCount();
|
||||
}
|
||||
|
||||
SpringMethodStat springMethodStat = SpringMethodStat.current();
|
||||
if (springMethodStat != null) {
|
||||
springMethodStat.incrementJdbcCommitCount();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() {
|
||||
WebRequestStat localStat = WebRequestStat.current();
|
||||
if (localStat != null) {
|
||||
localStat.incrementJdbcRollbackCount();
|
||||
WebRequestStat reqStat = WebRequestStat.current();
|
||||
if (reqStat != null) {
|
||||
reqStat.incrementJdbcRollbackCount();
|
||||
}
|
||||
|
||||
SpringMethodStat springMethodStat = SpringMethodStat.current();
|
||||
if (springMethodStat != null) {
|
||||
springMethodStat.incrementJdbcRollbackCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,11 +61,11 @@ public class WebRequestStat {
|
||||
return jdbcExecuteCount;
|
||||
}
|
||||
|
||||
public long getJdbcExecuteNano() {
|
||||
public long getJdbcExecuteTimeNano() {
|
||||
return jdbcExecuteNano;
|
||||
}
|
||||
|
||||
public void addJdbcExecuteNano(long nano) {
|
||||
public void addJdbcExecuteTimeNano(long nano) {
|
||||
jdbcExecuteNano += nano;
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ public class WebSessionStat {
|
||||
this.addJdbcUpdateCount(requestStat.getJdbcUpdateCount());
|
||||
this.addJdbcCommitCount(requestStat.getJdbcCommitCount());
|
||||
this.addJdbcRollbackCount(requestStat.getJdbcRollbackCount());
|
||||
this.addJdbcExecuteTimeNano(requestStat.getJdbcExecuteNano());
|
||||
this.addJdbcExecuteTimeNano(requestStat.getJdbcExecuteTimeNano());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.alibaba.druid.support.spring.stat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
|
||||
/**
|
||||
* 类BeanTypeAutoProxyCreator.java的实现描述:使用配置类型代替Springframework中配置名称的实现
|
||||
*
|
||||
* @author hualiang.lihl 2011-12-31 上午10:48:20
|
||||
*/
|
||||
public class BeanTypeAutoProxyCreator extends AbstractAutoProxyCreator implements InitializingBean, ApplicationContextAware {
|
||||
|
||||
private static final long serialVersionUID = -9094985530794052264L;
|
||||
|
||||
private Class<?> targetBeanType;
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
private List<String> beanNames = new ArrayList<String>();
|
||||
|
||||
/**
|
||||
* @param targetClass the targetClass to set
|
||||
*/
|
||||
public void setTargetBeanType(Class<?> targetClass) {
|
||||
this.targetBeanType = targetClass;
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify as bean to proxy if the bean name is in the configured list of names.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
|
||||
for (Iterator<String> it = this.beanNames.iterator(); it.hasNext();) {
|
||||
String mappedName = (String) it.next();
|
||||
if (FactoryBean.class.isAssignableFrom(beanClass)) {
|
||||
if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
|
||||
continue;
|
||||
}
|
||||
mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
|
||||
}
|
||||
if (isMatch(beanName, mappedName)) {
|
||||
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
|
||||
}
|
||||
}
|
||||
return DO_NOT_PROXY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the given bean name matches the mapped name.
|
||||
* <p>
|
||||
* The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches, as well as direct equality. Can be
|
||||
* overridden in subclasses.
|
||||
*
|
||||
* @param beanName the bean name to check
|
||||
* @param mappedName the name in the configured list of names
|
||||
* @return if the names match
|
||||
* @see org.springframework.util.PatternMatchUtils#simpleMatch(String, String)
|
||||
*/
|
||||
protected boolean isMatch(String beanName, String mappedName) {
|
||||
return PatternMatchUtils.simpleMatch(mappedName, beanName);
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(targetBeanType, "targetType cannot be null");
|
||||
String[] beanNames = context.getBeanNamesForType(targetBeanType);
|
||||
for (String name : beanNames) {
|
||||
this.beanNames.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.alibaba.druid.support.spring.stat;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import com.alibaba.druid.support.logging.Log;
|
||||
import com.alibaba.druid.support.logging.LogFactory;
|
||||
|
||||
public class DruidStatInterceptor implements MethodInterceptor, InitializingBean {
|
||||
|
||||
private final static Log LOG = LogFactory.getLog(DruidStatInterceptor.class);
|
||||
|
||||
private static SpringStat springStat = new SpringStat();
|
||||
|
||||
public DruidStatInterceptor() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
SpringStatManager.getInstance().addSpringStat(springStat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
SpringMethodStat lastMethodStat = SpringMethodStat.current();
|
||||
|
||||
MethodInfo methodInfo = getMethodInfo(invocation);
|
||||
|
||||
SpringMethodStat methodStat = springStat.getMethodStat(methodInfo, true);
|
||||
|
||||
if (methodStat != null) {
|
||||
methodStat.beforeInvoke();
|
||||
}
|
||||
|
||||
long startNanos = System.nanoTime();
|
||||
|
||||
Throwable error = null;
|
||||
try {
|
||||
Object returnObject = invocation.proceed();
|
||||
|
||||
return returnObject;
|
||||
} catch (Throwable e) {
|
||||
error = e;
|
||||
throw e;
|
||||
} finally {
|
||||
long endNanos = System.nanoTime();
|
||||
|
||||
long nanos = endNanos - startNanos;
|
||||
|
||||
if (methodStat != null) {
|
||||
methodStat.afterInvoke(error, nanos);
|
||||
}
|
||||
|
||||
SpringMethodStat.setCurrent(lastMethodStat);
|
||||
}
|
||||
}
|
||||
|
||||
public MethodInfo getMethodInfo(MethodInvocation invocation) {
|
||||
Object thisObject = invocation.getThis();
|
||||
Method method = invocation.getMethod();
|
||||
|
||||
if (thisObject == null) {
|
||||
return new MethodInfo(method.getDeclaringClass(), method);
|
||||
}
|
||||
|
||||
if (method.getDeclaringClass() == thisObject.getClass()) {
|
||||
return new MethodInfo(method.getDeclaringClass(), method);
|
||||
}
|
||||
|
||||
{
|
||||
Class<?> clazz = thisObject.getClass();
|
||||
boolean isCglibProxy = false;
|
||||
boolean isJavassistProxy = false;
|
||||
for (Class<?> item : clazz.getInterfaces()) {
|
||||
if (item.getName().equals("net.sf.cglib.proxy.Factory")) {
|
||||
isCglibProxy = true;
|
||||
break;
|
||||
} else if (item.getName().equals("javassist.util.proxy.ProxyObject")) {
|
||||
isJavassistProxy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isCglibProxy || isJavassistProxy) {
|
||||
Class<?> superClazz = clazz.getSuperclass();
|
||||
|
||||
return new MethodInfo(superClazz, method);
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> clazz = null;
|
||||
try {
|
||||
// 最多支持10层代理
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
if (thisObject instanceof org.springframework.aop.framework.Advised) {
|
||||
TargetSource targetSource = ((org.springframework.aop.framework.Advised) thisObject).getTargetSource();
|
||||
|
||||
if (targetSource == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
Object target = targetSource.getTarget();
|
||||
if (target != null) {
|
||||
thisObject = target;
|
||||
} else {
|
||||
clazz = targetSource.getTargetClass();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.error("getMethodInfo error", ex);
|
||||
}
|
||||
|
||||
if (clazz == null) {
|
||||
return new MethodInfo(method.getDeclaringClass(), method);
|
||||
}
|
||||
|
||||
return new MethodInfo(clazz, method);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.alibaba.druid.support.spring.stat;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class MethodInfo {
|
||||
|
||||
private final Class<?> instanceClass;
|
||||
private final Method method;
|
||||
private final String signature;
|
||||
|
||||
public MethodInfo(Class<?> instanceClass, Method method){
|
||||
super();
|
||||
this.instanceClass = instanceClass;
|
||||
this.method = method;
|
||||
signature = getMethodSignature(this.getMethod());
|
||||
}
|
||||
|
||||
public Class<?> getInstanceClass() {
|
||||
return instanceClass;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((instanceClass == null) ? 0 : instanceClass.hashCode());
|
||||
result = prime * result + ((method == null) ? 0 : method.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MethodInfo other = (MethodInfo) obj;
|
||||
|
||||
if (instanceClass != other.instanceClass) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (signature == null) {
|
||||
return other.signature == null;
|
||||
}
|
||||
|
||||
if (!signature.equals(other.signature)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String getMethodSignature(Method method) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
sb.append(method.getName() + "(");
|
||||
Class<?>[] params = method.getParameterTypes();
|
||||
for (int j = 0; j < params.length; j++) {
|
||||
sb.append(params[j].getName());
|
||||
if (j < (params.length - 1)) sb.append(",");
|
||||
}
|
||||
sb.append(")");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
package com.alibaba.druid.support.spring.stat;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class SpringMethodStat {
|
||||
|
||||
private final static ThreadLocal<SpringMethodStat> currentLocal = new ThreadLocal<SpringMethodStat>();
|
||||
|
||||
private final MethodInfo methodInfo;
|
||||
|
||||
private final AtomicInteger runningCount = new AtomicInteger();
|
||||
private final AtomicInteger concurrentMax = new AtomicInteger();
|
||||
private final AtomicLong executeCount = new AtomicLong(0);
|
||||
private final AtomicLong executeErrorCount = new AtomicLong(0);
|
||||
private final AtomicLong executeTimeNano = new AtomicLong();
|
||||
|
||||
private final AtomicLong jdbcFetchRowCount = new AtomicLong();
|
||||
private final AtomicLong jdbcUpdateCount = new AtomicLong();
|
||||
private final AtomicLong jdbcExecuteCount = new AtomicLong();
|
||||
private final AtomicLong jdbcExecuteTimeNano = new AtomicLong();
|
||||
|
||||
private final AtomicLong jdbcCommitCount = new AtomicLong();
|
||||
private final AtomicLong jdbcRollbackCount = new AtomicLong();
|
||||
|
||||
public SpringMethodStat(MethodInfo methodInfo){
|
||||
this.methodInfo = methodInfo;
|
||||
}
|
||||
|
||||
public MethodInfo getMethodInfo() {
|
||||
return methodInfo;
|
||||
}
|
||||
|
||||
public static SpringMethodStat current() {
|
||||
return currentLocal.get();
|
||||
}
|
||||
|
||||
public static void setCurrent(SpringMethodStat current) {
|
||||
currentLocal.set(current);
|
||||
}
|
||||
|
||||
public void beforeInvoke() {
|
||||
currentLocal.set(this);
|
||||
|
||||
int running = runningCount.incrementAndGet();
|
||||
|
||||
for (;;) {
|
||||
int max = concurrentMax.get();
|
||||
if (running > max) {
|
||||
if (concurrentMax.compareAndSet(max, running)) {
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
executeCount.incrementAndGet();
|
||||
}
|
||||
|
||||
public void afterInvoke(Throwable error, long nanos) {
|
||||
runningCount.decrementAndGet();
|
||||
executeTimeNano.addAndGet(nanos);
|
||||
|
||||
if (error != null) {
|
||||
executeErrorCount.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
public int getRunningCount() {
|
||||
return this.runningCount.get();
|
||||
}
|
||||
|
||||
public long getConcurrentMax() {
|
||||
return concurrentMax.get();
|
||||
}
|
||||
|
||||
public long getExecuteCount() {
|
||||
return executeCount.get();
|
||||
}
|
||||
|
||||
public long getExecuteErrorCount() {
|
||||
return executeErrorCount.get();
|
||||
}
|
||||
|
||||
public long getExecuteTimeNano() {
|
||||
return executeTimeNano.get();
|
||||
}
|
||||
|
||||
public long getExecuteTimeMillis() {
|
||||
return getExecuteTimeNano() / (1000 * 1000);
|
||||
}
|
||||
|
||||
public void addJdbcFetchRowCount(long delta) {
|
||||
this.jdbcFetchRowCount.addAndGet(delta);
|
||||
}
|
||||
|
||||
public long getJdbcFetchRowCount() {
|
||||
return jdbcFetchRowCount.get();
|
||||
}
|
||||
|
||||
public void addJdbcUpdateCount(long updateCount) {
|
||||
this.jdbcUpdateCount.addAndGet(updateCount);
|
||||
}
|
||||
|
||||
public long getJdbcUpdateCount() {
|
||||
return jdbcUpdateCount.get();
|
||||
}
|
||||
|
||||
public void incrementJdbcExecuteCount() {
|
||||
jdbcExecuteCount.incrementAndGet();
|
||||
}
|
||||
|
||||
public void addJdbcExecuteCount(long executeCount) {
|
||||
jdbcExecuteCount.addAndGet(executeCount);
|
||||
}
|
||||
|
||||
public long getJdbcExecuteCount() {
|
||||
return jdbcExecuteCount.get();
|
||||
}
|
||||
|
||||
public long getJdbcExecuteTimeMillis() {
|
||||
return getJdbcExecuteTimeNano() / (1000 * 1000);
|
||||
}
|
||||
|
||||
public long getJdbcExecuteTimeNano() {
|
||||
return jdbcExecuteTimeNano.get();
|
||||
}
|
||||
|
||||
public void addJdbcExecuteTimeNano(long nano) {
|
||||
jdbcExecuteTimeNano.addAndGet(nano);
|
||||
}
|
||||
|
||||
public void incrementJdbcCommitCount() {
|
||||
jdbcCommitCount.incrementAndGet();
|
||||
}
|
||||
|
||||
public long getJdbcCommitCount() {
|
||||
return jdbcCommitCount.get();
|
||||
}
|
||||
|
||||
public void addJdbcCommitCount(long commitCount) {
|
||||
this.jdbcCommitCount.addAndGet(commitCount);
|
||||
}
|
||||
|
||||
public void incrementJdbcRollbackCount() {
|
||||
jdbcRollbackCount.incrementAndGet();
|
||||
}
|
||||
|
||||
public long getJdbcRollbackCount() {
|
||||
return jdbcRollbackCount.get();
|
||||
}
|
||||
|
||||
public void addJdbcRollbackCount(long rollbackCount) {
|
||||
this.jdbcRollbackCount.addAndGet(rollbackCount);
|
||||
}
|
||||
|
||||
public Map<String, Object> getStatData() {
|
||||
Map<String, Object> data = new LinkedHashMap<String, Object>();
|
||||
|
||||
data.put("Class", this.getMethodInfo().getInstanceClass().getName());
|
||||
data.put("Method", this.getMethodInfo().getSignature());
|
||||
|
||||
data.put("RunningCount", this.getRunningCount());
|
||||
data.put("ConcurrentMax", this.getConcurrentMax());
|
||||
data.put("ExecuteCount", this.getExecuteCount());
|
||||
data.put("ExecuteErrorCount", this.getExecuteErrorCount());
|
||||
data.put("ExecuteTimeMillis", this.getExecuteTimeMillis());
|
||||
|
||||
data.put("JdbcCommitCount", this.getJdbcCommitCount());
|
||||
data.put("JdbcRollbackCount", this.getJdbcRollbackCount());
|
||||
|
||||
data.put("JdbcExecuteCount", this.getJdbcExecuteCount());
|
||||
data.put("JdbcExecuteTimeMillis", this.getJdbcExecuteTimeMillis());
|
||||
data.put("JdbcFetchRowCount", this.getJdbcFetchRowCount());
|
||||
data.put("JdbcUpdateCount", this.getJdbcUpdateCount());
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.alibaba.druid.support.spring.stat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class SpringStat {
|
||||
|
||||
private ConcurrentMap<MethodInfo, SpringMethodStat> methodStats = new ConcurrentHashMap<MethodInfo, SpringMethodStat>();
|
||||
|
||||
public SpringStat(){
|
||||
|
||||
}
|
||||
|
||||
public SpringMethodStat getMethodStat(MethodInfo methodInfo, boolean create) {
|
||||
SpringMethodStat methodStat = methodStats.get(methodInfo);
|
||||
if (methodStat != null) {
|
||||
return methodStat;
|
||||
}
|
||||
|
||||
if (create) {
|
||||
methodStats.putIfAbsent(methodInfo, new SpringMethodStat(methodInfo));
|
||||
methodStat = methodStats.get(methodInfo);
|
||||
}
|
||||
|
||||
return methodStat;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getMethodStatDataList() {
|
||||
List<Map<String, Object>> methodStatDataList = new ArrayList<Map<String, Object>>(this.methodStats.size());
|
||||
for (SpringMethodStat methodStat : this.methodStats.values()) {
|
||||
Map<String, Object> methodStatData = methodStat.getStatData();
|
||||
|
||||
int runningCount = ((Number) methodStatData.get("RunningCount")).intValue();
|
||||
long executeCount = (Long) methodStatData.get("ExecuteCount");
|
||||
|
||||
if (runningCount == 0 && executeCount == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
methodStatDataList.add(methodStatData);
|
||||
}
|
||||
return methodStatDataList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.alibaba.druid.support.spring.stat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
public class SpringStatManager {
|
||||
|
||||
public final static String SYS_PROP_INSTANCES = "druid.spring.springStat";
|
||||
|
||||
private final static SpringStatManager instance = new SpringStatManager();
|
||||
|
||||
private Set<Object> springStatSet = null;
|
||||
|
||||
public static SpringStatManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public Set<Object> getSpringStatSet() {
|
||||
if (springStatSet == null) {
|
||||
springStatSet = getSpringStatSetFromSysProperty();
|
||||
}
|
||||
|
||||
return springStatSet;
|
||||
}
|
||||
|
||||
public void addSpringStat(Object springStat) {
|
||||
getSpringStatSet().add(springStat);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Set<Object> getSpringStatSetFromSysProperty() {
|
||||
Properties properties = System.getProperties();
|
||||
Set<Object> webAppStats = (Set<Object>) properties.get(SYS_PROP_INSTANCES);
|
||||
|
||||
if (webAppStats == null) {
|
||||
synchronized (properties) {
|
||||
webAppStats = (Set<Object>) properties.get(SYS_PROP_INSTANCES);
|
||||
|
||||
if (webAppStats == null) {
|
||||
webAppStats = new CopyOnWriteArraySet<Object>();
|
||||
properties.put(SYS_PROP_INSTANCES, webAppStats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return webAppStats;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getMethodStatData() {
|
||||
Set<Object> stats = getSpringStatSet();
|
||||
|
||||
List<Map<String, Object>> allMethodStatDataList = new ArrayList<Map<String, Object>>();
|
||||
|
||||
for (Object stat : stats) {
|
||||
List<Map<String, Object>> methodStatDataList = SpringStatUtils.getMethodStatDataList(stat);
|
||||
allMethodStatDataList.addAll(methodStatDataList);
|
||||
}
|
||||
|
||||
return allMethodStatDataList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.alibaba.druid.support.spring.stat;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.druid.support.logging.Log;
|
||||
import com.alibaba.druid.support.logging.LogFactory;
|
||||
|
||||
public class SpringStatUtils {
|
||||
|
||||
private final static Log LOG = LogFactory.getLog(SpringStatUtils.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<Map<String, Object>> getMethodStatDataList(Object methodStat) {
|
||||
if (methodStat.getClass() == SpringStat.class) {
|
||||
return ((SpringStat) methodStat).getMethodStatDataList();
|
||||
}
|
||||
|
||||
try {
|
||||
Method method = methodStat.getClass().getMethod("getMethodStatDataList");
|
||||
Object obj = method.invoke(methodStat);
|
||||
return (List<Map<String, Object>>) obj;
|
||||
} catch (Exception e) {
|
||||
LOG.error("getMethodStatDataList error", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user