mirror of
https://github.com/encounter/log4jdbc.git
synced 2026-03-30 11:27:21 -07:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 90608d8ff1 | |||
| 425148e118 | |||
| 328a6da56f | |||
| 8c6125a59c | |||
| 8ab139da54 | |||
| 41064c0bc4 | |||
| 2ca89b4f6e | |||
| 2a9d6066a3 | |||
| 6c83eba2ce | |||
| c051b6fd1d | |||
| a3b1bf73d0 | |||
| 904fab365a | |||
| b4217f92f0 | |||
| a44c5fb045 | |||
| a11ea79c4f | |||
| 18fcaa4ddd | |||
| 6bbd8c79be | |||
| e1555464ed | |||
| 317f0b1334 | |||
| 667d5d6f2d | |||
| b7c95c912a | |||
| f481af8396 | |||
| b92cd4f844 | |||
| 0f12fec9d4 | |||
| 366cdf9383 | |||
| 0f602d3040 | |||
| 79e7d62d51 |
Executable
+29
@@ -0,0 +1,29 @@
|
||||
2007-07-25 1.1 alpha 2 Release
|
||||
|
||||
o JDBC 4.0 support!
|
||||
|
||||
o fix Null pointer exception bug that could happen with setObject call on PreparedStatementSpy
|
||||
|
||||
o added MySQL (com.mysql.jdbc.Driver) and PostgreSQL (org.postgresql.Driver)
|
||||
to list of "well known" drivers that log4jdbc looks for at startup.
|
||||
|
||||
2007-05-29 1.1 alpha 1 Release
|
||||
|
||||
o Fixed problem where when sql timing log was the only log turned on, log4jdbc would not recognize that
|
||||
logging was on at all.
|
||||
|
||||
o report sql exceptions in the sql timing log as well (when they occured during sql execution) and
|
||||
prominently show that the sql FAILED, and display how long it tried to chug on the sql
|
||||
before the exception was thrown
|
||||
|
||||
o Switch to Simple Logging Facade for Java SLF4J instead of using log4j directly, so that any underlying
|
||||
logging system can be easily used.
|
||||
|
||||
o option added to ant build script to generate javadoc with ydoc to include UML diagrams within the javadoc.
|
||||
|
||||
o dump batched sql correctly.
|
||||
|
||||
o add simple command line program (PostLogProfilerProcessor) for processing sqltiming log files to create
|
||||
a simple profiling report from log data.
|
||||
|
||||
2007-04-21 Initial 1.0 Release
|
||||
+3
-130
@@ -1,132 +1,5 @@
|
||||
[this software is open source, released under the Apache License, Version 2.0: see LICENSE file]
|
||||
|
||||
log4jdbc Version 1.0
|
||||
Release Date: 2007-04-21
|
||||
=========================
|
||||
|
||||
log4jdbc is a JDBC driver that can log SQL and/or JDBC calls (and optionally SQL timing information)
|
||||
for other jdbc drivers using the log4j 1.2.x logging system.
|
||||
|
||||
Features:
|
||||
=========
|
||||
|
||||
* Easy to drop in and use in existing systems, because it's a standard jdbc driver.
|
||||
The only other requirement is to have the log4j 1.2.x jar and your jdbc driver for your
|
||||
database.
|
||||
|
||||
* Easy to configure, in most cases all you need to do is change the driver class name
|
||||
and prepend "jdbc:log4" to your existing jdbc url, set up your log4j categories and
|
||||
you're ready to go!
|
||||
|
||||
* In the logged output, for prepared statements, the bind arguments are automatically
|
||||
inserted into the SQL output. This greatly Improves readability and debugging for
|
||||
many cases.
|
||||
|
||||
* SQL timing information can be generated to help identify how long SQL statements take
|
||||
to run, helping to identify statements that are running too slowly.
|
||||
|
||||
* SQL connection number information is generated to help identify connection pooling or
|
||||
threading problems.
|
||||
|
||||
* Works with any JDBC 3.0 driver, JDK 1.4 and above, and log4j 1.2.x.
|
||||
|
||||
This jdbc driver can be "dropped in" to log the SQL and jdbc calls of another JDBC driver.
|
||||
|
||||
Usage:
|
||||
======
|
||||
|
||||
1. Set your jdbc driver class to net.sf.log4jdbc.DriverSpy
|
||||
|
||||
The underlying driver that is being spied on in many cases will be loaded automatically
|
||||
without any additional configuration.
|
||||
|
||||
The log4jdbc "spy" driver will try and load the following popular jdbc drivers:
|
||||
|
||||
oracle.jdbc.driver.OracleDriver (oracle)
|
||||
com.sybase.jdbc2.jdbc.SybDriver (sybase)
|
||||
net.sourceforge.jtds.jdbc.Driver (sourceforge ms sql server driver)
|
||||
com.microsoft.jdbc.sqlserver.SQLServerDriver (microsoft ms sql server driver)
|
||||
weblogic.jdbc.sqlserver.SQLServerDriver (weblogic ms sql server driver)
|
||||
com.informix.jdbc.IfxDriver (informix)
|
||||
org.apache.derby.jdbc.ClientDriver (apache derby client/server driver)
|
||||
org.apache.derby.jdbc.EmbeddedDriver (apache derby embedded driver)
|
||||
|
||||
If you want to use a different underlying jdbc driver that is not already in the above supported list,
|
||||
set a system property, log4jdbc.drivers to the class name of the additional driver. This
|
||||
can also be a comma separated list of driver class names.
|
||||
|
||||
(optional) -Dlog4jdbc.drivers=<driver>[,<driver>...] If your driver is not one of the common preloaded drivers.
|
||||
|
||||
2. Prepend "jdbc:log4" to the normal jdbc url that you are using.
|
||||
|
||||
For example, if your normal jdbc url is "jdbc:derby://localhost:1527//db-derby-10.2.2.0-bin/databases/MyDatabase"
|
||||
You would change it to: "jdbc:log4jdbc:derby://localhost:1527//db-derby-10.2.2.0-bin/databases/MyDatabase" to use the
|
||||
log4jdbc spy driver.
|
||||
|
||||
3. Make sure log4jdbc-1.0.jar and the log4j jar (v1.2x) are in the classpath, as well as the jar file(s) for the
|
||||
actual jdbc driver that is being spied upon.
|
||||
|
||||
Use the following command line options to initialize log4j:
|
||||
|
||||
(optional) -Dlog4j.debug
|
||||
-Dlog4j.configuration=log4j.xml (make sure that log4j.xml is also in the classpath).
|
||||
|
||||
or alternatively initialize the log4j system in code.
|
||||
|
||||
5. Set up your log4j logging categories. There are 4 categories that are used by log4jdbc,
|
||||
If all 4 loggers are set to the FATAL level, then log4jdbc will not log anything, and in fact the actual (real)
|
||||
connection to the underlying database will be returned by the driver (thus allowing log4jdbc to be installed and
|
||||
available without imposing any performance loss). If any of the 4 logs are set to ERROR or higher, then log4jdbc
|
||||
will be activated, wrapping and logging all activity in the jdbc connections returned by the driver.
|
||||
|
||||
|
||||
Each of these logs can be set at either DEBUG, INFO or ERROR
|
||||
DEBUG includes the class name and line number (if available) at which the sql was executed.
|
||||
INFO includes the sql (or other information as applicable)
|
||||
ERROR will show the stack traces in the log output when sql exceptions occur.
|
||||
|
||||
jdbc.sqlonly shows only SQL in the log. SQL executed within a prepared statement is automatically shown with
|
||||
it's bind arguments replaced with the data bound at that position, for greatly increased readability.
|
||||
|
||||
jdbc.sqltiming shows the SQL, post-execution, including timing statistics on how long the sql took to execute.
|
||||
|
||||
jdbc.audit Logs ALL jdbc calls except for ResultSets. This is a very voluminous output, and is not normally
|
||||
needed unless tracking down a specific jdbc problem.
|
||||
|
||||
jdbc.resultset Even more voluminous, because all calls to ResultSet objects are logged.
|
||||
|
||||
|
||||
Additionally, there is one logger named log4jdbc.debug which is for use with internal debugging of log4jdbc.
|
||||
At this time it just prints out information on which underlying drivers were found and not found when the
|
||||
spy driver loads.
|
||||
|
||||
In a typical usage scenario, you might turn on only the jdbc.sqlonly logging at INFO level,
|
||||
just to view the sql coming out of your program.
|
||||
|
||||
Then if you wanted to view how long each sql statement is taking to execute, you might use jdbc.sqltiming.
|
||||
|
||||
jdbc.audit and jdbc.resultset are used for more in depth diagnosis of what is going on under the hood with jdbc
|
||||
as potentially almost every single call to jdbc could be logged (logs can grow very large very quickly with this.)
|
||||
|
||||
See the sample files log4j.xml and log4j.properties for more information.
|
||||
|
||||
6. Adjust debugging options. When logging at the DEBUG level, the class file and line number (if available) for the
|
||||
class that invoked jdbc is logged after each log statement. This is enormously useful for finding where in the
|
||||
code the SQL is generated. Be careful when using this on a production system because there is a small, but
|
||||
potentially significant penalty performance for generating this data on each logging statement.
|
||||
|
||||
In many cases, this call stack data is not very useful because the calling class into log4jdbc is a connection pool,
|
||||
object-persistance layer or other layer between log4jdbc and your application code-- but the class file and
|
||||
line number information you really are interested in seeing is where in your application the SQL was generated from.
|
||||
|
||||
There are a couple of very useful system properties you can set for log4jdc to help get around this problem.
|
||||
|
||||
(optional) -Dlog4jdbc.debug.stack.prefix=<package.prefix> <-- a String that is the partial (or full) package
|
||||
prefix for the package name of your application. The call stack will be searched down to the first occurence
|
||||
of a class that has the matching prefix. If this is not set, the actual class that called into log4jdbc is used
|
||||
in the debug output (in many cases this will be a connection pool class)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Please see the main log4jdbc web page at http://log4jdbc.sourceforge.net for detailed features and usage information.
|
||||
There should also be in this folder, a copy of the main web page as it existed when this release was made.
|
||||
See index.html.
|
||||
@@ -0,0 +1,18 @@
|
||||
o what about jdbc 2 back support??
|
||||
|
||||
o configuration that doesn't rely on system properties (jdbc parms?)
|
||||
|
||||
o PostLogProfilerProcessor needs to be able to handle exceptions in log, & needs to be more efficient, also needs command
|
||||
line switches to control the thresholds & counts, etc.
|
||||
|
||||
o intelligent array dumper?
|
||||
|
||||
o check for more different kinds of JDBC drivers at startup time
|
||||
|
||||
o support for data sources
|
||||
|
||||
o ALL String concatenation & dumping methods should take place ONLY if logging is ON!!
|
||||
|
||||
o review dumpedSql method - make auto line breaking option (& num chars used) be options
|
||||
|
||||
o need log4jdbc.debug.stack.regex so that the stack matching can take place via regex
|
||||
+130
-57
@@ -13,37 +13,38 @@
|
||||
|
||||
<h1><a name="top"/><img class="logo" src="log4jdbc-logo-gray.png"><br>
|
||||
|
||||
<a href="http://sourceforge.net/project/showfiles.php?group_id=194500&package_id=229335&release_id=502834">download</a> |
|
||||
<a href="http://sourceforge.net/project/showfiles.php?group_id=194500">download</a> |
|
||||
<a href="#news">news</a> |
|
||||
<a href="#features">features</a> |
|
||||
<a href="#usage">usage</a> |
|
||||
<a href="apidocs/net/sf/log4jdbc/package-summary.html">javadoc</a> |
|
||||
<a href="#license">license</a> |
|
||||
<a href="#feedback">feedback</a>
|
||||
<br>
|
||||
<a href="apidocs-jdbc3/net/sf/log4jdbc/package-summary.html">javadoc(JDK1.4: JDBC 3)</a> |
|
||||
<a href="apidocs-jdbc4/net/sf/log4jdbc/package-summary.html">javadoc(JDK1.6: JDBC 4)</a>
|
||||
</h1>
|
||||
|
||||
<p>
|
||||
<b>log4jdbc</b> is a JDBC driver that can log SQL and/or JDBC calls (and optionally SQL timing information)
|
||||
for other jdbc drivers using the <a href="http://logging.apache.org/log4j/docs/">log4j</a> 1.2.x logging system.
|
||||
for other jdbc drivers using the <a target="slf4j" href="http://www.slf4j.org/">Simple Logging Facade For Java</a> (SLF4J) logging system.
|
||||
</p>
|
||||
|
||||
|
||||
<h2><a name="news"/>news</h2>
|
||||
<p class="left"><b>2007-04-21:</b> log4jdbc 1.0 has been released! <a href="http://sourceforge.net/project/showfiles.php?group_id=194500&package_id=229335&release_id=502834">Download it</a> and give it a try!</p>
|
||||
<p class="left"><b>2007-07-25:</b> <a href="http://sourceforge.net/forum/forum.php?forum_id=719640">log4jdbc 1.1 alpha 2 released.</a> JDBC 4 support! See <a href="CHANGES">CHANGES</a> for all the release details.</p>
|
||||
<p class="left"><b>2007-05-29:</b> <a href="http://sourceforge.net/forum/forum.php?forum_id=700185">log4jdbc 1.1 alpha 1 released.</a> Most notable change is that the <a target="slf4j" href="http://slf4j.org">Simple Logging Facade for Java</a> is now used instead of <b>log4j</b> directly.
|
||||
<p class="left"><b>2007-04-21:</b> <a href="http://sourceforge.net/forum/forum.php?forum_id=688372">log4jdbc 1.0 has been released!</a> Download it and give it a try!</p>
|
||||
|
||||
<p class="right"><a href="#top">[back to top]</a></p>
|
||||
<h2><a name="features"/>features</h2>
|
||||
|
||||
<ul class="left">
|
||||
<li>
|
||||
Easy to drop in and use in existing systems, because it's a standard jdbc driver.
|
||||
The only other requirement is to have the log4j 1.2.x jar and your jdbc driver for your
|
||||
database.
|
||||
Full support for JDBC 3 and JDBC 4!
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Easy to configure, in most cases all you need to do is change the driver class name
|
||||
and prepend "jdbc:log4" to your existing jdbc url, set up your log4j categories and
|
||||
and prepend <b>"jdbc:log4"</b> to your existing jdbc url, set up your logging categories and
|
||||
you're ready to go!
|
||||
</li>
|
||||
|
||||
@@ -55,7 +56,9 @@ for other jdbc drivers using the <a href="http://logging.apache.org/log4j/docs/"
|
||||
|
||||
<li>
|
||||
SQL timing information can be generated to help identify how long SQL statements take
|
||||
to run, helping to identify statements that are running too slowly.
|
||||
to run, helping to identify statements that are running too slowly and this data can
|
||||
be post processed with an included tool to produce profiling report data for quickly
|
||||
identifying slow SQL in your application..
|
||||
</li>
|
||||
|
||||
<li>
|
||||
@@ -64,20 +67,72 @@ for other jdbc drivers using the <a href="http://logging.apache.org/log4j/docs/"
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Works with any JDBC 3.0 driver, JDK 1.4 and above, and log4j 1.2.x.
|
||||
Works with any underlying JDBC driver, with JDK 1.4 and above, and SLF4J 1.x.
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<p>
|
||||
This jdbc driver can be "dropped in" to log the SQL and jdbc calls of another JDBC driver.
|
||||
</p>
|
||||
|
||||
<p class="right"><a href="#top">[back to top]</a></p>
|
||||
<h2><a name="usage"/>usage</h2>
|
||||
|
||||
<ol class="left">
|
||||
|
||||
<li><p> Set your jdbc driver class to <code>net.sf.log4jdbc.DriverSpy</code> </p>
|
||||
<li><p> Decide if you need JDBC 3 or JDBC 4 support. The most straightforward way to decide this is:</p>
|
||||
<ul>
|
||||
<li>If you are using JDK 1.4 or 1.5, you should use the JDBC 3 version of log4jdbc.</li>
|
||||
<li>If you are using JDK 1.6 or 1.7, you should use the JDBC 4 version of log4jdbc (even if the actual underlying JDBC driver you are using is a JDBC 3 or older driver).</li>
|
||||
</ul>
|
||||
<p>
|
||||
Currently there are very few actual JDBC 4 drivers on the market. (The only major one that I really know about is Apache Derby aka The Java DB distributed with JDK 1.6.)
|
||||
JDBC 4 support was added with the JDK 1.6 release and adds many additional features over and above JDBC 3.
|
||||
However, the log4jdbc JDBC 4.0 driver can wrap a JDBC 3 or older driver and
|
||||
it's recommended that if you use JDK 1.6 or above, that you use the log4jdbc JDBC 4 driver that is compiled with JDK 1.6.
|
||||
</p>
|
||||
<p>
|
||||
Note that JDBC 2 is not currently supported by log4jdbc (there is an older unreleased version of log4jdbc with JDBC 2 support,
|
||||
but I decided not to release it because JDBC 3 has been out for so long, I don't anticipate much demand for a JDBC 2 version of
|
||||
log4jdbc at this point), although if you are using JDK 1.4 and above, the log4jdbc 3.0 or 4.0 driver
|
||||
should be able to wrap an older JDBC 2 driver as well-- log4jdbc just won't work with Java 1.3 and earlier.
|
||||
Please <a href="#feedback">email me</a> if you really really want a JDBC 2 version of log4jdbc. If there is enough demand, I may resurrect it.
|
||||
</p>
|
||||
</p>
|
||||
<pre>
|
||||
|
||||
Choose and <a href="http://sourceforge.net/project/showfiles.php?group_id=194500&package_id=229335&release_id=527690">download</a> one of the drivers .jar files:
|
||||
|
||||
log4jdbc3-1.1alpha2.jar JDBC 3 support for JDK 1.4 , JDK 1.5
|
||||
log4jdbc4-1.1alpha2.jar JDBC 4 support for JDK 1.6 , JDK 1.7
|
||||
|
||||
Place the log4jdbc jar that you choose into your application's classpath.
|
||||
</pre>
|
||||
|
||||
<li><p>Choose which java logging system you will use. </p>
|
||||
In many cases, you already know this, because it is dictated by your existing application.
|
||||
log4jdbc uses the Simple Logging Facade for Java (SLF4J) which is a very simple and very flexible little library that lets you pick among many common java logging systems:</p>
|
||||
<ul>
|
||||
<li>Log4j</li>
|
||||
<li>java.util logging in JDK 1.4</li>
|
||||
<li>logback</li>
|
||||
<li>Jakarta Commons Logging</li>
|
||||
</ul>
|
||||
|
||||
<p> SLF4J is designed to de-couple your application from the java logging system so you can choose any one you want. This is the same goal of Jakarta Commons Logging. However many people have
|
||||
had headaches and issues with classloading problems in complex environments using Jakarta Commons Logging. SLF4J solves these problems with it's much simpler design, and you can even integrate
|
||||
SLF4J to use Jakarta Commons Logging, if you really want to (or are required to) use it.</p>
|
||||
<pre>
|
||||
|
||||
<a href="http://www.slf4j.org/download.html">Download</a> the latest official SLF4J release.
|
||||
|
||||
You will need two jars:
|
||||
|
||||
slf4j-api-1.4.2.jar (or the latest available version) and
|
||||
whichever jar you pick depending on the java logging system you choose
|
||||
|
||||
Place these two .jar files into your application's classpath.
|
||||
</pre>
|
||||
|
||||
Please read the documentation at the <a target="slf4j" href="http://slf4j.org">SLF4J website</a>. It's really easy to set up!
|
||||
|
||||
</a>
|
||||
<li><p>Set your jdbc driver class to <code>net.sf.log4jdbc.DriverSpy</code> in your application's configuration.</p>
|
||||
<p>
|
||||
The underlying driver that is being spied on in many cases will be loaded automatically
|
||||
without any additional configuration.
|
||||
@@ -85,21 +140,23 @@ This jdbc driver can be "dropped in" to log the SQL and jdbc calls of another JD
|
||||
<p>
|
||||
The log4jdbc "spy" driver will try and load the following popular jdbc drivers:
|
||||
</p>
|
||||
<pre>
|
||||
<pre>
|
||||
|
||||
oracle.jdbc.driver.OracleDriver (oracle)
|
||||
com.sybase.jdbc2.jdbc.SybDriver (sybase)
|
||||
net.sourceforge.jtds.jdbc.Driver (sourceforge ms sql server driver)
|
||||
com.microsoft.jdbc.sqlserver.SQLServerDriver (microsoft ms sql server driver)
|
||||
weblogic.jdbc.sqlserver.SQLServerDriver (weblogic ms sql server driver)
|
||||
com.informix.jdbc.IfxDriver (informix)
|
||||
org.apache.derby.jdbc.ClientDriver (apache derby client/server driver)
|
||||
org.apache.derby.jdbc.EmbeddedDriver (apache derby embedded driver)
|
||||
oracle.jdbc.driver.OracleDriver (Oracle)
|
||||
com.sybase.jdbc2.jdbc.SybDriver (Sybase)
|
||||
net.sourceforge.jtds.jdbc.Driver (SourceForge SQL Server driver)
|
||||
com.microsoft.jdbc.sqlserver.SQLServerDriver (Microsoft SQL Server driver)
|
||||
weblogic.jdbc.sqlserver.SQLServerDriver (Weblogic SQL Server driver)
|
||||
com.informix.jdbc.IfxDriver (Informix)
|
||||
org.apache.derby.jdbc.ClientDriver (Apache Derby client/server driver)
|
||||
org.apache.derby.jdbc.EmbeddedDriver (Apache Derby embedded driver)
|
||||
com.mysql.jdbc.Driver (MySQL)
|
||||
org.postgresql.Driver (PostgresSQL)
|
||||
</pre>
|
||||
<p>
|
||||
If you want to use a different underlying jdbc driver that is not already in the above supported list,
|
||||
set a system property, log4jdbc.drivers to the class name of the additional driver. This
|
||||
can also be a comma separated list of driver class names.
|
||||
set a system property, <b>log4jdbc.drivers</b> to the class name of the additional driver. This
|
||||
can also be a comma separated list of driver class names if you need more than one.
|
||||
</p>
|
||||
<p>
|
||||
(optional) <code>-Dlog4jdbc.drivers=<driver>[,<driver>...]</code> If your driver is not one of the common preloaded drivers.
|
||||
@@ -107,27 +164,20 @@ This jdbc driver can be "dropped in" to log the SQL and jdbc calls of another JD
|
||||
</li>
|
||||
<li><p> Prepend <code>jdbc:log4</code> to the normal jdbc url that you are using.</p>
|
||||
|
||||
<p>For example, if your normal jdbc url is <code>jdbc:derby://localhost:1527//db-derby-10.2.2.0-bin/databases/MyDatabase</code>
|
||||
You would change it to: <code>jdbc:log4jdbc:derby://localhost:1527//db-derby-10.2.2.0-bin/databases/MyDatabase</code> to use the
|
||||
log4jdbc spy driver.</p>
|
||||
</li>
|
||||
<li><p>Make sure <span class="file">log4jdbc-1.0.jar</span> and the <span class="file">log4j jar</span> (v1.2x) are in
|
||||
the classpath, as well as the jar file(s) for the actual jdbc driver that is being spied upon.</p>
|
||||
<p>
|
||||
Use the following command line options to initialize log4j:
|
||||
</p>
|
||||
<pre>
|
||||
<p>For example, if your normal jdbc url is</p>
|
||||
|
||||
(optional) -Dlog4j.debug
|
||||
-Dlog4j.configuration=log4j.xml (make sure that log4j.xml is also in the classpath).
|
||||
</pre>
|
||||
<p>or alternatively initialize the log4j system in code. </p>
|
||||
<p><code>jdbc:derby://localhost:1527//db-derby-10.2.2.0-bin/databases/MyDatabase</code></p>
|
||||
<p>then You would change it to: </p>
|
||||
<p><code><b>jdbc:log4</b>jdbc:derby://localhost:1527//db-derby-10.2.2.0-bin/databases/MyDatabase</code></p>
|
||||
<p>to use <b>log4jdbc.</b></p>
|
||||
</li>
|
||||
<li> <p> Set up your log4j logging categories. There are 4 categories that are used by log4jdbc,
|
||||
If all 4 loggers are set to the FATAL level, then log4jdbc will not log anything, and in fact the actual (real)
|
||||
connection to the underlying database will be returned by the driver (thus allowing log4jdbc to be installed and
|
||||
available without imposing any performance loss). If any of the 4 logs are set to ERROR or higher, then log4jdbc
|
||||
will be activated, wrapping and logging all activity in the jdbc connections returned by the driver.</p>
|
||||
<li> <p> Set up your logging categories. There are 4 categories that are used by log4jdbc,
|
||||
If all 4 loggers are set to a level less than error (such as the FATAL level), then log4jdbc will not log
|
||||
anything, and in fact the actual (real) connection to the underlying database will be returned by the log4jdbc
|
||||
driver (thus allowing log4jdbc to be installed and available to turn on at runtime at a moment's notice,
|
||||
without imposing any actual performance loss when not being used). If any of the 4 logs are set to ERROR,INFO or
|
||||
DEBUG, then log4jdbc will be activated, wrapping and logging all activity in the jdbc connections returned by the
|
||||
underlying driver.</p>
|
||||
<pre>
|
||||
|
||||
Each of these logs can be set at either DEBUG, INFO or ERROR
|
||||
@@ -146,9 +196,9 @@ This jdbc driver can be "dropped in" to log the SQL and jdbc calls of another JD
|
||||
jdbc.resultset Even more voluminous, because all calls to ResultSet objects are logged.
|
||||
</pre>
|
||||
|
||||
<p>Additionally, there is one logger named log4jdbc.debug which is for use with internal debugging of log4jdbc.
|
||||
<p>Additionally, there is one logger named <b>log4jdbc.debug</b> which is for use with internal debugging of log4jdbc.
|
||||
At this time it just prints out information on which underlying drivers were found and not found when the
|
||||
spy driver loads.</p>
|
||||
log4jdbc spy driver loads.</p>
|
||||
|
||||
<p>In a typical usage scenario, you might turn on only the jdbc.sqlonly logging at INFO level,
|
||||
just to view the sql coming out of your program.</p>
|
||||
@@ -156,9 +206,11 @@ This jdbc driver can be "dropped in" to log the SQL and jdbc calls of another JD
|
||||
<p>Then if you wanted to view how long each sql statement is taking to execute, you might use jdbc.sqltiming.</p>
|
||||
|
||||
<p>jdbc.audit and jdbc.resultset are used for more in depth diagnosis of what is going on under the hood with jdbc
|
||||
as potentially almost every single call to jdbc could be logged (logs can grow very large very quickly with this.)</p>
|
||||
as potentially almost every single call to jdbc could be logged (logs can grow very large, very quickly with this!)</p>
|
||||
|
||||
<p>See the sample files <a href="log4j.xml">log4j.xml</a> and <a href="log4j.properties">log4j.properties</a> for more information.</p>
|
||||
<p>SLF4J is a logging facade that can be used with many popular java logging systems. The setup for the logging
|
||||
categories will vary depending on which underlying logger you use. Sample configuration files for log4j are
|
||||
provided here: <a href="log4j.xml">log4j.xml</a> and <a href="log4j.properties">log4j.properties</a>.</p>
|
||||
</li>
|
||||
<li><p>Adjust debugging options. When logging at the DEBUG level, the class file and line number (if available) for the
|
||||
class that invoked jdbc is logged after each log statement. This is enormously useful for finding where in the
|
||||
@@ -169,13 +221,27 @@ This jdbc driver can be "dropped in" to log the SQL and jdbc calls of another JD
|
||||
object-persistance layer or other layer between log4jdbc and your application code-- but the class file and
|
||||
line number information you really are interested in seeing is where in your application the SQL was generated from.</p>
|
||||
|
||||
<p>There are a couple of very useful system properties you can set for log4jdc to help get around this problem.</p>
|
||||
<p>Set the <code>log4jdbc.debug.stack.prefix</code> System property for log4jdc to help get around this problem:</p>
|
||||
|
||||
<p>
|
||||
(optional) <code>-Dlog4jdbc.debug.stack.prefix=<package.prefix></code> a String that is the partial (or full) package
|
||||
prefix for the package name of your application. The call stack will be searched down to the first occurence
|
||||
of a class that has the matching prefix. If this is not set, the actual class that called into log4jdbc is used
|
||||
in the debug output (in many cases this will be a connection pool class)</p>
|
||||
<p>
|
||||
For example, setting a system property such as this: <code>-Dlog4jdbc.debug.stack.prefix=com.mycompany.myapp</code>
|
||||
Would cause the call stack to be searched for the first call that came from code in the com.mycompany.myapp package or below,
|
||||
thus if all of your sql generating code was in code located in the com.mycompany.myapp package or any subpackages,
|
||||
this would be printed in the debug information, rather than the package name for a connection pool, object relational system, etc.
|
||||
</p>
|
||||
</li>
|
||||
<li>Starting with the 1.1 alpha 1 release, a new tool was included which you can use to post-process sql timing logs produced by log4jdbc
|
||||
to produce simple profiling reports with statistics and a dump of the sql statements that ran the slowest within the log.
|
||||
To invoke the tool, use the profsql.sh (for unix/linux) and profsql.cmd (for windows) scripts located in the scripts
|
||||
folder. These scripts take as one argument, the filename of a sql timing log (generated from the
|
||||
<code>jdbc.sqltiming</code> log category. They produce a profiling report to stdout.
|
||||
At this point the tool is experimental and I expect it to evolve quite a bit over the next few releases.
|
||||
Nevertheless, it has already been very useful to me for tracking down SQL performance problems.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
@@ -194,19 +260,26 @@ log4jdbc is open source software, licensed under the <b>Apache 2.0 license:</b>
|
||||
<p class="right"><a href="#top">[back to top]</a></p>
|
||||
<h1>
|
||||
|
||||
<a href="http://sourceforge.net/project/showfiles.php?group_id=194500&package_id=229335&release_id=502834">download</a> |
|
||||
<a href="http://sourceforge.net/project/showfiles.php?group_id=194500">download</a> |
|
||||
<a href="#news">news</a> |
|
||||
<a href="#features">features</a> |
|
||||
<a href="#usage">usage</a> |
|
||||
<a href="apidocs/net/sf/log4jdbc/package-summary.html">javadoc</a> |
|
||||
<a href="#license">license</a> |
|
||||
<a href="#feedback">feedback</a>
|
||||
<br>
|
||||
|
||||
<a href="apidocs-jdbc3/net/sf/log4jdbc/package-summary.html">javadoc(JDK1.4: JDBC 3)</a> |
|
||||
<a href="apidocs-jdbc4/net/sf/log4jdbc/package-summary.html">javadoc(JDK1.6: JDBC 4)</a>
|
||||
<br>
|
||||
<img class="logo" src="log4jdbc-logo-gray.png">
|
||||
|
||||
</h1>
|
||||
|
||||
|
||||
<p class="ad">
|
||||
YourKit is kindly supporting open source projects with its full-featured Java Profiler.
|
||||
YourKit, LLC is creator of innovative and intelligent tools for profiling
|
||||
Java and .NET applications. Take a look at YourKit's leading software products:
|
||||
<a href="http://www.yourkit.com/java/profiler/index.jsp">YourKit Java Profiler</a> and
|
||||
<a href="http://www.yourkit.com/.net/profiler/index.jsp">YourKit .NET Profiler</a>.
|
||||
</p>
|
||||
<a href="http://sourceforge.net/projects/log4jdbc/"><img alt="sourceforge" title="log4jdbc sourceforge page" class="sflogo" src="sourceforge_whitebg.gif"></a>
|
||||
</body>
|
||||
</html>
|
||||
+5
-1
@@ -23,4 +23,8 @@ li p {margin-left:0;}
|
||||
|
||||
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;}
|
||||
pre {border:2px dashed navy;margin-left:3em;margin-right:4em;margin-top:1em;margin-bottom:1em;white-space:pre-line;}
|
||||
|
||||
p.ad {font-size:1em;color:blue;}
|
||||
|
||||
.sflogo {float:right; margin-right:30px;}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,18 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
rem this is a bit convoluted because two jdk's must be invoked...
|
||||
|
||||
set ANT_HOME=c:\apache-ant-1.6.5
|
||||
|
||||
set JAVA_HOME=C:\j2sdk1.4.2_13
|
||||
set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin
|
||||
call java -version
|
||||
|
||||
call ant -Djdbc.level=3 all
|
||||
|
||||
set JAVA_HOME=c:\jdk1.6.0
|
||||
set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin
|
||||
call java -version
|
||||
|
||||
call ant -Djdbc.level=4 all
|
||||
+178
-16
@@ -1,18 +1,60 @@
|
||||
<?xml version='1.0' encoding='ISO-8859-1' ?>
|
||||
|
||||
<!--
|
||||
Very basic ant build script.
|
||||
tested with Apache Ant version 1.6.5
|
||||
Ant build script for log4jdbc
|
||||
|
||||
Tested with Apache Ant version 1.6.5 & 1.7
|
||||
|
||||
built with jdk 1.4.2_13 (for use with jdbc3)
|
||||
and/or jdk 1.6.0 (for use with jdbc4)
|
||||
-->
|
||||
|
||||
<project name="log4jdbc" default="all" basedir="..">
|
||||
|
||||
<!-- the jdbc.level flag should be set externally to either 3 or 4
|
||||
|
||||
the is the jdbc version and should be 3 if using a jdk 1.4 (or 1.5) (1.4 is recommended for maximum compatibility)
|
||||
|
||||
the jdbc.level flag should be set to 4 if using a jdk 1.6 or greater.
|
||||
|
||||
defaults to jdbc3 build if not set externally
|
||||
-->
|
||||
|
||||
<property name="jdbc.level" value="3" />
|
||||
<property name="jdbc.prefix" value="jdbc${jdbc.level}" />
|
||||
|
||||
<property name="src" value="src-${jdbc.prefix}" />
|
||||
<property name="classes" value="classes-${jdbc.prefix}" />
|
||||
<property name="apidocs" value="doc/apidocs-${jdbc.prefix}" />
|
||||
|
||||
|
||||
<!-- release version -->
|
||||
<property name="version" value="1.1alpha2"/>
|
||||
|
||||
<target name="all" depends="cleancompile,compile,cleanjar,jar"/>
|
||||
|
||||
<property name="version" value="1.0"/>
|
||||
<!--
|
||||
note that if jdbc.level is 3, a jdk 1.4 compiler should be used to build log4jdbc
|
||||
and if the jdbc.level is 4, a jdk 1.6 compiler should be used to build log4jdbc
|
||||
therefore to build both, ant should be invoked twice, setting the jdbc.level externally
|
||||
to 3 and then 4. and using the jdk 1.4 and then 1.6.
|
||||
|
||||
jdbc.level is explicitly set here to xxx so that the user is forced to set it externally.
|
||||
-->
|
||||
|
||||
<!-- ydoc.home.X is only used for the ydoc.X targets for producing javadoc with UML
|
||||
|
||||
it requires the commercial ydoc utility (see http://www.yworks.com/en/products_ydoc.htm)
|
||||
(use the javadoc target to generate regular javadoc)
|
||||
|
||||
ydoc.home.3 is for jdk1.4 / JDBC 3
|
||||
ydoc.home.4 is for jdk1.6 / JDBC 4
|
||||
-->
|
||||
<property name="ydoc.home.3" value="/ydoc-2.2_04"/>
|
||||
<property name="ydoc.home.4" value="/ydoc-2.2_04-jdk1.5"/>
|
||||
|
||||
<target name="compile" description="compile all the source code">
|
||||
<javac srcdir="src" destdir="classes" deprecation="true" debug="true">
|
||||
<javac srcdir="${src}" destdir="${classes}" deprecation="true" debug="true">
|
||||
<classpath>
|
||||
<pathelement location="$src"/>
|
||||
<fileset dir="lib">
|
||||
@@ -23,25 +65,50 @@
|
||||
</target>
|
||||
|
||||
<target name="cleancompile" description="delete all the .class files.">
|
||||
<delete dir="classes"/>
|
||||
<mkdir dir="classes"/>
|
||||
<delete dir="${classes}"/>
|
||||
<mkdir dir="${classes}"/>
|
||||
</target>
|
||||
|
||||
<target name="jar" description="jar up all the class files">
|
||||
<mkdir dir="build"/>
|
||||
<jar jarfile="build/log4jdbc-${version}.jar" basedir="classes"/>
|
||||
<jar jarfile="build/log4${jdbc.prefix}-${version}.jar" basedir="${classes}"/>
|
||||
</target>
|
||||
|
||||
<target name="cleanjar" description="delete the jar file">
|
||||
<delete file="build/log4jdbc-${version}.jar" description="delete the jar file"/>
|
||||
<delete file="build/log4${jdbc.prefix}-${version}.jar" description="delete the jar file"/>
|
||||
</target>
|
||||
|
||||
<target name="javadoc" description="generate the javadoc" >
|
||||
<delete dir="doc/apidocs" />
|
||||
<mkdir dir="doc/apidocs" />
|
||||
<javadoc destdir="doc/apidocs" packagenames="net.sf.log4jdbc.*"
|
||||
Windowtitle="log4jdbc ${version}"
|
||||
Header="<b><a href="http://log4jdbc.sourceforge.net">log4jdbc ${version}</a></b>"
|
||||
|
||||
<target name="cleanjavadoc">
|
||||
<delete dir="${apidocs}" />
|
||||
<mkdir dir="${apidocs}" />
|
||||
</target>
|
||||
|
||||
<target name="cleanrelease">
|
||||
<delete file="../log4jdbc-${version}.zip"/>
|
||||
<delete file="../log4jdbc-${version}.tar"/>
|
||||
<delete file="../log4jdbc-${version}.tar.gz"/>
|
||||
</target>
|
||||
|
||||
<target name="release" depends="cleanrelease" description="make a complete release distribution (a .jar zip and tar.gz file for release)">
|
||||
<zip destfile="../log4jdbc-${version}.zip">
|
||||
<zipfileset dir="." prefix="log4jdbc-${version}" excludes="*.zip,*.tar.gz,*,iml,*.ipr,*.iws,thirdparty-stuff/**,classes*/**"/>
|
||||
</zip>
|
||||
<tar destfile="../log4jdbc-${version}.tar">
|
||||
<tarfileset dir="." prefix="log4jdbc-${version}" excludes="*.zip,*.tar.gz,*,iml,*.ipr,*.iws,thirdparty-stuff/**,classes*/**"/>
|
||||
</tar>
|
||||
<gzip destfile="../log4jdbc-${version}.tar.gz" src="../log4jdbc-${version}.tar"/>
|
||||
<delete file="../log4jdbc-${version}.tar"/>
|
||||
</target>
|
||||
|
||||
<!-- make the javadoc (or ydoc which includes UML diagrams) -->
|
||||
|
||||
<target name="javadoc" description="generate the javadoc" depends="cleanjavadoc">
|
||||
<delete dir="${apidocs}" />
|
||||
<mkdir dir="${apidocs}" />
|
||||
<javadoc destdir="${apidocs}" packagenames="net.sf.log4jdbc.*"
|
||||
Windowtitle="log4${jdbc.prefix} ${version}"
|
||||
Header="<b><a href="http://log4jdbc.sourceforge.net">log4${jdbc.prefix} ${version}</a></b>"
|
||||
Use="true" breakiterator="true">
|
||||
<classpath>
|
||||
<pathelement location="$src"/>
|
||||
@@ -49,15 +116,110 @@
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
</classpath>
|
||||
<sourcepath path="src"/>
|
||||
<sourcepath path="${src}"/>
|
||||
|
||||
<!-- 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="/j2sdk1.4.2_13/src"/>
|
||||
<link href="http://java.sun.com/j2se/1.4.2/docs/api/"/>
|
||||
<link href="http://java.sun.com/j2ee/1.4/docs/api/"/>
|
||||
<link href="http://logging.apache.org/log4j/docs/api/"/>
|
||||
<link href="http://www.slf4j.org/api/"/>
|
||||
-->
|
||||
</javadoc>
|
||||
</target>
|
||||
|
||||
<target name="ydoc.3" description="(jdk1.4/JDBC3 version) create javadoc using ydoc doclet to include UML diagrams" depends="cleanjavadoc">
|
||||
|
||||
<property name="ps" value="${path.separator}" />
|
||||
|
||||
<javadoc destdir="${apidocs}" packagenames="net.sf.log4jdbc.*"
|
||||
Windowtitle="log4${jdbc.prefix} ${version}"
|
||||
Header="<b><a href="http://log4jdbc.sourceforge.net">log4${jdbc.prefix} ${version}</a></b>"
|
||||
Use="true" breakiterator="true">
|
||||
<classpath>
|
||||
<pathelement location="$src"/>
|
||||
<fileset dir="lib">
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
</classpath>
|
||||
<sourcepath path="${src}"/>
|
||||
|
||||
<!-- 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="/j2sdk1.4.2_13/src"/>
|
||||
<link href="http://java.sun.com/j2se/1.4.2/docs/api/"/>
|
||||
<!--
|
||||
<link href="http://java.sun.com/j2ee/1.4/docs/api/"/>
|
||||
-->
|
||||
<link href="http://www.slf4j.org/api/"/>
|
||||
|
||||
<!-- ydoc doclet for UML diagrams, see http://www.yworks.com/en/products_ydoc.htm -->
|
||||
<doclet name="ydoc.doclets.YStandard"
|
||||
path="${ydoc.home.3}/lib/ydoc.jar${ps}${ydoc.home.3}/lib/class2svg.jar${ps}${ydoc.home.3}/resources${ps}${ydoc.home.3}/doc${ps}./${classes}">
|
||||
<param name="-author"/>
|
||||
<param name="-generic"/>
|
||||
<param name="-umlautogen"/>
|
||||
<param name="-filterpath" value="${ydoc.home.3}/lib/ydoc.jar"/>
|
||||
<param name="-filter" value="ydoc.filters.ExcludeFilter"/>
|
||||
<param name="-tag" value="y.precondition"/>
|
||||
<param name="-tag" value="y.postcondition"/>
|
||||
<param name="-tag" value="y.complexity"/>
|
||||
<param name="-tag" value="param"/>
|
||||
<param name="-tag" value="return"/>
|
||||
<param name="-tag" value="see"/>
|
||||
<param name="-tag" value="y.uml"/>
|
||||
<param name="-linksource" value="true"/>
|
||||
</doclet>
|
||||
</javadoc>
|
||||
</target>
|
||||
|
||||
<target name="ydoc.4" description="(jdk1.6/JDBC4 version) create javadoc using ydoc doclet to include UML diagrams" depends="cleanjavadoc">
|
||||
|
||||
<property name="ps" value="${path.separator}"/>
|
||||
|
||||
<javadoc destdir="${apidocs}" packagenames="net.sf.log4jdbc.*"
|
||||
Windowtitle="log4${jdbc.prefix} ${version}"
|
||||
Header="<b><a href="http://log4jdbc.sourceforge.net">log4${jdbc.prefix} ${version}</a></b>"
|
||||
Use="true" breakiterator="true">
|
||||
<classpath>
|
||||
<pathelement location="$src"/>
|
||||
<fileset dir="lib">
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
</classpath>
|
||||
<sourcepath path="${src}"/>
|
||||
|
||||
<!-- 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/src"/>
|
||||
<link href="http://java.sun.com/javase/6/docs/api/"/>
|
||||
<!--
|
||||
<link href="http://java.sun.com/j2ee/1.4/docs/api/"/>
|
||||
-->
|
||||
<link href="http://www.slf4j.org/api/"/>
|
||||
|
||||
<!-- ydoc doclet for UML diagrams, see http://www.yworks.com/en/products_ydoc.htm -->
|
||||
<doclet name="ydoc.doclets.YStandard"
|
||||
path="${ydoc.home.4}/lib/ydoc.jar${ps}${ydoc.home.4}/lib/class2svg.jar${ps}${ydoc.home.4}/resources${ps}${ydoc.home.4}/doc${ps}./${classes}">
|
||||
<param name="-author"/>
|
||||
<param name="-generic"/>
|
||||
<param name="-umlautogen"/>
|
||||
<param name="-filterpath" value="${ydoc.home.4}/lib/ydoc.jar"/>
|
||||
<param name="-filter" value="ydoc.filters.ExcludeFilter"/>
|
||||
<param name="-tag" value="y.precondition"/>
|
||||
<param name="-tag" value="y.postcondition"/>
|
||||
<param name="-tag" value="y.complexity"/>
|
||||
<param name="-tag" value="param"/>
|
||||
<param name="-tag" value="return"/>
|
||||
<param name="-tag" value="see"/>
|
||||
<param name="-tag" value="y.uml"/>
|
||||
<param name="-linksource" value="true"/>
|
||||
</doclet>
|
||||
</javadoc>
|
||||
</target>
|
||||
|
||||
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
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 JAVA_HOME=C:\j2sdk1.4.2_13
|
||||
set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin
|
||||
call java -version
|
||||
|
||||
call ant -Djdbc.level=3 ydoc.3
|
||||
|
||||
set JAVA_HOME=c:\jdk1.6.0
|
||||
set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin
|
||||
call java -version
|
||||
|
||||
call ant -Djdbc.level=4 ydoc.4
|
||||
@@ -0,0 +1,28 @@
|
||||
@echo off
|
||||
|
||||
rem *************************************************************************************************
|
||||
rem * *
|
||||
rem * Copyright 2007 Arthur Blake *
|
||||
rem * *
|
||||
rem * Licensed under the Apache License, Version 2.0 (the "License"); *
|
||||
rem * you may not use this file except in compliance with the License. *
|
||||
rem * You may obtain a copy of the License at *
|
||||
rem * *
|
||||
rem * http://www.apache.org/licenses/LICENSE-2.0 *
|
||||
rem * *
|
||||
rem * Unless required by applicable law or agreed to in writing, software *
|
||||
rem * distributed under the License is distributed on an "AS IS" BASIS, *
|
||||
rem * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
|
||||
rem * See the License for the specific language governing permissions and *
|
||||
rem * limitations under the License. *
|
||||
rem * *
|
||||
rem *************************************************************************************************
|
||||
|
||||
rem *************************************************************************************************
|
||||
rem * *
|
||||
rem * Invoke the PostLogProfilerProcessor to process sqltiming log information into a simple *
|
||||
rem * profiling output report. *
|
||||
rem * *
|
||||
rem *************************************************************************************************
|
||||
|
||||
java -Xmx1024m -classpath ..\build\log4jdbc-1.1alpha1.jar net.sf.log4jdbc.PostLogProfilerProcessor %*
|
||||
@@ -0,0 +1,28 @@
|
||||
#! /bin/sh
|
||||
|
||||
# *************************************************************************************************
|
||||
# * *
|
||||
# * Copyright 2007 Arthur Blake *
|
||||
# * *
|
||||
# * Licensed under the Apache License, Version 2.0 (the "License"); *
|
||||
# * you may not use this file except in compliance with the License. *
|
||||
# * You may obtain a copy of the License at *
|
||||
# * *
|
||||
# * http://www.apache.org/licenses/LICENSE-2.0 *
|
||||
# * *
|
||||
# * Unless required by applicable law or agreed to in writing, software *
|
||||
# * distributed under the License is distributed on an "AS IS" BASIS, *
|
||||
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
|
||||
# * See the License for the specific language governing permissions and *
|
||||
# * limitations under the License. *
|
||||
# * *
|
||||
# *************************************************************************************************
|
||||
|
||||
# *************************************************************************************************
|
||||
# * *
|
||||
# * Invoke the PostLogProfilerProcessor to process sqltiming log information into a simple *
|
||||
# * profiling output report. *
|
||||
# * *
|
||||
# *************************************************************************************************
|
||||
|
||||
java -Xmx1024m -classpath ../build/log4jdbc-1.1alpha1.jar net.sf.log4jdbc.PostLogProfilerProcessor $@
|
||||
+27
-3
@@ -46,6 +46,29 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ConnectionSpy that wraps a given Connection.
|
||||
*
|
||||
* @param realConnection "real" Connection that this ConnectionSpy wraps.
|
||||
* @param rdbmsSpecifics the RdbmsSpecifics object for formatting logging appropriate for the Rdbms used.
|
||||
*/
|
||||
public ConnectionSpy(Connection realConnection, RdbmsSpecifics rdbmsSpecifics)
|
||||
{
|
||||
setRdbmsSpecifics(rdbmsSpecifics);
|
||||
if (realConnection == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Must pass in a non null real Connection");
|
||||
@@ -93,12 +116,12 @@ public class ConnectionSpy implements Connection, Spy
|
||||
|
||||
protected void reportException(String methodCall, SQLException exception, String sql)
|
||||
{
|
||||
log.exceptionOccured(this, methodCall, exception, sql);
|
||||
log.exceptionOccured(this, methodCall, exception, sql, -1L);
|
||||
}
|
||||
|
||||
protected void reportException(String methodCall, SQLException exception)
|
||||
{
|
||||
log.exceptionOccured(this, methodCall, exception, null);
|
||||
log.exceptionOccured(this, methodCall, exception, null, -1L);
|
||||
}
|
||||
|
||||
protected void reportAllReturns(String methodCall, String returnValue)
|
||||
@@ -404,7 +427,7 @@ public class ConnectionSpy implements Connection, Spy
|
||||
String methodCall = "isReadOnly()";
|
||||
try
|
||||
{
|
||||
return realConnection.isReadOnly();
|
||||
return reportReturn(methodCall,realConnection.isReadOnly());
|
||||
}
|
||||
catch (SQLException s)
|
||||
{
|
||||
@@ -549,6 +572,7 @@ public class ConnectionSpy implements Connection, Spy
|
||||
|
||||
public void setTypeMap(java.util.Map map) throws SQLException
|
||||
{
|
||||
//todo: dump map?
|
||||
String methodCall = "setTypeMap(" + map + ")";
|
||||
try
|
||||
{
|
||||
@@ -120,6 +120,8 @@ public class DriverSpy implements Driver
|
||||
subDrivers.add("com.informix.jdbc.IfxDriver");
|
||||
subDrivers.add("org.apache.derby.jdbc.ClientDriver");
|
||||
subDrivers.add("org.apache.derby.jdbc.EmbeddedDriver");
|
||||
subDrivers.add("com.mysql.jdbc.Driver");
|
||||
subDrivers.add("org.postgresql.Driver");
|
||||
|
||||
// look for additional driver specified in system properties
|
||||
String moreDrivers = System.getProperty("log4jdbc.drivers");
|
||||
@@ -158,7 +160,6 @@ public class DriverSpy implements Driver
|
||||
}
|
||||
catch (ClassNotFoundException c)
|
||||
{
|
||||
// log.debug(" ... (not found) ..." + driverClass);
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
@@ -261,8 +262,10 @@ public class DriverSpy implements Driver
|
||||
}
|
||||
|
||||
/**
|
||||
* Report whether the underlying driver is jdbcClient. If there is no underlying driver, false
|
||||
* will be returned, because the driver cannot actually do any work without an underlying driver.
|
||||
* Report whether the underlying driver is jdbc compliant.
|
||||
* If there is no underlying driver, false
|
||||
* will be returned, because the driver cannot actually do
|
||||
* any work without an underlying driver.
|
||||
*
|
||||
* @return <code>true</code> if the underlying driver is JDBC Compliant; <code>false</code>
|
||||
* otherwise.
|
||||
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* Copyright 2007 Arthur Blake
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package net.sf.log4jdbc;
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Post processes an existing sqltiming log, and creates a profiling report from it.
|
||||
* Name of log file is passed in on the command line as the only argument.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
* 1. Each sql statement in the log is separated by a blank line.
|
||||
* 2. Each sql statement is terminated with the timing string "{executed in N msec}" where N is the number of
|
||||
* milliseconds that the sql executed in.
|
||||
*
|
||||
*/
|
||||
public class PostLogProfilerProcessor {
|
||||
|
||||
//todo: needs to be able to gracefully handle sql exceptions in log output
|
||||
|
||||
/**
|
||||
* Post Process log4jdbc sqltiming log data.
|
||||
*
|
||||
* @param args command line arguments. Expects one argument, the name of the file to post process.
|
||||
* @throws Exception if something goes wrong during processing.
|
||||
*/
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
if (args.length < 1)
|
||||
{
|
||||
System.out.println("usage: java PostLogProfilerProcessor <log-file>");
|
||||
System.exit(1);
|
||||
}
|
||||
new PostLogProfilerProcessor(args[0], System.out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Total number of sql statements processed.
|
||||
*/
|
||||
private long totalSql = 0L;
|
||||
|
||||
/**
|
||||
* Number of lines processed.
|
||||
*/
|
||||
private long lineNo = 0L;
|
||||
|
||||
/**
|
||||
* Total number of milliseconds that all processed sql took to run.
|
||||
*/
|
||||
private long totalMsec = 0L;
|
||||
|
||||
/**
|
||||
* Milliseconds of the worst single offending sql statement.
|
||||
*/
|
||||
private long maxMsec = 0L;
|
||||
|
||||
/**
|
||||
* Total combined milliseconds of all flagged sql statements.
|
||||
*/
|
||||
private long flaggedSqlTotalMsec = 0L;
|
||||
|
||||
/**
|
||||
* Threshold at which sql is deemed to be running slow enough to be flagged.
|
||||
*/
|
||||
private long threshold = 100L;
|
||||
|
||||
/**
|
||||
* How many top offender sql statements to display in final report
|
||||
*/
|
||||
private long topOffenderCount = 1000L;
|
||||
|
||||
/**
|
||||
* Collection of all sql that took longer than "threshold" msec to run.
|
||||
*/
|
||||
private List flaggedSql = new LinkedList();
|
||||
|
||||
/**
|
||||
* Process given filename, and produce sql profiling report to given PrintStream.
|
||||
*
|
||||
* @param filename sqltiming log to process.
|
||||
* @param out PrintStream to write profiling report to.
|
||||
* @throws Exception if reading error occurs.
|
||||
*/
|
||||
public PostLogProfilerProcessor (String filename, PrintStream out) throws Exception
|
||||
{
|
||||
FileReader f= new FileReader(filename);
|
||||
LineNumberReader l = new LineNumberReader(f);
|
||||
|
||||
String line;
|
||||
boolean blankLine;
|
||||
|
||||
StringBuffer sql = new StringBuffer();
|
||||
|
||||
do
|
||||
{
|
||||
line = l.readLine();
|
||||
|
||||
if (line != null)
|
||||
{
|
||||
blankLine = line.length()==0;
|
||||
lineNo++;
|
||||
/*
|
||||
if (lineNo%100000L==0L)
|
||||
{
|
||||
out.println("" + lineNo + " lines...");
|
||||
}
|
||||
*/
|
||||
if (blankLine)
|
||||
{
|
||||
processSql(sql);
|
||||
sql = new StringBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
sql.append(line);
|
||||
}
|
||||
|
||||
}
|
||||
} while (line != null);
|
||||
|
||||
out.println("processed " + lineNo + " lines.");
|
||||
|
||||
f.close();
|
||||
|
||||
// display report to stdout
|
||||
|
||||
out.println("Number of sql statements: " + totalSql);
|
||||
out.println("Total number of msec : " + totalMsec);
|
||||
if (totalMsec>0)
|
||||
{
|
||||
out.println("Average msec/statement : " + totalSql/totalMsec);
|
||||
}
|
||||
|
||||
int flaggedSqlStmts = flaggedSql.size();
|
||||
|
||||
if (flaggedSqlStmts>0)
|
||||
{
|
||||
out.println("Sql statements that took more than "+ threshold + " msec were flagged.");
|
||||
out.println("Flagged sql statements : " + flaggedSqlStmts);
|
||||
out.println("Flagged sql Total number of msec : " + flaggedSqlTotalMsec);
|
||||
out.println("Flagged sql Average msec/statement : " + flaggedSqlTotalMsec/flaggedSqlStmts);
|
||||
|
||||
out.println("sorting...");
|
||||
|
||||
Object[] flaggedSqlArray = flaggedSql.toArray();
|
||||
Arrays.sort(flaggedSqlArray);
|
||||
|
||||
int execTimeSize = ("" + maxMsec).length();
|
||||
|
||||
|
||||
if (topOffenderCount > flaggedSqlArray.length)
|
||||
{
|
||||
topOffenderCount = flaggedSqlArray.length;
|
||||
}
|
||||
|
||||
out.println("top " + topOffenderCount + " offender"+ (topOffenderCount==1?"":"s") + ":");
|
||||
|
||||
ProfiledSql p;
|
||||
|
||||
for (int i=0; i < topOffenderCount; i++)
|
||||
{
|
||||
p = (ProfiledSql) flaggedSqlArray[i];
|
||||
out.println(Utilities.rightJustify(execTimeSize,""+p.getExecTime()) + " " + p.getSql());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void processSql(StringBuffer sql)
|
||||
{
|
||||
if (sql.length()>0)
|
||||
{
|
||||
totalSql++;
|
||||
String sqlStr = sql.toString();
|
||||
if (sqlStr.endsWith("msec}"))
|
||||
{
|
||||
int executedIn = sqlStr.indexOf("{executed in ");
|
||||
if (executedIn == -1)
|
||||
{
|
||||
System.err.println("WARNING: sql w/o timing info found at line " + lineNo);
|
||||
return;
|
||||
}
|
||||
|
||||
//todo: proper error handling for parse
|
||||
String msecStr = sqlStr.substring(executedIn+13, sqlStr.length()-6);
|
||||
long msec = Long.parseLong(msecStr);
|
||||
totalMsec +=msec;
|
||||
if (msec > maxMsec)
|
||||
{
|
||||
maxMsec = msec;
|
||||
}
|
||||
|
||||
if (msec >threshold)
|
||||
{
|
||||
flagSql(msec,sqlStr);
|
||||
flaggedSqlTotalMsec += msec;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("WARNING: sql w/o timing info found at line " + lineNo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void flagSql(long msec, String sql)
|
||||
{
|
||||
flaggedSql.add(new ProfiledSql(msec,sql));
|
||||
}
|
||||
|
||||
private class ProfiledSql implements Comparable {
|
||||
private Long execTime;
|
||||
private String sql;
|
||||
|
||||
public ProfiledSql (long msec, String sql)
|
||||
{
|
||||
this.execTime= new Long(msec);
|
||||
this.sql = sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this object with the specified object for order. Returns a
|
||||
* negative integer, zero, or a positive integer as this object is less
|
||||
* than, equal to, or greater than the specified object.<p>
|
||||
*
|
||||
* In this case the comparison is used to sort flagged sql in descending order.
|
||||
* @param o ProfiledSql Object to compare to this ProfiledSql. Must not be null.
|
||||
*/
|
||||
public int compareTo(Object o) {
|
||||
return ((ProfiledSql)o).execTime.compareTo(execTime);
|
||||
}
|
||||
|
||||
public Long getExecTime() {
|
||||
return execTime;
|
||||
}
|
||||
|
||||
public String getSql() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return this.execTime + " msec: " + this.sql;
|
||||
}
|
||||
}
|
||||
}
|
||||
+31
-20
@@ -34,6 +34,7 @@ import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wraps a PreparedStatement and reports method calls, returns and exceptions.
|
||||
@@ -48,7 +49,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
/**
|
||||
* holds list of bind variables for tracing
|
||||
*/
|
||||
protected final ArrayList argTrace = new ArrayList();
|
||||
protected final List argTrace = new ArrayList();
|
||||
|
||||
// a way to turn on and off type help...
|
||||
// todo: make this a configurable parameter
|
||||
@@ -226,7 +227,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException
|
||||
{
|
||||
String methodCall = "setCharacterStream(" + parameterIndex + ", " + reader + ", " + length + ")";
|
||||
argTraceSet(parameterIndex, "(CharacterStream)", reader + ":" + length);
|
||||
argTraceSet(parameterIndex, "(Reader)", "<Reader of length " + length + ">");
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setCharacterStream(parameterIndex, reader, length);
|
||||
@@ -405,19 +406,18 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public boolean execute() throws SQLException
|
||||
{
|
||||
String methodCall = "execute()";
|
||||
String dumpedSql = null;
|
||||
String dumpedSql = dumpedSql();
|
||||
reportSql(dumpedSql, methodCall);
|
||||
long tstart = System.currentTimeMillis();
|
||||
try
|
||||
{
|
||||
dumpedSql = dumpedSql();
|
||||
reportSql(dumpedSql, methodCall);
|
||||
long tstart = System.currentTimeMillis();
|
||||
boolean result = realPreparedStatement.execute();
|
||||
reportSqlTiming(System.currentTimeMillis() - tstart, dumpedSql, methodCall);
|
||||
return reportReturn(methodCall, result);
|
||||
}
|
||||
catch (SQLException s)
|
||||
{
|
||||
reportException(methodCall, s, dumpedSql);
|
||||
reportException(methodCall, s, dumpedSql, System.currentTimeMillis() - tstart);
|
||||
throw s;
|
||||
}
|
||||
}
|
||||
@@ -604,12 +604,11 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public ResultSet executeQuery() throws SQLException
|
||||
{
|
||||
String methodCall = "executeQuery()";
|
||||
String dumpedSql = null;
|
||||
String dumpedSql = dumpedSql();
|
||||
reportSql(dumpedSql, methodCall);
|
||||
long tstart = System.currentTimeMillis();
|
||||
try
|
||||
{
|
||||
dumpedSql = dumpedSql();
|
||||
reportSql(dumpedSql, methodCall);
|
||||
long tstart = System.currentTimeMillis();
|
||||
ResultSet r = realPreparedStatement.executeQuery();
|
||||
reportSqlTiming(System.currentTimeMillis() - tstart, dumpedSql, methodCall);
|
||||
ResultSetSpy rsp = new ResultSetSpy(this, r);
|
||||
@@ -617,15 +616,27 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
}
|
||||
catch (SQLException s)
|
||||
{
|
||||
reportException(methodCall, s, dumpedSql);
|
||||
reportException(methodCall, s, dumpedSql, System.currentTimeMillis() - tstart);
|
||||
throw s;
|
||||
}
|
||||
}
|
||||
|
||||
private String getTypeHelp(Object x)
|
||||
{
|
||||
if (x==null)
|
||||
{
|
||||
return "(null)";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "(" + x.getClass().getName() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
|
||||
{
|
||||
String methodCall = "setObject(" + parameterIndex + ", " + x + ", " + targetSqlType + ", " + scale + ")";
|
||||
argTraceSet(parameterIndex, "(" + x.getClass().getName() + ")", rdbmsSpecifics.formatParameterObject(x));
|
||||
argTraceSet(parameterIndex, getTypeHelp(x), rdbmsSpecifics.formatParameterObject(x));
|
||||
|
||||
try
|
||||
{
|
||||
@@ -642,7 +653,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, "(" + x.getClass().getName() + ")", rdbmsSpecifics.formatParameterObject(x));
|
||||
argTraceSet(parameterIndex, getTypeHelp(x), rdbmsSpecifics.formatParameterObject(x));
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setObject(parameterIndex, x, targetSqlType);
|
||||
@@ -658,7 +669,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void setObject(int parameterIndex, Object x) throws SQLException
|
||||
{
|
||||
String methodCall = "setObject(" + parameterIndex + ", " + x + ")";
|
||||
argTraceSet(parameterIndex, "(" + x.getClass().getName() + ")", rdbmsSpecifics.formatParameterObject(x));
|
||||
argTraceSet(parameterIndex, getTypeHelp(x), rdbmsSpecifics.formatParameterObject(x));
|
||||
try
|
||||
{
|
||||
realPreparedStatement.setObject(parameterIndex, x);
|
||||
@@ -706,19 +717,18 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public int executeUpdate() throws SQLException
|
||||
{
|
||||
String methodCall = "executeUpdate()";
|
||||
String dumpedSql = null;
|
||||
String dumpedSql = dumpedSql();
|
||||
reportSql(dumpedSql, methodCall);
|
||||
long tstart = System.currentTimeMillis();
|
||||
try
|
||||
{
|
||||
dumpedSql = dumpedSql();
|
||||
reportSql(dumpedSql, methodCall);
|
||||
long tstart = System.currentTimeMillis();
|
||||
int result = realPreparedStatement.executeUpdate();
|
||||
reportSqlTiming(System.currentTimeMillis() - tstart, dumpedSql, methodCall);
|
||||
return reportReturn(methodCall, result);
|
||||
}
|
||||
catch (SQLException s)
|
||||
{
|
||||
reportException(methodCall, s, dumpedSql);
|
||||
reportException(methodCall, s, dumpedSql, System.currentTimeMillis() - tstart);
|
||||
throw s;
|
||||
}
|
||||
}
|
||||
@@ -793,6 +803,7 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
|
||||
public void addBatch() throws SQLException
|
||||
{
|
||||
String methodCall = "addBatch()";
|
||||
currentBatch.add(dumpedSql());
|
||||
try
|
||||
{
|
||||
realPreparedStatement.addBatch();
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user