mirror of
https://github.com/encounter/log4jdbc.git
synced 2026-03-30 11:27:21 -07:00
Compare commits
3 Commits
1.1
...
MovedToGoogleCode
| Author | SHA1 | Date | |
|---|---|---|---|
| 48cb541e58 | |||
| 201d3b974b | |||
| 007ff20ed1 |
+63
@@ -1,3 +1,66 @@
|
||||
2008-11-08 1.2 alpha 1 Release
|
||||
|
||||
o added a new logger "jdbc.connection" to dump connection open and
|
||||
close events as well as dumping all open connection numbers. This
|
||||
is very useful for hunting down connection leak problems.
|
||||
|
||||
o several new options to produce better SQL output:
|
||||
|
||||
log4jdbc.dump.booleanastruefalse - many RDBMS's don't have a
|
||||
native boolean type and store booleans as a 1 or 0. Setting this
|
||||
option to false will show boolean bind variables as 1 or 0.
|
||||
Setting this to true will show the boolean as true or false.
|
||||
(Note that the default for this setting is false, contrary to the
|
||||
previous way log4jdbc worked.)
|
||||
|
||||
log4jdbc.dump.sql.maxlinelength - can be used to insert line
|
||||
breaks into long running SQL (at white space positions.)
|
||||
previous versions of log4jdbc did this automatically with a value
|
||||
of 90 (the default value is 90.) This line breaking can be turned
|
||||
off completely by setting this to 0.
|
||||
|
||||
log4jdbc.dump.fulldebugstacktrace - can be used in extreme
|
||||
debugging circumstances when you want to be able to see the full
|
||||
stack trace in the debug output. Be extra careful when using
|
||||
this as it will obviously produce much much more logging output.
|
||||
|
||||
o dump a null bind variable as NULL instead of <null> for more
|
||||
accurate and reuseable SQL output.
|
||||
|
||||
o several new options for controlling what types of SQL statements are
|
||||
logged:
|
||||
|
||||
log4jdbc.dump.sql.select default value is true
|
||||
log4jdbc.dump.sql.insert default value is true
|
||||
log4jdbc.dump.sql.update default value is true
|
||||
log4jdbc.dump.sql.delete default value is true
|
||||
log4jdbc.dump.sql.create default value is true
|
||||
|
||||
The default values for all of these are true, but they can be
|
||||
selectively turned on and off to filter out unwanted types of sql
|
||||
statements. For example, setting log4jdbc.dump.sql.delete will
|
||||
cause all DELETE sql commands to not be logged.
|
||||
|
||||
o A new option to add a semi colon to the end of the dumped sql:
|
||||
|
||||
log4jdbc.dump.sql.addsemicolon default value is false
|
||||
|
||||
Sometimes it's useful to use log4jdbc to produce sql scripts that
|
||||
can later be fed back into a SQL tool to execute against a
|
||||
database and this option can help to produce more re-useable sql
|
||||
output script data from a log file.
|
||||
|
||||
o added Microsoft SQL Server 2005 Driver
|
||||
(com.microsoft.sqlserver.jdbc.SQLServerDriver) to
|
||||
list of "well known" drivers that log4jdbc looks for at startup.
|
||||
(thanks to Rob Richards for pointing this out)
|
||||
|
||||
Note that the SQL Server 2000 Driver with the confusing name
|
||||
of (com.microsoft.jdbc.sqlserver.SQLServerDriver) is also still
|
||||
supported.
|
||||
|
||||
o other miscellaneous improvements.
|
||||
|
||||
2008-04-11 1.1 Release
|
||||
|
||||
o upgrade to SLF4J 1.5. Note that log4jdbc should still work with
|
||||
|
||||
+347
-101
File diff suppressed because it is too large
Load Diff
@@ -30,6 +30,11 @@ log4j.additivity.jdbc.sqlonly=false
|
||||
log4j.logger.jdbc.sqltiming=DEBUG,sqltiming
|
||||
log4j.additivity.jdbc.sqltiming=false
|
||||
|
||||
! Log connection open/close events and connection number dump
|
||||
log4j.logger.jdbc.connection=FATAL,connection
|
||||
log4j.additivity.jdbc.connection=false
|
||||
|
||||
|
||||
! the appender used for the JDBC API layer call logging above, sql only
|
||||
log4j.appender.sql=org.apache.log4j.FileAppender
|
||||
log4j.appender.sql.File=./logs/sql.log
|
||||
@@ -50,3 +55,10 @@ log4j.appender.jdbc.File=./logs/jdbc.log
|
||||
log4j.appender.jdbc.Append=false
|
||||
log4j.appender.jdbc.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.jdbc.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
|
||||
|
||||
! the appender used for the JDBC Connection open and close events
|
||||
log4j.appender.connection=org.apache.log4j.FileAppender
|
||||
log4j.appender.connection.File=./logs/connection.log
|
||||
log4j.appender.connection.Append=false
|
||||
log4j.appender.connection.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.connection.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
|
||||
|
||||
+16
-3
@@ -37,15 +37,23 @@
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<appender name="jdbc-connection" class="org.apache.log4j.FileAppender">
|
||||
<param name="File" value="./logs/connection.log"/>
|
||||
<param name="Append" value="false"/>
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %m%n"/>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<!--
|
||||
The Following 4 logs can be turned on and off while the server is running
|
||||
The Following 5 logs can be turned on and off while the server is running
|
||||
LIVE in order to trace the SQL and/or all JDBC coming out of the application.
|
||||
|
||||
To turn a log on, set the level value to INFO or DEBUG (to see class name and
|
||||
line number information in the log) The DEBUG setting is much more inefficient
|
||||
but the output is much more useful.
|
||||
|
||||
To turn off JDBC logging completely, you must set all 4 logs to a level higher
|
||||
To turn off JDBC logging completely, you must set all 5 logs to a level higher
|
||||
than ERROR (FATAL is suggested.)
|
||||
-->
|
||||
|
||||
@@ -75,7 +83,12 @@
|
||||
<level value="fatal"/>
|
||||
<appender-ref ref="jdbc-appender"/>
|
||||
</logger>
|
||||
|
||||
|
||||
<!-- log connection open/close events and dump of all open connection numbers -->
|
||||
<logger name="jdbc.connection" additivity="false">
|
||||
<level value="fatal"/>
|
||||
<appender-ref ref="connection-appender"/>
|
||||
</logger>
|
||||
|
||||
<!-- this log is for internal debugging of log4jdbc, itself -->
|
||||
<!-- debug logging for log4jdbc itself -->
|
||||
|
||||
+4
-1
@@ -26,7 +26,10 @@ code,pre {color:navy;background-color:beige;font-size:11pt;}
|
||||
|
||||
pre {border:2px dashed navy;margin-left:3em;margin-right:4em;margin-top:1em;margin-bottom:1em;white-space:pre-line;}
|
||||
|
||||
.ad {font-size:0.8em;color:blue}
|
||||
.copyright {font-size:0.8m;text-align:center}
|
||||
.copyright a {color:#ef39e9}
|
||||
.sflogo {float:right; margin-right:30px;}
|
||||
|
||||
table.options {margin-left:40px;margin-right:20px;border:1px solid black;border-collapse:collapse;}
|
||||
table.options thead th {text-align:center;border:1px solid black; padding:5px}
|
||||
table.options tbody td {text-align:left;border:1px solid black; padding:5px}
|
||||
@@ -0,0 +1,4 @@
|
||||
To build log4jdbc, you must have Ant 1.6.5 or later installed,
|
||||
and JDK 1.4 and JDK 1.6 installed.
|
||||
|
||||
The build.cmd file is useful for building both the jdbc 3 version (JDK 1.4) and the jdbc 4 version (under JDK 1.6) under windows.
|
||||
+1
-1
@@ -11,7 +11,7 @@ call java -version
|
||||
|
||||
call ant -Djdbc.level=3 all
|
||||
|
||||
set JAVA_HOME=C:\jdk1.6.0_03
|
||||
set JAVA_HOME=C:\jdk1.6.0_10
|
||||
set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin
|
||||
call java -version
|
||||
|
||||
|
||||
+3
-2
@@ -48,7 +48,7 @@
|
||||
|
||||
|
||||
<!-- release version -->
|
||||
<property name="version" value="1.1"/>
|
||||
<property name="version" value="1.2alpha1"/>
|
||||
|
||||
<target name="all" depends="cleancompile,compile,cleanjar,jar"/>
|
||||
|
||||
@@ -194,6 +194,7 @@
|
||||
<property name="ps" value="${path.separator}"/>
|
||||
|
||||
<javadoc destdir="${apidocs}" packagenames="net.sf.log4jdbc.*"
|
||||
maxmemory="512m"
|
||||
Windowtitle="log4${jdbc.prefix} ${version}"
|
||||
Header="<b><a href="http://log4jdbc.sourceforge.net">log4${jdbc.prefix} ${version}</a></b>"
|
||||
Use="true" breakiterator="true">
|
||||
@@ -208,7 +209,7 @@
|
||||
<!-- note that the jdk source code is referenced here so that javadoc will be generated from
|
||||
interface class methods when none is specified in the implementation -->
|
||||
|
||||
<sourcepath path="/jdk1.6.0_03/src"/>
|
||||
<sourcepath path="/jdk1.6.0_10/src"/>
|
||||
<link href="http://java.sun.com/javase/6/docs/api/"/>
|
||||
<!--
|
||||
<link href="http://java.sun.com/j2ee/1.4/docs/api/"/>
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@ rem run ydoc for jdbc 3 with jdk 1.4 and
|
||||
rem run ydoc for jdbc 4 with jdk 1.6
|
||||
|
||||
set ANT_HOME=c:\apache-ant-1.6.5
|
||||
set ANT_OPTS=-Xmx512m
|
||||
|
||||
set JAVA_HOME=C:\j2sdk1.4.2_13
|
||||
set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin
|
||||
@@ -12,7 +13,7 @@ call java -version
|
||||
|
||||
call ant -Djdbc.level=3 ydoc.3
|
||||
|
||||
set JAVA_HOME=c:\jdk1.6.0_03
|
||||
set JAVA_HOME=c:\jdk1.6.0_10
|
||||
set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin
|
||||
call java -version
|
||||
|
||||
|
||||
+1
-1
@@ -25,4 +25,4 @@ rem * profiling output report.
|
||||
rem * *
|
||||
rem *************************************************************************************************
|
||||
|
||||
java -Xmx1024m -classpath ..\build\log4jdbc3-1.1.jar net.sf.log4jdbc.PostLogProfilerProcessor %*
|
||||
java -Xmx1024m -classpath ..\build\log4jdbc3-1.2alpha1.jar net.sf.log4jdbc.PostLogProfilerProcessor %*
|
||||
+1
-1
@@ -25,4 +25,4 @@
|
||||
# * *
|
||||
# *************************************************************************************************
|
||||
|
||||
java -Xmx1024m -classpath ../build/log4jdbc3-1.1.jar net.sf.log4jdbc.PostLogProfilerProcessor $@
|
||||
java -Xmx1024m -classpath ../build/log4jdbc3-1.2alpha1.jar net.sf.log4jdbc.PostLogProfilerProcessor $@
|
||||
|
||||
@@ -39,8 +39,6 @@ import java.util.Map;
|
||||
*/
|
||||
public class CallableStatementSpy extends PreparedStatementSpy implements CallableStatement
|
||||
{
|
||||
private final SpyLogDelegator log;
|
||||
|
||||
protected void reportAllReturns(String methodCall, String msg)
|
||||
{
|
||||
log.methodReturned(this, methodCall, msg);
|
||||
@@ -52,7 +50,7 @@ public class CallableStatementSpy extends PreparedStatementSpy implements Callab
|
||||
private CallableStatement realCallableStatement;
|
||||
|
||||
/**
|
||||
* Create a CallableStatementSpy to spy upon a CallableStatement.
|
||||
* Create a CallableStatementSpy (JDBC 3 version) to spy upon a CallableStatement.
|
||||
*
|
||||
* @param sql The SQL used for this CallableStatement
|
||||
* @param connectionSpy The ConnectionSpy which produced this CallableStatementSpy
|
||||
@@ -62,7 +60,6 @@ public class CallableStatementSpy extends PreparedStatementSpy implements Callab
|
||||
{
|
||||
super(sql, connectionSpy, realCallableStatement);
|
||||
this.realCallableStatement = realCallableStatement;
|
||||
log = SpyLogFactory.getSpyLogDelegator();
|
||||
}
|
||||
|
||||
public String getClassType()
|
||||
@@ -624,6 +621,7 @@ public class CallableStatementSpy extends PreparedStatementSpy implements Callab
|
||||
|
||||
public void setBytes(String parameterName, byte[] x) throws SQLException
|
||||
{
|
||||
//todo: dump byte array?
|
||||
String methodCall = "setBytes(" + parameterName + ", " + x + ")";
|
||||
try
|
||||
{
|
||||
@@ -1040,7 +1038,6 @@ public class CallableStatementSpy extends PreparedStatementSpy implements Callab
|
||||
reportException(methodCall, s);
|
||||
throw s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException
|
||||
|
||||
@@ -23,10 +23,19 @@ import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.Savepoint;
|
||||
import java.sql.Statement;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Wraps a JDBC Connection and reports method calls, returns and exceptions.
|
||||
*
|
||||
* This version is for jdbc 3.
|
||||
*
|
||||
* @author Arthur Blake
|
||||
*/
|
||||
public class ConnectionSpy implements Connection, Spy
|
||||
@@ -35,9 +44,51 @@ public class ConnectionSpy implements Connection, Spy
|
||||
|
||||
private SpyLogDelegator log;
|
||||
|
||||
private int connectionNumber;
|
||||
private final Integer connectionNumber;
|
||||
private static int lastConnectionNumber = 0;
|
||||
private static final Object connectionNumberLock = new Object();
|
||||
|
||||
/**
|
||||
* Contains a Mapping of connectionNumber to currently open ConnectionSpy
|
||||
* objects.
|
||||
*/
|
||||
private static final Map connectionTracker = new HashMap();
|
||||
|
||||
/**
|
||||
* Get a dump of how many connections are open, and which connection numbers
|
||||
* are open.
|
||||
*
|
||||
* @return an open connection dump.
|
||||
*/
|
||||
public static String getOpenConnectionsDump()
|
||||
{
|
||||
StringBuffer dump = new StringBuffer();
|
||||
int size;
|
||||
Integer[] keysArr;
|
||||
synchronized (connectionTracker)
|
||||
{
|
||||
size = connectionTracker.size();
|
||||
if (size==0)
|
||||
{
|
||||
return "open connections: none";
|
||||
}
|
||||
Set keys = connectionTracker.keySet();
|
||||
keysArr = (Integer[]) keys.toArray(new Integer[keys.size()]);
|
||||
}
|
||||
|
||||
Arrays.sort(keysArr);
|
||||
|
||||
dump.append("open connections: ");
|
||||
for (int i=0; i < keysArr.length; i++)
|
||||
{
|
||||
dump.append(keysArr[i]);
|
||||
dump.append(" ");
|
||||
}
|
||||
|
||||
dump.append("(");
|
||||
dump.append(size);
|
||||
dump.append(")");
|
||||
return dump.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ConnectionSpy that wraps a given Connection.
|
||||
@@ -46,18 +97,7 @@ public class ConnectionSpy implements Connection, Spy
|
||||
*/
|
||||
public ConnectionSpy(Connection realConnection)
|
||||
{
|
||||
setRdbmsSpecifics(DriverSpy.defaultRdbmsSpecifics); // just in case it's not initialized
|
||||
if (realConnection == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Must pass in a non null real Connection");
|
||||
}
|
||||
this.realConnection = realConnection;
|
||||
log = SpyLogFactory.getSpyLogDelegator();
|
||||
|
||||
synchronized (connectionNumberLock)
|
||||
{
|
||||
connectionNumber = ++lastConnectionNumber;
|
||||
}
|
||||
this(realConnection, DriverSpy.defaultRdbmsSpecifics);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,6 +108,10 @@ public class ConnectionSpy implements Connection, Spy
|
||||
*/
|
||||
public ConnectionSpy(Connection realConnection, RdbmsSpecifics rdbmsSpecifics)
|
||||
{
|
||||
if (rdbmsSpecifics == null)
|
||||
{
|
||||
rdbmsSpecifics = DriverSpy.defaultRdbmsSpecifics;
|
||||
}
|
||||
setRdbmsSpecifics(rdbmsSpecifics);
|
||||
if (realConnection == null)
|
||||
{
|
||||
@@ -76,10 +120,13 @@ public class ConnectionSpy implements Connection, Spy
|
||||
this.realConnection = realConnection;
|
||||
log = SpyLogFactory.getSpyLogDelegator();
|
||||
|
||||
synchronized (connectionNumberLock)
|
||||
synchronized (connectionTracker)
|
||||
{
|
||||
connectionNumber = ++lastConnectionNumber;
|
||||
connectionNumber = new Integer(++lastConnectionNumber);
|
||||
connectionTracker.put(connectionNumber, this);
|
||||
}
|
||||
log.connectionOpened(this);
|
||||
reportReturn("new Connection");
|
||||
}
|
||||
|
||||
private RdbmsSpecifics rdbmsSpecifics;
|
||||
@@ -104,7 +151,7 @@ public class ConnectionSpy implements Connection, Spy
|
||||
return rdbmsSpecifics;
|
||||
}
|
||||
|
||||
public int getConnectionNumber()
|
||||
public Integer getConnectionNumber()
|
||||
{
|
||||
return connectionNumber;
|
||||
}
|
||||
@@ -685,6 +732,14 @@ public class ConnectionSpy implements Connection, Spy
|
||||
reportException(methodCall, s);
|
||||
throw s;
|
||||
}
|
||||
finally
|
||||
{
|
||||
synchronized (connectionTracker)
|
||||
{
|
||||
connectionTracker.remove(connectionNumber);
|
||||
}
|
||||
log.connectionClosed(this);
|
||||
}
|
||||
reportReturn(methodCall);
|
||||
}
|
||||
}
|
||||
@@ -45,10 +45,13 @@ import java.util.TreeSet;
|
||||
* <li>com.sybase.jdbc2.jdbc.SybDriver</li>
|
||||
* <li>net.sourceforge.jtds.jdbc.Driver</li>
|
||||
* <li>com.microsoft.jdbc.sqlserver.SQLServerDriver</li>
|
||||
* <li>com.microsoft.sqlserver.jdbc.SQLServerDriver</li>
|
||||
* <li>weblogic.jdbc.sqlserver.SQLServerDriver</li>
|
||||
* <li>com.informix.jdbc.IfxDriver</li>
|
||||
* <li>org.apache.derby.jdbc.ClientDriver</li>
|
||||
* <li>org.apache.derby.jdbc.EmbeddedDriver</li>
|
||||
* <li>com.mysql.jdbc.Driver</li>
|
||||
* <li>org.postgresql.Driver</li>
|
||||
* <li>org.hsqldb.jdbcDriver</li>
|
||||
* <li>org.h2.Driver</li>
|
||||
* </ul>
|
||||
@@ -137,6 +140,47 @@ public class DriverSpy implements Driver
|
||||
*/
|
||||
static long SqlTimingErrorThresholdMsec;
|
||||
|
||||
/**
|
||||
* When dumping boolean values, dump them as 'true' or 'false'.
|
||||
* If this option is not set, they will be dumped as 1 or 0 as many
|
||||
* databases do not have a boolean type, and this allows for more
|
||||
* portable sql dumping.
|
||||
*/
|
||||
static boolean DumpBooleanAsTrueFalse;
|
||||
|
||||
/**
|
||||
* When dumping SQL, if this is greater than 0, than the SQL will
|
||||
* be broken up into lines that are no longer than this value.
|
||||
*/
|
||||
static int DumpSqlMaxLineLength;
|
||||
|
||||
/**
|
||||
* Options to more finely control which types of SQL statements will
|
||||
* be dumped, when dumping SQL.
|
||||
* By default all 5 of the following will be true. If any one is set to
|
||||
* false, then that particular type of SQL will not be dumped.
|
||||
*/
|
||||
static boolean DumpSqlSelect;
|
||||
static boolean DumpSqlInsert;
|
||||
static boolean DumpSqlUpdate;
|
||||
static boolean DumpSqlDelete;
|
||||
static boolean DumpSqlCreate;
|
||||
|
||||
// only true if one ore more of the above 4 flags are false.
|
||||
static boolean DumpSqlFilteringOn;
|
||||
|
||||
/**
|
||||
* If true, add a semilcolon to the end of each SQL dump.
|
||||
*/
|
||||
static boolean DumpSqlAddSemicolon;
|
||||
|
||||
/**
|
||||
* If dumping in debug mode, dump the full stack trace.
|
||||
* This will result in a VERY voluminous output, but can be very useful
|
||||
* under some circumstances.
|
||||
*/
|
||||
static boolean DumpFullDebugStackTrace;
|
||||
|
||||
/**
|
||||
* Get a Long option from a system property and
|
||||
* log a debug message about this.
|
||||
@@ -164,7 +208,42 @@ public class DriverSpy implements Driver
|
||||
catch (NumberFormatException n)
|
||||
{
|
||||
log.debug("x " + propName + " \"" + propValue +
|
||||
"\" is not a valid long value");
|
||||
"\" is not a valid number");
|
||||
}
|
||||
}
|
||||
return longPropValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Long option from a system property and
|
||||
* log a debug message about this.
|
||||
*
|
||||
* @param propName System property key.
|
||||
*
|
||||
* @return the value of that System property key, converted
|
||||
* to a Long. Or null if not defined or is invalid.
|
||||
*/
|
||||
private static Long getLongOption(String propName, long defaultValue)
|
||||
{
|
||||
String propValue = System.getProperty(propName);
|
||||
Long longPropValue;
|
||||
if (propValue == null)
|
||||
{
|
||||
log.debug("x " + propName + " is not defined (using default of " + defaultValue +")");
|
||||
longPropValue = new Long(defaultValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
longPropValue = new Long(Long.parseLong(propValue));
|
||||
log.debug(" " + propName + " = " + longPropValue);
|
||||
}
|
||||
catch (NumberFormatException n)
|
||||
{
|
||||
log.debug("x " + propName + " \"" + propValue +
|
||||
"\" is not a valid number (using default of " + defaultValue +")");
|
||||
longPropValue = new Long(defaultValue);
|
||||
}
|
||||
}
|
||||
return longPropValue;
|
||||
@@ -192,6 +271,43 @@ public class DriverSpy implements Driver
|
||||
return propValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a boolean option from a system property and
|
||||
* log a debug message about this.
|
||||
*
|
||||
* @param propName property name to get.
|
||||
* @param defaultValue default value to use if undefined.
|
||||
*
|
||||
* @return boolean value found in property, or defaultValue if no property
|
||||
* found.
|
||||
*/
|
||||
private static boolean getBooleanOption(String propName, boolean defaultValue)
|
||||
{
|
||||
String propValue = System.getProperty(propName);
|
||||
boolean val;
|
||||
if (propValue == null)
|
||||
{
|
||||
log.debug("x " + propName + " is not defined (using default value " +
|
||||
defaultValue + ")");
|
||||
return defaultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
propValue = propValue.trim().toLowerCase();
|
||||
if (propValue.length() == 0)
|
||||
{
|
||||
val = defaultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
val= "true".equals(propValue) ||
|
||||
"yes".equals(propValue) || "on".equals(propValue);
|
||||
}
|
||||
}
|
||||
log.debug(" " + propName + " = " + val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
log.debug("... log4jdbc initializing ...");
|
||||
@@ -214,6 +330,26 @@ public class DriverSpy implements Driver
|
||||
SqlTimingErrorThresholdMsec = thresh.longValue();
|
||||
}
|
||||
|
||||
DumpBooleanAsTrueFalse =
|
||||
getBooleanOption("log4jdbc.dump.booleanastruefalse",false);
|
||||
|
||||
DumpSqlMaxLineLength = getLongOption("log4jdbc.dump.sql.maxlinelength", 90L).
|
||||
intValue();
|
||||
|
||||
DumpFullDebugStackTrace =
|
||||
getBooleanOption("log4jdbc.dump.fulldebugstacktrace",false);
|
||||
|
||||
DumpSqlSelect = getBooleanOption("log4jdbc.dump.sql.select",true);
|
||||
DumpSqlInsert = getBooleanOption("log4jdbc.dump.sql.insert",true);
|
||||
DumpSqlUpdate = getBooleanOption("log4jdbc.dump.sql.update",true);
|
||||
DumpSqlDelete = getBooleanOption("log4jdbc.dump.sql.delete",true);
|
||||
DumpSqlCreate = getBooleanOption("log4jdbc.dump.sql.create",true);
|
||||
|
||||
DumpSqlFilteringOn = !(DumpSqlSelect && DumpSqlInsert && DumpSqlUpdate &&
|
||||
DumpSqlDelete && DumpSqlCreate);
|
||||
|
||||
DumpSqlAddSemicolon = getBooleanOption("log4jdbc.dump.sql.addsemicolon",false);
|
||||
|
||||
// The Set of drivers that the log4jdbc driver will preload at instantiation
|
||||
// time. The driver can spy on any driver type, it's just a little bit
|
||||
// easier to configure log4jdbc if it's one of these types!
|
||||
@@ -222,7 +358,13 @@ public class DriverSpy implements Driver
|
||||
subDrivers.add("oracle.jdbc.driver.OracleDriver");
|
||||
subDrivers.add("com.sybase.jdbc2.jdbc.SybDriver");
|
||||
subDrivers.add("net.sourceforge.jtds.jdbc.Driver");
|
||||
|
||||
// MS driver for Sql Server 2000
|
||||
subDrivers.add("com.microsoft.jdbc.sqlserver.SQLServerDriver");
|
||||
|
||||
// MS driver for Sql Server 2005
|
||||
subDrivers.add("com.microsoft.sqlserver.jdbc.SQLServerDriver");
|
||||
|
||||
subDrivers.add("weblogic.jdbc.sqlserver.SQLServerDriver");
|
||||
subDrivers.add("com.informix.jdbc.IfxDriver");
|
||||
subDrivers.add("org.apache.derby.jdbc.ClientDriver");
|
||||
|
||||
@@ -33,7 +33,6 @@ import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -44,8 +43,6 @@ import java.util.List;
|
||||
public class PreparedStatementSpy extends StatementSpy implements PreparedStatement
|
||||
{
|
||||
|
||||
private final SpyLogDelegator log;
|
||||
|
||||
/**
|
||||
* holds list of bind variables for tracing
|
||||
*/
|
||||
@@ -65,6 +62,8 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
*/
|
||||
protected void argTraceSet(int i, String typeHelper, Object arg)
|
||||
{
|
||||
String tracedArg = rdbmsSpecifics.formatParameterObject(arg);
|
||||
|
||||
i--; // make the index 0 based
|
||||
synchronized (argTrace)
|
||||
{
|
||||
@@ -75,15 +74,11 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
}
|
||||
if (!showTypeHelp || typeHelper == null)
|
||||
{
|
||||
typeHelper = "";
|
||||
}
|
||||
if (arg != null)
|
||||
{
|
||||
argTrace.set(i, typeHelper + arg.toString());
|
||||
argTrace.set(i, tracedArg);
|
||||
}
|
||||
else
|
||||
{
|
||||
argTrace.set(i, typeHelper + "null");
|
||||
argTrace.set(i, typeHelper + tracedArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,30 +123,8 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
{
|
||||
dumpSql.append(sql.substring(lastPos, sql.length())); // dump last segment
|
||||
}
|
||||
|
||||
// insert line breaks into sql to make it more readable
|
||||
StringBuffer output = new StringBuffer();
|
||||
StringTokenizer st = new StringTokenizer(dumpSql.toString());
|
||||
|
||||
String token;
|
||||
int linelength = 0;
|
||||
|
||||
while (st.hasMoreElements())
|
||||
{
|
||||
token = (String) st.nextElement();
|
||||
|
||||
output.append(token);
|
||||
linelength += token.length();
|
||||
output.append(" ");
|
||||
linelength++;
|
||||
if (linelength > 90)
|
||||
{
|
||||
output.append("\n");
|
||||
linelength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return output.toString();
|
||||
|
||||
return dumpSql.toString();
|
||||
}
|
||||
|
||||
protected void reportAllReturns(String methodCall, String msg)
|
||||
@@ -170,7 +143,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
protected RdbmsSpecifics rdbmsSpecifics;
|
||||
|
||||
/**
|
||||
* Create a prepared statement spy for logging activity of another PreparedStatement.
|
||||
* Create a PreparedStatementSpy (JDBC 3 version) for logging activity of another PreparedStatement.
|
||||
*
|
||||
* @param sql SQL for the prepared statement that is being spied upon.
|
||||
* @param connectionSpy ConnectionSpy that was called to produce this PreparedStatement.
|
||||
@@ -181,7 +154,6 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
super(connectionSpy, realPreparedStatement); // does null check for us
|
||||
this.sql = sql;
|
||||
this.realPreparedStatement = realPreparedStatement;
|
||||
log = SpyLogFactory.getSpyLogDelegator();
|
||||
rdbmsSpecifics = connectionSpy.getRdbmsSpecifics();
|
||||
}
|
||||
|
||||
@@ -243,7 +215,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setNull(int parameterIndex, int sqlType) throws SQLException
|
||||
{
|
||||
String methodCall = "setNull(" + parameterIndex + ", " + sqlType + ")";
|
||||
argTraceSet(parameterIndex, null, "null");
|
||||
argTraceSet(parameterIndex, null, null);
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setNull(parameterIndex, sqlType);
|
||||
@@ -259,7 +231,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setNull(int paramIndex, int sqlType, String typeName) throws SQLException
|
||||
{
|
||||
String methodCall = "setNull(" + paramIndex + ", " + sqlType + ", " + typeName + ")";
|
||||
argTraceSet(paramIndex, null, "null");
|
||||
argTraceSet(paramIndex, null, null);
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setNull(paramIndex, sqlType, typeName);
|
||||
@@ -291,7 +263,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setBoolean(int parameterIndex, boolean x) throws SQLException
|
||||
{
|
||||
String methodCall = "setBoolean(" + parameterIndex + ", " + x + ")";
|
||||
argTraceSet(parameterIndex, "(boolean)", Boolean.toString(x));
|
||||
argTraceSet(parameterIndex, "(boolean)", x?Boolean.TRUE:Boolean.FALSE);
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setBoolean(parameterIndex, x);
|
||||
@@ -355,7 +327,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setByte(int parameterIndex, byte x) throws SQLException
|
||||
{
|
||||
String methodCall = "setByte(" + parameterIndex + ", " + x + ")";
|
||||
argTraceSet(parameterIndex, "(byte)", Byte.toString(x));
|
||||
argTraceSet(parameterIndex, "(byte)", new Byte(x));
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setByte(parameterIndex, x);
|
||||
@@ -390,7 +362,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setShort(int parameterIndex, short x) throws SQLException
|
||||
{
|
||||
String methodCall = "setShort(" + parameterIndex + ", " + x + ")";
|
||||
argTraceSet(parameterIndex, "(short)", Short.toString(x));
|
||||
argTraceSet(parameterIndex, "(short)", new Short(x));
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setShort(parameterIndex, x);
|
||||
@@ -425,7 +397,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setInt(int parameterIndex, int x) throws SQLException
|
||||
{
|
||||
String methodCall = "setInt(" + parameterIndex + ", " + x + ")";
|
||||
argTraceSet(parameterIndex, "(int)", Integer.toString(x));
|
||||
argTraceSet(parameterIndex, "(int)", new Integer(x));
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setInt(parameterIndex, x);
|
||||
@@ -441,7 +413,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setLong(int parameterIndex, long x) throws SQLException
|
||||
{
|
||||
String methodCall = "setLong(" + parameterIndex + ", " + x + ")";
|
||||
argTraceSet(parameterIndex, "(long)", Long.toString(x));
|
||||
argTraceSet(parameterIndex, "(long)", new Long(x));
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setLong(parameterIndex, x);
|
||||
@@ -457,7 +429,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setFloat(int parameterIndex, float x) throws SQLException
|
||||
{
|
||||
String methodCall = "setFloat(" + parameterIndex + ", " + x + ")";
|
||||
argTraceSet(parameterIndex, "(float)", Float.toString(x));
|
||||
argTraceSet(parameterIndex, "(float)", new Float(x));
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setFloat(parameterIndex, x);
|
||||
@@ -473,7 +445,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setDouble(int parameterIndex, double x) throws SQLException
|
||||
{
|
||||
String methodCall = "setDouble(" + parameterIndex + ", " + x + ")";
|
||||
argTraceSet(parameterIndex, "(double)", Double.toString(x));
|
||||
argTraceSet(parameterIndex, "(double)", new Double(x));
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setDouble(parameterIndex, x);
|
||||
@@ -505,7 +477,6 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setURL(int parameterIndex, URL x) throws SQLException
|
||||
{
|
||||
String methodCall = "setURL(" + parameterIndex + ", " + x + ")";
|
||||
|
||||
argTraceSet(parameterIndex, "(URL)", x);
|
||||
|
||||
try
|
||||
@@ -523,8 +494,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setString(int parameterIndex, String x) throws SQLException
|
||||
{
|
||||
String methodCall = "setString(" + parameterIndex + ", \"" + x + "\")";
|
||||
|
||||
argTraceSet(parameterIndex, "(String)", rdbmsSpecifics.formatParameterObject(x));
|
||||
argTraceSet(parameterIndex, "(String)", x);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -540,6 +510,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
|
||||
public void setBytes(int parameterIndex, byte[] x) throws SQLException
|
||||
{
|
||||
//todo: dump array?
|
||||
String methodCall = "setBytes(" + parameterIndex + ", " + x + ")";
|
||||
argTraceSet(parameterIndex, "(byte[])", "<byte[]>");
|
||||
try
|
||||
@@ -557,7 +528,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setDate(int parameterIndex, Date x) throws SQLException
|
||||
{
|
||||
String methodCall = "setDate(" + parameterIndex + ", " + x + ")";
|
||||
argTraceSet(parameterIndex, "(Date)", rdbmsSpecifics.formatParameterObject(x));
|
||||
argTraceSet(parameterIndex, "(Date)", x);
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setDate(parameterIndex, x);
|
||||
@@ -587,7 +558,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException
|
||||
{
|
||||
String methodCall = "setDate(" + parameterIndex + ", " + x + ", " + cal + ")";
|
||||
argTraceSet(parameterIndex, "(Date)", rdbmsSpecifics.formatParameterObject(x));
|
||||
argTraceSet(parameterIndex, "(Date)", x);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -636,7 +607,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
|
||||
{
|
||||
String methodCall = "setObject(" + parameterIndex + ", " + x + ", " + targetSqlType + ", " + scale + ")";
|
||||
argTraceSet(parameterIndex, getTypeHelp(x), rdbmsSpecifics.formatParameterObject(x));
|
||||
argTraceSet(parameterIndex, getTypeHelp(x), x);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -653,7 +624,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
|
||||
{
|
||||
String methodCall = "setObject(" + parameterIndex + ", " + x + ", " + targetSqlType + ")";
|
||||
argTraceSet(parameterIndex, getTypeHelp(x), rdbmsSpecifics.formatParameterObject(x));
|
||||
argTraceSet(parameterIndex, getTypeHelp(x), x);
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setObject(parameterIndex, x, targetSqlType);
|
||||
@@ -669,7 +640,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setObject(int parameterIndex, Object x) throws SQLException
|
||||
{
|
||||
String methodCall = "setObject(" + parameterIndex + ", " + x + ")";
|
||||
argTraceSet(parameterIndex, getTypeHelp(x), rdbmsSpecifics.formatParameterObject(x));
|
||||
argTraceSet(parameterIndex, getTypeHelp(x), x);
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setObject(parameterIndex, x);
|
||||
@@ -685,7 +656,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
|
||||
{
|
||||
String methodCall = "setTimestamp(" + parameterIndex + ", " + x + ")";
|
||||
argTraceSet(parameterIndex, "(Date)", rdbmsSpecifics.formatParameterObject(x));
|
||||
argTraceSet(parameterIndex, "(Date)", x);
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setTimestamp(parameterIndex, x);
|
||||
@@ -701,7 +672,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException
|
||||
{
|
||||
String methodCall = "setTimestamp(" + parameterIndex + ", " + x + ", " + cal + ")";
|
||||
argTraceSet(parameterIndex, "(Timestamp)", rdbmsSpecifics.formatParameterObject(x));
|
||||
argTraceSet(parameterIndex, "(Timestamp)", x);
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setTimestamp(parameterIndex, x, cal);
|
||||
@@ -736,7 +707,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
|
||||
{
|
||||
String methodCall = "setAsciiStream(" + parameterIndex + ", " + x + ", " + length + ")";
|
||||
argTraceSet(parameterIndex, "(Ascii InputStream)", "<Ascii InputStream of length " + x + ">");
|
||||
argTraceSet(parameterIndex, "(Ascii InputStream)", "<Ascii InputStream of length " + length + ">");
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setAsciiStream(parameterIndex, x, length);
|
||||
|
||||
@@ -46,12 +46,13 @@ class RdbmsSpecifics
|
||||
{
|
||||
if (object == null)
|
||||
{
|
||||
return "<null>";
|
||||
return "NULL";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (object instanceof String)
|
||||
{
|
||||
// todo: need to handle imbedded quotes??
|
||||
return "'" + object + "'";
|
||||
}
|
||||
else if (object instanceof Date)
|
||||
@@ -62,6 +63,12 @@ class RdbmsSpecifics
|
||||
{
|
||||
return object.toString();
|
||||
}
|
||||
else if (object instanceof Boolean)
|
||||
{
|
||||
return DriverSpy.DumpBooleanAsTrueFalse?
|
||||
((Boolean)object).booleanValue()?"true":"false"
|
||||
:((Boolean)object).booleanValue()?"1":"0";
|
||||
}
|
||||
else
|
||||
{
|
||||
return object.toString();
|
||||
|
||||
@@ -37,6 +37,8 @@ import java.util.Map;
|
||||
/**
|
||||
* Wraps a ResultSet and reports method calls, returns and exceptions.
|
||||
*
|
||||
* JDBC 3 version.
|
||||
*
|
||||
* @author Arthur Blake
|
||||
*/
|
||||
public class ResultSetSpy implements ResultSet, Spy
|
||||
@@ -84,6 +86,7 @@ public class ResultSetSpy implements ResultSet, Spy
|
||||
this.realResultSet = realResultSet;
|
||||
this.parent = parent;
|
||||
log = SpyLogFactory.getSpyLogDelegator();
|
||||
reportReturn("new ResultSet");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,7 +99,7 @@ public class ResultSetSpy implements ResultSet, Spy
|
||||
return classTypeDescription;
|
||||
}
|
||||
|
||||
public int getConnectionNumber()
|
||||
public Integer getConnectionNumber()
|
||||
{
|
||||
return parent.getConnectionNumber();
|
||||
}
|
||||
@@ -1328,6 +1331,7 @@ public class ResultSetSpy implements ResultSet, Spy
|
||||
}
|
||||
else
|
||||
{
|
||||
//todo: what's going on here?
|
||||
return (Statement) reportReturn(methodCall, new StatementSpy(new ConnectionSpy(s.getConnection()), s));
|
||||
}
|
||||
}
|
||||
@@ -1456,6 +1460,7 @@ public class ResultSetSpy implements ResultSet, Spy
|
||||
|
||||
public void updateBytes(int columnIndex, byte[] x) throws SQLException
|
||||
{
|
||||
// todo: dump array?
|
||||
String methodCall = "updateBytes(" + columnIndex + ", " + x + ")";
|
||||
try
|
||||
{
|
||||
@@ -1471,6 +1476,7 @@ public class ResultSetSpy implements ResultSet, Spy
|
||||
|
||||
public void updateBytes(String columnName, byte[] x) throws SQLException
|
||||
{
|
||||
// todo: dump array?
|
||||
String methodCall = "updateBytes(" + columnName + ", " + x + ")";
|
||||
try
|
||||
{
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package net.sf.log4jdbc;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -53,6 +55,12 @@ public class Slf4jSpyLogDelegator implements SpyLogDelegator
|
||||
* Logger that shows the SQL timing, post execution
|
||||
*/
|
||||
private final Logger sqlTimingLogger = LoggerFactory.getLogger("jdbc.sqltiming");
|
||||
|
||||
/**
|
||||
* Logger that shows connection open and close events as well as current number
|
||||
* of open connections.
|
||||
*/
|
||||
private final Logger connectionLogger = LoggerFactory.getLogger("jdbc.connection");
|
||||
|
||||
// admin/setup logging for log4jdbc.
|
||||
|
||||
@@ -70,7 +78,7 @@ public class Slf4jSpyLogDelegator implements SpyLogDelegator
|
||||
public boolean isJdbcLoggingEnabled()
|
||||
{
|
||||
return jdbcLogger.isErrorEnabled() || resultSetLogger.isErrorEnabled() || sqlOnlyLogger.isErrorEnabled() ||
|
||||
sqlTimingLogger.isErrorEnabled();
|
||||
sqlTimingLogger.isErrorEnabled() || connectionLogger.isErrorEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,7 +94,7 @@ public class Slf4jSpyLogDelegator implements SpyLogDelegator
|
||||
public void exceptionOccured(Spy spy, String methodCall, Exception e, String sql, long execTime)
|
||||
{
|
||||
String classType = spy.getClassType();
|
||||
int spyNo = spy.getConnectionNumber();
|
||||
Integer spyNo = spy.getConnectionNumber();
|
||||
String header = spyNo + ". " + classType + "." + methodCall;
|
||||
if (sql == null)
|
||||
{
|
||||
@@ -132,7 +140,7 @@ public class Slf4jSpyLogDelegator implements SpyLogDelegator
|
||||
public void methodReturned(Spy spy, String methodCall, String returnMsg)
|
||||
{
|
||||
String classType = spy.getClassType();
|
||||
int spyNo = spy.getConnectionNumber();
|
||||
Integer spyNo = spy.getConnectionNumber();
|
||||
String header = spyNo + ". " + classType + "." + methodCall + " returned " + returnMsg;
|
||||
if (ResultSetSpy.classTypeDescription.equals(classType))
|
||||
{
|
||||
@@ -170,6 +178,34 @@ public class Slf4jSpyLogDelegator implements SpyLogDelegator
|
||||
}
|
||||
|
||||
private static String nl = System.getProperty("line.separator");
|
||||
|
||||
/**
|
||||
* 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
|
||||
(DriverSpy.DumpSqlSelect && "select".equals(sql)) ||
|
||||
(DriverSpy.DumpSqlInsert && "insert".equals(sql)) ||
|
||||
(DriverSpy.DumpSqlUpdate && "update".equals(sql)) ||
|
||||
(DriverSpy.DumpSqlDelete && "delete".equals(sql)) ||
|
||||
(DriverSpy.DumpSqlCreate && "create".equals(sql));
|
||||
}
|
||||
|
||||
/**
|
||||
* Special call that is called only for JDBC method calls that contain SQL.
|
||||
@@ -180,16 +216,72 @@ public class Slf4jSpyLogDelegator implements SpyLogDelegator
|
||||
*/
|
||||
public void sqlOccured(Spy spy, String methodCall, String sql)
|
||||
{
|
||||
int spyNo = spy.getConnectionNumber();
|
||||
if (!DriverSpy.DumpSqlFilteringOn || shouldSqlBeLogged(sql))
|
||||
{
|
||||
sql = processSql(sql);
|
||||
|
||||
if (sqlOnlyLogger.isDebugEnabled())
|
||||
{
|
||||
sqlOnlyLogger.debug(getDebugInfo() + nl + spy.getConnectionNumber() + ". " + sql);
|
||||
}
|
||||
else if (sqlOnlyLogger.isInfoEnabled())
|
||||
{
|
||||
sqlOnlyLogger.info(sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sqlOnlyLogger.isDebugEnabled())
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
sqlOnlyLogger.debug(getDebugInfo() + nl + spyNo + ". " + sql);
|
||||
return null;
|
||||
}
|
||||
else if (sqlOnlyLogger.isInfoEnabled())
|
||||
|
||||
sql = sql.trim();
|
||||
|
||||
StringBuffer output = new StringBuffer();
|
||||
|
||||
if (DriverSpy.DumpSqlMaxLineLength <= 0)
|
||||
{
|
||||
sqlOnlyLogger.info(sql);
|
||||
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 > 90)
|
||||
{
|
||||
output.append("\n");
|
||||
linelength = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DriverSpy.DumpSqlAddSemicolon)
|
||||
{
|
||||
output.append(";");
|
||||
}
|
||||
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,10 +298,8 @@ public class Slf4jSpyLogDelegator implements SpyLogDelegator
|
||||
*/
|
||||
public void sqlTimingOccured(Spy spy, long execTime, String methodCall, String sql)
|
||||
{
|
||||
// un-comment to simulate random delay to make testing easier
|
||||
//execTime = execTime + (long)(Math.random() * 5000);
|
||||
|
||||
if (sqlTimingLogger.isErrorEnabled())
|
||||
if (sqlTimingLogger.isErrorEnabled() &&
|
||||
(!DriverSpy.DumpSqlFilteringOn || shouldSqlBeLogged(sql)))
|
||||
{
|
||||
if (DriverSpy.SqlTimingErrorThresholdEnabled &&
|
||||
execTime >= DriverSpy.SqlTimingErrorThresholdMsec)
|
||||
@@ -268,6 +358,13 @@ public class Slf4jSpyLogDelegator implements SpyLogDelegator
|
||||
out.append(spy.getConnectionNumber());
|
||||
out.append(". ");
|
||||
}
|
||||
|
||||
// NOTE: if both sql dump and sql timing dump are on, the processSql
|
||||
// algorithm will run TWICE once at the beginning and once at the end
|
||||
// this is not very efficient but usually
|
||||
// only one or the other dump should be on and not both.
|
||||
|
||||
sql = processSql(sql);
|
||||
|
||||
out.append(sql);
|
||||
out.append(" {executed in ");
|
||||
@@ -292,39 +389,72 @@ public class Slf4jSpyLogDelegator implements SpyLogDelegator
|
||||
{
|
||||
Throwable t = new Throwable();
|
||||
t.fillInStackTrace();
|
||||
|
||||
StackTraceElement[] stackTrace = t.getStackTrace();
|
||||
|
||||
if (stackTrace != null)
|
||||
{
|
||||
int firstLog4jdbcCall = 0;
|
||||
int lastApplicationCall = 0;
|
||||
|
||||
String className;
|
||||
for (int i = 0; i < stackTrace.length; i++)
|
||||
|
||||
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 (DriverSpy.DumpFullDebugStackTrace)
|
||||
{
|
||||
className = stackTrace[i].getClassName();
|
||||
if (className.startsWith("net.sf.log4jdbc"))
|
||||
boolean first=true;
|
||||
for (int i = 0; i < stackTrace.length; i++)
|
||||
{
|
||||
firstLog4jdbcCall = i;
|
||||
}
|
||||
else if (DriverSpy.TraceFromApplication &&
|
||||
className.startsWith(DriverSpy.DebugStackPrefix))
|
||||
{
|
||||
lastApplicationCall = i;
|
||||
break;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringBuffer dump = new StringBuffer(" ");
|
||||
int j = lastApplicationCall;
|
||||
|
||||
if (j == 0) // if app not found, then use whoever was the last guy that called a log4jdbc class.
|
||||
else
|
||||
{
|
||||
j = 1 + firstLog4jdbcCall;
|
||||
}
|
||||
dump.append(" ");
|
||||
int firstLog4jdbcCall = 0;
|
||||
int lastApplicationCall = 0;
|
||||
|
||||
dump.append(stackTrace[j].getClassName()).append(".").append(stackTrace[j].getMethodName()).append("(").
|
||||
append(stackTrace[j].getFileName()).append(":").append(stackTrace[j].getLineNumber()).append(")");
|
||||
for (int i = 0; i < stackTrace.length; i++)
|
||||
{
|
||||
className = stackTrace[i].getClassName();
|
||||
if (className.startsWith("net.sf.log4jdbc"))
|
||||
{
|
||||
firstLog4jdbcCall = i;
|
||||
}
|
||||
else if (DriverSpy.TraceFromApplication &&
|
||||
className.startsWith(DriverSpy.DebugStackPrefix))
|
||||
{
|
||||
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();
|
||||
}
|
||||
@@ -343,5 +473,42 @@ public class Slf4jSpyLogDelegator implements SpyLogDelegator
|
||||
{
|
||||
debugLogger.debug(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever a new connection spy is created.
|
||||
*
|
||||
* @param spy ConnectionSpy that was created.
|
||||
*/
|
||||
public void connectionOpened(Spy spy)
|
||||
{
|
||||
if (connectionLogger.isDebugEnabled())
|
||||
{
|
||||
connectionLogger.info(spy.getConnectionNumber() + ". Connection opened " +
|
||||
getDebugInfo());
|
||||
connectionLogger.debug(ConnectionSpy.getOpenConnectionsDump());
|
||||
}
|
||||
else
|
||||
{
|
||||
connectionLogger.info(spy.getConnectionNumber() + ". Connection opened");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever a connection spy is closed.
|
||||
*
|
||||
* @param spy ConnectionSpy that was closed.
|
||||
*/
|
||||
public void connectionClosed(Spy spy)
|
||||
{
|
||||
if (connectionLogger.isDebugEnabled())
|
||||
{
|
||||
connectionLogger.info(spy.getConnectionNumber() + ". Connection closed " +
|
||||
getDebugInfo());
|
||||
connectionLogger.debug(ConnectionSpy.getOpenConnectionsDump());
|
||||
}
|
||||
else
|
||||
{
|
||||
connectionLogger.info(spy.getConnectionNumber() + ". Connection closed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,5 +39,5 @@ public interface Spy
|
||||
*
|
||||
* @return the connection instance number.
|
||||
*/
|
||||
public int getConnectionNumber();
|
||||
public Integer getConnectionNumber();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ package net.sf.log4jdbc;
|
||||
*/
|
||||
public interface SpyLogDelegator
|
||||
{
|
||||
|
||||
/**
|
||||
* Determine if any of the jdbc or sql loggers are turned on.
|
||||
*
|
||||
@@ -54,7 +53,6 @@ public interface SpyLogDelegator
|
||||
*/
|
||||
public void methodReturned(Spy spy, String methodCall, String returnMsg);
|
||||
|
||||
|
||||
/**
|
||||
* Called when a spied upon object is constructed.
|
||||
*
|
||||
@@ -82,6 +80,20 @@ public interface SpyLogDelegator
|
||||
*/
|
||||
public void sqlTimingOccured(Spy spy, long execTime, String methodCall, String sql);
|
||||
|
||||
/**
|
||||
* Called whenever a new connection spy is created.
|
||||
*
|
||||
* @param spy ConnectionSpy that was created.
|
||||
*/
|
||||
public void connectionOpened(Spy spy);
|
||||
|
||||
/**
|
||||
* Called whenever a connection spy is closed.
|
||||
*
|
||||
* @param spy ConnectionSpy that was closed.
|
||||
*/
|
||||
public void connectionClosed(Spy spy);
|
||||
|
||||
/**
|
||||
* Log a Setup and/or administrative log message for log4jdbc.
|
||||
*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user