Merge pull request #338 from wenshao/master

0.2.19
This commit is contained in:
温高铁
2013-05-19 05:27:37 -07:00
19 changed files with 980 additions and 24 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>0.2.19-SNAPSHOT</version>
<version>0.2.19</version>
<packaging>jar</packaging>
<name>druid</name>
+1 -1
View File
@@ -19,7 +19,7 @@ public final class VERSION {
public final static int MajorVersion = 0;
public final static int MinorVersion = 2;
public final static int RevisionVersion = 18;
public final static int RevisionVersion = 19;
public static String getVersionNumber() {
return VERSION.MajorVersion + "." + VERSION.MinorVersion + "." + VERSION.RevisionVersion;
@@ -210,7 +210,7 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
private ObjectName objectName;
private final AtomicLong executeCount = new AtomicLong();
protected final AtomicLong executeCount = new AtomicLong();
protected volatile Throwable createError;
protected volatile Throwable lastError;
@@ -231,7 +231,10 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
private Boolean useUnfairLock = null;
private boolean useLocalSessionState = true;
private boolean useLocalSessionState = true;
protected long timeBetweenLogStatsMillis;
protected DruidDataSourceStatLogger statLogger = new DruidDataSourceStatLoggerImpl();
public DruidAbstractDataSource(boolean lockFair){
lock = new ReentrantLock(lockFair);
@@ -239,15 +242,42 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
notEmpty = lock.newCondition();
empty = lock.newCondition();
}
public boolean isUseLocalSessionState() {
return useLocalSessionState;
}
public void setUseLocalSessionState(boolean useLocalSessionState) {
this.useLocalSessionState = useLocalSessionState;
}
public DruidDataSourceStatLogger getStatLogger() {
return statLogger;
}
public void setStatLoggerClassName(String className) {
Class<?> clazz;
try {
clazz = Class.forName(className);
DruidDataSourceStatLogger statLogger = (DruidDataSourceStatLogger) clazz.newInstance();
this.setStatLogger(statLogger);
} catch (Exception e) {
throw new IllegalArgumentException(className, e);
}
}
public void setStatLogger(DruidDataSourceStatLogger statLogger) {
this.statLogger = statLogger;
}
public long getTimeBetweenLogStatsMillis() {
return timeBetweenLogStatsMillis;
}
public void setTimeBetweenLogStatsMillis(long timeBetweenLogStatsMillis) {
this.timeBetweenLogStatsMillis = timeBetweenLogStatsMillis;
}
public boolean isOracle() {
return isOracle;
}
@@ -82,6 +82,7 @@ import com.alibaba.druid.util.JdbcUtils;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.druid.wall.WallFilter;
;
/**
* @author ljw<ljw2083@alibaba-inc.com>
* @author wenshao<szujobs@hotmail.com>
@@ -119,6 +120,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
// threads
private CreateConnectionThread createConnectionThread;
private DestroyConnectionThread destoryConnectionThread;
private LogStatsThread logStatsThread;
private final CountDownLatch initedLatch = new CountDownLatch(2);
@@ -131,7 +133,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
private volatile boolean closed = false;
private long closeTimeMillis = -1L;
private JdbcDataSourceStat dataSourceStat;
protected JdbcDataSourceStat dataSourceStat;
private boolean useGloalDataSourceStat = false;
@@ -175,14 +177,23 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
{
String property = System.getProperty("druid.filters");
if (property == null || property.length() == 0) {
return;
if (property != null && property.length() > 0) {
try {
this.setFilters(property);
} catch (SQLException e) {
LOG.error("setFilters error", e);
}
}
try {
this.setFilters(property);
} catch (SQLException e) {
LOG.error("setFilters error", e);
}
{
String property = System.getProperty("druid.timeBetweenLogStatsMillis");
if (property != null && property.length() > 0) {
try {
long value = Long.parseLong(property);
this.setTimeBetweenLogStatsMillis(value);
} catch (NumberFormatException e) {
LOG.error("illegal property 'timeBetweenLogStatsMillis'", e);
}
}
}
}
@@ -436,6 +447,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
+ maxActive);
}
if (timeBetweenLogStatsMillis > 0 && useGloalDataSourceStat) {
throw new IllegalArgumentException("timeBetweenLogStatsMillis not support useGloalDataSourceStat=true");
}
if (this.driverClass != null) {
this.driverClass = driverClass.trim();
}
@@ -492,7 +507,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
SQLException connectError = null;
try {
// 初始化连接
// init connections
for (int i = 0, size = getInitialSize(); i < size; ++i) {
Connection conn = createPhysicalConnection();
DruidConnectionHolder holder = new DruidConnectionHolder(this, conn);
@@ -508,6 +523,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
connectError = ex;
}
createAndLogThread();
createAndStartCreatorThread();
createAndStartDestroyThread();
@@ -535,6 +551,16 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
}
}
private void createAndLogThread() {
if (this.timeBetweenLogStatsMillis <= 0) {
return;
}
String threadName = "Druid-ConnectionPool-Log-" + System.identityHashCode(this);
logStatsThread = new LogStatsThread(threadName);
logStatsThread.start();
}
private void createAndStartDestroyThread() {
String threadName = "Druid-ConnectionPool-Destory-" + System.identityHashCode(this);
destoryConnectionThread = new DestroyConnectionThread(threadName);
@@ -1047,7 +1073,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
recycleErrorCount.incrementAndGet();
}
}
public long getRecycleErrorCount() {
return recycleErrorCount.get();
}
@@ -1078,6 +1104,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
return;
}
if (logStatsThread != null) {
logStatsThread.interrupt();
}
if (createConnectionThread != null) {
createConnectionThread.interrupt();
}
@@ -1236,13 +1266,13 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
@Override
public Connection getConnection(String username, String password) throws SQLException {
if (!StringUtils.equals(username, this.username)) {
throw new UnsupportedOperationException("Not supported by DruidDataSource");
throw new UnsupportedOperationException("Not supported by DruidDataSource");
}
if (!StringUtils.equals(password, this.password)) {
throw new UnsupportedOperationException("Not supported by DruidDataSource");
throw new UnsupportedOperationException("Not supported by DruidDataSource");
}
return getConnection();
}
@@ -1311,6 +1341,103 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
}
}
public void logStats() {
final DruidDataSourceStatLogger statLogger = this.statLogger;
if (statLogger == null) {
return;
}
DruidDataSourceStatValue statValue = getStatValueAndReset();
statLogger.log(statValue);
}
public DruidDataSourceStatValue getStatValueAndReset() {
DruidDataSourceStatValue value = new DruidDataSourceStatValue();
lock.lock();
try {
value.poolingCount = this.poolingCount;
value.poolingPeak = this.poolingPeak;
value.poolingPeakTime = this.poolingPeakTime;
value.activeCount = this.activeCount;
value.activePeak = this.activePeak;
value.activePeakTime = this.activePeakTime;
value.connectCount = this.connectCount;
value.closeCount = this.closeCount;
value.waitThreadCount = lock.getWaitQueueLength(notEmpty);
value.notEmptyWaitCount = this.notEmptyWaitCount;
value.notEmptyWaitNanos = this.notEmptyWaitNanos;
// reset
this.poolingPeak = 0;
this.poolingPeakTime = 0;
this.activePeak = 0;
this.activePeakTime = 0;
this.connectCount = 0;
this.closeCount = 0;
this.notEmptyWaitCount = 0;
this.notEmptyWaitNanos = 0;
} finally {
lock.unlock();
}
value.name = this.getName();
value.dbType = this.getDbType();
value.driverClassName = this.getDriverClassName();
value.url = this.getUrl();
value.userName = this.getUsername();
value.filterClassNames = this.getFilterClassNames();
value.initialSize = this.getInitialSize();
value.minIdle = this.getMinIdle();
value.maxActive = this.getMaxActive();
value.queryTimeout = this.getQueryTimeout();
value.transactionQueryTimeout = this.getTransactionQueryTimeout();
value.loginTimeout = this.getLoginTimeout();
value.validConnectionCheckerClassName = this.getValidConnectionCheckerClassName();
value.exceptionSorterClassName = this.getExceptionSorterClassName();
value.testOnBorrow = this.isTestOnBorrow();
value.testOnReturn = this.isTestOnReturn();
value.testWhileIdle = this.isTestWhileIdle();
value.defaultAutoCommit = this.isDefaultAutoCommit();
value.defaultReadOnly = this.isDefaultAutoCommit();
value.defaultTransactionIsolation = this.getDefaultTransactionIsolation();
value.logicConnectErrorCount = connectErrorCount.getAndSet(0);
value.physicalConnectCount = createCount.getAndSet(0);
value.physicalCloseCount = destroyCount.getAndSet(0);
value.physicalConnectErrorCount = createErrorCount.getAndSet(0);
value.executeCount = this.executeCount.getAndSet(0);
value.errorCount = errorCount.getAndSet(0);
value.commitCount = commitCount.getAndSet(0);
value.rollbackCount = rollbackCount.getAndSet(0);
value.pstmtCacheHitCount = cachedPreparedStatementHitCount.getAndSet(0);
value.pstmtCacheMissCount = cachedPreparedStatementMissCount.getAndSet(0);
value.startTransactionCount = startTransactionCount.getAndSet(0);
value.transactionHistogram = this.getTransactionHistogram().toArrayAndReset();
value.connectionHoldTimeHistogram = this.getDataSourceStat().getConnectionHoldHistogram().toArrayAndReset();
value.removeAbandoned = this.isRemoveAbandoned();
value.clobOpenCount = this.getDataSourceStat().getClobOpenCountAndReset();
value.blobOpenCount = this.getDataSourceStat().getBlobOpenCountAndReset();
value.sqlList = this.getDataSourceStat().getSqlStatMapAndReset();
return value;
}
public long getRemoveAbandonedCount() {
return removeAbandonedCount;
}
@@ -1454,6 +1581,30 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
}
public class LogStatsThread extends Thread {
public LogStatsThread(String name){
super(name);
this.setDaemon(true);
}
public void run() {
try {
for (;;) {
try {
logStats();
} catch (Exception e) {
LOG.error("logStats error", e);
}
Thread.sleep(timeBetweenLogStatsMillis);
}
} catch (InterruptedException e) {
// skip
}
}
}
public int removeAbandoned() {
int removeCount = 0;
@@ -72,4 +72,10 @@ public interface DruidDataSourceMBean extends DruidAbstractDataSourceMBean {
void clearStatementCache() throws SQLException;
long getDiscardCount();
void setStatLoggerClassName(String className);
long getTimeBetweenLogStatsMillis();
void setTimeBetweenLogStatsMillis(long timeBetweenLogStatsMillis);
}
@@ -0,0 +1,21 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.pool;
public interface DruidDataSourceStatLogger {
void log(DruidDataSourceStatValue statValue);
}
@@ -0,0 +1,168 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.pool;
import static com.alibaba.druid.util.JdbcSqlStatUtils.rtrim;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
import com.alibaba.druid.stat.JdbcSqlStatValue;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
public class DruidDataSourceStatLoggerImpl implements DruidDataSourceStatLogger {
private static Log LOG = LogFactory.getLog(DruidDataSourceStatLoggerImpl.class);
@Override
public void log(DruidDataSourceStatValue statValue) {
if (LOG.isInfoEnabled()) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
map.put("url", statValue.url);
map.put("dbType", statValue.dbType);
map.put("name", statValue.name);
map.put("activeCount", statValue.activeCount);
if (statValue.activePeak > 0) {
map.put("activePeak", statValue.activePeak);
map.put("activePeakTime", statValue.getActivePeakTime());
}
map.put("poolingCount", statValue.poolingCount);
if (statValue.poolingPeak > 0) {
map.put("poolingPeak", statValue.poolingPeak);
map.put("poolingPeakTime", statValue.getPoolingPeakTime());
}
map.put("connectCount", statValue.connectCount);
map.put("closeCount", statValue.closeCount);
if (statValue.waitThreadCount > 0) {
map.put("waitThreadCount", statValue.waitThreadCount);
}
if (statValue.notEmptyWaitCount > 0) {
map.put("notEmptyWaitCount", statValue.notEmptyWaitCount);
}
if (statValue.getNotEmptyWaitMillis() > 0) {
map.put("notEmptyWaitMillis", statValue.getNotEmptyWaitMillis());
}
if (statValue.logicConnectErrorCount > 0) {
map.put("logicConnectErrorCount", statValue.logicConnectErrorCount);
}
if (statValue.physicalConnectCount > 0) {
map.put("physicalConnectCount", statValue.physicalConnectCount);
}
if (statValue.physicalCloseCount > 0) {
map.put("physicalCloseCount", statValue.physicalCloseCount);
}
if (statValue.physicalConnectErrorCount > 0) {
map.put("physicalConnectErrorCount", statValue.physicalConnectErrorCount);
}
if (statValue.executeCount > 0) {
map.put("executeCount", statValue.executeCount);
}
if (statValue.errorCount > 0) {
map.put("errorCount", statValue.errorCount);
}
if (statValue.commitCount > 0) {
map.put("commitCount", statValue.commitCount);
}
if (statValue.rollbackCount > 0) {
map.put("rollbackCount", statValue.rollbackCount);
}
if (statValue.pstmtCacheHitCount > 0) {
map.put("pstmtCacheHitCount", statValue.pstmtCacheHitCount);
}
if (statValue.pstmtCacheMissCount > 0) {
map.put("pstmtCacheMissCount", statValue.pstmtCacheMissCount);
}
if (statValue.startTransactionCount > 0) {
map.put("startTransactionCount", statValue.startTransactionCount);
map.put("transactionHistogram", rtrim(statValue.transactionHistogram));
}
if (statValue.connectCount > 0) {
map.put("connectionHoldTimeHistogram", rtrim(statValue.connectionHoldTimeHistogram));
}
if (statValue.clobOpenCount > 0) {
map.put("clobOpenCount", statValue.clobOpenCount);
}
if (statValue.blobOpenCount > 0) {
map.put("blobOpenCount", statValue.blobOpenCount);
}
ArrayList<Map<String, Object>> sqlList = new ArrayList<Map<String, Object>>();
if (statValue.sqlList.size() > 0) {
for (JdbcSqlStatValue sqlStat : statValue.sqlList) {
Map<String, Object> sqlStatMap = new LinkedHashMap<String, Object>();
sqlStatMap.put("sql", sqlStat.sql);
if (sqlStat.getExecuteCount() > 0) {
sqlStatMap.put("executeCount", sqlStat.getExecuteCount());
sqlStatMap.put("executeMillisMax", sqlStat.getExecuteMillisMax());
sqlStatMap.put("executeMillisTotal", sqlStat.getExecuteMillisTotal());
sqlStatMap.put("executeHistogram", rtrim(sqlStat.getExecuteHistogram()));
sqlStatMap.put("executeAndResultHoldHistogram",
rtrim(sqlStat.getExecuteAndResultHoldHistogram()));
}
if (sqlStat.executeErrorCount > 0) {
sqlStatMap.put("executeErrorCount", sqlStat.executeErrorCount);
}
if (sqlStat.runningCount > 0) {
sqlStatMap.put("runningCount", sqlStat.runningCount);
}
sqlStatMap.put("concurrentMax", sqlStat.concurrentMax);
if (sqlStat.fetchRowCount > 0) {
sqlStatMap.put("fetchRowCount", sqlStat.fetchRowCount);
sqlStatMap.put("fetchRowCount", sqlStat.fetchRowCountMax);
sqlStatMap.put("fetchRowHistogram", rtrim(sqlStat.getFetchRowHistogram()));
}
if (sqlStat.updateCount > 0) {
sqlStatMap.put("updateCount", sqlStat.updateCount);
sqlStatMap.put("updateCountMax", sqlStat.updateCountMax);
sqlStatMap.put("updateHistogram", rtrim(sqlStat.getUpdateHistogram()));
}
if (sqlStat.inTransactionCount > 0) {
sqlStatMap.put("inTransactionCount", sqlStat.inTransactionCount);
}
if (sqlStat.clobOpenCount > 0) {
sqlStatMap.put("clobOpenCount", sqlStat.clobOpenCount);
}
if (sqlStat.blobOpenCount > 0) {
sqlStatMap.put("blobOpenCount", sqlStat.blobOpenCount);
}
sqlList.add(sqlStatMap);
}
map.put("sqlList", sqlList);
}
String text = JSONUtils.toJSONString(map);
LOG.info(text);
}
}
}
@@ -0,0 +1,100 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.pool;
import java.util.Date;
import java.util.List;
import com.alibaba.druid.stat.JdbcSqlStatValue;
public class DruidDataSourceStatValue {
public String name;
public String dbType;
public String driverClassName;
public String url;
public String userName;
public List<String> filterClassNames;
public boolean removeAbandoned;
public int initialSize;
public int minIdle;
public int maxActive;
public int queryTimeout;
public int transactionQueryTimeout;
public int loginTimeout;
public String validConnectionCheckerClassName;
public String exceptionSorterClassName;
public boolean testOnBorrow;
public boolean testOnReturn;
public boolean testWhileIdle;
public boolean defaultAutoCommit;
public boolean defaultReadOnly;
public Integer defaultTransactionIsolation;
public int activeCount;
public int activePeak;
public long activePeakTime;
public int poolingCount;
public int poolingPeak;
public long poolingPeakTime;
public long connectCount;
public long closeCount;
public long waitThreadCount;
public long notEmptyWaitCount;
public long notEmptyWaitNanos;
public long logicConnectErrorCount;
public long physicalConnectCount;
public long physicalCloseCount;
public long physicalConnectErrorCount;
public long executeCount;
public long errorCount;
public long commitCount;
public long rollbackCount;
public long pstmtCacheHitCount;
public long pstmtCacheMissCount;
public long startTransactionCount;
public long[] transactionHistogram;
public long[] connectionHoldTimeHistogram;
public long clobOpenCount;
public long blobOpenCount;
public List<JdbcSqlStatValue> sqlList;
public Date getPoolingPeakTime() {
if (poolingPeakTime <= 0) {
return null;
}
return new Date(poolingPeakTime);
}
public Date getActivePeakTime() {
if (activePeakTime <= 0) {
return null;
}
return new Date(activePeakTime);
}
public long getNotEmptyWaitMillis() {
return notEmptyWaitNanos / (1000 * 1000);
}
}
@@ -15,9 +15,10 @@
*/
package com.alibaba.druid.stat;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
@@ -257,7 +258,7 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean {
}
public Map<String, JdbcSqlStat> getSqlStatMap() {
Map<String, JdbcSqlStat> map = new HashMap<String, JdbcSqlStat>();
Map<String, JdbcSqlStat> map = new LinkedHashMap<String, JdbcSqlStat>(sqlStatMap.size());
lock.readLock().lock();
try {
map.putAll(sqlStatMap);
@@ -266,6 +267,34 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean {
}
return map;
}
public List<JdbcSqlStatValue> getSqlStatMapAndReset() {
List<JdbcSqlStat> stats = new ArrayList<JdbcSqlStat>(sqlStatMap.size());
lock.writeLock().lock();
try {
Iterator<Map.Entry<String, JdbcSqlStat>> iter = sqlStatMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String, JdbcSqlStat> entry = iter.next();
JdbcSqlStat stat = entry.getValue();
if (stat.getExecuteCount() == 0 && stat.getRunningCount() == 0) {
stat.setRemoved(true);
iter.remove();
} else {
stats.add(entry.getValue());
}
}
} finally {
lock.writeLock().unlock();
}
List<JdbcSqlStatValue> values = new ArrayList<JdbcSqlStatValue>(stats.size());
for (int i = 0; i < stats.size(); ++i) {
JdbcSqlStat stat = stats.get(i);
JdbcSqlStatValue value = stat.getValueAndReset();
values.add(value);
}
return values;
}
public JdbcSqlStat getSqlStat(String sql) {
lock.readLock().lock();
@@ -346,6 +375,10 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean {
public long getClobOpenCount() {
return clobOpenCount.get();
}
public long getClobOpenCountAndReset() {
return clobOpenCount.getAndSet(0);
}
public void incrementClobOpenCount() {
clobOpenCount.incrementAndGet();
@@ -354,6 +387,10 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean {
public long getBlobOpenCount() {
return blobOpenCount.get();
}
public long getBlobOpenCountAndReset() {
return blobOpenCount.getAndSet(0);
}
public void incrementBlobOpenCount() {
blobOpenCount.incrementAndGet();
@@ -323,7 +323,6 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean {
executeSpanNanoTotalUpdater.set(this, 0);
executeSpanNanoMaxUpdater.set(this, 0);
executeNanoSpanMaxOccurTime = 0;
runningCountUpdater.set(this, 0);
concurrentMaxUpdater.set(this, 0);
executeErrorCountUpdater.set(this, 0);
@@ -380,6 +379,88 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean {
readerOpenCountUpdater.set(this, 0);
}
public JdbcSqlStatValue getValueAndReset() {
JdbcSqlStatValue val = new JdbcSqlStatValue();
val.sql = sql;
val.executeLastStartTime = executeLastStartTime;
executeLastStartTime = 0;
val.executeBatchSizeTotal = executeBatchSizeTotalUpdater.getAndSet(this, 0);
val.executeBatchSizeMax = executeBatchSizeMaxUpdater.getAndSet(this, 0);
val.executeSuccessCount = executeSuccessCountUpdater.getAndSet(this, 0);
val.executeSpanNanoTotal = executeSpanNanoTotalUpdater.getAndSet(this, 0);
val.executeSpanNanoMax = executeSpanNanoMaxUpdater.getAndSet(this, 0);
val.executeNanoSpanMaxOccurTime = executeNanoSpanMaxOccurTime;
executeNanoSpanMaxOccurTime = 0;
val.runningCount = this.runningCount;
val.concurrentMax = concurrentMaxUpdater.getAndSet(this, 0);
val.executeErrorCount = executeErrorCountUpdater.getAndSet(this, 0);
val.executeErrorLast = executeErrorLast;
executeErrorLast = null;
val.executeErrorLastTime = executeErrorLastTime;
executeErrorLastTime = 0;
val.updateCount = updateCountUpdater.getAndSet(this, 0);
val.updateCountMax = updateCountMaxUpdater.getAndSet(this, 0);
val.fetchRowCount = fetchRowCountUpdater.getAndSet(this, 0);
val.fetchRowCountMax = fetchRowCountMaxUpdater.getAndSet(this, 0);
val.histogram_0_1 = histogram_0_1_Updater.getAndSet(this, 0);
val.histogram_1_10 = histogram_1_10_Updater.getAndSet(this, 0);
val.histogram_10_100 = histogram_10_100_Updater.getAndSet(this, 0);
val.histogram_100_1000 = histogram_100_1000_Updater.getAndSet(this, 0);
val.histogram_1000_10000 = histogram_1000_10000_Updater.getAndSet(this, 0);
val.histogram_10000_100000 = histogram_10000_100000_Updater.getAndSet(this, 0);
val.histogram_100000_1000000 = histogram_100000_1000000_Updater.getAndSet(this, 0);
val.histogram_1000000_more = histogram_1000000_more_Updater.getAndSet(this, 0);
val.lastSlowParameters = lastSlowParameters;
lastSlowParameters = null;
val.inTransactionCount = inTransactionCountUpdater.getAndSet(this, 0);
val.resultSetHoldTimeNano = resultSetHoldTimeNanoUpdater.getAndSet(this, 0);
val.executeAndResultSetHoldTime = executeAndResultSetHoldTimeUpdater.getAndSet(this, 0);
val.fetchRowCount_0_1 = fetchRowCount_0_1_Updater.getAndSet(this, 0);
val.fetchRowCount_1_10 = fetchRowCount_1_10_Updater.getAndSet(this, 0);
val.fetchRowCount_10_100 = fetchRowCount_10_100_Updater.getAndSet(this, 0);
val.fetchRowCount_100_1000 = fetchRowCount_100_1000_Updater.getAndSet(this, 0);
val.fetchRowCount_1000_10000 = fetchRowCount_1000_10000_Updater.getAndSet(this, 0);
val.fetchRowCount_10000_more = fetchRowCount_10000_more_Updater.getAndSet(this, 0);
val.updateCount_0_1 = updateCount_0_1_Updater.getAndSet(this, 0);
val.updateCount_1_10 = updateCount_1_10_Updater.getAndSet(this, 0);
val.updateCount_10_100 = updateCount_10_100_Updater.getAndSet(this, 0);
val.updateCount_100_1000 = updateCount_100_1000_Updater.getAndSet(this, 0);
val.updateCount_1000_10000 = updateCount_1000_10000_Updater.getAndSet(this, 0);
val.updateCount_10000_more = updateCount_10000_more_Updater.getAndSet(this, 0);
val.executeAndResultHoldTime_0_1 = executeAndResultHoldTime_0_1_Updater.getAndSet(this, 0);
val.executeAndResultHoldTime_1_10 = executeAndResultHoldTime_1_10_Updater.getAndSet(this, 0);
val.executeAndResultHoldTime_10_100 = executeAndResultHoldTime_10_100_Updater.getAndSet(this, 0);
val.executeAndResultHoldTime_100_1000 = executeAndResultHoldTime_100_1000_Updater.getAndSet(this, 0);
val.executeAndResultHoldTime_1000_10000 = executeAndResultHoldTime_1000_10000_Updater.getAndSet(this, 0);
val.executeAndResultHoldTime_10000_100000 = executeAndResultHoldTime_10000_100000_Updater.getAndSet(this, 0);
val.executeAndResultHoldTime_100000_1000000 = executeAndResultHoldTime_100000_1000000_Updater.getAndSet(this, 0);
val.executeAndResultHoldTime_1000000_more = executeAndResultHoldTime_1000000_more_Updater.getAndSet(this, 0);
val.blobOpenCount = blobOpenCountUpdater.getAndSet(this, 0);
val.clobOpenCount = clobOpenCountUpdater.getAndSet(this, 0);
val.readStringLength = readStringLengthUpdater.getAndSet(this, 0);
val.readBytesLength = readBytesLengthUpdater.getAndSet(this, 0);
val.inputStreamOpenCount = inputStreamOpenCountUpdater.getAndSet(this, 0);
val.readerOpenCount = readerOpenCountUpdater.getAndSet(this, 0);
return val;
}
public long getConcurrentMax() {
return concurrentMax;
}
@@ -0,0 +1,150 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.stat;
public class JdbcSqlStatValue {
public String sql;
public long id;
public String dataSource;
public long executeLastStartTime;
public long executeBatchSizeTotal;
public int executeBatchSizeMax;
public long executeSuccessCount;
public long executeSpanNanoTotal;
public long executeSpanNanoMax;
public int runningCount;
public int concurrentMax;
public long resultSetHoldTimeNano;
public long executeAndResultSetHoldTime;
public String name;
public String file;
public String dbType;
public long executeNanoSpanMaxOccurTime;
public long executeErrorCount;
public Throwable executeErrorLast;
public long executeErrorLastTime;
public long updateCount;
public long updateCountMax;
public long fetchRowCount;
public long fetchRowCountMax;
public long inTransactionCount;
public String lastSlowParameters;
public long clobOpenCount;
public long blobOpenCount;
public long readStringLength;
public long readBytesLength;
public long inputStreamOpenCount;
public long readerOpenCount;
public long histogram_0_1;
public long histogram_1_10;
public int histogram_10_100;
public int histogram_100_1000;
public int histogram_1000_10000;
public int histogram_10000_100000;
public int histogram_100000_1000000;
public int histogram_1000000_more;
public long[] getExecuteHistogram() {
return new long[] { histogram_0_1, //
histogram_1_10, //
histogram_10_100, //
histogram_100_1000, //
histogram_1000_10000, //
histogram_10000_100000, //
histogram_100000_1000000, //
histogram_1000000_more, //
};
}
public long executeAndResultHoldTime_0_1;
public long executeAndResultHoldTime_1_10;
public int executeAndResultHoldTime_10_100;
public int executeAndResultHoldTime_100_1000;
public int executeAndResultHoldTime_1000_10000;
public int executeAndResultHoldTime_10000_100000;
public int executeAndResultHoldTime_100000_1000000;
public int executeAndResultHoldTime_1000000_more;
public long[] getExecuteAndResultHoldHistogram() {
return new long[] { executeAndResultHoldTime_0_1, //
executeAndResultHoldTime_1_10, //
executeAndResultHoldTime_10_100, //
executeAndResultHoldTime_100_1000, //
executeAndResultHoldTime_1000_10000, //
executeAndResultHoldTime_10000_100000, //
executeAndResultHoldTime_100000_1000000, //
executeAndResultHoldTime_1000000_more, //
};
}
public long fetchRowCount_0_1;
public long fetchRowCount_1_10;
public long fetchRowCount_10_100;
public int fetchRowCount_100_1000;
public int fetchRowCount_1000_10000;
public int fetchRowCount_10000_more;
public long[] getFetchRowHistogram() {
return new long[] { fetchRowCount_0_1, //
fetchRowCount_1_10, //
fetchRowCount_10_100, //
fetchRowCount_100_1000, //
fetchRowCount_1000_10000, //
fetchRowCount_10000_more, //
};
}
public long updateCount_0_1;
public long updateCount_1_10;
public long updateCount_10_100;
public int updateCount_100_1000;
public int updateCount_1000_10000;
public int updateCount_10000_more;
public long[] getUpdateHistogram() {
return new long[] { updateCount_0_1, //
updateCount_1_10, //
updateCount_10_100, //
updateCount_100_1000, //
updateCount_1000_10000, //
updateCount_10000_more, //
};
}
public long getExecuteCount() {
return executeErrorCount + executeSuccessCount;
}
public long getExecuteMillisMax() {
return executeSpanNanoMax / (1000 * 1000);
}
public long getExecuteMillisTotal() {
return executeSpanNanoTotal / (1000 * 1000);
}
}
@@ -66,6 +66,7 @@ public class SLF4JImpl implements Log {
@Override
public void info(String msg) {
infoCount++;
log.log(null, callerFQCN, LocationAwareLogger.INFO_INT, msg, null, null);
}
@Override
@@ -77,6 +77,15 @@ public class Histogram {
return array;
}
public long[] toArrayAndReset() {
long[] array = new long[rangeCounters.length()];
for (int i = 0; i < rangeCounters.length(); i++) {
array[i] = rangeCounters.getAndSet(i, 0);
}
return array;
}
public long[] getRanges() {
return ranges;
}
@@ -16,6 +16,7 @@
package com.alibaba.druid.util;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import com.alibaba.druid.stat.JdbcSqlStat;
@@ -41,4 +42,19 @@ public class JdbcSqlStatUtils {
return null;
}
}
public static long[] rtrim(long[] array) {
int notZeroLen = array.length;
for (int i = array.length - 1; i >= 0; --i, notZeroLen--) {
if (array[i] != 0) {
break;
}
}
if (notZeroLen != array.length) {
array = Arrays.copyOf(array, notZeroLen);
}
return array;
}
}
@@ -5,9 +5,10 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Iterator;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.stat.DruidDataSourceStatManager;
import com.alibaba.druid.stat.JdbcSqlStat;
@@ -24,6 +25,7 @@ public class TestOnBorrowFileAndNameTest extends TestCase {
dataSource.setName("com.alibaba.dragoon.monitor");
dataSource.setMinIdle(0);
dataSource.setPoolPreparedStatements(false);
dataSource.setTestOnBorrow(true);
dataSource.setValidationQuery("SELECT 1");
dataSource.setFilters("stat");
@@ -0,0 +1,30 @@
package com.alibaba.druid.bvt.pool;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.JdbcUtils;
public class TimeBetweenLogStatsMillisTest extends TestCase {
private DruidDataSource dataSource;
protected void setUp() throws Exception {
dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mock:xxx");
dataSource.setTimeBetweenLogStatsMillis(1000);
// dataSource.setFilters("log4j");
}
protected void tearDown() throws Exception {
JdbcUtils.close(dataSource);
}
public void test_0() throws Exception {
dataSource.init();
Assert.assertEquals(1000, dataSource.getTimeBetweenLogStatsMillis());
}
}
@@ -0,0 +1,30 @@
package com.alibaba.druid.bvt.pool;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.JdbcUtils;
public class TimeBetweenLogStatsMillisTest2 extends TestCase {
private DruidDataSource dataSource;
protected void setUp() throws Exception {
System.setProperty("druid.timeBetweenLogStatsMillis", "1000");
dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mock:xxx");
}
protected void tearDown() throws Exception {
JdbcUtils.close(dataSource);
System.clearProperty("druid.timeBetweenLogStatsMillis");
}
public void test_0() throws Exception {
dataSource.init();
Assert.assertEquals(1000, dataSource.getTimeBetweenLogStatsMillis());
}
}
@@ -0,0 +1,46 @@
package com.alibaba.druid.bvt.pool;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.JdbcUtils;
public class TimeBetweenLogStatsMillisTest3 extends TestCase {
private DruidDataSource dataSource;
protected void setUp() throws Exception {
System.setProperty("druid.timeBetweenLogStatsMillis", "10");
dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mock:xxx");
dataSource.setFilters("stat");
}
protected void tearDown() throws Exception {
JdbcUtils.close(dataSource);
System.clearProperty("druid.timeBetweenLogStatsMillis");
}
public void test_0() throws Exception {
dataSource.init();
for (int i = 0; i < 10; ++i) {
Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement("select ?");
stmt.setString(1, "aaa");
ResultSet rs = stmt.executeQuery();
rs.close();
stmt.close();
conn.close();
Thread.sleep(10);
}
Assert.assertEquals(10, dataSource.getTimeBetweenLogStatsMillis());
}
}
@@ -0,0 +1,78 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.bvt.proxy.filter;
import java.sql.Connection;
import java.sql.Statement;
import java.util.Set;
import javax.management.openmbean.TabularData;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.stat.DruidDataSourceStatManager;
import com.alibaba.druid.stat.JdbcStatManager;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.druid.util.JdbcUtils;
public class MergeStatFilterTest_tddl_2 extends TestCase {
private DruidDataSource dataSource;
protected void setUp() throws Exception {
TabularData sqlList = JdbcStatManager.getInstance().getSqlList();
if (sqlList.size() > 0) {
for (Object item : JdbcStatManager.getInstance().getSqlList().values()) {
String text = JSONUtils.toJSONString(item);
System.out.println(text);
}
}
Assert.assertEquals(0, JdbcStatManager.getInstance().getSqlList().size());
dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mock:xx");
dataSource.setFilters("mergeStat");
dataSource.setDbType("mysql");
}
protected void tearDown() throws Exception {
JdbcUtils.close(dataSource);
Assert.assertEquals(0, JdbcStatManager.getInstance().getSqlList().size());
}
public void test_merge() throws Exception {
for (int i = 1000; i < 2000; ++i) {
String tableName = "t" + i;
String sql = "insert into " + tableName + " (fid, fname) values (?, ?)";
Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement();
stmt.execute(sql);
stmt.close();
conn.close();
}
Assert.assertEquals(1, dataSource.getDataSourceStat().getSqlStatMap().size());
}
}