@Override
  public void filteredExceptionOccured(
      Spy spy, String methodCall, Exception e, String sql, long execTime) {
    String classType = spy.getClassType();
    Integer spyNo = spy.getConnectionNumber();
    String header = spyNo + ". " + classType + "." + methodCall;
    if (sql == null) {
      jdbcLogger.error(header, e);
      sqlOnlyLogger.error(header, e);
      sqlTimingLogger.error(header, e);
    } else {
      sql = processSql(sql);
      jdbcLogger.error(header + " " + sql, e);

      // if at debug level, display debug info to error log
      if (sqlOnlyLogger.isDebugEnabled()) {
        sqlOnlyLogger.error(getDebugInfo() + nl + spyNo + ". " + sql, e);
      } else {
        sqlOnlyLogger.error(header + " " + sql, e);
      }

      // if at debug level, display debug info to error log
      if (sqlTimingLogger.isDebugEnabled()) {
        sqlTimingLogger.error(
            getDebugInfo() + nl + spyNo + ". " + sql + " {FAILED after " + execTime + " msec}", e);
      } else {
        sqlTimingLogger.error(
            header + " FAILED! " + sql + " {FAILED after " + execTime + " msec}", e);
      }
    }
  }
 public void methodReturned(Spy spy, String methodCall, String returnMsg) {
   String classType = spy.getClassType();
   Logger logger =
       ResultSetSpy.classTypeDescription.equals(classType) ? resultSetLogger : jdbcLogger;
   if (logger.isInfoEnabled()) {
     String header =
         spy.getConnectionNumber()
             + ". "
             + classType
             + "."
             + methodCall
             + " returned "
             + returnMsg;
     if (logger.isDebugEnabled()) {
       logger.debug(header + " " + getDebugInfo());
     } else {
       logger.info(header);
     }
   }
 }