diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java index 690cbdc9c1..6adb7d53bb 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java @@ -251,6 +251,25 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements 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; } diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 036e100749..c10d4c0ea5 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -1412,8 +1412,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat value.commitCount = commitCount.getAndSet(0); value.rollbackCount = rollbackCount.getAndSet(0); - value.PSCacheHitCount = cachedPreparedStatementHitCount.getAndSet(0); - value.PSCacheMissCount = cachedPreparedStatementMissCount.getAndSet(0); + value.pstmtCacheHitCount = cachedPreparedStatementHitCount.getAndSet(0); + value.pstmtCacheMissCount = cachedPreparedStatementMissCount.getAndSet(0); value.startTransactionCount = startTransactionCount.getAndSet(0); value.transactionHistogram = this.getTransactionHistogram().toArrayAndReset(); diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSourceMBean.java b/src/main/java/com/alibaba/druid/pool/DruidDataSourceMBean.java index 5e2d5e364c..270de4d309 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSourceMBean.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSourceMBean.java @@ -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); } diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerImpl.java b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerImpl.java index 783501f539..0de10684f0 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerImpl.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatLoggerImpl.java @@ -15,11 +15,117 @@ */ package com.alibaba.druid.pool; +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 map = new LinkedHashMap(); + map.put("url", statValue.url); + map.put("dbType", statValue.dbType); + map.put("name", statValue.name); + map.put("activeCount", statValue.activeCount); + map.put("activePeak", statValue.activePeak); + + map.put("activePeakTime", statValue.getActivePeakTime()); + map.put("poolingCount", statValue.poolingCount); + map.put("poolingPeak", statValue.poolingPeak); + map.put("poolingPeakTime", statValue.getPoolingPeakTime()); + map.put("connectCount", statValue.connectCount); + + map.put("closeCount", statValue.closeCount); + map.put("waitThreadCount", statValue.waitThreadCount); + map.put("notEmptyWaitCount", statValue.notEmptyWaitCount); + map.put("notEmptyWaitMillis", statValue.getNotEmptyWaitMillis()); + map.put("logicConnectErrorCount", statValue.logicConnectErrorCount); + + map.put("physicalConnectCount", statValue.physicalConnectCount); + map.put("physicalCloseCount", statValue.physicalCloseCount); + map.put("physicalConnectErrorCount", statValue.physicalConnectErrorCount); + 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); + } + map.put("pstmtCacheHitCount", statValue.pstmtCacheHitCount); + map.put("pstmtCacheMissCount", statValue.pstmtCacheMissCount); + if (statValue.startTransactionCount > 0) { + map.put("startTransactionCount", statValue.startTransactionCount); + map.put("transactionHistogram", statValue.transactionHistogram); + } + map.put("connectionHoldTimeHistogram", statValue.connectionHoldTimeHistogram); + if (statValue.clobOpenCount > 0) { + map.put("clobOpenCount", statValue.clobOpenCount); + } + if (statValue.blobOpenCount > 0) { + map.put("blobOpenCount", statValue.blobOpenCount); + } + + ArrayList> sqlList = new ArrayList>(); + for (JdbcSqlStatValue sqlStat : statValue.sqlList) { + Map sqlStatMap = new LinkedHashMap(); + sqlStatMap.put("sql", sqlStat.sql); + sqlStatMap.put("executeCount", sqlStat.getExecuteCount()); + if (sqlStat.executeErrorCount > 0) { + sqlStatMap.put("executeErrorCount", sqlStat.executeErrorCount); + } + if (sqlStat.runningCount > 0) { + sqlStatMap.put("runningCount", sqlStat.runningCount); + } + sqlStatMap.put("concurrentMax", sqlStat.concurrentMax); + + sqlStatMap.put("executeMillisMax", sqlStat.getExecuteMillisMax()); + sqlStatMap.put("executeMillisTotal", sqlStat.getExecuteMillisTotal()); + + sqlStatMap.put("executeHistogram", sqlStat.getExecuteHistogram()); + sqlStatMap.put("executeAndResultHoldHistogram", sqlStat.getExecuteAndResultHoldHistogram()); + if (sqlStat.fetchRowCount > 0) { + sqlStatMap.put("fetchRowCount", sqlStat.fetchRowCount); + sqlStatMap.put("fetchRowCount", sqlStat.fetchRowCountMax); + sqlStatMap.put("fetchRowHistogram", sqlStat.getFetchRowHistogram()); + } + + if (sqlStat.updateCount > 0) { + sqlStatMap.put("updateCount", sqlStat.updateCount); + sqlStatMap.put("updateCountMax", sqlStat.updateCountMax); + sqlStatMap.put("updateHistogram", 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); + } + + } + + String text = JSONUtils.toJSONString(map); + + LOG.info(text); + } } } diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatValue.java b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatValue.java index 05018f9977..524bd2726c 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatValue.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSourceStatValue.java @@ -15,63 +15,86 @@ */ package com.alibaba.druid.pool; +import java.util.Date; import java.util.List; import com.alibaba.druid.stat.JdbcSqlStatValue; public class DruidDataSourceStatValue { - public int activeCount; - public int activePeak; - public long activePeakTime; + public String name; + public String dbType; + public String driverClassName; + public String url; + public String userName; + public List filterClassNames; + public boolean removeAbandoned; - public int poolingCount; - public int poolingPeak; - public long poolingPeakTime; + 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 connectCount; - public long closeCount; - public long waitThreadCount; - public long notEmptyWaitCount; - public long notEmptyWaitNanos; + public int activeCount; + public int activePeak; + public long activePeakTime; - public String name; - public String dbType; - public String driverClassName; - public String url; - public String userName; - public List filterClassNames; + 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 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; + + 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); + } } diff --git a/src/main/java/com/alibaba/druid/stat/JdbcSqlStatValue.java b/src/main/java/com/alibaba/druid/stat/JdbcSqlStatValue.java index 67b8a7b5fb..751aafb0cf 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcSqlStatValue.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcSqlStatValue.java @@ -69,27 +69,82 @@ public class JdbcSqlStatValue { 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[] 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 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 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 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[] 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); + } }