You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by ce...@apache.org on 2004/05/19 19:58:09 UTC
cvs commit: logging-log4j/tests/src/java/org/apache/log4j/db FullCycleDBTest.java
ceki 2004/05/19 10:58:09
Modified: tests/input/db postgresql.properties.sample
mysql.properties.sample
tests build.xml
src/java/org/apache/log4j/db DataSourceConnectionSource.java
JNDIConnectionSource.java
DriverManagerConnectionSource.java
tests/src/java/org/apache/log4j/db FullCycleDBTest.java
Added: tests/input/db append-with-drivermanager1.xml
append-with-pooled-datasource1.xml
read-with-drivermanager1.xml
read-with-pooled-datasource1.xml
src/java/org/apache/log4j/db/dialect Util.java
Removed: tests/input/db readPooled1.xml writeCS1.xml readCS1.xml
Log:
- Improved testbed for the o.a.l.db package.
- The JNDIConnectionSource is still not integrated with the testbed.
Revision Changes Path
1.2 +2 -1 logging-log4j/tests/input/db/postgresql.properties.sample
Index: postgresql.properties.sample
===================================================================
RCS file: /home/cvs/logging-log4j/tests/input/db/postgresql.properties.sample,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- postgresql.properties.sample 18 May 2004 16:50:43 -0000 1.1
+++ postgresql.properties.sample 19 May 2004 17:58:09 -0000 1.2
@@ -8,7 +8,8 @@
# The DataSource class for PostgreSQL
dataSourceClass=org.postgresql.jdbc2.optional.SimpleDataSource
-
+# Native pooled DataSource class for PostgreSQL
+pooledDataSourceClass=org.postgresql.jdbc3.Jdbc3PoolingDataSource
# =======================================================
# The following parameters should be set for your machine.
1.3 +3 -0 logging-log4j/tests/input/db/mysql.properties.sample
Index: mysql.properties.sample
===================================================================
RCS file: /home/cvs/logging-log4j/tests/input/db/mysql.properties.sample,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- mysql.properties.sample 18 May 2004 16:50:43 -0000 1.2
+++ mysql.properties.sample 19 May 2004 17:58:09 -0000 1.3
@@ -4,9 +4,12 @@
# The JDBC driver class for MySQL
driverClass=com.mysql.jdbc.Driver
+
# The DataSource class for MySQL
dataSourceClass=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
+# Native pooled DataSource class for MySQL
+pooledDataSourceClass=com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
# The following parameters should be set for your machine.
url=jdbc:mysql:///test
1.1 logging-log4j/tests/input/db/append-with-drivermanager1.xml
Index: append-with-drivermanager1.xml
===================================================================
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration>
<log4j:configuration debug="true">
<substitutionProperty file="input/db/db.properties"/>
<appender name="DB" class="org.apache.log4j.db.DBAppender">
<connectionSource class="org.apache.log4j.db.DriverManagerConnectionSource">
<param name="driverClass" value="${driverClass}"/>
<param name="url" value="${url}"/>
<param name="user" value="${user}"/>
<param name="password" value="${password}"/>
</connectionSource>
</appender>
<appender name="VECTOR" class="org.apache.log4j.VectorAppender">
</appender>
<root>
<level value ="debug"/>
<appender-ref ref="DB" />
<appender-ref ref="VECTOR" />
</root>
</log4j:configuration>
1.1 logging-log4j/tests/input/db/append-with-pooled-datasource1.xml
Index: append-with-pooled-datasource1.xml
===================================================================
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration>
<log4j:configuration debug="true">
<substitutionProperty file="input/db/db.properties"/>
<appender name="DB" class="org.apache.log4j.db.DBAppender">
<connectionSource class="org.apache.log4j.db.DataSourceConnectionSource">
<dataSource class="${pooledDataSourceClass}">
<param name="url" value="${url}"/>
<param name="serverName" value="${serverName}"/>
<param name="databaseName" value="${databaseName}"/>
</dataSource>
<param name="user" value="${user}"/>
<param name="password" value="${password}"/>
</connectionSource>
</appender>
<appender name="VECTOR" class="org.apache.log4j.VectorAppender">
</appender>
<root>
<level value ="debug"/>
<appender-ref ref="DB" />
<appender-ref ref="VECTOR" />
</root>
</log4j:configuration>
1.1 logging-log4j/tests/input/db/read-with-drivermanager1.xml
Index: read-with-drivermanager1.xml
===================================================================
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration>
<log4j:configuration debug="true">
<substitutionProperty file="input/db/db.properties"/>
<plugin name="DB1" class="org.apache.log4j.db.DBReceiver">
<connectionSource class="org.apache.log4j.db.DriverManagerConnectionSource">
<param name="driverClass" value="${driverClass}"/>
<param name="url" value="${url}"/>
<param name="user" value="${user}"/>
<param name="password" value="${password}"/>
</connectionSource>
</plugin>
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="READING %relative %level %logger - %message%n"/>
</layout>
</appender>
<appender name="VECTOR" class="org.apache.log4j.VectorAppender">
</appender>
<root>
<level value="debug"/>
<appender-ref ref="VECTOR" />
<appender-ref ref="CONSOLE" />
</root>
</log4j:configuration>
1.1 logging-log4j/tests/input/db/read-with-pooled-datasource1.xml
Index: read-with-pooled-datasource1.xml
===================================================================
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration>
<log4j:configuration debug="true">
<substitutionProperty file="input/db/db.properties"/>
<substitutionProperty file="input/db/db.properties"/>
<plugin name="DBPlugin" class="org.apache.log4j.db.DBReceiver">
<connectionSource class="org.apache.log4j.db.DataSourceConnectionSource">
<dataSource class="${pooledDataSourceClass}">
<param name="url" value="${url}"/>
<param name="serverName" value="${serverName}"/>
<param name="databaseName" value="${databaseName}"/>
</dataSource>
<param name="user" value="${user}"/>
<param name="password" value="${password}"/>
</connectionSource>
</plugin>
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="READING %relative %level %logger - %message%n"/>
</layout>
</appender>
<appender name="VECTOR" class="org.apache.log4j.VectorAppender">
</appender>
<root>
<level value="debug"/>
<appender-ref ref="VECTOR" />
<appender-ref ref="CONSOLE" />
</root>
</log4j:configuration>
1.55 +53 -17 logging-log4j/tests/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/logging-log4j/tests/build.xml,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -r1.54 -r1.55
--- build.xml 18 May 2004 16:50:43 -0000 1.54
+++ build.xml 19 May 2004 17:58:09 -0000 1.55
@@ -504,7 +504,21 @@
defining access as well as necessary class files are available. Otherwise,
the test is skipped.
-->
+
+
+ <!-- The target that performs the actual test -->
+ <target name="DB">
+ <junit printsummary="yes" fork="no" haltonfailure="yes">
+ <sysproperty key="toto" value="${toto}"/>
+ <sysproperty key="appendConfigFile" value="${appendConfigFile}"/>
+ <sysproperty key="readConfigFile" value="${readConfigFile}"/>
+ <classpath refid="tests.classpath"/>
+ <formatter type="plain" usefile="false"/>
+ <test name="org.apache.log4j.db.FullCycleDBTest" />
+ </junit>
+ </target>
+ <!-- ============ MySQL specific tests ============== -->
<target name="mysqlCheck">
<condition property="mysql-present">
<and>
@@ -515,22 +529,33 @@
</and>
</condition>
</target>
-
-
+
<target name="mysql" depends="mysqlCheck, build" if="mysql-present">
-
<delete file="./input/db/db.properties"/>
<echo message="MySQL available"/>
<copy file="./input/db/mysql.properties" tofile="./input/db/db.properties"/>
+
+ <echo message="Running test case with DriverManager config file"/>
+ <antcall target="DB">
+ <param name="appendConfigFile" value="./input/db/append-with-drivermanager1.xml"/>
+ <param name="readConfigFile" value="./input/db/read-with-drivermanager1.xml"/>
+ </antcall>
+
+ <echo message="Running test case with DataSource"/>
+ <antcall target="DB">
+ <param name="appendConfigFile" value="./input/db/append-with-datasource1.xml"/>
+ <param name="readConfigFile" value="./input/db/read-with-datasource1.xml"/>
+ </antcall>
+
+ <echo message="Running test case with *pooled* DataSource"/>
+ <antcall target="DB">
+ <param name="appendConfigFile" value="./input/db/append-with-pooled-datasource1.xml"/>
+ <param name="readConfigFile" value="./input/db/read-with-pooled-datasource1.xml"/>
+ </antcall>
- <junit printsummary="yes" fork="no" haltonfailure="yes">
- <sysproperty key="runLen" value="100"/>
- <classpath refid="tests.classpath"/>
- <formatter type="plain" usefile="false"/>
- <test name="org.apache.log4j.db.FullCycleDBTest" />
- </junit>
</target>
+ <!-- ============ PostgreSQL specific tests ============== -->
<target name="postgresqlCheck">
<condition property="postgresql-present">
@@ -542,18 +567,29 @@
</and>
</condition>
</target>
-
+
<target name="postgresql" depends="postgresqlCheck, build" if="postgresql-present">
<delete file="./input/db/db.properties"/>
<echo message="PostgreSQL available"/>
<copy file="./input/db/postgresql.properties" tofile="./input/db/db.properties"/>
-
- <junit printsummary="yes" fork="no" haltonfailure="yes">
- <sysproperty key="runLen" value="100"/>
- <classpath refid="tests.classpath"/>
- <formatter type="plain" usefile="false"/>
- <test name="org.apache.log4j.db.FullCycleDBTest" />
- </junit>
+
+ <echo message="Running test case with DriverManager config file"/>
+ <antcall target="DB">
+ <param name="appendConfigFile" value="./input/db/append-with-drivermanager1.xml"/>
+ <param name="readConfigFile" value="./input/db/read-with-drivermanager1.xml"/>
+ </antcall>
+
+ <echo message="Running test case with DataSource"/>
+ <antcall target="DB">
+ <param name="appendConfigFile" value="./input/db/append-with-datasource1.xml"/>
+ <param name="readConfigFile" value="./input/db/read-with-datasource1.xml"/>
+ </antcall>
+
+ <echo message="Running test case with *pooled* DataSource"/>
+ <antcall target="DB">
+ <param name="appendConfigFile" value="./input/db/append-with-pooled-datasource1.xml"/>
+ <param name="readConfigFile" value="./input/db/read-with-pooled-datasource1.xml"/>
+ </antcall>
</target>
<!-- ================================================================= -->
1.1 logging-log4j/src/java/org/apache/log4j/db/dialect/Util.java
Index: Util.java
===================================================================
/*
* Copyright 1999,2004 The Apache Software Foundation.
*
* 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 org.apache.log4j.db.dialect;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.apache.log4j.db.ConnectionSource;
import org.apache.log4j.helpers.LogLog;
/**
*
* @author Ceki Gulcu
*
*/
public class Util {
private static final String POSTGRES_PART = "postgresql";
private static final String MYSQL_PART = "mysql";
private static final String ORACLE_PART = "oracle";
private static final String MSSQL_PART = "mssqlserver4";
static public int discoverSQLDialect(Connection connection ) {
int dialectCode = 0;
try {
DatabaseMetaData meta = connection.getMetaData();
String dbName = meta.getDatabaseProductName().toLowerCase();
LogLog.debug("**db name is " + dbName);
if (dbName.indexOf(POSTGRES_PART) != -1) {
LogLog.debug("POSTGRESQL dialect selected");
return ConnectionSource.POSTGRES_DIALECT;
} else if (dbName.indexOf(MYSQL_PART) != -1) {
return ConnectionSource.MYSQL_DIALECT;
} else if (dbName.indexOf(ORACLE_PART) != -1) {
return ConnectionSource.ORACLE_DIALECT;
} else if (dbName.indexOf(MSSQL_PART) != -1) {
return ConnectionSource.MSSQL_DIALECT;
} else {
return ConnectionSource.UNKNOWN_DIALECT;
}
} catch (SQLException sqle) {
// we can't do much here
}
return dialectCode;
}
}
1.3 +9 -35 logging-log4j/src/java/org/apache/log4j/db/DataSourceConnectionSource.java
Index: DataSourceConnectionSource.java
===================================================================
RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/db/DataSourceConnectionSource.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- DataSourceConnectionSource.java 18 May 2004 17:00:08 -0000 1.2
+++ DataSourceConnectionSource.java 19 May 2004 17:58:09 -0000 1.3
@@ -16,10 +16,10 @@
package org.apache.log4j.db;
+import org.apache.log4j.db.dialect.Util;
import org.apache.log4j.helpers.LogLog;
import java.sql.Connection;
-import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import javax.sql.DataSource;
@@ -35,16 +35,12 @@
* @author Ceki Gülcü
*/
public class DataSourceConnectionSource extends ConnectionSourceSkeleton {
- private static final String POSTGRES_PART = "postgresql";
- private static final String MYSQL_PART = "mysql";
- private static final String ORACLE_PART = "oracle";
- private static final String MSSQL_PART = "mssqlserver4";
-
+
private DataSource dataSource;
int dialectCode;
public void activateOptions() {
- LogLog.debug("**********DataSourceConnectionSource.activateOptions called");
+ //LogLog.debug("**********DataSourceConnectionSource.activateOptions called");
if (dataSource == null) {
LogLog.warn("WARNING: No data source specified");
@@ -52,7 +48,12 @@
errorHandler.error("WARNING: No data source specified");
}
} else {
- dialectCode = discoverSQLDialect();
+ try {
+ Connection connection = getConnection();
+ dialectCode = Util.discoverSQLDialect(connection);
+ } catch(SQLException se) {
+ LogLog.warn("Could not discover the dialect to use.", se);
+ }
}
}
@@ -84,33 +85,6 @@
}
public int getSQLDialect() {
- return dialectCode;
- }
- public int discoverSQLDialect() {
- int dialectCode = 0;
-
- try {
- Connection connection = getConnection();
- DatabaseMetaData meta = connection.getMetaData();
- String dbName = meta.getDatabaseProductName().toLowerCase();
- LogLog.debug("**************db name is " + dbName);
-
- if (dbName.indexOf(POSTGRES_PART) != -1) {
- LogLog.debug("POSTGRESQL dialect selected");
- return ConnectionSource.POSTGRES_DIALECT;
- } else if (dbName.indexOf(MYSQL_PART) != -1) {
- return ConnectionSource.MYSQL_DIALECT;
- } else if (dbName.indexOf(ORACLE_PART) != -1) {
- return ConnectionSource.ORACLE_DIALECT;
- } else if (dbName.indexOf(MSSQL_PART) != -1) {
- return ConnectionSource.MSSQL_DIALECT;
- } else {
- return ConnectionSource.UNKNOWN_DIALECT;
- }
- } catch (SQLException sqle) {
- // we can't do much here
- }
-
return dialectCode;
}
}
1.3 +20 -12 logging-log4j/src/java/org/apache/log4j/db/JNDIConnectionSource.java
Index: JNDIConnectionSource.java
===================================================================
RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/db/JNDIConnectionSource.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- JNDIConnectionSource.java 18 May 2004 16:50:42 -0000 1.2
+++ JNDIConnectionSource.java 19 May 2004 17:58:09 -0000 1.3
@@ -25,6 +25,7 @@
import javax.rmi.PortableRemoteObject;
import javax.sql.DataSource;
+import org.apache.log4j.db.dialect.Util;
import org.apache.log4j.helpers.LogLog;
/**
@@ -65,8 +66,26 @@
extends ConnectionSourceSkeleton {
private String jndiLocation = null;
private DataSource dataSource = null;
+ int dialectCode = ConnectionSource.UNKNOWN_DIALECT;
/**
+ * @see org.apache.log4j.spi.OptionHandler#activateOptions()
+ */
+ public void activateOptions() {
+ if (jndiLocation == null && errorHandler != null) {
+ errorHandler.error("No JNDI location specified for JNDIConnectionSource.");
+ }
+
+ try {
+ Connection connection = getConnection();
+ dialectCode = Util.discoverSQLDialect(connection);
+ } catch(SQLException se) {
+ LogLog.warn("Could not discover the dialect to use.", se);
+ }
+
+ }
+
+ /**
* @see org.apache.log4j.db.ConnectionSource#getConnection()
*/
public Connection getConnection()
@@ -100,17 +119,6 @@
return conn;
}
-
- /**
- * @see org.apache.log4j.spi.OptionHandler#activateOptions()
- */
- public void activateOptions() {
- if (jndiLocation == null && errorHandler != null) {
- errorHandler.error("No JNDI location specified for JNDIConnectionSource.");
- }
- }
-
-
/**
* Returns the jndiLocation.
* @return String
@@ -139,7 +147,7 @@
public int getSQLDialect() {
- return 0;
+ return dialectCode;
}
private DataSource lookupDataSource()
1.3 +2 -2 logging-log4j/src/java/org/apache/log4j/db/DriverManagerConnectionSource.java
Index: DriverManagerConnectionSource.java
===================================================================
RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/db/DriverManagerConnectionSource.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- DriverManagerConnectionSource.java 18 May 2004 17:00:08 -0000 1.2
+++ DriverManagerConnectionSource.java 19 May 2004 17:58:09 -0000 1.3
@@ -154,8 +154,8 @@
return ConnectionSource.MYSQL_DIALECT;
} else if (url.indexOf(ORACLE_PART) != -1) {
return ConnectionSource.ORACLE_DIALECT;
- } else if (url.indexOf(ORACLE_PART) != -1) {
- return ConnectionSource.ORACLE_DIALECT;
+ } else if (url.indexOf(MSSQL_PART) != -1) {
+ return ConnectionSource.MSSQL_DIALECT;
} else {
return ConnectionSource.UNKNOWN_DIALECT;
}
1.5 +39 -30 logging-log4j/tests/src/java/org/apache/log4j/db/FullCycleDBTest.java
Index: FullCycleDBTest.java
===================================================================
RCS file: /home/cvs/logging-log4j/tests/src/java/org/apache/log4j/db/FullCycleDBTest.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- FullCycleDBTest.java 18 May 2004 16:50:43 -0000 1.4
+++ FullCycleDBTest.java 19 May 2004 17:58:09 -0000 1.5
@@ -46,6 +46,9 @@
Vector witnessEvents;
LoggerRepository lrWrite;
LoggerRepository lrRead;
+ String appendConfigFile = null;
+ String readConfigFile = null;
+
/*
* @see TestCase#setUp()
@@ -53,6 +56,11 @@
protected void setUp()
throws Exception {
super.setUp();
+ appendConfigFile = System.getProperty("appendConfigFile");
+ assertNotNull("[appendConfigFile] property must be set for this test", appendConfigFile);
+ readConfigFile = System.getProperty("readConfigFile");
+ assertNotNull("[readConfigFile] property must be set for this test", readConfigFile);
+
witnessEvents = new Vector();
lrWrite = new Hierarchy(new RootLogger(Level.DEBUG));
IntializationUtil.log4jInternalConfiguration(lrWrite);
@@ -91,7 +99,7 @@
public void testSingleOutput()
throws Exception {
JoranConfigurator jc1 = new JoranConfigurator();
- jc1.doConfigure("input/db/writeCS1.xml", lrWrite);
+ jc1.doConfigure(appendConfigFile, lrWrite);
long startTime = System.currentTimeMillis();
LogLog.info("***startTime is "+startTime);
@@ -105,33 +113,33 @@
assertEquals(1, witnessEvents.size());
// now read it back
- readBack("input/db/readCS1.xml", startTime);
+ readBack(readConfigFile, startTime);
}
-
- public void testDataSource()
- throws Exception {
-
- LogLog.setInternalDebugging(true);
- JoranConfigurator jc1 = new JoranConfigurator();
- jc1.doConfigure("input/db/append-with-datasource1.xml", lrWrite);
-
-
- long startTime = System.currentTimeMillis();
- LogLog.info("startTime is "+startTime);
-
- // Write out just one log message
- Logger out = lrWrite.getLogger("testSingleOutput.out");
- out.debug("some message"+startTime);
-
- VectorAppender witnessAppender = (VectorAppender) lrWrite.getRootLogger().getAppender("VECTOR");
- witnessEvents = witnessAppender.getVector();
- assertEquals(1, witnessEvents.size());
-
- LogLog.info("----------------------------------------------");
- // now read it back
- readBack("input/db/read-with-datasource1.xml", startTime);
- }
+//
+// public void testDataSource()
+// throws Exception {
+//
+// LogLog.setInternalDebugging(true);
+// JoranConfigurator jc1 = new JoranConfigurator();
+// jc1.doConfigure("input/db/append-with-datasource1.xml", lrWrite);
+//
+//
+// long startTime = System.currentTimeMillis();
+// LogLog.info("startTime is "+startTime);
+//
+// // Write out just one log message
+// Logger out = lrWrite.getLogger("testSingleOutput.out");
+// out.debug("some message"+startTime);
+//
+// VectorAppender witnessAppender = (VectorAppender) lrWrite.getRootLogger().getAppender("VECTOR");
+// witnessEvents = witnessAppender.getVector();
+// assertEquals(1, witnessEvents.size());
+//
+// LogLog.info("----------------------------------------------");
+// // now read it back
+// readBack("input/db/read-with-datasource1.xml", startTime);
+// }
@@ -147,7 +155,7 @@
*/
public void testAllFields() {
JoranConfigurator jc1 = new JoranConfigurator();
- jc1.doConfigure("input/db/writeCS1.xml", lrWrite);
+ jc1.doConfigure(appendConfigFile, lrWrite);
long startTime = System.currentTimeMillis();
@@ -174,7 +182,7 @@
witnessEvents = witnessAppender.getVector();
assertEquals(2, witnessEvents.size());
- readBack("input/db/readCS1.xml", startTime);
+ readBack(readConfigFile, startTime);
}
@@ -264,8 +272,9 @@
public static Test suite() {
TestSuite suite = new TestSuite();
//suite.addTest(new FullCycleDBTest("test1"));
- //suite.addTest(new FullCycleDBTest("testSingleOutput"));
- suite.addTest(new FullCycleDBTest("testDataSource"));
+ suite.addTest(new FullCycleDBTest("testSingleOutput"));
+ //suite.addTest(new FullCycleDBTest("testAllFields"));
+ //suite.addTest(new FullCycleDBTest("testDataSource"));
return suite;
---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org