View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.monitoring.jdbc;
19  
20  import org.apache.commons.monitoring.Role;
21  import org.apache.commons.monitoring.counters.Counter;
22  import org.apache.commons.monitoring.repositories.Repository;
23  import org.apache.commons.monitoring.stopwatches.StopWatch;
24  
25  import java.lang.reflect.InvocationHandler;
26  import java.lang.reflect.InvocationTargetException;
27  import java.lang.reflect.Method;
28  import java.sql.SQLException;
29  import java.sql.Statement;
30  
31  public class MonitoredStatement implements InvocationHandler {
32      private final Statement statement;
33  
34      public MonitoredStatement(final Statement statement) {
35          this.statement = statement;
36      }
37  
38      protected SQLException monitor(final SQLException sqle) {
39          final String name = "SQLException:" + sqle.getSQLState() + ":" + sqle.getErrorCode();
40          Repository.INSTANCE.getCounter(new Counter.Key(Role.FAILURES, name)).add(1);
41          return sqle;
42      }
43  
44      @Override
45      public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
46          final String name = method.getName();
47          if (name.startsWith("execute")) {
48              final StopWatch stopWatch;
49              if (name.endsWith("Batch") && (args == null || args.length == 0)) {
50                  stopWatch = Repository.INSTANCE.start(Repository.INSTANCE.getCounter(new Counter.Key(Role.JDBC, "batch")));
51              } else {
52                  stopWatch = Repository.INSTANCE.start(Repository.INSTANCE.getCounter(new Counter.Key(Role.JDBC, (String) args[0])));
53              }
54  
55              try {
56                  return doInvoke(method, args);
57              } catch (final InvocationTargetException e) {
58                  throw extractSQLException(e);
59              } finally {
60                  stopWatch.stop();
61              }
62          }
63          return doInvoke(method, args);
64      }
65  
66      private Object doInvoke(final Method method, final Object[] args) throws IllegalAccessException, InvocationTargetException {
67          return method.invoke(statement, args);
68      }
69  
70      protected Throwable extractSQLException(final InvocationTargetException e) throws Throwable {
71          final Throwable th = e.getCause();
72          if (SQLException.class.isInstance(th)) {
73              return monitor(SQLException.class.cast(th));
74          }
75          return th;
76      }
77  }