mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
add webStat support
This commit is contained in:
@@ -184,7 +184,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
String property = properties.getProperty("druid.stat.logSlowSql");
|
||||
if ("true".equals(property)) {
|
||||
@@ -439,6 +439,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
|
||||
sqlStat.incrementExecuteSuccessCount();
|
||||
for (int updateCount : updateCountArray) {
|
||||
sqlStat.addUpdateCount(updateCount);
|
||||
StatFilterContext.getInstance().addUpdateCount(updateCount);
|
||||
}
|
||||
|
||||
sqlStat.decrementRunningCount();
|
||||
@@ -518,9 +519,10 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
|
||||
}
|
||||
buf.append(']');
|
||||
sqlStat.setLastSlowParameters(buf.toString());
|
||||
|
||||
|
||||
if (logSlowSql) {
|
||||
LOG.error("slow sql " + millis + " millis. \n" + statement.getLastExecuteSql() + "\n" + buf.toString());
|
||||
LOG.error("slow sql " + millis + " millis. \n" + statement.getLastExecuteSql() + "\n"
|
||||
+ buf.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -564,19 +566,19 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
|
||||
|
||||
long nanoSpan = System.nanoTime() - resultSet.getConstructNano();
|
||||
|
||||
int fetchCount = resultSet.getFetchRowCount();
|
||||
int fetchRowCount = resultSet.getFetchRowCount();
|
||||
|
||||
dataSourceStat.getResultSetStat().afterClose(nanoSpan);
|
||||
|
||||
dataSourceStat.getResultSetStat().addFetchRowCount(fetchCount);
|
||||
|
||||
dataSourceStat.getResultSetStat().addFetchRowCount(fetchRowCount);
|
||||
dataSourceStat.getResultSetStat().incrementCloseCounter();
|
||||
|
||||
StatFilterContext.getInstance().addFetchRowCount(fetchRowCount);
|
||||
|
||||
String sql = resultSet.getSql();
|
||||
if (sql != null) {
|
||||
JdbcSqlStat sqlStat = resultSet.getSqlStat();
|
||||
if (sqlStat != null && resultSet.getCloseCount() == 0) {
|
||||
sqlStat.addFetchRowCount(fetchCount);
|
||||
sqlStat.addFetchRowCount(fetchRowCount);
|
||||
long stmtExecuteNano = resultSet.getStatementProxy().getLastExecuteTimeNano();
|
||||
sqlStat.addResultSetHoldTimeNano(stmtExecuteNano, nanoSpan);
|
||||
}
|
||||
@@ -837,4 +839,6 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean {
|
||||
return features;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.alibaba.druid.filter.stat;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class StatFilterContext {
|
||||
|
||||
private List<StatFilterContextListener> listeners = new CopyOnWriteArrayList<StatFilterContextListener>();
|
||||
|
||||
private static final StatFilterContext instance = new StatFilterContext();
|
||||
|
||||
public final static StatFilterContext getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void addContextListener(StatFilterContextListener listener) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public boolean removeContextListener(StatFilterContextListener listener) {
|
||||
return listeners.remove(listener);
|
||||
}
|
||||
|
||||
public List<StatFilterContextListener> getListeners() {
|
||||
return listeners;
|
||||
}
|
||||
|
||||
protected 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) {
|
||||
for (int i = 0; i < listeners.size(); ++i) {
|
||||
StatFilterContextListener listener = listeners.get(i);
|
||||
listener.addFetchRowCount(fetchRowCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.alibaba.druid.filter.stat;
|
||||
|
||||
|
||||
public interface StatFilterContextListener {
|
||||
void addUpdateCount(int updateCount);
|
||||
|
||||
void addFetchRowCount(int fetchRowCount);
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.alibaba.druid.support.http;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
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.support.http.stat.WebAppStat;
|
||||
import com.alibaba.druid.support.http.stat.WebURIStat;
|
||||
|
||||
public class WebStatFilter implements Filter {
|
||||
|
||||
private WebAppStat webAppStat = null;
|
||||
private WebStatFilterContextListener statFilterContextListener = new WebStatFilterContextListener();
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
|
||||
ServletException {
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
|
||||
final String requestURI = getRequestURI(httpRequest);
|
||||
|
||||
if (isExclusion(requestURI)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
long startNano = System.nanoTime();
|
||||
webAppStat.beforeInvoke(requestURI);
|
||||
|
||||
try {
|
||||
chain.doFilter(request, response);
|
||||
} finally {
|
||||
long nanoSpan = System.nanoTime() - startNano;
|
||||
|
||||
webAppStat.afterInvoke(nanoSpan);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isExclusion(String uri) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getRequestURI(HttpServletRequest request) {
|
||||
return request.getRequestURI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig config) throws ServletException {
|
||||
config.getServletContext().getContextPath();
|
||||
|
||||
StatFilterContext.getInstance().addContextListener(statFilterContextListener);
|
||||
|
||||
webAppStat = new WebAppStat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
StatFilterContext.getInstance().removeContextListener(statFilterContextListener);
|
||||
}
|
||||
|
||||
class WebStatFilterContextListener implements StatFilterContextListener {
|
||||
|
||||
@Override
|
||||
public void addUpdateCount(int updateCount) {
|
||||
WebURIStat stat = WebURIStat.current();
|
||||
if (stat != null) {
|
||||
stat.addJdbcUpdateCount(updateCount);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFetchRowCount(int fetchRowCount) {
|
||||
WebURIStat stat = WebURIStat.current();
|
||||
if (stat != null) {
|
||||
stat.addJdbcFetchRowCount(fetchRowCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.alibaba.druid.support.http.stat;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import com.alibaba.druid.support.logging.Log;
|
||||
import com.alibaba.druid.support.logging.LogFactory;
|
||||
|
||||
public class WebAppStat {
|
||||
|
||||
private final static Log LOG = LogFactory.getLog(WebAppStat.class);
|
||||
|
||||
public final static int DEFAULT_MAX_STAT_URI_COUNT = 1000;
|
||||
|
||||
private volatile int maxStatUriCount = DEFAULT_MAX_STAT_URI_COUNT;
|
||||
|
||||
private final AtomicInteger runningCount = new AtomicInteger();
|
||||
private final AtomicInteger concurrentMax = new AtomicInteger();
|
||||
private final AtomicLong count = new AtomicLong(0);
|
||||
|
||||
private final static ThreadLocal<WebAppStat> currentLocal = new ThreadLocal<WebAppStat>();
|
||||
|
||||
private final ConcurrentMap<String, WebURIStat> uriStatMap = new ConcurrentHashMap<String, WebURIStat>();
|
||||
|
||||
private final AtomicLong uriStatMapFullCount = new AtomicLong();
|
||||
|
||||
public static WebAppStat current() {
|
||||
return currentLocal.get();
|
||||
}
|
||||
|
||||
public void beforeInvoke(String uri) {
|
||||
currentLocal.set(this);
|
||||
|
||||
int running = runningCount.incrementAndGet();
|
||||
|
||||
for (;;) {
|
||||
int max = concurrentMax.get();
|
||||
if (running > max) {
|
||||
if (concurrentMax.compareAndSet(max, running)) {
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
count.incrementAndGet();
|
||||
|
||||
WebURIStat uriStat = getURIStat(uri);
|
||||
|
||||
if (uriStat != null) {
|
||||
uriStat.beforeInvoke(uri);
|
||||
}
|
||||
}
|
||||
|
||||
public WebURIStat getURIStat(String uri) {
|
||||
if (uriStatMap.size() >= this.getMaxStatUriCount()) {
|
||||
long fullCount = uriStatMapFullCount.getAndIncrement();
|
||||
|
||||
if (fullCount == 0) {
|
||||
LOG.error("urlStatMap is full");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
WebURIStat uriStat = uriStatMap.get(uri);
|
||||
|
||||
if (uriStat == null) {
|
||||
uriStatMap.putIfAbsent(uri, new WebURIStat(uri));
|
||||
uriStat = uriStatMap.get(uri);
|
||||
}
|
||||
|
||||
return uriStat;
|
||||
}
|
||||
|
||||
public void afterInvoke(long nanoSpan) {
|
||||
runningCount.decrementAndGet();
|
||||
|
||||
currentLocal.set(null);
|
||||
|
||||
WebURIStat uriStat = WebURIStat.current();
|
||||
if (uriStat != null) {
|
||||
uriStat.afterInvoke(nanoSpan);
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxStatUriCount() {
|
||||
return maxStatUriCount;
|
||||
}
|
||||
|
||||
public void setMaxStatUriCount(int maxStatUriCount) {
|
||||
this.maxStatUriCount = maxStatUriCount;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.alibaba.druid.support.http.stat;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class WebURIStat {
|
||||
|
||||
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 jdbcFetchRowCount = new AtomicLong();
|
||||
private final AtomicLong jdbcFetchRowPeak = new AtomicLong();
|
||||
private final AtomicLong jdbcUpdateCount = new AtomicLong();
|
||||
private final AtomicLong jdbcExecuteCount = new AtomicLong();
|
||||
private final AtomicLong jdbcCommitCount = new AtomicLong();
|
||||
private final AtomicLong jdbcRollbackCount = new AtomicLong();
|
||||
|
||||
private final static ThreadLocal<WebURIStat> currentLocal = new ThreadLocal<WebURIStat>();
|
||||
|
||||
public WebURIStat(String uri){
|
||||
super();
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public static WebURIStat current() {
|
||||
return currentLocal.get();
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
public void beforeInvoke(String uri) {
|
||||
currentLocal.set(this);
|
||||
|
||||
int running = runningCount.incrementAndGet();
|
||||
|
||||
for (;;) {
|
||||
int max = concurrentMax.get();
|
||||
if (running > max) {
|
||||
if (concurrentMax.compareAndSet(max, running)) {
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
count.incrementAndGet();
|
||||
}
|
||||
|
||||
public void afterInvoke(long nanoSpan) {
|
||||
runningCount.decrementAndGet();
|
||||
|
||||
currentLocal.set(null);
|
||||
}
|
||||
|
||||
public void addJdbcFetchRowCount(long delta) {
|
||||
this.jdbcFetchRowCount.addAndGet(delta);
|
||||
}
|
||||
|
||||
public long getJdbcFetchRowCount() {
|
||||
return jdbcFetchRowCount.get();
|
||||
}
|
||||
|
||||
public long getJdbcFetchRowPeak() {
|
||||
return jdbcFetchRowPeak.get();
|
||||
}
|
||||
|
||||
public void addJdbcUpdateCount(int updateCount) {
|
||||
this.jdbcUpdateCount.addAndGet(updateCount);
|
||||
}
|
||||
|
||||
public long getJdbcUpdateCount() {
|
||||
return jdbcUpdateCount.get();
|
||||
}
|
||||
|
||||
public void incrementJdbcExecuteCount() {
|
||||
jdbcExecuteCount.incrementAndGet();
|
||||
}
|
||||
|
||||
public long getJdbcExecuteCount() {
|
||||
return jdbcExecuteCount.get();
|
||||
}
|
||||
|
||||
public void incrementJdbcCommitCount() {
|
||||
jdbcCommitCount.incrementAndGet();
|
||||
}
|
||||
|
||||
public long getJdbcCommitCount() {
|
||||
return jdbcCommitCount.get();
|
||||
}
|
||||
|
||||
public void incrementJdbcRollbackCount() {
|
||||
jdbcRollbackCount.incrementAndGet();
|
||||
}
|
||||
|
||||
public long getJdbcRollbackCount() {
|
||||
return jdbcRollbackCount.get();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user