From e5365eae94e50a7b51cd1d1ab2ed0cd029738eb4 Mon Sep 17 00:00:00 2001
From: zhouhaibin <283595276@qq.com>
Date: Fri, 10 Aug 2012 09:58:18 +0800
Subject: [PATCH 1/4] update the slowSqlView function
---
.../druid/support/http/StatViewServlet.java | 20 ++++++++++++++++-
.../support/http/resources/js/sql.js | 10 +++++++--
.../resources/support/http/resources/sql.html | 22 ++++++++++---------
3 files changed, 39 insertions(+), 13 deletions(-)
diff --git a/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java b/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java
index 009a0e373d..693dcf4e42 100644
--- a/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java
+++ b/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java
@@ -1,6 +1,8 @@
package com.alibaba.druid.support.http;
import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
import java.util.List;
import javax.servlet.ServletException;
@@ -35,6 +37,7 @@ public class StatViewServlet extends HttpServlet {
private static JSONDruidStatService jsonDruidStatService = JSONDruidStatService.getInstance();
public String templatePage;
+ private static DateFormat format = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss:SSS");
public void init() throws ServletException {
try {
@@ -131,7 +134,22 @@ public class StatViewServlet extends HttpServlet {
content.append("
");
content.append("
API:com.alibaba.druid.sql.SQLUtils.format(sql,DBType);
");
content.append("
");
-
+
+ if (sqlStat.getLastSlowParameters() != null && sqlStat.getLastSlowParameters().trim().length() > 0) {
+ content.append("LastSlow SQL View:
");
+ content.append("");
+ content.append("");
+ content.append("| MaxTimespanOccurTime | ");
+ content.append("" + format.format(sqlStat.getExecuteNanoSpanMaxOccurTime()) + " | ");
+ content.append("
");
+ content.append("");
+ content.append("| LastSlowParameters | ");
+ content.append("" + sqlStat.getLastSlowParameters() + " | ");
+ content.append("
");
+ content.append("
");
+ content.append("
");
+ }
+
List statementList = SQLUtils.parseStatements(sqlStat.getSql(), sqlStat.getDbType());
if (!statementList.isEmpty()) {
content.append("Parse View:
");
diff --git a/src/main/resources/support/http/resources/js/sql.js b/src/main/resources/support/http/resources/js/sql.js
index 02172ba557..ef769229b8 100644
--- a/src/main/resources/support/http/resources/js/sql.js
+++ b/src/main/resources/support/http/resources/js/sql.js
@@ -94,6 +94,7 @@ function ajaxResponseForDataSourceSqlStatInfo() {
for ( var i = 0; i < sqlStatList.length; i++) {
var sqlStat = sqlStatList[i];
var newRow = sqlStatTable.insertRow(-1);
+ newRow.insertCell(-1).innerHTML = i+1;
newRow.insertCell(-1).innerHTML = '' + subSqlString(sqlStat.SQL, 25) + '';
// if (sqlStat.File)
// newRow.insertCell(-1).innerHTML = sqlStat.File;
@@ -105,7 +106,12 @@ function ajaxResponseForDataSourceSqlStatInfo() {
// newRow.insertCell(-1).innerHTML = '';
newRow.insertCell(-1).innerHTML = sqlStat.ExecuteCount;
newRow.insertCell(-1).innerHTML = sqlStat.TotalTime;
- newRow.insertCell(-1).innerHTML = sqlStat.MaxTimespan;
+ //显示执行的时间比配置的均值时间慢的SQL链接
+ var lastSlowHtml = sqlStat.MaxTimespan;
+ if(sqlStat.LastSlowParameters!=null&&sqlStat.LastSlowParameters.length>0){
+ lastSlowHtml =''+sqlStat.MaxTimespan+'';
+ }
+ newRow.insertCell(-1).innerHTML = lastSlowHtml;
newRow.insertCell(-1).innerHTML = sqlStat.InTransactionCount;
newRow.insertCell(-1).innerHTML = sqlStat.ErrorCount;
newRow.insertCell(-1).innerHTML = sqlStat.EffectedRowCount;
@@ -120,8 +126,8 @@ function ajaxResponseForDataSourceSqlStatInfo() {
// hiHtml += 'ExecAndRsHold';
newRow.insertCell(-1).innerHTML = '[' + sqlStat.Histogram + ']';
+ newRow.insertCell(-1).innerHTML = '[' + sqlStat.ExecuteAndResultHoldTimeHistogram + ']';
newRow.insertCell(-1).innerHTML = '[' + sqlStat.FetchRowCountHistogram + ']';
newRow.insertCell(-1).innerHTML = '[' + sqlStat.EffectedRowCountHistogram + ']';
- newRow.insertCell(-1).innerHTML = '[' + sqlStat.ExecuteAndResultHoldTimeHistogram + ']';
}
}
\ No newline at end of file
diff --git a/src/main/resources/support/http/resources/sql.html b/src/main/resources/support/http/resources/sql.html
index a2515003be..480de266ce 100644
--- a/src/main/resources/support/http/resources/sql.html
+++ b/src/main/resources/support/http/resources/sql.html
@@ -24,6 +24,7 @@
From 339e5f944f419f9198ddd44f96c20948aa3c2e4b Mon Sep 17 00:00:00 2001
From: zhouhaibin <283595276@qq.com>
Date: Fri, 10 Aug 2012 12:45:48 +0800
Subject: [PATCH 2/4] Merge remote-tracking branch 'zhb/master'
Conflicts:
src/main/java/com/alibaba/druid/support/http/StatViewServlet.java
---
.../alibaba/druid/filter/stat/StatFilter.java | 7 +-
.../druid/pool/DataSourceClosedException.java | 21 ++
.../alibaba/druid/pool/DruidDataSource.java | 40 ++-
.../DruidDataSourceStatDefaultStrategy.java | 204 +++++++++++++
.../DruidDataSourceStatJNDIStatStrategy.java | 53 ++++
.../stat/DruidDataSourceStatStrategy.java | 22 ++
.../DruidDataSourceStatStrategyContext.java | 44 +++
.../druid/stat/DruidStatManagerFacade.java | 271 +++---------------
.../com/alibaba/druid/stat/JdbcSqlStat.java | 8 +-
.../druid/support/JSONDruidStatService.java | 16 +-
.../druid/support/http/StatViewServlet.java | 53 ++--
.../alibaba/druid/util/ReflectionUtils.java | 25 +-
.../com/alibaba/druid/util/StringUtils.java | 6 +
.../alibaba/druid/bvt/pool/ClosedTest.java | 32 +++
.../druid/bvt/pool/ConfigErrorTest.java | 13 +-
.../druid/bvt/pool/ConfigErrorTest2.java | 13 +-
.../druid/bvt/pool/ConfigErrorTest3.java | 14 +-
.../druid/bvt/pool/SlowSqlMillisTest.java | 32 +++
.../druid/bvt/pool/SlowSqlMillisTest2.java | 38 +++
test.html | 0
20 files changed, 611 insertions(+), 301 deletions(-)
create mode 100644 src/main/java/com/alibaba/druid/pool/DataSourceClosedException.java
create mode 100644 src/main/java/com/alibaba/druid/stat/DruidDataSourceStatDefaultStrategy.java
create mode 100644 src/main/java/com/alibaba/druid/stat/DruidDataSourceStatJNDIStatStrategy.java
create mode 100644 src/main/java/com/alibaba/druid/stat/DruidDataSourceStatStrategy.java
create mode 100644 src/main/java/com/alibaba/druid/stat/DruidDataSourceStatStrategyContext.java
create mode 100644 src/test/java/com/alibaba/druid/bvt/pool/ClosedTest.java
create mode 100644 src/test/java/com/alibaba/druid/bvt/pool/SlowSqlMillisTest.java
create mode 100644 src/test/java/com/alibaba/druid/bvt/pool/SlowSqlMillisTest2.java
create mode 100644 test.html
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 2ffd9e4e89..615097cdff 100644
--- a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java
+++ b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java
@@ -96,6 +96,10 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
this.dbType = dbType;
}
+ public long getSlowSqlMillis() {
+ return slowSqlMillis;
+ }
+
public boolean isConnectionStackTraceEnable() {
return connectionStackTraceEnable;
}
@@ -406,7 +410,8 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
}
}
- private final void internalAfterStatementExecute(StatementProxy statement, boolean firstResult, int... updateCountArray) {
+ private final void internalAfterStatementExecute(StatementProxy statement, boolean firstResult,
+ int... updateCountArray) {
final JdbcStatementStat.Entry entry = getStatementInfo(statement);
diff --git a/src/main/java/com/alibaba/druid/pool/DataSourceClosedException.java b/src/main/java/com/alibaba/druid/pool/DataSourceClosedException.java
new file mode 100644
index 0000000000..c003909874
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/pool/DataSourceClosedException.java
@@ -0,0 +1,21 @@
+package com.alibaba.druid.pool;
+
+import java.sql.SQLException;
+
+public class DataSourceClosedException extends SQLException {
+
+ private static final long serialVersionUID = 1L;
+
+ public DataSourceClosedException(){
+ super();
+ }
+
+ public DataSourceClosedException(String reason){
+ super(reason);
+ }
+
+ public DataSourceClosedException(Throwable cause){
+ super(cause);
+ }
+
+}
diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java
index f29afaa9af..75735e20a5 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 {
- public final static Log LOG = LogFactory.getLog(DruidDataSource.class);
+ private final static Log LOG = LogFactory.getLog(DruidDataSource.class);
private static final long serialVersionUID = 1L;
@@ -117,6 +117,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
private String initStackTrace;
private boolean closed = false;
+ private long closeTimeMillis = -1L;
private JdbcDataSourceStat dataSourceStat;
@@ -274,23 +275,23 @@ 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");
}
}
@@ -301,9 +302,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();
@@ -366,7 +367,7 @@ 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'");
@@ -554,6 +555,11 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
}
try {
+ if (closed) {
+ connectErrorCount.incrementAndGet();
+ throw new DataSourceClosedException("dataSource already closed at " + new Date(closeTimeMillis));
+ }
+
if (!enable) {
connectErrorCount.incrementAndGet();
throw new DataSourceDisableException();
@@ -775,6 +781,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
notEmptySignalCount++;
this.closed = true;
+ this.closeTimeMillis = System.currentTimeMillis();
for (Filter filter : filters) {
filter.destory();
@@ -782,6 +789,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
} finally {
lock.unlock();
}
+
+ LOG.warn("dataSource " + this.getID() + " closed");
}
void incrementCreateCount() {
@@ -879,7 +888,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
if (createError != null) {
throw new GetConnectionTimeoutException(createError);
} else {
- throw new GetConnectionTimeoutException("loopWaitCount " + i + ", wait millis " + (nanos - estimate)/(1000 * 1000));
+ throw new GetConnectionTimeoutException("loopWaitCount " + i + ", wait millis "
+ + (nanos - estimate) / (1000 * 1000));
}
}
}
@@ -1105,11 +1115,11 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
for (; iter.hasNext();) {
Map.Entry entry = iter.next();
DruidPooledConnection pooledConnection = entry.getKey();
-
+
if (pooledConnection.isRunning()) {
continue;
}
-
+
ActiveConnectionTraceInfo activeInfo = entry.getValue();
long timeMillis = currentMillis - activeInfo.getConnectTime();
@@ -1447,15 +1457,15 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
PreparedStatementPool stmtPool = connHolder.getStatementPool();
for (PreparedStatementHolder stmtHolder : stmtPool.getMap().values()) {
Map stmtInfo = new LinkedHashMap();
-
+
stmtInfo.put("sql", stmtHolder.getKey().getSql());
stmtInfo.put("defaultRowPretch", stmtHolder.getDefaultRowPretch());
stmtInfo.put("rowPrefetch", stmtHolder.getRowPrefetch());
stmtInfo.put("hitCount", stmtHolder.getHitCount());
-
+
stmtCache.add(stmtInfo);
}
-
+
map.put("pscache", stmtCache);
}
diff --git a/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatDefaultStrategy.java b/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatDefaultStrategy.java
new file mode 100644
index 0000000000..4e692646d8
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatDefaultStrategy.java
@@ -0,0 +1,204 @@
+package com.alibaba.druid.stat;
+
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.JMException;
+
+import com.alibaba.druid.VERSION;
+import com.alibaba.druid.pool.DruidDataSource;
+
+public class DruidDataSourceStatDefaultStrategy implements DruidDataSourceStatStrategy {
+
+ private Set getDruidDataSourceInstances() {
+ return DruidDataSourceStatManager.getDruidDataSourceInstances();
+ }
+
+ public void resetDataSourceStat() {
+ DruidDataSourceStatManager.getInstance().reset();
+ }
+
+ public void resetSqlStat() {
+ JdbcStatManager.getInstance().reset();
+ }
+
+ public void resetAll() {
+ resetSqlStat();
+ resetDataSourceStat();
+ }
+
+ private JdbcSqlStat getSqlStatById(Integer id) {
+
+ for (DruidDataSource ds : getDruidDataSourceInstances()) {
+ JdbcSqlStat sqlStat = ds.getDataSourceStat().getSqlStat(id);
+ if (sqlStat != null)
+ return sqlStat;
+ }
+ return null;
+ }
+
+ public Map getDataSourceStatData(Integer id) {
+ if (id == null) {
+ return null;
+ }
+ DruidDataSource datasource = getDruidDataSourceById(id);
+ return datasource == null ? null : dataSourceToMapData(datasource);
+ }
+
+ private DruidDataSource getDruidDataSourceById(Integer identity) {
+
+ if (identity == null) {
+ return null;
+ }
+
+ for (DruidDataSource datasource : getDruidDataSourceInstances()) {
+ if (System.identityHashCode(datasource) == identity) {
+ return datasource;
+ }
+ }
+ return null;
+ }
+
+ public List