You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ni...@apache.org on 2014/02/07 23:35:03 UTC
svn commit: r1565838 - in /logging/log4j/log4j2/trunk:
log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/
log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jdbc/
log4j-core/src/test/resources/org/apache/logging/lo...
Author: nickwilliams
Date: Fri Feb 7 22:35:02 2014
New Revision: 1565838
URL: http://svn.apache.org/r1565838
Log:
Removed the DataSourceConnectionSource and the <DriverManager> plugin for the JDBC Appender. It is not safe to use. Please use the DataSource or factory connection sources backed by a connection pool.
Removed:
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/DriverManagerConnectionSource.java
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jdbc/DriverManagerConnectionSourceTest.java
logging/log4j/log4j2/trunk/log4j-core/src/test/resources/org/apache/logging/log4j/core/appender/db/jdbc/log4j2-h2-driver-manager.xml
logging/log4j/log4j2/trunk/log4j-core/src/test/resources/org/apache/logging/log4j/core/appender/db/jdbc/log4j2-hsqldb-driver-manager.xml
Modified:
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jdbc/AbstractJdbcAppenderTest.java
logging/log4j/log4j2/trunk/src/changes/changes.xml
logging/log4j/log4j2/trunk/src/site/xdoc/manual/appenders.xml
Modified: logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jdbc/AbstractJdbcAppenderTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jdbc/AbstractJdbcAppenderTest.java?rev=1565838&r1=1565837&r2=1565838&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jdbc/AbstractJdbcAppenderTest.java (original)
+++ logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/db/jdbc/AbstractJdbcAppenderTest.java Fri Feb 7 22:35:02 2014
@@ -167,56 +167,6 @@ public abstract class AbstractJdbcAppend
}
@Test
- public void testDriverManagerConfig() throws Exception {
- this.setUp("dmLogEntry", "log4j2-" + this.databaseType + "-driver-manager.xml");
-
- final RuntimeException exception = new RuntimeException("Hello, world!");
- final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- final PrintWriter writer = new PrintWriter(outputStream);
- exception.printStackTrace(writer);
- writer.close();
- final String stackTrace = outputStream.toString();
-
- final long millis = System.currentTimeMillis();
-
- final Logger logger = LogManager.getLogger(this.getClass().getName() + ".testDriverManagerConfig");
- logger.info("Test my message 01.");
- logger.warn("This is another message 02.", exception);
-
- final Statement statement = this.connection.createStatement();
- final ResultSet resultSet = statement.executeQuery("SELECT * FROM dmLogEntry ORDER BY id");
-
- assertTrue("There should be at least one row.", resultSet.next());
-
- long date = resultSet.getTimestamp("eventDate").getTime();
- assertTrue("The date should be later than pre-logging (1).", date >= millis);
- assertTrue("The date should be earlier than now (1).", date <= System.currentTimeMillis());
- assertEquals("The literal column is not correct (1).", "Literal Value Test String",
- resultSet.getString("literalColumn"));
- assertEquals("The level column is not correct (1).", "INFO", resultSet.getNString("level"));
- assertEquals("The logger column is not correct (1).", logger.getName(), resultSet.getNString("logger"));
- assertEquals("The message column is not correct (1).", "Test my message 01.", resultSet.getString("message"));
- assertEquals("The exception column is not correct (1).", "",
- IOUtils.readStringAndClose(resultSet.getNClob("exception").getCharacterStream(), -1));
-
- assertTrue("There should be two rows.", resultSet.next());
-
- date = resultSet.getTimestamp("eventDate").getTime();
- assertTrue("The date should be later than pre-logging (2).", date >= millis);
- assertTrue("The date should be earlier than now (2).", date <= System.currentTimeMillis());
- assertEquals("The literal column is not correct (2).", "Literal Value Test String",
- resultSet.getString("literalColumn"));
- assertEquals("The level column is not correct (2).", "WARN", resultSet.getNString("level"));
- assertEquals("The logger column is not correct (2).", logger.getName(), resultSet.getNString("logger"));
- assertEquals("The message column is not correct (2).", "This is another message 02.",
- resultSet.getString("message"));
- assertEquals("The exception column is not correct (2).", stackTrace,
- IOUtils.readStringAndClose(resultSet.getNClob("exception").getCharacterStream(), -1));
-
- assertFalse("There should not be three rows.", resultSet.next());
- }
-
- @Test
public void testFactoryMethodConfig() throws Exception {
this.setUp("fmLogEntry", "log4j2-" + this.databaseType + "-factory-method.xml");
@@ -269,7 +219,7 @@ public abstract class AbstractJdbcAppend
@Test
public void testPerformanceOfAppenderWith10000Events() throws Exception {
- this.setUp("dmLogEntry", "log4j2-" + this.databaseType + "-driver-manager.xml");
+ this.setUp("fmLogEntry", "log4j2-" + this.databaseType + "-factory-method.xml");
final RuntimeException exception = new RuntimeException("Hello, world!");
@@ -294,7 +244,7 @@ public abstract class AbstractJdbcAppend
final Statement statement = this.connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
- final ResultSet resultSet = statement.executeQuery("SELECT * FROM dmLogEntry ORDER BY id");
+ final ResultSet resultSet = statement.executeQuery("SELECT * FROM fmLogEntry ORDER BY id");
resultSet.last();
assertEquals("The number of records is not correct.", 10001, resultSet.getRow());
Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1565838&r1=1565837&r2=1565838&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
+++ logging/log4j/log4j2/trunk/src/changes/changes.xml Fri Feb 7 22:35:02 2014
@@ -21,8 +21,13 @@
</properties>
<body>
<release version="2.0-RC1" date="2014-MM-DD" description="Bug fixes and enhancements">
+ <action dev="nickwilliams" type="delete">
+ Removed the DataSourceConnectionSource and the <DriverManager> plugin for the JDBC Appender. It is not
+ safe to use. Please use the DataSource or factory connection sources backed by a connection pool.
+ </action>
<action issue="LOG4J2-530" dev="rpopma" type="add">
- (JMX) JMX Client GUI should dynamically update when LoggerContext MBeans are registered/unregistered in MBean server.
+ (JMX) JMX Client GUI should dynamically update when LoggerContext MBeans are registered/unregistered in MBean
+ server.
</action>
<action issue="LOG4J2-500" dev="rpopma" type="fix">
(JMX) Unloading one webapp unloads JMX MBeans for all webapps.
Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/appenders.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/appenders.xml?rev=1565838&r1=1565837&r2=1565838&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/site/xdoc/manual/appenders.xml (original)
+++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/appenders.xml Fri Feb 7 22:35:02 2014
@@ -1055,8 +1055,9 @@
<a name="JDBCAppender"/>
<subsection name="JDBCAppender">
<p>The JDBCAppender writes log events to a relational database table using standard JDBC. It can be configured
- to obtain JDBC connections using the <code>DriverManager</code>, a JNDI <code>DataSource</code> or a custom
- factory method.</p>
+ to obtain JDBC connections using a JNDI <code>DataSource</code> or a custom factory method. Whichever
+ approach you take, it <strong><em>must</em></strong> be backed by a connection pool. Otherwise, logging
+ performance will suffer greatly.</p>
<table>
<tr>
<th>Parameter Name</th>
@@ -1107,32 +1108,8 @@
<caption align="top">JDBCAppender Parameters</caption>
</table>
<p>When configuring the JDBCAppender, you must specify a <code>ConnectionSource</code> implementation from
- which the Appender gets JDBC connections. You must use exactly one of the
- <code><DriverManager></code>, <code><DataSource></code>, or
- <code><ConnectionFactory></code> nested elements.</p>
- <table>
- <tr>
- <th>Parameter Name</th>
- <th>Type</th>
- <th>Description</th>
- </tr>
- <tr>
- <td>url</td>
- <td>String</td>
- <td><em>Required.</em> The JDBC URL, such as <code>jdbc:mysql://example.org:3306/exampleDb</code>.</td>
- </tr>
- <tr>
- <td>username</td>
- <td>String</td>
- <td>The user to connect as, if required.</td>
- </tr>
- <tr>
- <td>password</td>
- <td>String</td>
- <td>The password to authenticate with, if a username is specified.</td>
- </tr>
- <caption align="top">DriverManager Parameters</caption>
- </table>
+ which the Appender gets JDBC connections. You must use exactly one of the <code><DataSource></code>
+ or <code><ConnectionFactory></code> nested elements.</p>
<table>
<tr>
<th>Parameter Name</th>
@@ -1142,8 +1119,9 @@
<tr>
<td>jndiName</td>
<td>String</td>
- <td><em>Required.</em> The full, prefixed JNDI name that the data source is bound to, such as
- <code>java:/comp/env/jdbc/LoggingDatabase</code>.</td>
+ <td><em>Required.</em> The full, prefixed JNDI name that the <code>javax.sql.DataSource</code> is bound
+ to, such as <code>java:/comp/env/jdbc/LoggingDatabase</code>. The <code>DataSource</code> must be backed
+ by a connection pool; otherwise, logging will be very slow.</td>
</tr>
<caption align="top">DataSource Parameters</caption>
</table>
@@ -1164,8 +1142,10 @@
<td>Method</td>
<td><em>Required.</em> The name of a static factory method for obtaining JDBC connections. This method
must have no parameters and its return type must be either <code>java.sql.Connection</code> or
- <code>javax.sql.DataSource</code>. If the method returns <code>Connection</code>s, it must return a new
- connection every time it is called.</td>
+ <code>DataSource</code>. If the method returns <code>Connection</code>s, it must obtain them from a
+ connection pool (and they will be returned to the pool when Log4j is done with them); otherwise, logging
+ will be very slow. If the method returns a <code>DataSource</code>, the <code>DataSource</code> will
+ only be retrieved once, and it must be backed by a connection pool for the same reasons.</td>
</tr>
<caption align="top">ConnectionFactory Parameters</caption>
</table>
@@ -1229,26 +1209,8 @@
<caption align="top">Column Parameters</caption>
</table>
<p>
- Here are a few sample configurations for the JDBCAppender:
-
- <pre class="prettyprint linenums lang-xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="error">
- <Appenders>
- <JDBC name="databaseAppender" tableName="application_log">
- <DriverManager url="jdbc:mysql://example.org:3306/exampleDb" username="logging" password="abc123" />
- <Column name="eventDate" isEventTimestamp="true" />
- <Column name="level" pattern="%level" />
- <Column name="logger" pattern="%logger" />
- <Column name="message" pattern="%message" />
- <Column name="exception" pattern="%ex{full}" />
- </JDBC>
- </Appenders>
- <Loggers>
- <Root level="warn">
- <AppenderRef ref="databaseAppender"/>
- </Root>
- </Loggers>
-</Configuration>]]></pre>
+ Here are a couple sample configurations for the JDBCAppender, as well as a sample factory implementation
+ that uses Commons Pooling and Commons DBCP to pool database connections:
<pre class="prettyprint linenums lang-xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
@@ -1273,7 +1235,7 @@
<Configuration status="error">
<Appenders>
<JDBC name="databaseAppender" tableName="LOGGING.APPLICATION_LOG">
- <ConnectionFactory class="net.example.db.ConnectionFactory" method="getNewDatabaseConnection" />
+ <ConnectionFactory class="net.example.db.ConnectionFactory" method="getDatabaseConnection" />
<Column name="EVENT_ID" literal="LOGGING.APPLICATION_LOG_SEQUENCE.NEXTVAL" />
<Column name="EVENT_DATE" isEventTimestamp="true" />
<Column name="LEVEL" pattern="%level" />
@@ -1288,6 +1250,47 @@
</Root>
</Loggers>
</Configuration>]]></pre>
+ <pre class="prettyprint linenums lang-java"><![CDATA[package net.example.db;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import javax.sql.DataSource;
+
+import org.apache.commons.dbcp.DriverManagerConnectionFactory;
+import org.apache.commons.dbcp.PoolableConnection;
+import org.apache.commons.dbcp.PoolableConnectionFactory;
+import org.apache.commons.dbcp.PoolingDataSource;
+import org.apache.commons.pool.impl.GenericObjectPool;
+
+public class ConnectionFactory {
+ private static interface Singleton {
+ final ConnectionFactory INSTANCE = new ConnectionFactory();
+ }
+
+ private final DataSource dataSource;
+
+ private ConnectionFactory() {
+ Properties properties = new Properties();
+ properties.setProperty("user", "logging");
+ properties.setProperty("password", "abc123"); // or get properties from some configuration file
+
+ GenericObjectPool<PoolableConnection> pool = new GenericObjectPool<PoolableConnection>();
+ DriverManagerConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
+ "jdbc:mysql://example.org:3306/exampleDb", properties
+ );
+ new PoolableConnectionFactory(
+ connectionFactory, pool, null, "SELECT 1", 3, false, false, Connection.TRANSACTION_READ_COMMITTED
+ );
+
+ this.dataSource = new PoolingDataSource(pool);
+ }
+
+ public static Connection getDatabaseConnection() throws SQLException {
+ return Singleton.INSTANCE.dataSource.getConnection();
+ }
+}]]></pre>
</p>
</subsection>
<a name="JMSQueueAppender"/>