diff --git a/pom.xml b/pom.xml index e950290e56..9cf18e9825 100644 --- a/pom.xml +++ b/pom.xml @@ -170,6 +170,50 @@ + + + default-profile + + true + + ${java.home}/../lib/jconsole.jar + + + + ${java.home}/../lib/jconsole.jar + + + + + com.alibaba + jconsole + 1.6.0 + system + ${jconsolejar} + true + + + + + mac-profile + + false + + ${java.home}/../Classes/jconsole.jar + + + + + com.alibaba + jconsole + 1.6.0 + system + ${java.home}/../Classes/jconsole.jar + + + + + javax.servlet diff --git a/src/main/java/com/alibaba/druid/filter/logging/LogFilter.java b/src/main/java/com/alibaba/druid/filter/logging/LogFilter.java index 1562177d21..c5499fda17 100644 --- a/src/main/java/com/alibaba/druid/filter/logging/LogFilter.java +++ b/src/main/java/com/alibaba/druid/filter/logging/LogFilter.java @@ -21,6 +21,8 @@ import java.sql.Types; import com.alibaba.druid.filter.FilterChain; import com.alibaba.druid.filter.FilterEventAdapter; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.pool.DruidPooledConnection; import com.alibaba.druid.proxy.jdbc.CallableStatementProxy; import com.alibaba.druid.proxy.jdbc.ConnectionProxy; import com.alibaba.druid.proxy.jdbc.DataSourceProxy; @@ -298,7 +300,7 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM super.connection_commit(chain, connection); if (connectionCommitAfterLogEnable && isConnectionLogEnabled()) { - connectionLog("connect commited. id " + connection.getId()); + connectionLog("connect committed. id " + connection.getId()); } } @@ -306,7 +308,7 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM public void connection_setAutoCommit(FilterChain chain, ConnectionProxy connection, boolean autoCommit) throws SQLException { - connectionLog("connect setAutoComment " + autoCommit + ". id " + connection.getId()); + connectionLog("connect setAutoCommit " + autoCommit + ". id " + connection.getId()); chain.connection_setAutoCommit(connection, autoCommit); } @@ -578,5 +580,34 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM } } } + + @Override + public void dataSource_releaseConnection(FilterChain chain, DruidPooledConnection conn) throws SQLException { + long connectionId = -1; + + if (conn.getConnectionHolder() != null) { + ConnectionProxy connection = (ConnectionProxy) conn.getConnectionHolder().getConnection(); + connectionId = connection.getId(); + } + + chain.dataSource_recycle(conn); + + if (connectionCloseAfterLogEnable && isConnectionLogEnabled()) { + connectionLog("{conn-" + connectionId + "} pool-recycle"); + } + } + + @Override + public DruidPooledConnection dataSource_getConnection(FilterChain chain, DruidDataSource dataSource, long maxWaitMillis) throws SQLException { + DruidPooledConnection conn = chain.dataSource_connect(dataSource, maxWaitMillis); + + ConnectionProxy connection = (ConnectionProxy) conn.getConnectionHolder().getConnection(); + + if (connectionConnectAfterLogEnable && isConnectionLogEnabled()) { + connectionLog("{conn-" + connection.getId() + "} pool-connect"); + } + + return conn; + } } diff --git a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java index c475aa61a1..2ffd9e4e89 100644 --- a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java +++ b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java @@ -312,7 +312,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { @Override protected void statementExecuteUpdateAfter(StatementProxy statement, String sql, int updateCount) { - internalAfterStatementExecute(statement, updateCount); + internalAfterStatementExecute(statement, false, updateCount); } @Override @@ -322,7 +322,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { @Override protected void statementExecuteQueryAfter(StatementProxy statement, String sql, ResultSetProxy resultSet) { - internalAfterStatementExecute(statement); + internalAfterStatementExecute(statement, true); } @Override @@ -331,8 +331,8 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { } @Override - protected void statementExecuteAfter(StatementProxy statement, String sql, boolean result) { - internalAfterStatementExecute(statement); + protected void statementExecuteAfter(StatementProxy statement, String sql, boolean firstResult) { + internalAfterStatementExecute(statement, firstResult); } @Override @@ -341,7 +341,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { final int batchSize = statement.getBatchSqlList().size(); JdbcSqlStat sqlStat = statement.getSqlStat(); - if (sqlStat == null) { + if (sqlStat == null || sqlStat.isRemoved()) { sqlStat = createSqlStat(statement, sql); statement.setSqlStat(sqlStat); } @@ -356,7 +356,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { @Override protected void statementExecuteBatchAfter(StatementProxy statement, int[] result) { - internalAfterStatementExecute(statement, result); + internalAfterStatementExecute(statement, false, result); } @@ -380,7 +380,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { // //////////SQL JdbcSqlStat sqlStat = statement.getSqlStat(); - if (sqlStat == null) { + if (sqlStat == null || sqlStat.isRemoved()) { sqlStat = createSqlStat(statement, sql); statement.setSqlStat(sqlStat); } @@ -406,7 +406,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { } } - private final void internalAfterStatementExecute(StatementProxy statement, int... updateCountArray) { + private final void internalAfterStatementExecute(StatementProxy statement, boolean firstResult, int... updateCountArray) { final JdbcStatementStat.Entry entry = getStatementInfo(statement); @@ -426,7 +426,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { } sqlStat.decrementRunningCount(); - sqlStat.addExecuteTime(statement.getLastExecuteType(), nanoSpan); + sqlStat.addExecuteTime(statement.getLastExecuteType(), firstResult, nanoSpan); statement.setLastExecuteTimeNano(nanoSpan); if ((!statement.isFirstResultSet()) && statement.getLastExecuteType() == StatementExecuteType.Execute) { try { @@ -525,7 +525,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { if (sqlStat != null) { sqlStat.error(error); - sqlStat.addExecuteTime(statement.getLastExecuteType(), nanoSpan); + sqlStat.addExecuteTime(statement.getLastExecuteType(), statement.isFirstResultSet(), nanoSpan); statement.setLastExecuteTimeNano(nanoSpan); } diff --git a/src/main/java/com/alibaba/druid/mock/MockDriver.java b/src/main/java/com/alibaba/druid/mock/MockDriver.java index 7c3447d95c..c4e99d5061 100644 --- a/src/main/java/com/alibaba/druid/mock/MockDriver.java +++ b/src/main/java/com/alibaba/druid/mock/MockDriver.java @@ -235,12 +235,12 @@ public class MockDriver implements Driver, MockDriverMBean { return true; } - protected ResultSet executeQuery(MockStatement stmt, String sql) throws SQLException { + public ResultSet executeQuery(MockStatementBase stmt, String sql) throws SQLException { if (logExecuteQueryEnable && LOG.isDebugEnabled()) { LOG.debug("executeQuery " + sql); } - MockConnection conn = stmt.getMockConnection(); + MockConnection conn = stmt.getConnection(); long idleTimeMillis = System.currentTimeMillis() - conn.getLastActiveTimeMillis(); if (idleTimeMillis >= this.idleTimeCount) { diff --git a/src/main/java/com/alibaba/druid/mock/MockPreparedStatement.java b/src/main/java/com/alibaba/druid/mock/MockPreparedStatement.java index aac0e05575..ff69946319 100644 --- a/src/main/java/com/alibaba/druid/mock/MockPreparedStatement.java +++ b/src/main/java/com/alibaba/druid/mock/MockPreparedStatement.java @@ -21,7 +21,7 @@ import java.sql.SQLException; import com.alibaba.druid.util.jdbc.PreparedStatementBase; -public class MockPreparedStatement extends PreparedStatementBase implements PreparedStatement { +public class MockPreparedStatement extends PreparedStatementBase implements MockStatementBase, PreparedStatement { private final String sql; diff --git a/src/main/java/com/alibaba/druid/mock/MockStatement.java b/src/main/java/com/alibaba/druid/mock/MockStatement.java index 3ff6c4c592..6bbf5394d1 100644 --- a/src/main/java/com/alibaba/druid/mock/MockStatement.java +++ b/src/main/java/com/alibaba/druid/mock/MockStatement.java @@ -22,7 +22,7 @@ import java.sql.Statement; import com.alibaba.druid.util.jdbc.StatementBase; -public class MockStatement extends StatementBase implements Statement { +public class MockStatement extends StatementBase implements MockStatementBase, Statement { public final static String ERROR_SQL = "THROW ERROR"; @@ -46,7 +46,7 @@ public class MockStatement extends StatementBase implements Statement { } } - public MockConnection getMockConnection() { + public MockConnection getConnection() { return mockConnection; } diff --git a/src/main/java/com/alibaba/druid/mock/MockStatementBase.java b/src/main/java/com/alibaba/druid/mock/MockStatementBase.java new file mode 100644 index 0000000000..93fa75f6e6 --- /dev/null +++ b/src/main/java/com/alibaba/druid/mock/MockStatementBase.java @@ -0,0 +1,9 @@ +package com.alibaba.druid.mock; + +import java.sql.SQLException; +import java.sql.Statement; + + +public interface MockStatementBase extends Statement { + MockConnection getConnection() throws SQLException; +} diff --git a/src/main/java/com/alibaba/druid/mock/handler/MockExecuteHandler.java b/src/main/java/com/alibaba/druid/mock/handler/MockExecuteHandler.java index 2d225ea02a..ffd2f67345 100644 --- a/src/main/java/com/alibaba/druid/mock/handler/MockExecuteHandler.java +++ b/src/main/java/com/alibaba/druid/mock/handler/MockExecuteHandler.java @@ -3,9 +3,9 @@ package com.alibaba.druid.mock.handler; import java.sql.ResultSet; import java.sql.SQLException; -import com.alibaba.druid.mock.MockStatement; +import com.alibaba.druid.mock.MockStatementBase; public interface MockExecuteHandler { - ResultSet executeQuery(MockStatement statement, String sql) throws SQLException; + ResultSet executeQuery(MockStatementBase statement, String sql) throws SQLException; } diff --git a/src/main/java/com/alibaba/druid/mock/handler/MySqlMockExecuteHandlerImpl.java b/src/main/java/com/alibaba/druid/mock/handler/MySqlMockExecuteHandlerImpl.java index 03d27b5121..14d348acf9 100644 --- a/src/main/java/com/alibaba/druid/mock/handler/MySqlMockExecuteHandlerImpl.java +++ b/src/main/java/com/alibaba/druid/mock/handler/MySqlMockExecuteHandlerImpl.java @@ -8,7 +8,7 @@ import java.util.List; import com.alibaba.druid.mock.MockResultSet; import com.alibaba.druid.mock.MockResultSetMetaData; -import com.alibaba.druid.mock.MockStatement; +import com.alibaba.druid.mock.MockStatementBase; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; @@ -35,7 +35,7 @@ import com.alibaba.druid.util.jdbc.ResultSetMetaDataBase.ColumnMetaData; public class MySqlMockExecuteHandlerImpl implements MockExecuteHandler { @Override - public ResultSet executeQuery(MockStatement statement, String sql) throws SQLException { + public ResultSet executeQuery(MockStatementBase statement, String sql) throws SQLException { SQLStatementParser parser = new MySqlStatementParser(sql); List stmtList = parser.parseStatementList(); // @@ -67,7 +67,7 @@ public class MySqlMockExecuteHandlerImpl implements MockExecuteHandler { throw new SQLException("TODO"); } - public ResultSet executeQuery(MockStatement statement, SQLSelectQueryBlock query) throws SQLException { + public ResultSet executeQuery(MockStatementBase statement, SQLSelectQueryBlock query) throws SQLException { SQLTableSource from = query.getFrom(); if (from instanceof SQLExprTableSource) { @@ -87,7 +87,7 @@ public class MySqlMockExecuteHandlerImpl implements MockExecuteHandler { } } - public ResultSet showStatus(MockStatement statement) throws SQLException { + public ResultSet showStatus(MockStatementBase statement) throws SQLException { MockResultSet rs = new MockResultSet(statement); MockResultSetMetaData metaData = rs.getMockMetaData(); @@ -102,7 +102,7 @@ public class MySqlMockExecuteHandlerImpl implements MockExecuteHandler { return rs; } - public ResultSet executeQueryFromDual(MockStatement statement, SQLSelectQueryBlock query) throws SQLException { + public ResultSet executeQueryFromDual(MockStatementBase statement, SQLSelectQueryBlock query) throws SQLException { MockResultSet rs = new MockResultSet(statement); MockResultSetMetaData metaData = rs.getMockMetaData(); diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index d83f8e8b9a..f29afaa9af 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -72,7 +72,7 @@ import com.alibaba.druid.util.JdbcUtils; */ public class DruidDataSource extends DruidAbstractDataSource implements DruidDataSourceMBean, ManagedDataSource, Referenceable, Closeable, Cloneable, ConnectionPoolDataSource { - private final static Log LOG = LogFactory.getLog(DruidDataSource.class); + public final static Log LOG = LogFactory.getLog(DruidDataSource.class); private static final long serialVersionUID = 1L; @@ -274,6 +274,26 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (this.driverClass != null) { this.driverClass = driverClass.trim(); } + + if (isTestOnBorrow() || isTestOnReturn() || isTestWhileIdle()) { + if (this.getValidationQuery() == null || this.getValidationQuery().length() == 0) { + String errorMessage = ""; + + if (isTestOnBorrow()) { + errorMessage += "testOnBorrow is true, "; + } + + if (isTestOnReturn()) { + errorMessage += "testOnReturn is true, "; + } + + if (isTestWhileIdle()) { + errorMessage += "testWhileIdle is true, "; + } + + LOG.error(errorMessage + "validationQuery not set"); + } + } if (this.jdbcUrl != null) { this.jdbcUrl = this.jdbcUrl.trim(); @@ -281,6 +301,9 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (jdbcUrl.startsWith(DruidDriver.DEFAULT_PREFIX)) { DataSourceProxyConfig config = DruidDriver.parseConfig(jdbcUrl, null); this.driverClass = config.getRawDriverClassName(); + + LOG.error("error url : '" + jdbcUrl + "', it should be : '" + config.getRawUrl() + "'"); + this.jdbcUrl = config.getRawUrl(); if (this.name == null) { this.name = config.getName(); @@ -343,6 +366,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } else if (realDriverClassName.equals("com.alibaba.druid.mock.MockDriver")) { this.exceptionSorter = new MockExceptionSorter(); } + + if (realDriverClassName.equals("com.mysql.jdbc.Driver")) { + if (this.isPoolPreparedStatements()) { + LOG.error("mysql should not use 'PoolPreparedStatements'"); + } + } dataSourceStat = new JdbcDataSourceStat(this.name, this.jdbcUrl, this.dbType); diff --git a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourcePreparedStatement.java b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourcePreparedStatement.java index 89c5e3a7bd..13b4995ba2 100644 --- a/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourcePreparedStatement.java +++ b/src/main/java/com/alibaba/druid/pool/ha/MultiDataSourcePreparedStatement.java @@ -26,10 +26,11 @@ public class MultiDataSourcePreparedStatement extends PreparedStatementProxyImpl FilterChain chain = createChain(); if (chain.getFilterSize() == 0) { - return this.statement.execute(); + firstResultSet = this.statement.execute(); + } else { + firstResultSet = chain.preparedStatement_execute(this); } - firstResultSet = chain.preparedStatement_execute(this); return firstResultSet; } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxyImpl.java index 37b373e975..ad26d7b631 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxyImpl.java @@ -40,7 +40,6 @@ import java.util.Map; import java.util.TreeMap; import com.alibaba.druid.proxy.jdbc.JdbcParameter.TYPE; -import com.alibaba.druid.stat.JdbcSqlStat; /** * @author wenshao @@ -94,6 +93,7 @@ public class PreparedStatementProxyImpl extends StatementProxyImpl implements Pr @Override public ResultSet executeQuery() throws SQLException { + firstResultSet = true; updateCount = null; lastExecuteType = StatementExecuteType.ExecuteQuery; return createChain().preparedStatement_executeQuery(this); @@ -101,6 +101,7 @@ public class PreparedStatementProxyImpl extends StatementProxyImpl implements Pr @Override public int executeUpdate() throws SQLException { + firstResultSet = false; lastExecuteType = StatementExecuteType.ExecuteUpdate; updateCount = createChain().preparedStatement_executeUpdate(this); return updateCount; @@ -466,13 +467,4 @@ public class PreparedStatementProxyImpl extends StatementProxyImpl implements Pr return super.unwrap(iface); } - - public JdbcSqlStat getSqlStat() { - if (sqlStat != null && sqlStat.isRemoved()) { - JdbcSqlStat sqlStat = this.getConnectionProxy().getDirectDataSource().getDataSourceStat().createSqlStat(sql); - sqlStat.setDbType(this.sqlStat.getDbType()); - this.sqlStat = sqlStat; - } - return sqlStat; - } } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java index 1908704e2d..4eeba26887 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java @@ -141,6 +141,7 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro @Override public int[] executeBatch() throws SQLException { + firstResultSet = false; lastExecuteType = StatementExecuteType.ExecuteBatch; int[] updateCounts = createChain().statement_executeBatch(this); @@ -153,6 +154,7 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro @Override public ResultSet executeQuery(String sql) throws SQLException { + firstResultSet = true; updateCount = null; lastExecuteSql = sql; lastExecuteType = StatementExecuteType.ExecuteQuery; @@ -161,6 +163,7 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro @Override public int executeUpdate(String sql) throws SQLException { + firstResultSet = false; lastExecuteSql = sql; lastExecuteType = StatementExecuteType.ExecuteUpdate; updateCount = createChain().statement_executeUpdate(this, sql); @@ -169,6 +172,7 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + firstResultSet = false; lastExecuteSql = sql; lastExecuteType = StatementExecuteType.ExecuteUpdate; updateCount = createChain().statement_executeUpdate(this, sql, autoGeneratedKeys); @@ -177,6 +181,7 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro @Override public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { + firstResultSet = false; lastExecuteSql = sql; lastExecuteType = StatementExecuteType.ExecuteUpdate; updateCount = createChain().statement_executeUpdate(this, sql, columnIndexes); @@ -185,6 +190,7 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro @Override public int executeUpdate(String sql, String[] columnNames) throws SQLException { + firstResultSet = false; lastExecuteSql = sql; lastExecuteType = StatementExecuteType.ExecuteUpdate; updateCount = createChain().statement_executeUpdate(this, sql, columnNames); diff --git a/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java b/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java index fe6dd287f8..f48d4dbbdf 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java @@ -336,8 +336,8 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { return executeSuccessCount.get(); } - public void addExecuteTime(StatementExecuteType executeType, long nanoSpan) { - if (StatementExecuteType.ExecuteQuery != executeType) { + public void addExecuteTime(StatementExecuteType executeType, boolean firstResultSet, long nanoSpan) { + if (StatementExecuteType.ExecuteQuery != executeType && !firstResultSet) { executeAndResultHoldTimeHistogram.record((nanoSpan) / 1000 / 1000); } addExecuteTime(nanoSpan); diff --git a/src/main/java/com/alibaba/druid/support/jconsole/DruidDataSourcePanel.java b/src/main/java/com/alibaba/druid/support/jconsole/DruidDataSourcePanel.java new file mode 100644 index 0000000000..d9d8345043 --- /dev/null +++ b/src/main/java/com/alibaba/druid/support/jconsole/DruidDataSourcePanel.java @@ -0,0 +1,7 @@ +package com.alibaba.druid.support.jconsole; + +public class DruidDataSourcePanel extends DruidPanel { + + private static final long serialVersionUID = 1L; + +} diff --git a/src/main/java/com/alibaba/druid/support/jconsole/DruidDriverPanel.java b/src/main/java/com/alibaba/druid/support/jconsole/DruidDriverPanel.java new file mode 100644 index 0000000000..81a2fc6685 --- /dev/null +++ b/src/main/java/com/alibaba/druid/support/jconsole/DruidDriverPanel.java @@ -0,0 +1,7 @@ +package com.alibaba.druid.support.jconsole; + +public class DruidDriverPanel extends DruidPanel { + + private static final long serialVersionUID = 1L; + +} diff --git a/src/main/java/com/alibaba/druid/support/jconsole/DruidPanel.java b/src/main/java/com/alibaba/druid/support/jconsole/DruidPanel.java new file mode 100644 index 0000000000..8f1b2e4bf3 --- /dev/null +++ b/src/main/java/com/alibaba/druid/support/jconsole/DruidPanel.java @@ -0,0 +1,21 @@ +package com.alibaba.druid.support.jconsole; + +import javax.management.MBeanServerConnection; +import javax.swing.JPanel; + +import com.sun.tools.jconsole.JConsoleContext; + +public class DruidPanel extends JPanel { + + private static final long serialVersionUID = 1L; + + protected Object doInBackground(JConsoleContext context) throws Exception { + doInBackground(context.getMBeanServerConnection()); + + return null; + } + + protected void doInBackground(MBeanServerConnection conn) throws Exception { + System.out.println("doInBackground"); + } +} diff --git a/src/main/java/com/alibaba/druid/support/jconsole/DruidPlugin.java b/src/main/java/com/alibaba/druid/support/jconsole/DruidPlugin.java new file mode 100644 index 0000000000..80b7f9e73d --- /dev/null +++ b/src/main/java/com/alibaba/druid/support/jconsole/DruidPlugin.java @@ -0,0 +1,47 @@ +package com.alibaba.druid.support.jconsole; + +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.swing.JPanel; +import javax.swing.SwingWorker; + +import com.sun.tools.jconsole.JConsolePlugin; + +public class DruidPlugin extends JConsolePlugin { + + private final Map tabs = new LinkedHashMap(); + + public DruidPlugin(){ + tabs.put("Druid-Driver", new DruidDriverPanel()); + tabs.put("Druid-DataSource", new DruidDataSourcePanel()); + tabs.put("Druid-SQL", new DruidSQLPanel()); + } + + @Override + public Map getTabs() { + return tabs; + } + + @Override + public SwingWorker newSwingWorker() { + SwingWorker worer = new SwingWorker() { + + @Override + protected Object doInBackground() throws Exception { + return DruidPlugin.this.doInBackground(); + } + }; + + return worer; + } + + protected Object doInBackground() throws Exception { + for (JPanel panel : tabs.values()) { + ((DruidPanel) panel).doInBackground(this.getContext()); + } + + return null; + } + +} diff --git a/src/main/java/com/alibaba/druid/support/jconsole/DruidSQLPanel.java b/src/main/java/com/alibaba/druid/support/jconsole/DruidSQLPanel.java new file mode 100644 index 0000000000..287013431e --- /dev/null +++ b/src/main/java/com/alibaba/druid/support/jconsole/DruidSQLPanel.java @@ -0,0 +1,8 @@ +package com.alibaba.druid.support.jconsole; + + +public class DruidSQLPanel extends DruidPanel { + + private static final long serialVersionUID = 1L; + +} diff --git a/src/main/java/com/alibaba/druid/support/logging/JakartaCommonsLoggingImpl.java b/src/main/java/com/alibaba/druid/support/logging/JakartaCommonsLoggingImpl.java index c09c9b83a3..0d77caf47a 100644 --- a/src/main/java/com/alibaba/druid/support/logging/JakartaCommonsLoggingImpl.java +++ b/src/main/java/com/alibaba/druid/support/logging/JakartaCommonsLoggingImpl.java @@ -7,6 +7,8 @@ public class JakartaCommonsLoggingImpl implements com.alibaba.druid.support.logg private Log log; + private int errorCount; + public JakartaCommonsLoggingImpl(Class clazz){ log = LogFactory.getLog(clazz); } @@ -17,10 +19,12 @@ public class JakartaCommonsLoggingImpl implements com.alibaba.druid.support.logg public void error(String s, Throwable e) { log.error(s, e); + errorCount++; } public void error(String s) { log.error(s); + errorCount++; } public void debug(String s) { @@ -40,4 +44,14 @@ public class JakartaCommonsLoggingImpl implements com.alibaba.druid.support.logg log.warn(s, e); } + public int getErrorCount() { + return errorCount; + } + + + @Override + public void resetStat() { + errorCount = 0; + } + } diff --git a/src/main/java/com/alibaba/druid/support/logging/Jdk14LoggingImpl.java b/src/main/java/com/alibaba/druid/support/logging/Jdk14LoggingImpl.java index 70bdcd042c..8eeb543769 100644 --- a/src/main/java/com/alibaba/druid/support/logging/Jdk14LoggingImpl.java +++ b/src/main/java/com/alibaba/druid/support/logging/Jdk14LoggingImpl.java @@ -6,6 +6,8 @@ import java.util.logging.Logger; public class Jdk14LoggingImpl implements Log { private Logger log; + + private int errorCount; public Jdk14LoggingImpl(Class clazz){ log = Logger.getLogger(clazz.toString()); @@ -17,10 +19,12 @@ public class Jdk14LoggingImpl implements Log { public void error(String s, Throwable e) { log.log(Level.SEVERE, s, e); + errorCount++; } public void error(String s) { log.log(Level.SEVERE, s); + errorCount++; } public void debug(String s) { @@ -40,4 +44,13 @@ public class Jdk14LoggingImpl implements Log { log.log(Level.WARNING, s, e); } + public int getErrorCount() { + return errorCount; + } + + + @Override + public void resetStat() { + errorCount = 0; + } } diff --git a/src/main/java/com/alibaba/druid/support/logging/Log.java b/src/main/java/com/alibaba/druid/support/logging/Log.java index fe59eaa116..6127466053 100644 --- a/src/main/java/com/alibaba/druid/support/logging/Log.java +++ b/src/main/java/com/alibaba/druid/support/logging/Log.java @@ -16,4 +16,7 @@ public interface Log { void warn(String s, Throwable e); + int getErrorCount(); + + void resetStat(); } diff --git a/src/main/java/com/alibaba/druid/support/logging/Log4jImpl.java b/src/main/java/com/alibaba/druid/support/logging/Log4jImpl.java index f09643eea8..2fa2a7d098 100644 --- a/src/main/java/com/alibaba/druid/support/logging/Log4jImpl.java +++ b/src/main/java/com/alibaba/druid/support/logging/Log4jImpl.java @@ -5,6 +5,8 @@ import org.apache.log4j.Logger; public class Log4jImpl implements Log { private Logger log; + + private int errorCount; public Log4jImpl(Class clazz){ log = Logger.getLogger(clazz); @@ -37,5 +39,13 @@ public class Log4jImpl implements Log { public void warn(String s, Throwable e) { log.warn(s, e); } + + public int getErrorCount() { + return errorCount; + } + @Override + public void resetStat() { + errorCount = 0; + } } diff --git a/src/main/java/com/alibaba/druid/support/logging/NoLoggingImpl.java b/src/main/java/com/alibaba/druid/support/logging/NoLoggingImpl.java index 89688f14dd..57fe946003 100644 --- a/src/main/java/com/alibaba/druid/support/logging/NoLoggingImpl.java +++ b/src/main/java/com/alibaba/druid/support/logging/NoLoggingImpl.java @@ -2,6 +2,8 @@ package com.alibaba.druid.support.logging; public class NoLoggingImpl implements Log { + private int errorCount; + public NoLoggingImpl(Class clazz){ } @@ -10,9 +12,11 @@ public class NoLoggingImpl implements Log { } public void error(String s, Throwable e) { + errorCount++; } public void error(String s) { + errorCount++; } public void debug(String s) { @@ -29,4 +33,12 @@ public class NoLoggingImpl implements Log { } + public int getErrorCount() { + return errorCount; + } + + @Override + public void resetStat() { + errorCount = 0; + } } diff --git a/src/main/resources/META-INF/services/com.sun.tools.jconsole.JConsolePlugin b/src/main/resources/META-INF/services/com.sun.tools.jconsole.JConsolePlugin index 8515387e7b..61086f8e00 100644 --- a/src/main/resources/META-INF/services/com.sun.tools.jconsole.JConsolePlugin +++ b/src/main/resources/META-INF/services/com.sun.tools.jconsole.JConsolePlugin @@ -1 +1 @@ -com.alibaba.druid.jconsole.DruidPlugin \ No newline at end of file +com.alibaba.druid.support.jconsole.DruidPlugin \ No newline at end of file diff --git a/src/test/java/com/alibaba/druid/bvt/filter/StatFilterExecuteFirstResultSetTest.java b/src/test/java/com/alibaba/druid/bvt/filter/StatFilterExecuteFirstResultSetTest.java new file mode 100644 index 0000000000..38c5afbffd --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/StatFilterExecuteFirstResultSetTest.java @@ -0,0 +1,92 @@ +package com.alibaba.druid.bvt.filter; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.mock.MockConnection; +import com.alibaba.druid.mock.MockDriver; +import com.alibaba.druid.mock.MockPreparedStatement; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.stat.JdbcSqlStat; +import com.alibaba.druid.util.Histogram; +import com.alibaba.druid.util.JdbcUtils; + +public class StatFilterExecuteFirstResultSetTest extends TestCase { + + private DruidDataSource dataSource; + + protected void setUp() throws Exception { + dataSource = new DruidDataSource(); + + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setFilters("stat"); + dataSource.setTestOnBorrow(false); + + MockDriver driver = new MockDriver() { + + public MockPreparedStatement createMockPreparedStatement(MockConnection conn, String sql) { + return new MyMockPreparedStatement(conn, sql); + } + }; + + dataSource.setDriver(driver); + + dataSource.init(); + } + + protected void tearDown() throws Exception { + JdbcUtils.close(dataSource); + } + + public void test_stat() throws Exception { + + Assert.assertTrue(dataSource.isInited()); + final String sql = "select 1"; + + Connection conn = dataSource.getConnection(); + + PreparedStatement stmt = conn.prepareStatement(sql); + boolean firstResult = stmt.execute(); + Assert.assertTrue(firstResult); + + ResultSet rs = stmt.getResultSet(); + rs.next(); + rs.close(); + + stmt.close(); + + conn.close(); + + JdbcSqlStat sqlStat = dataSource.getDataSourceStat().getSqlStat(sql); + + Histogram histogram = sqlStat.getHistogram(); + Assert.assertEquals(1, + histogram.getValue(0) + histogram.getValue(1) + histogram.getValue(2) + + histogram.getValue(3)); + + Histogram rsHoldHistogram = sqlStat.getExecuteAndResultHoldTimeHistogram(); + + Assert.assertEquals(1, rsHoldHistogram.getValue(0) + rsHoldHistogram.getValue(1) + rsHoldHistogram.getValue(2) + + rsHoldHistogram.getValue(3)); + } + + static class MyMockPreparedStatement extends MockPreparedStatement { + + public MyMockPreparedStatement(MockConnection conn, String sql){ + super(conn, sql); + } + + public boolean execute() throws SQLException { + return true; + } + + public ResultSet getResultSet() throws SQLException { + return getConnection().getDriver().executeQuery(this, getSql()); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/pool/ConfigErrorTest.java b/src/test/java/com/alibaba/druid/bvt/pool/ConfigErrorTest.java new file mode 100644 index 0000000000..f87d99ddfb --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/ConfigErrorTest.java @@ -0,0 +1,33 @@ +package com.alibaba.druid.bvt.pool; + +import java.sql.Connection; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.pool.DruidDataSource; + +public class ConfigErrorTest extends TestCase { + + private DruidDataSource dataSource; + + protected void setUp() throws Exception { + dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setTestOnBorrow(true); + } + + protected void tearDown() throws Exception { + dataSource.close(); + } + + public void test_connect() throws Exception { + DruidDataSource.LOG.resetStat(); + Assert.assertEquals(0, DruidDataSource.LOG.getErrorCount()); + + Connection conn = dataSource.getConnection(); + conn.close(); + + Assert.assertEquals(1, DruidDataSource.LOG.getErrorCount()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/pool/ConfigErrorTest2.java b/src/test/java/com/alibaba/druid/bvt/pool/ConfigErrorTest2.java new file mode 100644 index 0000000000..4b7d4470cb --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/ConfigErrorTest2.java @@ -0,0 +1,35 @@ +package com.alibaba.druid.bvt.pool; + +import java.sql.Connection; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.pool.DruidDataSource; + +public class ConfigErrorTest2 extends TestCase { + + private DruidDataSource dataSource; + + protected void setUp() throws Exception { + dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:wrap-jdbc:jdbc:mock:xxx"); + dataSource.setTestOnBorrow(false); + dataSource.setTestOnReturn(false); + dataSource.setTestWhileIdle(false); + } + + protected void tearDown() throws Exception { + dataSource.close(); + } + + public void test_connect() throws Exception { + DruidDataSource.LOG.resetStat(); + Assert.assertEquals(0, DruidDataSource.LOG.getErrorCount()); + + Connection conn = dataSource.getConnection(); + conn.close(); + + Assert.assertEquals(1, DruidDataSource.LOG.getErrorCount()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/pool/ConfigErrorTest3.java b/src/test/java/com/alibaba/druid/bvt/pool/ConfigErrorTest3.java new file mode 100644 index 0000000000..0a6a83a755 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/ConfigErrorTest3.java @@ -0,0 +1,32 @@ +package com.alibaba.druid.bvt.pool; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.pool.DruidDataSource; + +public class ConfigErrorTest3 extends TestCase { + + private DruidDataSource dataSource; + + protected void setUp() throws Exception { + dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mysql:xxx"); + dataSource.setTestOnBorrow(false); + dataSource.setTestOnReturn(false); + dataSource.setTestWhileIdle(false); + dataSource.setInitialSize(0); + dataSource.setPoolPreparedStatements(true); + } + + protected void tearDown() throws Exception { + dataSource.close(); + } + + public void test_connect() throws Exception { + DruidDataSource.LOG.resetStat(); + Assert.assertEquals(0, DruidDataSource.LOG.getErrorCount()); + dataSource.init(); + Assert.assertEquals(1, DruidDataSource.LOG.getErrorCount()); + } +}