mirror of
https://github.com/encounter/log4jdbc.git
synced 2026-03-30 11:27:21 -07:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c816e8ad1 |
@@ -0,0 +1,130 @@
|
||||
# log4jdbc and Datasources + WebSphere #
|
||||
|
||||
I was playing around with log4jdbc and I noticed, as others have, that
|
||||
log4jdbc dos not support data sources out of the box. So using
|
||||
log4jdbc with more modern application servers is not plug'n'play. But
|
||||
how difficult could it be? In fact it was very easy, and this post
|
||||
will provide a little example of how you can quickly build a logged
|
||||
data source and use it in WebSphere.
|
||||
|
||||
So... what is a data source exactly? A data source is a Java Bean that
|
||||
provides connections to a data source. They are usually accessed via JNDI in the form of "jdbc/MyDataSource".
|
||||
|
||||
Typically for any modern application server there are two types of
|
||||
data sources:
|
||||
|
||||
* Pooled connection
|
||||
* XA Connection
|
||||
|
||||
I won't get into the details of those, but it is important to know
|
||||
which one is used by your application. This can be easily determined
|
||||
in your application server data source provider settings.
|
||||
Once you know which one you need, you'll have to write to small
|
||||
delegation classes to wrap the data source connections with "spied"
|
||||
connections. Take a pooled data source connection for example:
|
||||
|
||||
```
|
||||
public class PooledLoggingConnection implements PooledConnection {
|
||||
|
||||
protected PooledConnection parent;
|
||||
|
||||
public PooledLoggingConnection( PooledConnection pConnection ) {
|
||||
parent = pConnection;
|
||||
}
|
||||
|
||||
public void addConnectionEventListener( ConnectionEventListener pListener ) {
|
||||
parent.addConnectionEventListener( pListener );
|
||||
}
|
||||
|
||||
public void close() throws SQLException {
|
||||
parent.close();
|
||||
}
|
||||
|
||||
public Connection getConnection() throws SQLException {
|
||||
return new ConnectionSpy( parent.getConnection() ); // -- log4jdbc entry point!!!
|
||||
}
|
||||
|
||||
public void removeConnectionEventListener( ConnectionEventListener pListener ) {
|
||||
parent.removeConnectionEventListener( pListener );
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Next, you must write the delegating data source which will use the
|
||||
pooled logging connection class. Notice we extend the existing
|
||||
OracleConnectionPooledDataSource so we essentially have a drop in data
|
||||
source for the no logging version. Notice, the log4j properties are
|
||||
initialised here as well as data sources are usually loaded in a
|
||||
seperate class loader than the applications.
|
||||
|
||||
```
|
||||
|
||||
public class OracleLoggingConnectionPooledDataSource extends OracleConnectionPooledDataSource {
|
||||
|
||||
public OracleLoggingConnectionPooledDataSource () throws java.sql.SQLException {
|
||||
super();
|
||||
initLogging();
|
||||
}
|
||||
|
||||
protected void initLogging() {
|
||||
try {
|
||||
PropertyConfigurator.configure(
|
||||
getClass().getClassLoader().getResource("log4jdbc_log4j.properties" ) );
|
||||
} catch( Exception pEx ) {
|
||||
System.err.println( "Error configuring log4jdbc logging: " + pEx.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
public PooledConnection getPooledConnection( Properties arg0 ) throws SQLException {
|
||||
return new PooledLoggingConnection( super.getPooledConnection( arg0 ) );
|
||||
}
|
||||
|
||||
public PooledConnection getPooledConnection( String arg0, String arg1 ) throws SQLException {
|
||||
return new PooledLoggingConnection( super.getPooledConnection( arg0, arg1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
For XA data sources, it is a matter of implementing the appropriate
|
||||
XAConnection and OracleXADataSource classes instead of
|
||||
PooledConnection and OracleConnectionPooledDataSource.
|
||||
Once you have these ready, package them into a jar so you can used
|
||||
them in an application server such as WebSphere.
|
||||
|
||||
There is some pre-configuration to use log4jdbc in WebSphere:
|
||||
|
||||
* First prepare a folder in your project containing your new data source jar plus all the necessary jars needed to run log4jdbc: slf4j-api-1.5.11.jar, slf4j-log4j12-1.5.11.jar, log4jdbc3-1.2beta1.jar, log4j-1.2.14.jar, **<your datasource jar>**
|
||||
* Second grab a copy of the log4jdbc log4j property file and put it in
|
||||
this folder as well as: log4jdbc\_log4j.properties
|
||||
|
||||
Now we can configure Websphere:
|
||||
|
||||
To use this data source in Websphere 6.x, simply access the admin
|
||||
console and add a user-defined JDBC data source provider. Name your
|
||||
provider something like: "Oracle Logged Data Source Provider"
|
||||
When asked for the implementation class, enter the full class name of
|
||||
your **<my package>**.OracleLoggingConnectionPooledDataSource class.
|
||||
When asked for the class path, provide the folder you created above,
|
||||
plus the folder containing the JDBC driver jar (for example, oracle:
|
||||
ojdbc14.jar)
|
||||
|
||||
Now to use this data source provider, create a new data source and
|
||||
select "Oracle Logged Data Source Provider" as the provider. You can
|
||||
basically replace any of your existing Oracle data sources with a new
|
||||
ones provided from our new data source provider.
|
||||
|
||||
You might have noticed that WebSphere will use a generic data source
|
||||
provider helper for our data source provider, so some configuration
|
||||
properties will be missing from the web GUI, the data source URL to be
|
||||
specific. You can simply add a custom property "URL" to get around
|
||||
this. Further, any addition data source properties can be set this way
|
||||
as the properties are set using bean introspection. So any getter/
|
||||
setter pairs can be set on the data source using custom properties.
|
||||
|
||||
Finally, the 'log4jdbc\_log4j.properties' file in the folder we
|
||||
prepared earlier can be used to configure the logging output.
|
||||
|
||||
_Contributed by Kris Fudalewski, 2010-05-12_
|
||||
|
||||
Original Post: http://groups.google.com/group/log4jdbc/browse_thread/thread/d4f3544030a90791
|
||||
@@ -0,0 +1,26 @@
|
||||
# How do I use log4jdbc with a data source? #
|
||||
|
||||
At this time log4jdbc does not have direct support for data sources. It is one of the top features I would like to add at some point.
|
||||
|
||||
There is an alternative way to use log4jdbc that has worked really well for some people using data sources:
|
||||
|
||||
If you have a central location in your code where your application obtains connections, you can simply wrap the Connection object returned. Example:
|
||||
|
||||
```
|
||||
// get connection from datasource
|
||||
Connection conn = dataSource.getConnection();
|
||||
|
||||
// wrap the connection with log4jdbc
|
||||
conn = new net.sf.log4jdbc.ConnectionSpy(conn);
|
||||
|
||||
// now use Connection as normal (but it will be audited by log4jdbc)
|
||||
```
|
||||
|
||||
Since log4jdbc is being used in code instead of through the wrapper driver, it has the extra benefit of not requiring the log4jdbc driver to be initialized and the jdbc URL doesn't need to be changed either.
|
||||
|
||||
|
||||
Here is a write up on how one user got datasources working on WebSphere with log4jdbc: DataSourceExampleForWebSphere
|
||||
|
||||
# What about Maven support? #
|
||||
|
||||
Another feature, I plan to add at some point. I just haven't had time.
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
**log4jdbc** is a Java JDBC driver that can log SQL and/or JDBC calls (and optionally SQL timing information) for other JDBC drivers using the [Simple Logging Facade For Java](http://www.slf4j.org) (SLF4J) logging system.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
## News ##
|
||||
**2012-02-17:** log4jdbc 1.2 final release! (It's about time, huh?)
|
||||
[Full changelist here.](https://code.google.com/p/log4jdbc/source/browse/doc/CHANGES)
|
||||
|
||||
**2010-06-09:** log4jdbc 1.2 beta 2 released: fixes and several new useful features.
|
||||
|
||||
**2010-03-20:** log4jdbc 1.2 beta 1 released: fixes and performance improvements.
|
||||
|
||||
**2009-02-26:** [log4jdbc 1.2 alpha 2 released](http://arthurblake.wordpress.com/2009/02/26/log4jdbc-12-alpha-2-released/): one bug fix and a couple of small new features...
|
||||
|
||||
**2008-11-26:** So long SourceForge... (and thanks for all the fish!) Moved to Google Code! Also, created a new [google group](http://arthurblake.wordpress.com/2008/11/26/log4jdbc-support-group/) for general support, feedback and questions.
|
||||
|
||||
**2008-11-08:** [log4jdbc 1.2 alpha 1 released.](http://arthurblake.wordpress.com/2008/11/08/log4jdbc-12-alpha1-released/) Many new options for controlling SQL output and a new log for viewing connection open/close events (very useful for hunting down connection leak issues.) See CHANGES for all the release details.
|
||||
|
||||
**2008-04-11:** [log4jdbc 1.1 final release out!](http://arthurblake.wordpress.com/2008/04/11/log4jdbc-11-released/)
|
||||
|
||||
**2007-11-10:** log4jdbc 1.1 beta 1 released. New optional timing threshold settings for honing in on slow SQL.
|
||||
|
||||
**2007-07-25:** log4jdbc 1.1 alpha 2 released. JDBC 4 support!
|
||||
|
||||
**2007-05-29:** log4jdbc 1.1 alpha 1 released. Most notable change is that the Simple Logging Facade for Java is now used instead of log4j directly.
|
||||
|
||||
**2007-04-21:** log4jdbc 1.0 has been released! Download it and give it a try!
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Features ##
|
||||
|
||||
* Full support for JDBC 3 and JDBC 4!
|
||||
* Easy to configure, in most cases all you need to do is change the driver class name to **net.sf.log4jdbc.DriverSpy** and prepend **"jdbc:log4"** to your existing jdbc url, set up your logging 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 and this data can be post processed with an included tool to produce profiling report data for quickly identifying slow SQL in your application..
|
||||
* SQL connection number information is generated to help identify connection pooling or threading problems.
|
||||
* Works with any underlying JDBC driver, with JDK 1.4 and above, and SLF4J 1.x.
|
||||
* Open source software, licensed under the business friendly **Apache 2.0 license**: http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Usage ##
|
||||
|
||||
Using data sources or maven? See the [FAQ](FAQ.md).
|
||||
|
||||
### 1. Decide if you need JDBC 3 or JDBC 4 support. ###
|
||||
* If you are using JDK 1.4 or 1.5, you should use the JDBC 3 version of log4jdbc.
|
||||
* 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).
|
||||
|
||||
> 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 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.
|
||||
|
||||
> Note that JDBC 2 is not currently supported by log4jdbc, although if you are using JDK 1.4 and above, the log4jdbc 3 or 4 driver should be able to wrap an older JDBC 2 driver as well-- log4jdbc just won't work with Java 1.3 and earlier.
|
||||
|
||||
> Choose and download one of the driver .jar files:
|
||||
* [log4jdbc3-1.2.jar](http://log4jdbc.googlecode.com/files/log4jdbc3-1.2.jar) for JDBC 3 support in JDK 1.4 , JDK 1.5
|
||||
* [log4jdbc4-1.2.jar](http://log4jdbc.googlecode.com/files/log4jdbc4-1.2.jar) for JDBC 4 support in JDK 1.6 , JDK 1.7
|
||||
> Place the log4jdbc jar that you choose into your application's classpath.
|
||||
### 2. Choose which java logging system you will use. ###
|
||||
> 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:
|
||||
* Log4j
|
||||
* java.util logging in JDK 1.4
|
||||
* logback
|
||||
* Jakarta Commons Logging
|
||||
|
||||
> 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.
|
||||
|
||||
> [Download](http://www.slf4j.org/download.html) the latest official SLF4J release.
|
||||
|
||||
> You will need two jars: slf4j-api-1.5.0.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.
|
||||
|
||||
> Please read the documentation at the [SLF4J website](http://slf4j.org/). It's really easy to set up!
|
||||
### 3. Set your JDBC driver class to net.sf.log4jdbc.DriverSpy in your application's configuration. ###
|
||||
|
||||
> 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:
|
||||
|
||||
| **Driver Class** | **Database Type** |
|
||||
|:-----------------|:------------------|
|
||||
| oracle.jdbc.driver.OracleDriver | Older Oracle Driver |
|
||||
| oracle.jdbc.OracleDriver | Newer Oracle Driver |
|
||||
| com.sybase.jdbc2.jdbc.SybDriver | Sybase |
|
||||
| net.sourceforge.jtds.jdbc.Driver | jTDS SQL Server & Sybase driver |
|
||||
| com.microsoft.jdbc.sqlserver.SQLServerDriver | Microsoft SQL Server 2000 driver |
|
||||
| com.microsoft.sqlserver.jdbc.SQLServerDriver | Microsoft SQL Server 2005 driver |
|
||||
| weblogic.jdbc.sqlserver.SQLServerDriver | Weblogic SQL Server driver |
|
||||
| com.informix.jdbc.IfxDriver | Informix |
|
||||
| org.apache.derby.jdbc.ClientDriver | Apache Derby client/server driver, aka the Java DB |
|
||||
| org.apache.derby.jdbc.EmbeddedDriver | Apache Derby embedded driver, aka the Java DB |
|
||||
| com.mysql.jdbc.Driver | MySQL |
|
||||
| org.postgresql.Driver | PostgresSQL |
|
||||
| org.hsqldb.jdbcDriver | HSQLDB pure Java database |
|
||||
| org.h2.Driver | H2 pure Java database |
|
||||
|
||||
> 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 if you need more than one.
|
||||
|
||||
```
|
||||
-Dlog4jdbc.drivers=<driverclass>[,<driverclass>...]
|
||||
```
|
||||
|
||||
> If you don't want to attempt to auto-load drivers at all, you can set a system property, **log4jdbc.auto.load.popular.drivers** to false. In this case, it will only load the drivers specified in the **log4jdbc.drivers** property.
|
||||
|
||||
|
||||
### 4. 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
|
||||
```
|
||||
> then You would change it to:
|
||||
```
|
||||
jdbc:log4jdbc:derby://localhost:1527//db-derby-10.2.2.0-bin/databases/MyDatabase
|
||||
```
|
||||
> to use log4jdbc.
|
||||
### 5. Set up your loggers. ###
|
||||
There are 5 loggers that are used by log4jdbc, If all 5 are turned off (or for example, set to a level less than error, such as the FATAL level in log4j), 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 5 logs are set to ERROR level or above (e.g ERROR, INFO or DEBUG) then log4jdbc will be activated, wrapping and logging activity in the JDBC connections returned by the underlying driver.
|
||||
|
||||
> Each of these logs can be set at either DEBUG, INFO or ERROR level.
|
||||
* **DEBUG** includes the class name and line number (if available) at which the SQL was executed. **Use DEBUG level with extra care, as this imposes an additional performance penalty when in use.**
|
||||
* **INFO** includes the SQL (or other information as applicable.)
|
||||
* **ERROR** will show the stack traces in the log output when SQLExceptions occur.
|
||||
|
||||
| **logger** | **description** | **since** |
|
||||
|:-----------|:----------------|:----------|
|
||||
| jdbc.sqlonly | Logs only SQL. 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. | 1.0 |
|
||||
| jdbc.sqltiming | Logs the SQL, post-execution, including timing statistics on how long the SQL took to execute. | 1.0 |
|
||||
| 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. | 1.0 |
|
||||
| jdbc.resultset | Even more voluminous, because all calls to ResultSet objects are logged. | 1.0 |
|
||||
| jdbc.connection | Logs connection open and close events as well as dumping all open connection numbers. This is very useful for hunting down connection leak problems. | 1.2alpha1 |
|
||||
|
||||
> 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 log4jdbc 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, jdbc.resultset and jdbc.connection 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 jdbc.audit and jdbc.resultset!)
|
||||
|
||||
> Because SLF4J can be used with many popular java logging systems, the setup for your loggers will vary depending on which underlying logging system you use. Sample configuration files for log4j are provided here: [log4j.xml](http://code.google.com/p/log4jdbc/source/browse/trunk/doc/log4j.xml) and [log4j.properties](http://code.google.com/p/log4jdbc/source/browse/trunk/doc/log4j.properties).
|
||||
|
||||
### 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.
|
||||
|
||||
Set the log4jdbc.debug.stack.prefix System property for log4jdc to help get around this problem:
|
||||
|
||||
```
|
||||
-Dlog4jdbc.debug.stack.prefix=<package.prefix>
|
||||
```
|
||||
|
||||
Where <package.prefix> is 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)
|
||||
|
||||
For example, setting a system property such as this:
|
||||
|
||||
```
|
||||
-Dlog4jdbc.debug.stack.prefix=com.mycompany.myapp
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Options ##
|
||||
|
||||
log4jdbc options are controlled via system properties. The simplest way to set these is with the java -D command line option. For example:
|
||||
```
|
||||
java -Dlog4jdbc.drivers=my.funky.DriverClass -classpath ./classes my.funky.Program
|
||||
```
|
||||
|
||||
Starting with log4jdbc 1.2 beta 2, you can also define any of these property settings in a file named **log4jdbc.properties** stored in the classpath. log4jdbc will look for properties both in this file (if it exists) and in the system properties, with the file taking precedence for any properties defined in both locations.
|
||||
|
||||
| **property** | **default** | **description** | **since** |
|
||||
|:-------------|:------------|:----------------|:----------|
|
||||
| log4jdbc.drivers | | One or more fully qualified class names for JDBC drivers that log4jdbc should load and wrap. If more than one driver needs to be specified here, they should be comma separated with no spaces. This option is not normally needed because most popular JDBC drivers are already loaded by default-- this should be used if one or more additional JDBC drivers that (log4jdbc doesn't already wrap) needs to be included. | 1.0 |
|
||||
| log4jdbc.auto.load.popular.drivers | true | Set this to false to disable the feature where popular drivers are automatically loaded. If this is false, you must set the log4jdbc.drivers property in order to load the driver(s) you want. | 1.2beta2 |
|
||||
| log4jdbc.debug.stack.prefix | | The partial (or full) package prefix for the package name of your application. The call stack will be searched down to the first occurrence 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.) For example, setting a system property such as this: -Dlog4jdbc.debug.stack.prefix=com.mycompany.myapp 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. | 1.0 |
|
||||
| log4jdbc.sqltiming.warn.threshold | | Millisecond time value. Causes SQL that takes the number of milliseconds specified or more time to execute to be logged at the warning level in the sqltiming log. Note that the sqltiming log must be enabled at the warn log level for this feature to work. Also the logged output for this setting will log with debug information that is normally only shown when the sqltiming log is enabled at the debug level. This can help you to more quickly find slower running SQL without adding overhead or logging for normal running SQL that executes below the threshold level (if the logging level is set appropriately.) | 1.1beta1 |
|
||||
| log4jdbc.sqltiming.error.threshold | | Millisecond time value. Causes SQL that takes the number of milliseconds specified or more time to execute to be logged at the error level in the sqltiming log. Note that the sqltiming log must be enabled at the error log level for this feature to work. Also the logged output for this setting will log with debug information that is normally only shown when the sqltiming log is enabled at the debug level. This can help you to more quickly find slower running SQL without adding overhead or logging for normal running SQL that executes below the threshold level (if the logging level is set appropriately.) | 1.1beta1 |
|
||||
| log4jdbc.dump.booleanastruefalse | false | When dumping boolean values in SQL, 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. | 1.2alpha1 |
|
||||
| log4jdbc.dump.sql.maxlinelength | 90 | When dumping SQL, if this is greater than 0, than the dumped SQL will be broken up into lines that are no longer than this value. Set this value to 0 if you don't want log4jdbc to try and break the SQL into lines this way. In future versions of log4jdbc, this will probably default to 0. | 1.2alpha1 |
|
||||
| log4jdbc.dump.fulldebugstacktrace | false | If dumping in debug mode, dump the full stack trace. This will result in EXTREMELY voluminous output, but can be very useful under some circumstances when trying to track down the call chain for generated SQL. | 1.2alpha1 |
|
||||
| log4jdbc.dump.sql.select | true | Set this to false to suppress SQL select statements in the output. | 1.2alpha1 |
|
||||
| log4jdbc.dump.sql.insert | true | Set this to false to suppress SQL insert statements in the output. | 1.2alpha1 |
|
||||
| log4jdbc.dump.sql.update | true | Set this to false to suppress SQL update statements in the output. | 1.2alpha1 |
|
||||
| log4jdbc.dump.sql.delete | true | Set this to false to suppress SQL delete statements in the output. | 1.2alpha1 |
|
||||
| log4jdbc.dump.sql.create | true | Set this to false to suppress SQL create statements in the output. | 1.2alpha1 |
|
||||
| log4jdbc.dump.sql.addsemicolon | false | Set this to true to add an extra semicolon to the end of SQL in the output. This can be useful when you want to generate SQL from a program with log4jdbc in order to create a script to feed back into a database to run at a later time. | 1.2alpha1 |
|
||||
| log4jdbc.statement.warn | false | Set this to true to display warnings ([Why would you care?](http://arthurblake.wordpress.com/2009/02/26/log4jdbc-12-alpha-2-released/)) in the log when Statements are used in the log. NOTE, this was always true in releases previous to 1.2alpha2. It is false by default starting with release 1.2 alpha 2. | 1.2alpha2 |
|
||||
| log4jdbc.trim.sql | true | Set this to false to not trim the logged SQL. (Previous versions always trimmed the SQL.) | 1.2beta2 |
|
||||
| log4jdbc.trim.sql.extrablanklines | true | Set this to false to not trim extra blank lines in the logged SQL (by default, when more than one blank line in a row occurs, the contiguous lines are collapsed to just one blank line.) (Previous versions didn't trim extra blank lines at all.) | 1.2 |
|
||||
| log4jdbc.suppress.generated.keys.exception | false | Set to true to ignore any exception produced by the method, **Statement.getGeneratedKeys()** (Useful for using log4jdbc with Coldfusion.) | 1.2beta2 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Other ##
|
||||
|
||||
A simple tool is included which you can use to post-process sql timing logs produced by log4jdbc. It can output simple profiling reports with statistics and a dump of the sql statements that ran the slowest within the log. To invoke the tool, use **profsql.sh** (for unix/linux) and **profsql.cmd** (for windows) located in the scripts folder. These scripts take as one argument, the filename of a sql timing log (generated from the jdbc.sqltiming log category. They produce a profiling report to stdout. The tool is currently 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.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Similar Tools ##
|
||||
|
||||
**Some other tools and libraries that are similiar to log4jdbc.**
|
||||
|
||||
* [P6Spy](http://www.p6spy.com/) is probably the most well known JDBC logging driver but it hasn't been updated in over 5 years.
|
||||
* [Craftsman Spy](http://zer0.free.fr/craftsman/spy.php) appears to overlap quite a bit with the feature set in log4jdbc. This library hasn't been updated in 2 years and depends on Jakarta Commons Logging.
|
||||
* [JAMon](http://jamonapi.sourceforge.net/) (Java Application Monitor) is a comprehensive application monitor and monitoring API which includes JDBC/SQL monitoring as part of it's very large feature set.
|
||||
* [JdbcProxy](http://sourceforge.net/projects/jdbcproxy/) The driver can also emulate another JDBC driver to test the application without a database.
|
||||
* [LogDriver](http://rkbloom.net/logdriver/index.html) appears to be similiar to log4jdbc and the author has written a nice [article](http://java.sys-con.com/read/204723.htm) on JDBC logging in general and his motivation and experience of writing LogDriver.
|
||||
* and yet another [JDBC logger](http://jdbclogger.sourceforge.net/)
|
||||
|
||||
* [log4jdbc-remix](http://code.google.com/p/log4jdbc-remix/) an experimental fork of log4jdbc with some interesting features.
|
||||
|
||||
* [jdbcdslog](http://code.google.com/p/jdbcdslog/) Another new jdbc wrapper with a lot of crossover with log4jdbc features.
|
||||
|
||||
* [SqlRecorder](https://github.com/gokulesh/SqlRecorder) A library that is a wrapper around a JDBC driver to record all executed queries to different locations like a file,console or any other remote server via plugins.
|
||||
|
||||
* [log4jdbc-log4j2](https://code.google.com/p/log4jdbc-log4j2/) Another fork of log4jdbc that includes the log4jdbc-remix fork and other features of it's own.
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
log4jdbc is open source software, released under the Apache License, Version 2.0:
|
||||
|
||||
Copyright 2007 Arthur Blake
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use log4jdbc 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.
|
||||
-132
@@ -1,132 +0,0 @@
|
||||
[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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-212
@@ -1,212 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>log4jdbc - A JDBC Driver for logging SQL and JDBC calls.</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" href="reset-fonts-grids.css" />
|
||||
<link rel="stylesheet" href="log4jdbc.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<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="#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>
|
||||
</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.
|
||||
</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="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.
|
||||
</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
|
||||
you're ready to go!
|
||||
</li>
|
||||
|
||||
<li>
|
||||
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.
|
||||
</li>
|
||||
|
||||
<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.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
SQL connection number information is generated to help identify connection pooling or
|
||||
threading problems.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Works with any JDBC 3.0 driver, JDK 1.4 and above, and log4j 1.2.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>
|
||||
<p>
|
||||
The underlying driver that is being spied on in many cases will be loaded automatically
|
||||
without any additional configuration.
|
||||
</p>
|
||||
<p>
|
||||
The log4jdbc "spy" driver will try and load the following popular jdbc drivers:
|
||||
</p>
|
||||
<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)
|
||||
</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.
|
||||
</p>
|
||||
<p>
|
||||
(optional) <code>-Dlog4jdbc.drivers=<driver>[,<driver>...]</code> If your driver is not one of the common preloaded drivers.
|
||||
</p>
|
||||
</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>
|
||||
|
||||
(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>
|
||||
</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>
|
||||
<pre>
|
||||
|
||||
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.
|
||||
</pre>
|
||||
|
||||
<p>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.</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>
|
||||
|
||||
<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>
|
||||
|
||||
<p>See the sample files <a href="log4j.xml">log4j.xml</a> and <a href="log4j.properties">log4j.properties</a> for more information.</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
|
||||
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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>There are a couple of very useful system properties you can set 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>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p class="right"><a href="#top">[back to top]</a></p>
|
||||
|
||||
<h2><a name="license"/>license</h2>
|
||||
<p>
|
||||
log4jdbc is open source software, licensed under the <b>Apache 2.0 license:</b> <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>
|
||||
</p>
|
||||
|
||||
<p class="right"><a href="#top">[back to top]</a></p>
|
||||
<h2><a name="feedback"/>feedback</h2>
|
||||
|
||||
<p>Feedback and suggestions would be greatly appreciated. Email me at arthur_blake at users.sourceforge.net</p>
|
||||
|
||||
<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="#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>
|
||||
|
||||
<img class="logo" src="log4jdbc-logo-gray.png">
|
||||
|
||||
</h1>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,52 +0,0 @@
|
||||
!==============================================================================
|
||||
! log4j.properties - An example configuration properties file for log4j.
|
||||
!
|
||||
! Logging levels are:
|
||||
! DEBUG < INFO < WARN < ERROR < FATAL
|
||||
!==============================================================================
|
||||
|
||||
! turn on the internal log4j debugging flag so we can see what it is doing
|
||||
log4j.debug=true
|
||||
|
||||
!==============================================================================
|
||||
! JDBC API layer call logging :
|
||||
! INFO shows logging, DEBUG also shows where in code the jdbc calls were made,
|
||||
! setting DEBUG to true might cause minor slow-down in some environments.
|
||||
! If you experience too much slowness, use INFO instead.
|
||||
|
||||
! Log all JDBC calls except for ResultSet calls
|
||||
log4j.logger.jdbc.audit=INFO,jdbc
|
||||
log4j.additivity.jdbc.audit=false
|
||||
|
||||
! Log only JDBC calls to ResultSet objects
|
||||
log4j.logger.jdbc.resultset=INFO,jdbc
|
||||
log4j.additivity.jdbc.resultset=false
|
||||
|
||||
! Log only the SQL that is executed.
|
||||
log4j.logger.jdbc.sqlonly=DEBUG,sql
|
||||
log4j.additivity.jdbc.sqlonly=false
|
||||
|
||||
! Log timing information about the SQL that is executed.
|
||||
log4j.logger.jdbc.sqltiming=DEBUG,sqltiming
|
||||
log4j.additivity.jdbc.sqltiming=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
|
||||
log4j.appender.sql.Append=false
|
||||
log4j.appender.sql.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.sql.layout.ConversionPattern=-----> %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n%n
|
||||
|
||||
! the appender used for the JDBC API layer call logging above, sql timing
|
||||
log4j.appender.sqltiming=org.apache.log4j.FileAppender
|
||||
log4j.appender.sqltiming.File=./logs/sqltiming.log
|
||||
log4j.appender.sqltiming.Append=false
|
||||
log4j.appender.sqltiming.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.sqltiming.layout.ConversionPattern=-----> %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n%n
|
||||
|
||||
! the appender used for the JDBC API layer call logging above
|
||||
log4j.appender.jdbc=org.apache.log4j.FileAppender
|
||||
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
|
||||
@@ -1,92 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||
|
||||
<!-- An example log4j configuration xml file for log4jdbc -->
|
||||
<!-- Logging levels are: -->
|
||||
<!-- DEBUG < INFO < WARN < ERROR < FATAL -->
|
||||
|
||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
|
||||
|
||||
<appender name="stdout-appender" class="org.apache.log4j.ConsoleAppender">
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p %c{1}: %m%n"/>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<appender name="sql-appender" class="org.apache.log4j.FileAppender">
|
||||
<param name="File" value="./logs/sql.log"/>
|
||||
<param name="Append" value="false"/>
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="-----> %d{yyyy-MM-dd HH:mm:ss.SSS} <%t> %m%n%n"/>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<appender name="sql-timing-appender" class="org.apache.log4j.FileAppender">
|
||||
<param name="File" value="./logs/sqltiming.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%n"/>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<appender name="jdbc-appender" class="org.apache.log4j.FileAppender">
|
||||
<param name="File" value="./logs/jdbc.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
|
||||
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
|
||||
than ERROR (FATAL is suggested.)
|
||||
-->
|
||||
|
||||
<!-- log SQL (pre-execution) plus exceptions caused by SQL -->
|
||||
<logger name="jdbc.sqlonly" additivity="false">
|
||||
<level value="debug"/>
|
||||
<appender-ref ref="sql-appender"/>
|
||||
</logger>
|
||||
|
||||
<!-- log SQL with timing information, post execution -->
|
||||
<logger name="jdbc.sqltiming" additivity="false">
|
||||
<level value="fatal"/>
|
||||
<appender-ref ref="sql-timing-appender"/>
|
||||
</logger>
|
||||
|
||||
<!-- only use the two logs below to trace ALL JDBC information,
|
||||
NOTE: This can be very voluminous! -->
|
||||
|
||||
<!-- log all jdbc calls except ResultSet calls -->
|
||||
<logger name="jdbc.audit" additivity="false">
|
||||
<level value="fatal"/>
|
||||
<appender-ref ref="jdbc-appender"/>
|
||||
</logger>
|
||||
|
||||
<!-- log the jdbc ResultSet calls -->
|
||||
<logger name="jdbc.resultset" additivity="false">
|
||||
<level value="fatal"/>
|
||||
<appender-ref ref="jdbc-appender"/>
|
||||
</logger>
|
||||
|
||||
|
||||
<!-- this log is for internal debugging of log4jdbc, itself -->
|
||||
<!-- debug logging for log4jdbc itself -->
|
||||
<logger name="log4jdbc.debug" additivity="false">
|
||||
<level value="debug"/>
|
||||
<appender-ref ref="stdout-appender"/>
|
||||
</logger>
|
||||
|
||||
<!-- by default, log everything to the console with a level of WARN or higher -->
|
||||
<root>
|
||||
<level value="warn"/>
|
||||
<appender-ref ref="stdout-appender"/>
|
||||
</root>
|
||||
</log4j:configuration>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 996 B |
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
red in logo is #f06
|
||||
purple in logo is #ef39e9
|
||||
*/
|
||||
|
||||
.left {text-align:left;}
|
||||
.right{text-align:right;}
|
||||
.usage {text-align:left;}
|
||||
h1 {font-size:1em;color:#f06;background-color:#eee;display:block;padding:0.8em;}
|
||||
h2 {font-size:1.2em;color:#f06;background-color:#eee;display:block;height:2em;padding-top:0.8em;}
|
||||
a {text-decoration:none;}
|
||||
a:link {color: #f06;}
|
||||
a:visited {color: #f06;}
|
||||
p {padding:10px;}
|
||||
span.file {font-weight:bold;}
|
||||
ul {padding:10px;list-style:square}
|
||||
ol {padding:10px;list-style:decimal;}
|
||||
|
||||
ul li {margin-left:2em;padding:0.3em;}
|
||||
ol li {margin-left:2em;padding:0.3em;}
|
||||
|
||||
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;}
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -1,63 +0,0 @@
|
||||
<?xml version='1.0' encoding='ISO-8859-1' ?>
|
||||
|
||||
<!--
|
||||
Very basic ant build script.
|
||||
tested with Apache Ant version 1.6.5
|
||||
-->
|
||||
|
||||
<project name="log4jdbc" default="all" basedir="..">
|
||||
|
||||
<target name="all" depends="cleancompile,compile,cleanjar,jar"/>
|
||||
|
||||
<property name="version" value="1.0"/>
|
||||
|
||||
<target name="compile" description="compile all the source code">
|
||||
<javac srcdir="src" destdir="classes" deprecation="true" debug="true">
|
||||
<classpath>
|
||||
<pathelement location="$src"/>
|
||||
<fileset dir="lib">
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<target name="cleancompile" description="delete all the .class files.">
|
||||
<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"/>
|
||||
</target>
|
||||
|
||||
<target name="cleanjar" description="delete the jar file">
|
||||
<delete file="build/log4jdbc-${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>"
|
||||
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://logging.apache.org/log4j/docs/api/"/>
|
||||
</javadoc>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,407 +0,0 @@
|
||||
/**
|
||||
* 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.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.DriverPropertyInfo;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* A JDBC driver which is a facade that delegates to one or more real underlying JDBC drivers.
|
||||
* The driver will spy on any other JDBC driver that is loaded, simply by prepending <code>jdbc:log4</code>
|
||||
* to the normal jdbc driver URL used by any other JDBC driver. The driver also loads several well known drivers at
|
||||
* class load time, so that this driver can be "dropped in" to any java program that uses these drivers
|
||||
* without making any code changes. The well known driver classes that are loaded are:
|
||||
* <p/>
|
||||
* <code>
|
||||
* <ul>
|
||||
* <p/>
|
||||
* <li>oracle.jdbc.driver.OracleDriver</li>
|
||||
* <li>com.sybase.jdbc2.jdbc.SybDriver</li>
|
||||
* <li>net.sourceforge.jtds.jdbc.Driver</li>
|
||||
* <li>com.microsoft.jdbc.sqlserver.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>
|
||||
* <p/>
|
||||
* </ul>
|
||||
* </code>
|
||||
* <p/>
|
||||
* Additional drivers can be set via a system property: <b>log4jdbc.drivers</b>
|
||||
* This can be either a single driver class name or a list of comma separated driver class names.
|
||||
* <p/>
|
||||
* If any of the above driver classes cannot be loaded, the driver continues on without failing.
|
||||
* <p/>
|
||||
* Note that the <code>getMajorVersion</code>, <code>getMinorVersion</code> and <code>jdbcCompliant</code>
|
||||
* method calls attempt to delegate to the last underlying driver requested through any other call that
|
||||
* accepts a JDBC URL.
|
||||
* <p/>
|
||||
* This can cause unexpected behavior in certain circumstances. For example, if one of these
|
||||
* 3 methods is called before any underlying driver has been established, then they will return
|
||||
* default values that might not be correct in all situations. Similarly, if this spy driver
|
||||
* is used to spy on more than one underlying driver concurrently, the values returned by these
|
||||
* 3 method calls may change depending on what the last underlying driver used was at the time.
|
||||
* This will not usually be a problem, since the driver is retrieved by it's URL from the DriverManager
|
||||
* in the first place (thus establishing an underlying real driver), and in most applications
|
||||
* their is only one database.
|
||||
*
|
||||
* @author Arthur Blake
|
||||
*/
|
||||
public class DriverSpy implements Driver
|
||||
{
|
||||
/**
|
||||
* The last actual, underlying driver that was requested via a URL.
|
||||
*/
|
||||
private Driver lastUnderlyingDriverRequested;
|
||||
|
||||
/**
|
||||
* Maps driver class names to RdbmsSpecifics objects for each kind of database.
|
||||
*/
|
||||
private static Map rdbmsSpecifics;
|
||||
|
||||
static final SpyLogDelegator log = SpyLogFactory.getSpyLogDelegator();
|
||||
|
||||
/**
|
||||
* Optional package prefix to use for finding application generating point of SQL.
|
||||
*/
|
||||
static final String DebugStackPrefix;
|
||||
|
||||
/**
|
||||
* Flag to indicate debug trace info should be from app point of view (true if DebugStackPrefix is set.)
|
||||
*/
|
||||
static final boolean TraceFromApplication;
|
||||
|
||||
static
|
||||
{
|
||||
log.debug(" log4jdbc initializing...");
|
||||
|
||||
// look for additional driver specified in system properties
|
||||
DebugStackPrefix = System.getProperty("log4jdbc.debug.stack.prefix");
|
||||
TraceFromApplication = DebugStackPrefix != null && DebugStackPrefix.length() > 0;
|
||||
|
||||
if (TraceFromApplication)
|
||||
{
|
||||
log.debug(" debug entry point prefix is \"" + DebugStackPrefix + "\"");
|
||||
}
|
||||
|
||||
// the Set of drivers that this driver spy will preload at instantiation time
|
||||
// the driver will spy on any driver
|
||||
|
||||
Set subDrivers = new TreeSet();
|
||||
subDrivers.add("oracle.jdbc.driver.OracleDriver");
|
||||
subDrivers.add("com.sybase.jdbc2.jdbc.SybDriver");
|
||||
subDrivers.add("net.sourceforge.jtds.jdbc.Driver");
|
||||
subDrivers.add("com.microsoft.jdbc.sqlserver.SQLServerDriver");
|
||||
subDrivers.add("weblogic.jdbc.sqlserver.SQLServerDriver");
|
||||
subDrivers.add("com.informix.jdbc.IfxDriver");
|
||||
subDrivers.add("org.apache.derby.jdbc.ClientDriver");
|
||||
subDrivers.add("org.apache.derby.jdbc.EmbeddedDriver");
|
||||
|
||||
// look for additional driver specified in system properties
|
||||
String moreDrivers = System.getProperty("log4jdbc.drivers");
|
||||
|
||||
if (moreDrivers != null && moreDrivers.length() > 0)
|
||||
{
|
||||
String[] moreDriversArr = moreDrivers.split(",");
|
||||
|
||||
for (int i = 0; i < moreDriversArr.length; i++)
|
||||
{
|
||||
subDrivers.add(moreDriversArr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
DriverManager.registerDriver(new DriverSpy());
|
||||
}
|
||||
catch (SQLException s)
|
||||
{
|
||||
// this exception should never be thrown, JDBC just defines it
|
||||
// for completeness
|
||||
throw (RuntimeException) new RuntimeException("could not register log4jdbc driver!").initCause(s);
|
||||
}
|
||||
|
||||
// instantiate all the supported drivers and remove
|
||||
// those not found
|
||||
String driverClass;
|
||||
for (Iterator i = subDrivers.iterator(); i.hasNext();)
|
||||
{
|
||||
driverClass = (String) i.next();
|
||||
try
|
||||
{
|
||||
Class.forName(driverClass);
|
||||
log.debug("FOUND " + driverClass);
|
||||
}
|
||||
catch (ClassNotFoundException c)
|
||||
{
|
||||
// log.debug(" ... (not found) ..." + driverClass);
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (subDrivers.size() == 0)
|
||||
{
|
||||
log.debug("WARNING! log4jdbc couldn't find any underlying jdbc drivers.");
|
||||
}
|
||||
|
||||
SqlServerRdbmsSpecifics sqlServer = new SqlServerRdbmsSpecifics();
|
||||
|
||||
/** create lookup Map for specific rdbms formatters */
|
||||
rdbmsSpecifics = new HashMap();
|
||||
rdbmsSpecifics.put("oracle.jdbc.driver.OracleDriver", new OracleRdbmsSpecifics());
|
||||
rdbmsSpecifics.put("net.sourceforge.jtds.jdbc.Driver", sqlServer);
|
||||
rdbmsSpecifics.put("com.microsoft.jdbc.sqlserver.SQLServerDriver", sqlServer);
|
||||
rdbmsSpecifics.put("weblogic.jdbc.sqlserver.SQLServerDriver", sqlServer);
|
||||
|
||||
log.debug(" ... log4jdbc initialized!");
|
||||
}
|
||||
|
||||
static RdbmsSpecifics defaultRdbmsSpecifics = new RdbmsSpecifics();
|
||||
|
||||
/**
|
||||
* Get the RdbmsSpecifics object for a given Connection.
|
||||
*
|
||||
* @param conn jdbc connection to get RdbmsSpecifics for.
|
||||
* @return RdbmsSpecifics for the given connection.
|
||||
*/
|
||||
static RdbmsSpecifics getRdbmsSpecifics(Connection conn)
|
||||
{
|
||||
String driverName = "";
|
||||
try
|
||||
{
|
||||
DatabaseMetaData dbm = conn.getMetaData();
|
||||
driverName = dbm.getDriverName();
|
||||
}
|
||||
catch (SQLException s)
|
||||
{
|
||||
// silently fail
|
||||
}
|
||||
|
||||
log.debug("driver name is " + driverName);
|
||||
|
||||
RdbmsSpecifics r = (RdbmsSpecifics) rdbmsSpecifics.get(driverName);
|
||||
|
||||
if (r == null)
|
||||
{
|
||||
return defaultRdbmsSpecifics;
|
||||
}
|
||||
else
|
||||
{
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public DriverSpy()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the major version of the driver.
|
||||
* This call will be delegated to the underlying driver that is being spied upon.
|
||||
* (if there is no underlying driver found, then 1 will be returned.)
|
||||
*
|
||||
* @return the major version of the jdbc driver.
|
||||
*/
|
||||
public int getMajorVersion()
|
||||
{
|
||||
if (lastUnderlyingDriverRequested == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return lastUnderlyingDriverRequested.getMajorVersion();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minor version of the driver.
|
||||
* This call will be delegated to the underlying driver that is being spied upon.
|
||||
* (if there is no underlying driver found, then 0 will be returned.)
|
||||
*
|
||||
* @return the minor version of the jdbc driver.
|
||||
*/
|
||||
public int getMinorVersion()
|
||||
{
|
||||
if (lastUnderlyingDriverRequested == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return lastUnderlyingDriverRequested.getMinorVersion();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return <code>true</code> if the underlying driver is JDBC Compliant; <code>false</code>
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean jdbcCompliant()
|
||||
{
|
||||
return lastUnderlyingDriverRequested != null && lastUnderlyingDriverRequested.jdbcCompliant();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a <code>jdbc:log4</code> url and if the url is for an underlying driver
|
||||
* that this DriverSpy can spy on.
|
||||
*
|
||||
* @param url jdbc url.
|
||||
* @return true if this Driver can handle the url.
|
||||
* @throws SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean acceptsURL(String url) throws SQLException
|
||||
{
|
||||
Driver d = getUnderlyingDriver(url);
|
||||
if (d != null)
|
||||
{
|
||||
lastUnderlyingDriverRequested = d;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a <code>jdbc:log4</code> type URL, find the underlying real driver
|
||||
* that accepts the URL.
|
||||
*
|
||||
* @param url jdbc connection url.
|
||||
* @return Underlying driver for the given url. Null is returned if the url is not a <code>jdbc:log4</code> type URL
|
||||
* or there is no underlying driver that accepts the URL.
|
||||
* @throws SQLException if a database access error occurs.
|
||||
*/
|
||||
private Driver getUnderlyingDriver(String url) throws SQLException
|
||||
{
|
||||
if (url.startsWith("jdbc:log4"))
|
||||
{
|
||||
url = url.substring(9);
|
||||
|
||||
Enumeration e = DriverManager.getDrivers();
|
||||
|
||||
Driver d;
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
d = (Driver) e.nextElement();
|
||||
|
||||
if (d.acceptsURL(url))
|
||||
{
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Connection to the database from the underlying driver that this
|
||||
* DriverSpy is spying on.
|
||||
* <p/>
|
||||
* If logging is not enabled, an actual Connection to the database returned.
|
||||
* If logging is enabled, a ConnectionSpy object which wraps the real Connection
|
||||
* is returned.
|
||||
*
|
||||
* @param url jdbc connection url.
|
||||
* @param info a list of arbitrary string tag/value pairs as
|
||||
* connection arguments. Normally at least a "user" and
|
||||
* "password" property should be included.
|
||||
* @return a <code>Connection</code> object that represents a
|
||||
* connection to the URL.
|
||||
* @throws SQLException if a database access error occurs
|
||||
*/
|
||||
public Connection connect(String url, Properties info) throws SQLException
|
||||
{
|
||||
Driver d = getUnderlyingDriver(url);
|
||||
if (d == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
url = url.substring(9); // get actual URL that the real driver expects (strip off "jdbc:log4" from url)
|
||||
|
||||
lastUnderlyingDriverRequested = d;
|
||||
Connection c = d.connect(url, info);
|
||||
|
||||
if (c == null)
|
||||
{
|
||||
throw new SQLException("invalid or unknown driver url: " + url);
|
||||
}
|
||||
if (log.isJdbcLoggingEnabled())
|
||||
{
|
||||
ConnectionSpy cspy = new ConnectionSpy(c);
|
||||
RdbmsSpecifics r = null;
|
||||
String dclass = d.getClass().getName();
|
||||
if (dclass != null && dclass.length() > 0)
|
||||
{
|
||||
r = (RdbmsSpecifics) rdbmsSpecifics.get(dclass);
|
||||
}
|
||||
|
||||
if (r == null)
|
||||
{
|
||||
r = defaultRdbmsSpecifics;
|
||||
}
|
||||
cspy.setRdbmsSpecifics(r);
|
||||
return cspy;
|
||||
}
|
||||
else
|
||||
{
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information about the possible properties for the underlying driver.
|
||||
*
|
||||
* @param url the URL of the database to which to connect
|
||||
* @param info a proposed list of tag/value pairs that will be sent on
|
||||
* connect open
|
||||
* @return an array of <code>DriverPropertyInfo</code> objects describing
|
||||
* possible properties. This array may be an empty array if
|
||||
* no properties are required.
|
||||
* @throws SQLException if a database access error occurs
|
||||
*/
|
||||
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException
|
||||
{
|
||||
Driver d = getUnderlyingDriver(url);
|
||||
if (d == null)
|
||||
{
|
||||
return new DriverPropertyInfo[0];
|
||||
}
|
||||
|
||||
lastUnderlyingDriverRequested = d;
|
||||
return d.getPropertyInfo(url, info);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
/**
|
||||
* 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 org.apache.log4j.Level;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Delegates JDBC spy events to the log4j logger.
|
||||
*
|
||||
* @author Arthur Blake
|
||||
*/
|
||||
public class Log4jSpyLogDelegator implements SpyLogDelegator
|
||||
{
|
||||
/**
|
||||
* Create a SpyLogDelegator specific to the log4j logging system.
|
||||
*/
|
||||
public Log4jSpyLogDelegator()
|
||||
{
|
||||
}
|
||||
|
||||
// logs for sql and jdbc
|
||||
|
||||
/**
|
||||
* Logger that shows all JDBC calls on INFO level (exception ResultSet calls)
|
||||
*/
|
||||
public static final Logger jdbcLogger = Logger.getLogger("jdbc.audit");
|
||||
|
||||
/**
|
||||
* Logger that shows JDBC calls for ResultSet operations
|
||||
*/
|
||||
public static final Logger resultSetLogger = Logger.getLogger("jdbc.resultset");
|
||||
|
||||
/**
|
||||
* Logger that shows only the SQL that is occuring
|
||||
*/
|
||||
public static final Logger sqlOnlyLogger = Logger.getLogger("jdbc.sqlonly");
|
||||
|
||||
/**
|
||||
* Logger that shows the SQL timing, post execution
|
||||
*/
|
||||
public static final Logger sqlTimingLogger = Logger.getLogger("jdbc.sqltiming");
|
||||
|
||||
// admin/setup logging for log4jdbc.
|
||||
|
||||
/**
|
||||
* Logger just for debugging things within log4jdbc itself (admin, setup, etc.)
|
||||
*/
|
||||
public static final Logger debugLogger = Logger.getLogger("log4jdbc.debug");
|
||||
|
||||
/**
|
||||
* Determine if any of the spy loggers are turned on.
|
||||
*
|
||||
* @return true if any of the spy jdbc/sql loggers are enabled at error level or higher.
|
||||
*/
|
||||
public boolean isJdbcLoggingEnabled()
|
||||
{
|
||||
return jdbcLogger.isEnabledFor(Level.ERROR) || resultSetLogger.isEnabledFor(Level.ERROR) ||
|
||||
sqlOnlyLogger.isEnabledFor(Level.ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a jdbc method throws an Exception.
|
||||
*
|
||||
* @param spy the Spy wrapping the class that threw an Exception.
|
||||
* @param methodCall a description of the name and call parameters of the method generated the Exception.
|
||||
* @param e the Exception that was thrown.
|
||||
* @param sql optional sql that occured just before the exception occured.
|
||||
*/
|
||||
public void exceptionOccured(Spy spy, String methodCall, Exception e, String sql)
|
||||
{
|
||||
String classType = spy.getClassType();
|
||||
int spyNo = spy.getConnectionNumber();
|
||||
if (sql == null)
|
||||
{
|
||||
jdbcLogger.error(spyNo + ". " + classType + "." + methodCall, e);
|
||||
sqlOnlyLogger.error(spyNo + ". " + classType + "." + methodCall, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
jdbcLogger.error(spyNo + ". " + classType + "." + methodCall + " " + sql, e);
|
||||
sqlOnlyLogger.error(spyNo + ". " + classType + "." + methodCall + " " + sql, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a jdbc method from a Connection, Statement, PreparedStatement, CallableStatement or ResultSet
|
||||
* returns.
|
||||
*
|
||||
* @param spy the Spy wrapping the class that called the method that returned.
|
||||
* @param methodCall a description of the name and call parameters of the method that returned.
|
||||
* @param returnMsg return value converted to a String for integral types, or String representation for Object
|
||||
* return types this will be null for void return types.
|
||||
*/
|
||||
public void methodReturned(Spy spy, String methodCall, String returnMsg)
|
||||
{
|
||||
String classType = spy.getClassType();
|
||||
int spyNo = spy.getConnectionNumber();
|
||||
if (ResultSetSpy.classTypeDescription.equals(classType))
|
||||
{
|
||||
if (resultSetLogger.isDebugEnabled())
|
||||
{
|
||||
resultSetLogger.debug(
|
||||
spyNo + ". " + classType + "." + methodCall + " returned " + returnMsg + " " + getDebugInfo());
|
||||
}
|
||||
else if (resultSetLogger.isInfoEnabled())
|
||||
{
|
||||
resultSetLogger.info(spyNo + ". " + classType + "." + methodCall + " returned " + returnMsg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (jdbcLogger.isDebugEnabled())
|
||||
{
|
||||
jdbcLogger.debug(
|
||||
spyNo + ". " + classType + "." + methodCall + " returned " + returnMsg + " " + getDebugInfo());
|
||||
}
|
||||
else if (jdbcLogger.isInfoEnabled())
|
||||
{
|
||||
jdbcLogger.info(spyNo + ". " + classType + "." + methodCall + " returned " + returnMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a spied upon object is constructed.
|
||||
*
|
||||
* @param spy the Spy wrapping the class that called the method that returned.
|
||||
* @param constructionInfo information about the object construction
|
||||
*/
|
||||
public void constructorReturned(Spy spy, String constructionInfo)
|
||||
{
|
||||
// not used in this implementation -- yet
|
||||
}
|
||||
|
||||
|
||||
private static String nl = System.getProperty("line.separator");
|
||||
|
||||
/**
|
||||
* Special call that is called only for JDBC method calls that contain SQL.
|
||||
*
|
||||
* @param spy the Spy wrapping the class where the SQL occured.
|
||||
* @param methodCall a description of the name and call parameters of the method that generated the SQL.
|
||||
* @param sql sql that occured.
|
||||
*/
|
||||
public void sqlOccured(Spy spy, String methodCall, String sql)
|
||||
{
|
||||
int spyNo = spy.getConnectionNumber();
|
||||
|
||||
if (sqlOnlyLogger.isDebugEnabled())
|
||||
{
|
||||
sqlOnlyLogger.debug(getDebugInfo() + nl + spyNo + ". " + sql);
|
||||
}
|
||||
else if (sqlOnlyLogger.isInfoEnabled())
|
||||
{
|
||||
sqlOnlyLogger.info(sql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Special call that is called only for JDBC method calls that contain SQL.
|
||||
*
|
||||
* @param spy the Spy wrapping the class where the SQL occured.
|
||||
* @param execTime how long it took the sql to run, in msec.
|
||||
* @param methodCall a description of the name and call parameters of the method that generated the SQL.
|
||||
* @param sql sql that occured.
|
||||
*/
|
||||
public void sqlTimingOccured(Spy spy, long execTime, String methodCall, String sql)
|
||||
{
|
||||
int spyNo = spy.getConnectionNumber();
|
||||
|
||||
if (sqlTimingLogger.isDebugEnabled())
|
||||
{
|
||||
sqlTimingLogger.debug(getDebugInfo() + nl + spyNo + ". " + sql + " {executed in " + execTime + " msec}");
|
||||
}
|
||||
else if (sqlTimingLogger.isInfoEnabled())
|
||||
{
|
||||
sqlTimingLogger.info(sql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get debugging info - the module and line number that called the logger
|
||||
* version that prints the stack trace information from the point just before we got it (net.sf.log4jdbc)
|
||||
*
|
||||
* if the optional log4jdbc.debug.stack.prefix system property is defined then
|
||||
* the last call point from an application is shown in the debug
|
||||
* trace output, instead of the last direct caller into log4jdbc
|
||||
*
|
||||
* @return debugging info for whoever called into jdbc from within the application.
|
||||
*/
|
||||
private static String getDebugInfo()
|
||||
{
|
||||
Throwable t = new Throwable();
|
||||
t.fillInStackTrace();
|
||||
StackTraceElement[] stackTrace = t.getStackTrace();
|
||||
|
||||
if (stackTrace != null)
|
||||
{
|
||||
int firstLog4jdbcCall = 0;
|
||||
int lastApplicationCall = 0;
|
||||
|
||||
String className;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
{
|
||||
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();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a Setup and/or administrative log message for log4jdbc.
|
||||
*
|
||||
* @param msg message to log.
|
||||
*/
|
||||
public void debug(String msg)
|
||||
{
|
||||
debugLogger.debug(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* RDBMS specifics for the Oracle DB.
|
||||
*
|
||||
* @author Arthur Blake
|
||||
*/
|
||||
class OracleRdbmsSpecifics extends RdbmsSpecifics
|
||||
{
|
||||
OracleRdbmsSpecifics()
|
||||
{
|
||||
super();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* 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.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* Encapsulate sql formatting details about a particular relational database management system so that
|
||||
* accurate, useable SQL can be composed for that RDMBS.
|
||||
*
|
||||
* @author Arthur Blake
|
||||
*/
|
||||
class RdbmsSpecifics
|
||||
{
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
RdbmsSpecifics()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Format an Object that is being bound to a PreparedStatement parameter, for display. The goal is to reformat the
|
||||
* object in a format that can be re-run against the native SQL client of the particular Rdbms being used. This
|
||||
* class should be extended to provide formatting instances that format objects correctly for different RDBMS
|
||||
* types.
|
||||
*
|
||||
* @param object jdbc object to be formatted.
|
||||
* @return formatted dump of the object.
|
||||
*/
|
||||
String formatParameterObject(Object object)
|
||||
{
|
||||
if (object == null)
|
||||
{
|
||||
return "<null>";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (object instanceof String)
|
||||
{
|
||||
return "'" + object + "'";
|
||||
}
|
||||
else if (object instanceof Date)
|
||||
{
|
||||
return object.toString();
|
||||
}
|
||||
else if (object instanceof Timestamp)
|
||||
{
|
||||
return object.toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return object.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user