add webStat support

This commit is contained in:
wenshao
2012-08-12 13:57:47 +08:00
parent f1cfe2e305
commit 1b27e9ab59
8 changed files with 433 additions and 93 deletions
@@ -376,6 +376,8 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
}
private final void internalBeforeStatementExecute(StatementProxy statement, String sql) {
final long startNano = System.nanoTime();
dataSourceStat.getStatementStat().beforeExecute();
@@ -383,7 +385,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
final ConnectionProxy connection = statement.getConnectionProxy();
final JdbcConnectionStat.Entry connectionCounter = getConnectionInfo(connection);
statementStat.setLastExecuteStartNano(System.nanoTime());
statementStat.setLastExecuteStartNano(startNano);
statementStat.setLastExecuteSql(sql);
connectionCounter.setLastSql(sql);
@@ -406,19 +408,23 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
sqlStat.setFile(statContext.getFile());
}
boolean inTransaction = false;
try {
inTransaction = !statement.getConnectionProxy().getAutoCommit();
} catch (SQLException e) {
LOG.error("getAutoCommit error", e);
}
if (sqlStat != null) {
sqlStat.setExecuteLastStartTime(System.currentTimeMillis());
sqlStat.incrementRunningCount();
try {
boolean inTransaction = !statement.getConnectionProxy().getAutoCommit();
if (inTransaction) {
sqlStat.incrementInTransactionCount();
}
} catch (SQLException e) {
LOG.error("getAutoCommit error", e);
if (inTransaction) {
sqlStat.incrementInTransactionCount();
}
}
StatFilterContext.getInstance().executeBefore(sql, inTransaction);
}
private final void internalAfterStatementExecute(StatementProxy statement, boolean firstResult,
@@ -426,13 +432,11 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
final JdbcStatementStat.Entry entry = getStatementInfo(statement);
long nowNano = System.nanoTime();
long nanoSpan = nowNano - entry.getLastExecuteStartNano();
final long nowNano = System.nanoTime();
final long nanoSpan = nowNano - entry.getLastExecuteStartNano();
dataSourceStat.getStatementStat().afterExecute(nanoSpan);
// // SQL
final JdbcSqlStat sqlStat = statement.getSqlStat();
if (sqlStat != null) {
@@ -456,68 +460,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
long millis = nanoSpan / (1000 * 1000);
if (millis >= slowSqlMillis) {
StringBuilder buf = new StringBuilder();
buf.append('[');
int index = 0;
for (JdbcParameter parameter : statement.getParameters().values()) {
if (index != 0) {
buf.append(',');
}
Object value = parameter.getValue();
if (value == null) {
buf.append("null");
} else if (value instanceof String) {
buf.append('"');
String text = (String) value;
if (text.length() > 100) {
for (int i = 0; i < 97; ++i) {
char ch = text.charAt(i);
if (ch == '\'') {
buf.append('\\');
buf.append(ch);
} else {
buf.append(ch);
}
}
buf.append("...");
} else {
for (int i = 0; i < text.length(); ++i) {
char ch = text.charAt(i);
if (ch == '\'') {
buf.append('\\');
buf.append(ch);
} else {
buf.append(ch);
}
}
}
buf.append('"');
} else if (value instanceof Number) {
buf.append(value.toString());
} else if (value instanceof java.util.Date) {
java.util.Date date = (java.util.Date) value;
buf.append(date.getClass().getSimpleName());
buf.append('(');
buf.append(date.getTime());
buf.append(')');
} else if (value instanceof Boolean) {
buf.append(value.toString());
} else if (value instanceof InputStream) {
buf.append("<InputStream>");
} else if (value instanceof Clob) {
buf.append("<Clob>");
} else if (value instanceof NClob) {
buf.append("<NClob>");
} else if (value instanceof Blob) {
buf.append("<Blob>");
} else {
buf.append('<');
buf.append(value.getClass().getName());
buf.append('>');
}
index++;
}
buf.append(']');
StringBuilder buf = buildSlowParameters(statement);
sqlStat.setLastSlowParameters(buf.toString());
if (logSlowSql) {
@@ -526,8 +469,11 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
}
}
}
String sql = statement.getLastExecuteSql();
StatFilterContext.getInstance().executeAfter(sql, nanoSpan, null);
}
@Override
protected void statement_executeErrorAfter(StatementProxy statement, String sql, Throwable error) {
@@ -550,8 +496,74 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
sqlStat.addExecuteTime(statement.getLastExecuteType(), statement.isFirstResultSet(), nanoSpan);
statement.setLastExecuteTimeNano(nanoSpan);
}
StatFilterContext.getInstance().executeAfter(sql, nanoSpan, error);
}
super.statement_executeErrorAfter(statement, sql, error);
private StringBuilder buildSlowParameters(StatementProxy statement) {
StringBuilder buf = new StringBuilder();
buf.append('[');
int index = 0;
for (JdbcParameter parameter : statement.getParameters().values()) {
if (index != 0) {
buf.append(',');
}
Object value = parameter.getValue();
if (value == null) {
buf.append("null");
} else if (value instanceof String) {
buf.append('"');
String text = (String) value;
if (text.length() > 100) {
for (int i = 0; i < 97; ++i) {
char ch = text.charAt(i);
if (ch == '\'') {
buf.append('\\');
buf.append(ch);
} else {
buf.append(ch);
}
}
buf.append("...");
} else {
for (int i = 0; i < text.length(); ++i) {
char ch = text.charAt(i);
if (ch == '\'') {
buf.append('\\');
buf.append(ch);
} else {
buf.append(ch);
}
}
}
buf.append('"');
} else if (value instanceof Number) {
buf.append(value.toString());
} else if (value instanceof java.util.Date) {
java.util.Date date = (java.util.Date) value;
buf.append(date.getClass().getSimpleName());
buf.append('(');
buf.append(date.getTime());
buf.append(')');
} else if (value instanceof Boolean) {
buf.append(value.toString());
} else if (value instanceof InputStream) {
buf.append("<InputStream>");
} else if (value instanceof Clob) {
buf.append("<Clob>");
} else if (value instanceof NClob) {
buf.append("<NClob>");
} else if (value instanceof Blob) {
buf.append("<Blob>");
} else {
buf.append('<');
buf.append(value.getClass().getName());
buf.append('>');
}
index++;
}
buf.append(']');
return buf;
}
@Override
@@ -571,7 +583,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
dataSourceStat.getResultSetStat().afterClose(nanoSpan);
dataSourceStat.getResultSetStat().addFetchRowCount(fetchRowCount);
dataSourceStat.getResultSetStat().incrementCloseCounter();
StatFilterContext.getInstance().addFetchRowCount(fetchRowCount);
String sql = resultSet.getSql();
@@ -840,5 +852,4 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
}
}
}
@@ -5,9 +5,9 @@ import java.util.concurrent.CopyOnWriteArrayList;
public class StatFilterContext {
private List<StatFilterContextListener> listeners = new CopyOnWriteArrayList<StatFilterContextListener>();
private List<StatFilterContextListener> listeners = new CopyOnWriteArrayList<StatFilterContextListener>();
private static final StatFilterContext instance = new StatFilterContext();
private static final StatFilterContext instance = new StatFilterContext();
public final static StatFilterContext getInstance() {
return instance;
@@ -16,7 +16,7 @@ public class StatFilterContext {
public void addContextListener(StatFilterContextListener listener) {
this.listeners.add(listener);
}
public boolean removeContextListener(StatFilterContextListener listener) {
return listeners.remove(listener);
}
@@ -25,17 +25,33 @@ public class StatFilterContext {
return listeners;
}
protected void addUpdateCount(int updateCount) {
public void addUpdateCount(int updateCount) {
for (int i = 0; i < listeners.size(); ++i) {
StatFilterContextListener listener = listeners.get(i);
listener.addUpdateCount(updateCount);
}
}
protected void addFetchRowCount(int fetchRowCount) {
public void addFetchRowCount(int fetchRowCount) {
for (int i = 0; i < listeners.size(); ++i) {
StatFilterContextListener listener = listeners.get(i);
listener.addFetchRowCount(fetchRowCount);
}
}
public void executeBefore(String sql, boolean inTransaction) {
}
public void executeAfter(String sql, long nanoSpan, Throwable error) {
}
public void commit() {
}
public void rollback() {
}
}
@@ -1,8 +1,16 @@
package com.alibaba.druid.filter.stat;
public interface StatFilterContextListener {
void addUpdateCount(int updateCount);
void addFetchRowCount(int fetchRowCount);
void executeBefore(String sql, boolean inTransaction);
void executeAfter(String sql, long nanoSpan, Throwable error);
void commit();
void rollback();
}
@@ -0,0 +1,35 @@
package com.alibaba.druid.filter.stat;
public class StatFilterContextListenerAdapter implements StatFilterContextListener {
@Override
public void addUpdateCount(int updateCount) {
}
@Override
public void addFetchRowCount(int fetchRowCount) {
}
@Override
public void executeBefore(String sql, boolean inTransaction) {
}
@Override
public void executeAfter(String sql, long nanoSpan, Throwable error) {
}
@Override
public void commit() {
}
@Override
public void rollback() {
}
}
@@ -11,8 +11,9 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import com.alibaba.druid.filter.stat.StatFilterContext;
import com.alibaba.druid.filter.stat.StatFilterContextListener;
import com.alibaba.druid.filter.stat.StatFilterContextListenerAdapter;
import com.alibaba.druid.support.http.stat.WebAppStat;
import com.alibaba.druid.support.http.stat.WebAppStatManager;
import com.alibaba.druid.support.http.stat.WebURIStat;
public class WebStatFilter implements Filter {
@@ -55,18 +56,24 @@ public class WebStatFilter implements Filter {
@Override
public void init(FilterConfig config) throws ServletException {
config.getServletContext().getContextPath();
StatFilterContext.getInstance().addContextListener(statFilterContextListener);
webAppStat = new WebAppStat();
WebAppStatManager.getInstance().addWebAppStatSet(webAppStat);
}
@Override
public void destroy() {
StatFilterContext.getInstance().removeContextListener(statFilterContextListener);
if (webAppStat != null) {
WebAppStatManager.getInstance().remove(webAppStat);
}
}
class WebStatFilterContextListener implements StatFilterContextListener {
class WebStatFilterContextListener extends StatFilterContextListenerAdapter {
@Override
public void addUpdateCount(int updateCount) {
@@ -83,5 +90,34 @@ public class WebStatFilter implements Filter {
stat.addJdbcFetchRowCount(fetchRowCount);
}
}
@Override
public void executeBefore(String sql, boolean inTransaction) {
WebURIStat stat = WebURIStat.current();
if (stat != null) {
stat.incrementJdbcExecuteCount();
}
}
@Override
public void executeAfter(String sql, long nanoSpan, Throwable error) {
}
@Override
public void commit() {
WebURIStat stat = WebURIStat.current();
if (stat != null) {
stat.incrementJdbcCommitCount();
}
}
@Override
public void rollback() {
WebURIStat stat = WebURIStat.current();
if (stat != null) {
stat.incrementJdbcRollbackCount();
}
}
}
}
@@ -1,5 +1,9 @@
package com.alibaba.druid.support.http.stat;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
@@ -18,7 +22,7 @@ public class WebAppStat {
private final AtomicInteger runningCount = new AtomicInteger();
private final AtomicInteger concurrentMax = new AtomicInteger();
private final AtomicLong count = new AtomicLong(0);
private final AtomicLong requestCount = new AtomicLong(0);
private final static ThreadLocal<WebAppStat> currentLocal = new ThreadLocal<WebAppStat>();
@@ -26,10 +30,24 @@ public class WebAppStat {
private final AtomicLong uriStatMapFullCount = new AtomicLong();
private String contextPath;
public static WebAppStat current() {
return currentLocal.get();
}
public WebAppStat(){
}
public WebAppStat(String contextPath){
this.contextPath = contextPath;
}
public String getContextPath() {
return contextPath;
}
public void beforeInvoke(String uri) {
currentLocal.set(this);
@@ -48,7 +66,7 @@ public class WebAppStat {
}
}
count.incrementAndGet();
requestCount.incrementAndGet();
WebURIStat uriStat = getURIStat(uri);
@@ -97,4 +115,43 @@ public class WebAppStat {
this.maxStatUriCount = maxStatUriCount;
}
public int getRunningCount() {
return this.runningCount.get();
}
public long getConcurrentMax() {
return concurrentMax.get();
}
public long getRequestCount() {
return requestCount.get();
}
public Map<String, Object> getStatData() {
Map<String, Object> data = new LinkedHashMap<String, Object>();
data.put("ContextPath", this.getContextPath());
data.put("RunningCount", this.getRunningCount());
data.put("ConcurrentMax", this.getConcurrentMax());
data.put("RequestCount", this.getRequestCount());
List<Map<String, Object>> uriStatDataList = new ArrayList<Map<String, Object>>(this.uriStatMap.size());
for (WebURIStat uriStat : this.uriStatMap.values()) {
Map<String, Object> uriStatData = uriStat.getStatData();
long runningCount = (Long) uriStatData.get("RunningCount");
long requestCount = (Long) uriStatData.get("RequestCount");
if (runningCount == 0 && requestCount == 0) {
continue;
}
uriStatDataList.add(uriStatData);
}
data.put("URIList", uriStatDataList);
return data;
}
}
@@ -0,0 +1,54 @@
package com.alibaba.druid.support.http.stat;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public class WebAppStatManager {
public final static String SYS_PROP_INSTANCES = "druid.web.webAppStat";
private final static WebAppStatManager instance = new WebAppStatManager();
private Set<Object> webAppStatSet = null;
public static WebAppStatManager getInstance() {
return instance;
}
public Set<Object> getWebAppStatSet() {
if (webAppStatSet == null) {
webAppStatSet = getWebAppStatSet0();
}
return webAppStatSet;
}
public void addWebAppStatSet(Object webAppStat) {
getWebAppStatSet().add(webAppStat);
}
public boolean remove(Object webAppStat) {
return getWebAppStatSet().remove(webAppStat);
}
@SuppressWarnings("unchecked")
static Set<Object> getWebAppStatSet0() {
Properties properties = System.getProperties();
Set<Object> webAppStats = (Set<Object>) properties.get(SYS_PROP_INSTANCES);
if (webAppStats == null) {
synchronized (properties) {
webAppStats = (Set<Object>) properties.get(SYS_PROP_INSTANCES);
if (webAppStats == null) {
webAppStats = new CopyOnWriteArraySet<Object>();
properties.put(SYS_PROP_INSTANCES, webAppStats);
}
}
}
return webAppStats;
}
}
@@ -1,24 +1,39 @@
package com.alibaba.druid.support.http.stat;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
public class WebURIStat {
static class RequestStat {
long jdbcExecuteCount;
long jdbcUpdateCount;
long jdbcFetchRowCount;
}
private final String uri;
private final AtomicInteger runningCount = new AtomicInteger();
private final AtomicInteger concurrentMax = new AtomicInteger();
private final AtomicLong count = new AtomicLong(0);
private final AtomicLong requestCount = new AtomicLong(0);
private final AtomicLong jdbcFetchRowCount = new AtomicLong();
private final AtomicLong jdbcFetchRowPeak = new AtomicLong();
private final AtomicLong jdbcFetchRowPeak = new AtomicLong(); // 单次请求读取行数的峰值
private final AtomicLong jdbcUpdateCount = new AtomicLong();
private final AtomicLong jdbcUpdatePeak = new AtomicLong(); // 单次请求更新行数的峰值
private final AtomicLong jdbcExecuteCount = new AtomicLong();
private final AtomicLong jdbcExecutePeak = new AtomicLong(); // 单次请求执行SQL次数的峰值
private final AtomicLong jdbcCommitCount = new AtomicLong();
private final AtomicLong jdbcRollbackCount = new AtomicLong();
private final static ThreadLocal<WebURIStat> currentLocal = new ThreadLocal<WebURIStat>();
private static ThreadLocal<RequestStat> localRequestStat = new ThreadLocal<RequestStat>();
public WebURIStat(String uri){
super();
@@ -35,6 +50,7 @@ public class WebURIStat {
public void beforeInvoke(String uri) {
currentLocal.set(this);
localRequestStat.set(new RequestStat());
int running = runningCount.incrementAndGet();
@@ -51,17 +67,83 @@ public class WebURIStat {
}
}
count.incrementAndGet();
requestCount.incrementAndGet();
}
public void afterInvoke(long nanoSpan) {
runningCount.decrementAndGet();
{
RequestStat localStat = localRequestStat.get();
if (localStat != null) {
{
long fetchRowCount = localStat.jdbcFetchRowCount;
for (;;) {
long peak = jdbcFetchRowPeak.get();
if (fetchRowCount <= peak) {
break;
}
if (jdbcFetchRowPeak.compareAndSet(peak, fetchRowCount)) {
break;
}
}
}
{
long executeCount = localStat.jdbcExecuteCount;
for (;;) {
long peak = jdbcExecutePeak.get();
if (executeCount <= peak) {
break;
}
if (jdbcExecutePeak.compareAndSet(peak, executeCount)) {
break;
}
}
}
{
long updateCount = localStat.jdbcUpdateCount;
for (;;) {
long peak = jdbcUpdatePeak.get();
if (updateCount <= peak) {
break;
}
if (jdbcUpdatePeak.compareAndSet(peak, updateCount)) {
break;
}
}
}
}
}
currentLocal.set(null);
localRequestStat.set(null);
}
public int getRunningCount() {
return this.runningCount.get();
}
public long getConcurrentMax() {
return concurrentMax.get();
}
public long getRequestCount() {
return requestCount.get();
}
public void addJdbcFetchRowCount(long delta) {
this.jdbcFetchRowCount.addAndGet(delta);
RequestStat localStat = localRequestStat.get();
if (localStat != null) {
localStat.jdbcFetchRowCount += delta;
}
}
public long getJdbcFetchRowCount() {
@@ -74,20 +156,38 @@ public class WebURIStat {
public void addJdbcUpdateCount(int updateCount) {
this.jdbcUpdateCount.addAndGet(updateCount);
RequestStat localStat = localRequestStat.get();
if (localStat != null) {
localStat.jdbcExecuteCount += updateCount;
}
}
public long getJdbcUpdateCount() {
return jdbcUpdateCount.get();
}
public long getJdbcUpdatePeak() {
return jdbcUpdatePeak.get();
}
public void incrementJdbcExecuteCount() {
jdbcExecuteCount.incrementAndGet();
RequestStat localStat = localRequestStat.get();
if (localStat != null) {
localStat.jdbcExecuteCount++;
}
}
public long getJdbcExecuteCount() {
return jdbcExecuteCount.get();
}
public long getJdbcExecutePeak() {
return jdbcExecutePeak.get();
}
public void incrementJdbcCommitCount() {
jdbcCommitCount.incrementAndGet();
}
@@ -103,4 +203,27 @@ public class WebURIStat {
public long getJdbcRollbackCount() {
return jdbcRollbackCount.get();
}
public Map<String, Object> getStatData() {
Map<String, Object> data = new LinkedHashMap<String, Object>();
data.put("URI", this.getUri());
data.put("RunningCount", this.getRunningCount());
data.put("ConcurrentMax", this.getConcurrentMax());
data.put("RequestCount", this.getRequestCount());
data.put("JdbcCommitCount", this.getJdbcCommitCount());
data.put("JdbcRollbackCount", this.getJdbcRollbackCount());
data.put("JdbcExecuteCount", this.getJdbcExecuteCount());
data.put("JdbcExecutePeak", this.getJdbcExecutePeak());
data.put("JdbcFetchRowCount", this.getJdbcFetchRowCount());
data.put("JdbcFetchRowPeak", this.getJdbcFetchRowPeak());
data.put("JdbcUpdateCount", this.getJdbcUpdateCount());
data.put("JdbcUpdatePeak", this.getJdbcUpdatePeak());
return data;
}
}