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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org