diff --git a/src/main/java/com/alibaba/druid/proxy/DruidDriver.java b/src/main/java/com/alibaba/druid/proxy/DruidDriver.java index f89ef69dbf..b7cd804472 100644 --- a/src/main/java/com/alibaba/druid/proxy/DruidDriver.java +++ b/src/main/java/com/alibaba/druid/proxy/DruidDriver.java @@ -46,7 +46,7 @@ public class DruidDriver implements Driver, DruidDriverMBean { private final static DruidDriver instance = new DruidDriver(); - private final static ConcurrentMap dataSources = new ConcurrentHashMap(); + private final static ConcurrentMap proxyDataSources = new ConcurrentHashMap(); private final static AtomicInteger dataSourceIdSeed = new AtomicInteger(0); public final static String DEFAULT_PREFIX = "jdbc:wrap-jdbc:"; @@ -128,7 +128,7 @@ public class DruidDriver implements Driver, DruidDriverMBean { * @throws SQLException */ private DataSourceProxyImpl getDataSource(String url, Properties info) throws SQLException { - DataSourceProxyImpl dataSource = dataSources.get(url); + DataSourceProxyImpl dataSource = proxyDataSources.get(url); if (dataSource == null) { String restUrl = url.substring(DEFAULT_PREFIX.length()); @@ -193,7 +193,7 @@ public class DruidDriver implements Driver, DruidDriverMBean { DataSourceProxyImpl newDataSource = new DataSourceProxyImpl(rawDriver, config); - DataSourceProxy oldDataSource = dataSources.putIfAbsent(url, newDataSource); // 多线程处理需要 + DataSourceProxy oldDataSource = proxyDataSources.putIfAbsent(url, newDataSource); // 多线程处理需要 if (oldDataSource == null) { // 放进去的线程负责初始化 int dataSourceId = createDataSourceId(); @@ -208,7 +208,7 @@ public class DruidDriver implements Driver, DruidDriverMBean { } } - dataSource = dataSources.get(url); + dataSource = proxyDataSources.get(url); } return dataSource; } @@ -264,10 +264,10 @@ public class DruidDriver implements Driver, DruidDriverMBean { @Override public String[] getDataSourceUrls() { - return dataSources.keySet().toArray(new String[dataSources.size()]); + return proxyDataSources.keySet().toArray(new String[proxyDataSources.size()]); } - public static ConcurrentMap getDataSources() { - return dataSources; + public static ConcurrentMap getProxyDataSources() { + return proxyDataSources; } } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/DataSourceProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/DataSourceProxyImpl.java index 7e2355c14e..f292b2205a 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/DataSourceProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/DataSourceProxyImpl.java @@ -28,11 +28,7 @@ import java.util.Properties; import java.util.concurrent.atomic.AtomicLong; import javax.management.JMException; -import javax.management.openmbean.ArrayType; import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.SimpleType; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; @@ -41,6 +37,7 @@ import com.alibaba.druid.filter.FilterChain; import com.alibaba.druid.filter.FilterChainImpl; import com.alibaba.druid.filter.stat.StatFilter; import com.alibaba.druid.stat.JdbcDataSourceStat; +import com.alibaba.druid.stat.JdbcStatManager; import com.alibaba.druid.util.JdbcUtils; /** @@ -179,49 +176,6 @@ public class DataSourceProxyImpl implements DataSourceProxy, DataSourceProxyImpl return properties.toString(); } - private static CompositeType COMPOSITE_TYPE = null; - - public static CompositeType getCompositeType() throws JMException { - - if (COMPOSITE_TYPE != null) { - return COMPOSITE_TYPE; - } - - OpenType[] indexTypes = new OpenType[] { // - SimpleType.LONG, SimpleType.STRING, SimpleType.STRING, new ArrayType>(SimpleType.STRING, false), SimpleType.DATE, // - SimpleType.STRING, SimpleType.STRING, SimpleType.INTEGER, SimpleType.INTEGER, SimpleType.STRING // - , SimpleType.LONG, SimpleType.INTEGER, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG // - , SimpleType.DATE, SimpleType.LONG, SimpleType.DATE, SimpleType.STRING, SimpleType.STRING // - , SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.INTEGER // - , SimpleType.INTEGER, SimpleType.LONG, SimpleType.LONG, SimpleType.DATE, SimpleType.STRING // - , SimpleType.STRING, SimpleType.LONG, SimpleType.INTEGER, SimpleType.DATE, SimpleType.LONG // - , SimpleType.LONG, SimpleType.INTEGER, SimpleType.INTEGER, SimpleType.LONG, SimpleType.DATE // - , SimpleType.LONG, SimpleType.LONG, SimpleType.DATE, SimpleType.STRING, SimpleType.STRING // - , SimpleType.LONG, SimpleType.STRING, SimpleType.STRING, SimpleType.LONG, SimpleType.INTEGER // - , SimpleType.LONG, SimpleType.DATE, SimpleType.LONG, SimpleType.LONG - // - }; - - String[] indexNames = { "ID", "URL", "Name", "FilterClasses", "CreatedTime", // - "RawUrl", "RawDriverClassName", "RawDriverMajorVersion", "RawDriverMinorVersion", "Properties" // - , "ConnectionActiveCount", "ConnectionActiveCountMax", "ConnectionCloseCount", "ConnectionCommitCount", "ConnectionRollbackCount" // - , "ConnectionConnectLastTime", "ConnectionConnectErrorCount", "ConnectionConnectErrorLastTime", "ConnectionConnectErrorLastMessage", "ConnectionConnectErrorLastStackTrace" // - , "StatementCreateCount", "StatementPrepareCount", "StatementPreCallCount", "StatementExecuteCount", "StatementRunningCount" // - , "StatementConcurrentMax", "StatementCloseCount", "StatementErrorCount", "StatementLastErrorTime", "StatementLastErrorMessage" // - , "StatementLastErrorStackTrace", "StatementExecuteMillis", "ConnectionConnectingCount", "StatementExecuteLastTime", "ResultSetCloseCount" // - , "ResultSetOpenCount", "ResultSetOpenningCount", "ResultSetOpenningMax", "ResultSetFetchRowCount", "ResultSetLastOpenTime" // - , "ResultSetErrorCount", "ResultSetOpenningMillisTotal", "ResultSetLastErrorTime", "ResultSetLastErrorMessage", "ResultSetLastErrorStackTrace" - , "ConnectionConnectCount", "ConnectionErrorLastMessage", "ConnectionErrorLastStackTrace", "ConnectionConnectMillisTotal", "ConnectionConnectingCountMax" // - , "ConnectionConnectMillisMax", "ConnectionErrorLastTime", "ConnectionAliveMillisMax", "ConnectionAliveMillisMin" - // - }; - - String[] indexDescriptions = indexNames; - COMPOSITE_TYPE = new CompositeType("DataSourceStatistic", "DataSource Statistic", indexNames, indexDescriptions, indexTypes); - - return COMPOSITE_TYPE; - } - public CompositeDataSupport getCompositeData() throws JMException { StatFilter statFilter = null; JdbcDataSourceStat stat = null; @@ -391,7 +345,7 @@ public class DataSourceProxyImpl implements DataSourceProxy, DataSourceProxyImpl map.put("ConnectionAliveMillisMin", null); } - return new CompositeDataSupport(getCompositeType(), map); + return new CompositeDataSupport(JdbcStatManager.getDataSourceCompositeType(), map); } @Override diff --git a/src/main/java/com/alibaba/druid/stat/JdbcConnectionStat.java b/src/main/java/com/alibaba/druid/stat/JdbcConnectionStat.java index 9335688303..c0001a2782 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcConnectionStat.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcConnectionStat.java @@ -206,8 +206,8 @@ public class JdbcConnectionStat implements JdbcConnectionStatMBean { for (;;) { long min = aliveNanoMin.get(); - if (aliveNano < min) { - if (aliveNanoMax.compareAndSet(min, aliveNano)) { + if (min == 0 || aliveNano < min) { + if (aliveNanoMin.compareAndSet(min, aliveNano)) { break; } else { continue; diff --git a/src/main/java/com/alibaba/druid/stat/JdbcResultSetStat.java b/src/main/java/com/alibaba/druid/stat/JdbcResultSetStat.java index c6e72e50cd..2a01e4a5e6 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcResultSetStat.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcResultSetStat.java @@ -28,6 +28,8 @@ public class JdbcResultSetStat implements JdbcResultSetStatMBean { private final AtomicLong errorCount = new AtomicLong(); private final AtomicLong aliveNanoTotal = new AtomicLong(); + private final AtomicLong aliveNanoMax = new AtomicLong(); + private final AtomicLong aliveNanoMin = new AtomicLong(); private Throwable lastError; private long lastErrorTime; @@ -41,6 +43,8 @@ public class JdbcResultSetStat implements JdbcResultSetStatMBean { openCount.set(0); errorCount.set(0); aliveNanoTotal.set(0); + aliveNanoMax.set(0); + aliveNanoMin.set(0); lastError = null; lastErrorTime = 0; lastOpenTime = 0; @@ -99,11 +103,45 @@ public class JdbcResultSetStat implements JdbcResultSetStatMBean { public long getAliveMillisTotal() { return aliveNanoTotal.get() / (1000 * 1000); } + + public long getAliveMilisMin() { + return aliveNanoMin.get() / (1000 * 1000); + } + + public long getAliveMilisMax() { + return aliveNanoMax.get() / (1000 * 1000); + } - public void afterClose(long nanoSpan) { + public void afterClose(long aliveNano) { openningCount.decrementAndGet(); - aliveNanoTotal.addAndGet(nanoSpan); + aliveNanoTotal.addAndGet(aliveNano); + + for (;;) { + long max = aliveNanoMax.get(); + if (aliveNano > max) { + if (aliveNanoMax.compareAndSet(max, aliveNano)) { + break; + } else { + continue; + } + } else { + break; + } + } + + for (;;) { + long min = aliveNanoMin.get(); + if (aliveNano < min) { + if (aliveNanoMin.compareAndSet(min, aliveNano)) { + break; + } else { + continue; + } + } else { + break; + } + } } public Throwable getLastError() { diff --git a/src/main/java/com/alibaba/druid/stat/JdbcStatManager.java b/src/main/java/com/alibaba/druid/stat/JdbcStatManager.java index d549071b08..e23b651b37 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcStatManager.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcStatManager.java @@ -21,8 +21,11 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicLong; import javax.management.JMException; +import javax.management.openmbean.ArrayType; import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeType; +import javax.management.openmbean.OpenType; +import javax.management.openmbean.SimpleType; import javax.management.openmbean.TabularData; import javax.management.openmbean.TabularDataSupport; import javax.management.openmbean.TabularType; @@ -91,16 +94,59 @@ public class JdbcStatManager implements JdbcStatManagerMBean { public JdbcConnectionStat getConnectionstat() { return connectionStat; } + + private static CompositeType COMPOSITE_TYPE = null; + + public static CompositeType getDataSourceCompositeType() throws JMException { + + if (COMPOSITE_TYPE != null) { + return COMPOSITE_TYPE; + } + + OpenType[] indexTypes = new OpenType[] { // + SimpleType.LONG, SimpleType.STRING, SimpleType.STRING, new ArrayType>(SimpleType.STRING, false), SimpleType.DATE, // + SimpleType.STRING, SimpleType.STRING, SimpleType.INTEGER, SimpleType.INTEGER, SimpleType.STRING // + , SimpleType.LONG, SimpleType.INTEGER, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG // + , SimpleType.DATE, SimpleType.LONG, SimpleType.DATE, SimpleType.STRING, SimpleType.STRING // + , SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.INTEGER // + , SimpleType.INTEGER, SimpleType.LONG, SimpleType.LONG, SimpleType.DATE, SimpleType.STRING // + , SimpleType.STRING, SimpleType.LONG, SimpleType.INTEGER, SimpleType.DATE, SimpleType.LONG // + , SimpleType.LONG, SimpleType.INTEGER, SimpleType.INTEGER, SimpleType.LONG, SimpleType.DATE // + , SimpleType.LONG, SimpleType.LONG, SimpleType.DATE, SimpleType.STRING, SimpleType.STRING // + , SimpleType.LONG, SimpleType.STRING, SimpleType.STRING, SimpleType.LONG, SimpleType.INTEGER // + , SimpleType.LONG, SimpleType.DATE, SimpleType.LONG, SimpleType.LONG + // + }; + + String[] indexNames = { "ID", "URL", "Name", "FilterClasses", "CreatedTime", // + "RawUrl", "RawDriverClassName", "RawDriverMajorVersion", "RawDriverMinorVersion", "Properties" // + , "ConnectionActiveCount", "ConnectionActiveCountMax", "ConnectionCloseCount", "ConnectionCommitCount", "ConnectionRollbackCount" // + , "ConnectionConnectLastTime", "ConnectionConnectErrorCount", "ConnectionConnectErrorLastTime", "ConnectionConnectErrorLastMessage", "ConnectionConnectErrorLastStackTrace" // + , "StatementCreateCount", "StatementPrepareCount", "StatementPreCallCount", "StatementExecuteCount", "StatementRunningCount" // + , "StatementConcurrentMax", "StatementCloseCount", "StatementErrorCount", "StatementLastErrorTime", "StatementLastErrorMessage" // + , "StatementLastErrorStackTrace", "StatementExecuteMillis", "ConnectionConnectingCount", "StatementExecuteLastTime", "ResultSetCloseCount" // + , "ResultSetOpenCount", "ResultSetOpenningCount", "ResultSetOpenningMax", "ResultSetFetchRowCount", "ResultSetLastOpenTime" // + , "ResultSetErrorCount", "ResultSetOpenningMillisTotal", "ResultSetLastErrorTime", "ResultSetLastErrorMessage", "ResultSetLastErrorStackTrace" + , "ConnectionConnectCount", "ConnectionErrorLastMessage", "ConnectionErrorLastStackTrace", "ConnectionConnectMillisTotal", "ConnectionConnectingCountMax" // + , "ConnectionConnectMillisMax", "ConnectionErrorLastTime", "ConnectionAliveMillisMax", "ConnectionAliveMillisMin" + // + }; + + String[] indexDescriptions = indexNames; + COMPOSITE_TYPE = new CompositeType("DataSourceStatistic", "DataSource Statistic", indexNames, indexDescriptions, indexTypes); + + return COMPOSITE_TYPE; + } @Override public TabularData getDataSourceList() throws JMException { - CompositeType rowType = DataSourceProxyImpl.getCompositeType(); + CompositeType rowType = getDataSourceCompositeType(); String[] indexNames = rowType.keySet().toArray(new String[rowType.keySet().size()]); TabularType tabularType = new TabularType("DataSourceStat", "DataSourceStat", rowType, indexNames); TabularData data = new TabularDataSupport(tabularType); - final ConcurrentMap dataSources = DruidDriver.getDataSources(); + final ConcurrentMap dataSources = DruidDriver.getProxyDataSources(); for (DataSourceProxyImpl dataSource : dataSources.values()) { data.put(dataSource.getCompositeData()); } @@ -135,7 +181,7 @@ public class JdbcStatManager implements JdbcStatManagerMBean { TabularType tabularType = new TabularType("ConnectionList", "ConnectionList", rowType, indexNames); TabularData data = new TabularDataSupport(tabularType); - final ConcurrentMap dataSources = DruidDriver.getDataSources(); + final ConcurrentMap dataSources = DruidDriver.getProxyDataSources(); for (DataSourceProxyImpl dataSource : dataSources.values()) { for (Filter filter : dataSource.getConfig().getFilters()) { if (filter instanceof StatFilter) { @@ -160,7 +206,7 @@ public class JdbcStatManager implements JdbcStatManagerMBean { statementStat.reset(); resultSetStat.reset(); - final ConcurrentMap dataSources = DruidDriver.getDataSources(); + final ConcurrentMap dataSources = DruidDriver.getProxyDataSources(); for (DataSourceProxyImpl dataSource : dataSources.values()) { for (Filter filter : dataSource.getConfig().getFilters()) { if (filter instanceof StatFilter) { diff --git a/src/test/java/com/alibaba/druid/pool/TestOracle.java b/src/test/java/com/alibaba/druid/pool/TestOracle.java index e53f9c4ee9..37695c4d40 100644 --- a/src/test/java/com/alibaba/druid/pool/TestOracle.java +++ b/src/test/java/com/alibaba/druid/pool/TestOracle.java @@ -1,10 +1,16 @@ package com.alibaba.druid.pool; import java.sql.Connection; +import java.util.TreeMap; + +import javax.management.openmbean.TabularData; import junit.framework.TestCase; -import com.alibaba.druid.pool.vendor.MySqlExceptionSorter; +import com.alibaba.druid.pool.vendor.OracleExceptionSorter; +import com.alibaba.druid.stat.JdbcStatManager; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; public class TestOracle extends TestCase { @@ -23,10 +29,16 @@ public class TestOracle extends TestCase { dataSource.setUrl(jdbcUrl); dataSource.setUsername(user); dataSource.setPassword(password); - // dataSource.setFilters("stat"); - dataSource.setExceptionSoter(MySqlExceptionSorter.class.getName()); + dataSource.setFilters("stat"); + dataSource.setExceptionSoter(OracleExceptionSorter.class.getName()); Connection conn = dataSource.getConnection(); conn.close(); + + TabularData dataSourcesList = JdbcStatManager.getInstance().getDataSourceList(); + for (Object item : dataSourcesList.values()) { + String text = JSON.toJSONString(item, SerializerFeature.UseISO8601DateFormat); + System.out.println(JSON.toJSONString(JSON.parseObject(text, TreeMap.class), true)); + } } } diff --git a/src/test/java/com/alibaba/druid/proxy/TestOracle.java b/src/test/java/com/alibaba/druid/proxy/TestOracle.java index c18c1389df..0604a3b005 100644 --- a/src/test/java/com/alibaba/druid/proxy/TestOracle.java +++ b/src/test/java/com/alibaba/druid/proxy/TestOracle.java @@ -4,6 +4,7 @@ import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; +import java.util.TreeMap; import javax.management.openmbean.TabularData; @@ -11,20 +12,22 @@ import junit.framework.TestCase; import com.alibaba.druid.stat.JdbcStatManager; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; public class TestOracle extends TestCase { + private String jdbcUrl; private String user; private String password; public void setUp() throws Exception { jdbcUrl = "jdbc:wrap-jdbc:filters=default:name=oracleTest:jdbc:oracle:thin:@10.20.149.85:1521:ocnauto"; - jdbcUrl = "jdbc:wrap-jdbc:filters=default:name=oracleTest:jdbc:mock:xx"; + // jdbcUrl = "jdbc:wrap-jdbc:filters=default:name=oracleTest:jdbc:mock:xx"; user = "alibaba"; password = "ccbuauto"; } - - public void test_0 () throws Exception { + + public void test_0() throws Exception { Connection conn = DriverManager.getConnection(jdbcUrl, user, password); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT 1 FROM DUAL"); @@ -32,9 +35,12 @@ public class TestOracle extends TestCase { rs.close(); stmt.close(); conn.close(); - + TabularData dataSourcesList = JdbcStatManager.getInstance().getDataSourceList(); - String text = JSON.toJSONString(dataSourcesList); - System.out.println(JSON.toJSONString(JSON.parse(text), true)); + for (Object item : dataSourcesList.values()) { + String text = JSON.toJSONString(item, SerializerFeature.UseISO8601DateFormat); + System.out.println(JSON.toJSONString(JSON.parseObject(text, TreeMap.class), true)); + } + } }