From 5f8b154bb2fc07666f3edacd6c698b1139e2ae2a Mon Sep 17 00:00:00 2001 From: wenshao Date: Sat, 18 May 2013 22:01:29 +0800 Subject: [PATCH] bug fixed sql runningCount & add statLog support --- .../druid/pool/DruidAbstractDataSource.java | 19 ++- .../alibaba/druid/pool/DruidDataSource.java | 155 +++++++++++++++++- .../druid/pool/DruidDataSourceStatLogger.java | 21 +++ .../pool/DruidDataSourceStatLoggerImpl.java | 25 +++ .../druid/pool/DruidDataSourceStatValue.java | 77 +++++++++ .../druid/stat/JdbcDataSourceStat.java | 41 ++++- .../com/alibaba/druid/stat/JdbcSqlStat.java | 82 ++++++++- .../alibaba/druid/stat/JdbcSqlStatValue.java | 95 +++++++++++ .../com/alibaba/druid/util/Histogram.java | 8 + .../bvt/pool/TestOnBorrowFileAndNameTest.java | 4 +- .../pool/TimeBetweenLogStatsMillisTest.java | 30 ++++ .../filter/MergeStatFilterTest_tddl_2.java | 78 +++++++++ 12 files changed, 620 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLogger.java create mode 100644 src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerImpl.java create mode 100644 src/main/java/com/alibaba/druid/pool/DruidDataSourceStatValue.java create mode 100644 src/main/java/com/alibaba/druid/stat/JdbcSqlStatValue.java create mode 100644 src/test/java/com/alibaba/druid/bvt/pool/TimeBetweenLogStatsMillisTest.java create mode 100644 src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest_tddl_2.java diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java index 6fc3528c78..690cbdc9c1 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java @@ -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,23 @@ 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 long getTimeBetweenLogStatsMillis() { + return timeBetweenLogStatsMillis; + } + + public void setTimeBetweenLogStatsMillis(long timeBetweenLogStatsMillis) { + this.timeBetweenLogStatsMillis = timeBetweenLogStatsMillis; + } + public boolean isOracle() { return isOracle; } diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 6ddbc2c4f1..036e100749 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -119,6 +119,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 +132,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; @@ -436,6 +437,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 +497,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 +513,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat connectError = ex; } + createAndLogThread(); createAndStartCreatorThread(); createAndStartDestroyThread(); @@ -535,6 +541,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 +1063,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat recycleErrorCount.incrementAndGet(); } } - + public long getRecycleErrorCount() { return recycleErrorCount.get(); } @@ -1078,6 +1094,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat return; } + if (logStatsThread != null) { + logStatsThread.interrupt(); + } + if (createConnectionThread != null) { createConnectionThread.interrupt(); } @@ -1236,13 +1256,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 +1331,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.PSCacheHitCount = cachedPreparedStatementHitCount.getAndSet(0); + value.PSCacheMissCount = 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 +1571,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; diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLogger.java b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLogger.java new file mode 100644 index 0000000000..80b46da108 --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLogger.java @@ -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); +} diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerImpl.java b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerImpl.java new file mode 100644 index 0000000000..783501f539 --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerImpl.java @@ -0,0 +1,25 @@ +/* + * 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 class DruidDataSourceStatLoggerImpl implements DruidDataSourceStatLogger { + + @Override + public void log(DruidDataSourceStatValue statValue) { + + } + +} diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatValue.java b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatValue.java new file mode 100644 index 0000000000..05018f9977 --- /dev/null +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatValue.java @@ -0,0 +1,77 @@ +/* + * 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.List; + +import com.alibaba.druid.stat.JdbcSqlStatValue; + +public class DruidDataSourceStatValue { + + 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 String name; + public String dbType; + public String driverClassName; + public String url; + public String userName; + public List filterClassNames; + + 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 int defaultTransactionIsolation; + 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 PSCacheHitCount; + public long PSCacheMissCount; + public long startTransactionCount; + public long[] transactionHistogram; + public long[] connectionHoldTimeHistogram; + public boolean removeAbandoned; + public long clobOpenCount; + public long blobOpenCount; + + public List sqlList; +} diff --git a/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java b/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java index 661b06dea1..b34d71c410 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcDataSourceStat.java @@ -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 getSqlStatMap() { - Map map = new HashMap(); + Map map = new LinkedHashMap(sqlStatMap.size()); lock.readLock().lock(); try { map.putAll(sqlStatMap); @@ -266,6 +267,34 @@ public class JdbcDataSourceStat implements JdbcDataSourceStatMBean { } return map; } + + public List getSqlStatMapAndReset() { + List stats = new ArrayList(sqlStatMap.size()); + lock.writeLock().lock(); + try { + Iterator> iter = sqlStatMap.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry 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 values = new ArrayList(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(); diff --git a/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java b/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java index 33de13886a..7d5943f256 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java @@ -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,87 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { readerOpenCountUpdater.set(this, 0); } + public JdbcSqlStatValue getValueAndReset() { + JdbcSqlStatValue val = new JdbcSqlStatValue(); + + 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; } diff --git a/src/main/java/com/alibaba/druid/stat/JdbcSqlStatValue.java b/src/main/java/com/alibaba/druid/stat/JdbcSqlStatValue.java new file mode 100644 index 0000000000..67b8a7b5fb --- /dev/null +++ b/src/main/java/com/alibaba/druid/stat/JdbcSqlStatValue.java @@ -0,0 +1,95 @@ +/* + * 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 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 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 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; + +} diff --git a/src/main/java/com/alibaba/druid/util/Histogram.java b/src/main/java/com/alibaba/druid/util/Histogram.java index 147c746e36..468985297b 100644 --- a/src/main/java/com/alibaba/druid/util/Histogram.java +++ b/src/main/java/com/alibaba/druid/util/Histogram.java @@ -76,6 +76,14 @@ 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; diff --git a/src/test/java/com/alibaba/druid/bvt/pool/TestOnBorrowFileAndNameTest.java b/src/test/java/com/alibaba/druid/bvt/pool/TestOnBorrowFileAndNameTest.java index d520a83716..60caa98cc1 100644 --- a/src/test/java/com/alibaba/druid/bvt/pool/TestOnBorrowFileAndNameTest.java +++ b/src/test/java/com/alibaba/druid/bvt/pool/TestOnBorrowFileAndNameTest.java @@ -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"); diff --git a/src/test/java/com/alibaba/druid/bvt/pool/TimeBetweenLogStatsMillisTest.java b/src/test/java/com/alibaba/druid/bvt/pool/TimeBetweenLogStatsMillisTest.java new file mode 100644 index 0000000000..7179724e94 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/TimeBetweenLogStatsMillisTest.java @@ -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()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest_tddl_2.java b/src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest_tddl_2.java new file mode 100644 index 0000000000..7918fe4e3b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/proxy/filter/MergeStatFilterTest_tddl_2.java @@ -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()); + + } + +}