/** * Determine if the given sql should be logged or not based on the various DumpSqlXXXXXX flags. * * @param sql SQL to test. * @return true if the SQL should be logged, false if not. */ private boolean shouldSqlBeLogged(String sql) { if (sql == null) { return false; } sql = sql.trim(); if (sql.length() < 6) { return false; } sql = sql.substring(0, 6).toLowerCase(); return (Properties.isDumpSqlSelect() && "select".equals(sql)) || (Properties.isDumpSqlInsert() && "insert".equals(sql)) || (Properties.isDumpSqlUpdate() && "update".equals(sql)) || (Properties.isDumpSqlDelete() && "delete".equals(sql)) || (Properties.isDumpSqlCreate() && "create".equals(sql)); }
public void sqlOccurred(Spy spy, String methodCall, String sql) { if (!Properties.isDumpSqlFilteringOn() || shouldSqlBeLogged(sql)) { if (sqlOnlyLogger.isDebugEnabled()) { sqlOnlyLogger.debug( getDebugInfo() + nl + spy.getConnectionNumber() + ". " + processSql(sql)); } else if (sqlOnlyLogger.isInfoEnabled()) { sqlOnlyLogger.info(processSql(sql)); } } }
/** * Special call that is called only for JDBC method calls that contain SQL. * * @param spy the Spy wrapping the class where the SQL occurred. * @param execTime how long it took the SQL to run, in milliseconds. * @param methodCall a description of the name and call parameters of the method that generated * the SQL. * @param sql SQL that occurred. */ public void sqlTimingOccurred(Spy spy, long execTime, String methodCall, String sql) { if (sqlTimingLogger.isErrorEnabled() && (!Properties.isDumpSqlFilteringOn() || shouldSqlBeLogged(sql))) { if (Properties.isSqlTimingErrorThresholdEnabled() && execTime >= Properties.getSqlTimingErrorThresholdMsec()) { sqlTimingLogger.error( buildSqlTimingDump(spy, execTime, methodCall, sql, sqlTimingLogger.isDebugEnabled())); } else if (sqlTimingLogger.isWarnEnabled()) { if (Properties.isSqlTimingWarnThresholdEnabled() && execTime >= Properties.getSqlTimingWarnThresholdMsec()) { sqlTimingLogger.warn( buildSqlTimingDump(spy, execTime, methodCall, sql, sqlTimingLogger.isDebugEnabled())); } else if (sqlTimingLogger.isDebugEnabled()) { sqlTimingLogger.debug(buildSqlTimingDump(spy, execTime, methodCall, sql, true)); } else if (sqlTimingLogger.isInfoEnabled()) { sqlTimingLogger.info(buildSqlTimingDump(spy, execTime, methodCall, sql, false)); } } } }
/** * Get debugging info - the module and line number that called the logger version that prints the * stack trace information from the point just before we got it (net.sf.log4jdbc) * * <p>if the optional log4jdbc.debug.stack.prefix system property is defined then the last call * point from an application is shown in the debug trace output, instead of the last direct caller * into log4jdbc * * @return debugging info for whoever called into JDBC from within the application. */ private static String getDebugInfo() { Throwable t = new Throwable(); t.fillInStackTrace(); StackTraceElement[] stackTrace = t.getStackTrace(); if (stackTrace != null) { String className; StringBuffer dump = new StringBuffer(); /** * The DumpFullDebugStackTrace option is useful in some situations when we want to see the * full stack trace in the debug info- watch out though as this will make the logs HUGE! */ if (Properties.isDumpFullDebugStackTrace()) { boolean first = true; for (int i = 0; i < stackTrace.length; i++) { className = stackTrace[i].getClassName(); if (!className.startsWith("net.sf.log4jdbc")) { if (first) { first = false; } else { dump.append(" "); } dump.append("at "); dump.append(stackTrace[i]); dump.append(nl); } } } else { dump.append(" "); int firstLog4jdbcCall = 0; int lastApplicationCall = 0; for (int i = 0; i < stackTrace.length; i++) { className = stackTrace[i].getClassName(); if (className.startsWith("net.sf.log4jdbc")) { firstLog4jdbcCall = i; } else if (Properties.isTraceFromApplication() && Pattern.matches(Properties.getDebugStackPrefix(), className)) { lastApplicationCall = i; break; } } int j = lastApplicationCall; if (j == 0) // if app not found, then use whoever was the last guy that called a log4jdbc // class. { j = 1 + firstLog4jdbcCall; } dump.append(stackTrace[j].getClassName()) .append(".") .append(stackTrace[j].getMethodName()) .append("(") .append(stackTrace[j].getFileName()) .append(":") .append(stackTrace[j].getLineNumber()) .append(")"); } return dump.toString(); } return null; }
/** * Break an SQL statement up into multiple lines in an attempt to make it more readable * * @param sql SQL to break up. * @return SQL broken up into multiple lines */ private String processSql(String sql) { if (sql == null) { return null; } if (Properties.isSqlTrim()) { sql = sql.trim(); } StringBuilder output = new StringBuilder(); if (Properties.getDumpSqlMaxLineLength() <= 0) { output.append(sql); } else { // insert line breaks into sql to make it more readable StringTokenizer st = new StringTokenizer(sql); String token; int linelength = 0; while (st.hasMoreElements()) { token = (String) st.nextElement(); output.append(token); linelength += token.length(); output.append(" "); linelength++; if (linelength > Properties.getDumpSqlMaxLineLength()) { output.append(nl); linelength = 0; } } } if (Properties.isDumpSqlAddSemicolon()) { output.append(";"); } String stringOutput = output.toString(); if (Properties.isTrimExtraBlankLinesInSql()) { LineNumberReader lineReader = new LineNumberReader(new StringReader(stringOutput)); output = new StringBuilder(); int contiguousBlankLines = 0; try { while (true) { String line = lineReader.readLine(); if (line == null) { break; } // is this line blank? if (line.trim().length() == 0) { contiguousBlankLines++; // skip contiguous blank lines if (contiguousBlankLines > 1) { continue; } } else { contiguousBlankLines = 0; output.append(line); } output.append(nl); } } catch (IOException e) { // since we are reading from a buffer, this isn't likely to happen, // but if it does we just ignore it and treat it like its the end of the stream } stringOutput = output.toString(); } return stringOutput; }