You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by fh...@apache.org on 2008/12/11 23:07:43 UTC
svn commit: r725836 - in
/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor:
AbstractCreateStatementInterceptor.java SlowQueryReport.java
StatementFinalizer.java
Author: fhanik
Date: Thu Dec 11 14:07:43 2008
New Revision: 725836
URL: http://svn.apache.org/viewvc?rev=725836&view=rev
Log:
Refactor slow query report so that it is extensible and one can override the methods
Modified:
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java
Modified: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java?rev=725836&r1=725835&r2=725836&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java (original)
+++ tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java Thu Dec 11 14:07:43 2008
@@ -47,8 +47,10 @@
boolean process = false;
process = process(statements, method, process);
if (process) {
+ long start = System.currentTimeMillis();
Object statement = super.invoke(proxy,method,args);
- return createStatement(proxy,method,args,statement);
+ long delta = System.currentTimeMillis() - start;
+ return createStatement(proxy,method,args,statement, delta);
} else {
return super.invoke(proxy,method,args);
}
@@ -64,7 +66,7 @@
* @param statement
* @return
*/
- public abstract Object createStatement(Object proxy, Method method, Object[] args, Object statement);
+ public abstract Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time);
public abstract void closeInvoked();
Modified: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java?rev=725836&r1=725835&r2=725836&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java (original)
+++ tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java Thu Dec 11 14:07:43 2008
@@ -128,7 +128,7 @@
* Creates a statement interceptor to monitor query response times
*/
@Override
- public Object createStatement(Object proxy, Method method, Object[] args, Object statement) {
+ public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) {
try {
Object result = null;
String name = method.getName();
@@ -141,10 +141,18 @@
//prepareStatement
sql = (String)args[0];
constructor = getConstructor(1,PreparedStatement.class);
+ if (sql!=null) {
+ QueryStats qs = getQueryStats(sql);
+ qs.prepare(time, System.currentTimeMillis());
+ }
}else if (compare(statements[2],name)) {
//prepareCall
sql = (String)args[0];
constructor = getConstructor(2,CallableStatement.class);
+ if (sql!=null) {
+ QueryStats qs = getQueryStats(sql);
+ qs.prepare(time, System.currentTimeMillis());
+ }
}else {
//do nothing, might be a future unsupported method
//so we better bail out and let the system continue
@@ -187,6 +195,66 @@
perPoolStats.remove(pool.getName());
super.poolClosed(pool);
}
+
+ protected void reportFailedQuery(String query, Object[] args, final String name, long start, Throwable t) {
+ //extract the query string
+ String sql = (query==null && args!=null && args.length>0)?(String)args[0]:query;
+ //if we do batch execution, then we name the query 'batch'
+ if (sql==null && compare(executes[3],name)) {
+ sql = "batch";
+ }
+ //if we have a query, record the stats
+ if (sql!=null) {
+ QueryStats qs = getQueryStats(sql);
+ if (qs!=null) qs.failure(System.currentTimeMillis()-start,start);
+ }
+ }
+
+ protected void reportSlowQuery(String query, Object[] args, final String name, long start, long delta) {
+ //extract the query string
+ String sql = (query==null && args!=null && args.length>0)?(String)args[0]:query;
+ //if we do batch execution, then we name the query 'batch'
+ if (sql==null && compare(executes[3],name)) {
+ sql = "batch";
+ }
+ //if we have a query, record the stats
+ if (sql!=null) {
+ QueryStats qs = getQueryStats(sql);
+ if (qs!=null) qs.add(delta,start);
+ }
+ }
+
+ protected QueryStats getQueryStats(String sql) {
+ ConcurrentHashMap<String,QueryStats> queries = SlowQueryReport.this.queries;
+ if (queries==null) return null;
+ QueryStats qs = queries.get(sql);
+ if (qs == null) {
+ qs = new QueryStats(sql);
+ if (queries.putIfAbsent(sql,qs)!=null) {
+ qs = queries.get(sql);
+ } else {
+ //we added a new element, see if we need to remove the oldest
+ if (queries.size() > maxQueries) {
+ removeOldest(queries);
+ }
+ }
+ }
+ return qs;
+ }
+
+ /**
+ * TODO - implement a better algorithm
+ * @param queries
+ */
+ protected void removeOldest(ConcurrentHashMap<String,QueryStats> queries) {
+ Iterator<String> it = queries.keySet().iterator();
+ while (queries.size()>maxQueries && it.hasNext()) {
+ String sql = it.next();
+ it.remove();
+ if (log.isDebugEnabled()) log.debug("Removing slow query, capacity reached:"+sql);
+ }
+ }
+
/**
*
@@ -201,6 +269,9 @@
private long minInvocationTime = Long.MAX_VALUE;
private long minInvocationDate;
private long totalInvocationTime;
+ private long failures;
+ private int prepareCount;
+ private long prepareTime;
private volatile long lastInvocation = 0;
public String toString() {
@@ -220,6 +291,12 @@
buf.append(totalInvocationTime);
buf.append(", averageInvocationTime:");
buf.append((float)totalInvocationTime / (float)nrOfInvocations);
+ buf.append(", failures:");
+ buf.append(failures);
+ buf.append(", prepareCount:");
+ buf.append(prepareCount);
+ buf.append(", prepareTime:");
+ buf.append(prepareTime);
buf.append("]");
return buf.toString();
}
@@ -228,6 +305,12 @@
this.query = query;
}
+ public void prepare(long invocationTime, long now) {
+ prepareCount++;
+ prepareTime+=invocationTime;
+
+ }
+
public void add(long invocationTime, long now) {
//not thread safe, but don't sacrifice performance for this kind of stuff
maxInvocationTime = Math.max(invocationTime, maxInvocationTime);
@@ -243,6 +326,12 @@
lastInvocation = now;
}
+ public void failure(long invocationTime, long now) {
+ add(invocationTime,now);
+ failures++;
+
+ }
+
public String getQuery() {
return query;
}
@@ -318,15 +407,21 @@
process = process(executes, method, process);
//if we are executing, get the current time
long start = (process)?System.currentTimeMillis():0;
- //execute the query
- Object result = method.invoke(delegate,args);
+ Object result = null;
+ try {
+ //execute the query
+ result = method.invoke(delegate,args);
+ }catch (Throwable t) {
+ reportFailedQuery(query,args,name,start,t);
+ throw t;
+ }
//measure the time
long delta = (process)?(System.currentTimeMillis()-start):Long.MIN_VALUE;
//see if we meet the requirements to measure
if (delta>threshold) {
try {
//report the slow query
- reportSlowQuery(args, name, start, delta);
+ reportSlowQuery(query, args, name, start, delta);
}catch (Exception t) {
if (log.isWarnEnabled()) log.warn("Unable to process slow query",t);
}
@@ -338,50 +433,5 @@
}
return result;
}
-
- protected void reportSlowQuery(Object[] args, final String name, long start, long delta) {
- //extract the query string
- String sql = (query==null && args!=null && args.length>0)?(String)args[0]:query;
- //if we do batch execution, then we name the query 'batch'
- if (sql==null && compare(executes[3],name)) {
- sql = "batch";
- }
- //if we have a query, record the stats
- if (sql!=null) {
- QueryStats qs = getQueryStats(sql);
- if (qs!=null) qs.add(delta,start);
- }
- }
-
- private QueryStats getQueryStats(String sql) {
- ConcurrentHashMap<String,QueryStats> queries = SlowQueryReport.this.queries;
- if (queries==null) return null;
- QueryStats qs = queries.get(sql);
- if (qs == null) {
- qs = new QueryStats(sql);
- if (queries.putIfAbsent(sql,qs)!=null) {
- qs = queries.get(sql);
- } else {
- //we added a new element, see if we need to remove the oldest
- if (queries.size() > maxQueries) {
- removeOldest(queries);
- }
- }
- }
- return qs;
- }
-
- /**
- * TODO - implement a better algorithm
- * @param queries
- */
- protected void removeOldest(ConcurrentHashMap<String,QueryStats> queries) {
- Iterator<String> it = queries.keySet().iterator();
- while (queries.size()>maxQueries && it.hasNext()) {
- String sql = it.next();
- it.remove();
- if (log.isDebugEnabled()) log.debug("Removing slow query, capacity reached:"+sql);
- }
- }
}
}
Modified: tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java?rev=725836&r1=725835&r2=725836&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java (original)
+++ tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java Thu Dec 11 14:07:43 2008
@@ -36,7 +36,7 @@
protected ArrayList<WeakReference<Statement>> statements = new ArrayList<WeakReference<Statement>>();
@Override
- public Object createStatement(Object proxy, Method method, Object[] args, Object statement) {
+ public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) {
// TODO Auto-generated method stub
try {
statements.add(new WeakReference((Statement)statement));
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org