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