diff --git a/README.md b/README.md
index 48bb155..e71b918 100644
--- a/README.md
+++ b/README.md
@@ -28,10 +28,10 @@ More details are at the [Project site](http://log4mongo.org/display/PUB/Log4mong
* Jay Patel
# Pre-requisites
-* JDK 1.5+
-* MongoDB Server v2.0+ (tested with 2.6.5)
-* MongoDB Java Driver v2.7+ (tested with 2.12.4)
-* Log4J 1.2+ (tested with 1.2.16 - note: tests won't work on earlier versions due to Log4J API changes)
+* JDK 1.8+
+* MongoDB Server v3.0+ (tested with 3.4.1)
+* MongoDB Java Driver v3.0+ (tested with 3.4.1)
+* Log4J 1.2+ (tested with 1.2.17 - note: tests won't work on earlier versions due to Log4J API changes)
* Privateer (used only in unit tests - a copy is in the lib dir, in case you can't get it
from the central Maven repo)
diff --git a/lib/privateer-0.1.1.jar b/lib/privateer-0.1.1.jar
deleted file mode 100644
index 7471931..0000000
Binary files a/lib/privateer-0.1.1.jar and /dev/null differ
diff --git a/pom.xml b/pom.xml
index 11e03cb..706546c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,175 +1,171 @@
- 4.0.0
- org.log4mongo
- log4mongo-java
- jar
- log4mongo-java
- Log4J Appender for MongoDB
- 0.7.5
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ 4.0.0
+ org.log4mongo
+ log4mongo-java
+ jar
+ log4mongo-java
+ Log4J Appender for MongoDB
+ 0.8.0
-
- org.sonatype.oss
- oss-parent
- 7
-
+
+ org.sonatype.oss
+ oss-parent
+ 7
+
-
-
- UTF-8
-
-
- UTF-8
-
-
+
+
+ UTF-8
+
+
+ UTF-8
+
+
-
-
- Apache 2
- http://www.apache.org/licenses/LICENSE-2.0.txt
- repo
-
-
+
+
+ Apache 2
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ repo
+
+
-
-
- pmonks
- Peter Monks
- pmonks@gmail.com
-
-
- jsk
- Jozef Sevcik
- sevcik@styxys.com
-
-
- wombatnation
- Robert Stewart
- robert@wombatnation.com
-
-
+
+
+ pmonks
+ Peter Monks
+ pmonks@gmail.com
+
+
+ jsk
+ Jozef Sevcik
+ sevcik@styxys.com
+
+
+ wombatnation
+ Robert Stewart
+ robert@wombatnation.com
+
+
+ ScheRas
+ Šimon Schierreich
+ simon.schierreich@messenger.cz
+
+
-
- Github
- https://github.com/log4mongo/log4mongo-java/issues
-
+
+ Github
+ https://github.com/log4mongo/log4mongo-java/issues
+
-
- scm:git:git@github.com:log4mongo/log4mongo-java.git
- scm:git:git@github.com:log4mongo/log4mongo-java.git
- scm:git:git@github.com:log4mongo/log4mongo-java
-
+
+ scm:git:git@github.com:log4mongo/log4mongo-java.git
+ scm:git:git@github.com:log4mongo/log4mongo-java.git
+ scm:git:git@github.com:log4mongo/log4mongo-java
+
-
-
- junit
- junit
- 4.8.2
- test
-
-
- log4j
- log4j
- 1.2.16
- provided
-
-
- com.sun.jmx
- jmxri
-
-
- com.sun.jdmk
- jmxtools
-
-
-
-
- org.mongodb
- mongo-java-driver
- 2.12.4
-
-
- com.wombatnation
- privateer
- 0.1.1
- test
-
-
+
+
+ log4j
+ log4j
+ 1.2.17
+ provided
+
+
+ org.mongodb
+ mongo-java-driver
+ 3.4.2
+
-
-
-
- org.apache.maven.wagon
- wagon-webdav
- 1.0-beta-2
-
-
-
-
- maven-compiler-plugin
- 3.2
-
- 1.5
- 1.5
-
-
-
- org.apache.maven.plugins
- maven-release-plugin
- 2.0-beta-9
-
-
- org.apache.maven.plugins
- maven-gpg-plugin
- 1.5
-
-
- sign-artifacts
- verify
-
- sign
-
-
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
- 2.4
-
-
- attach-sources
-
- jar
-
-
-
-
-
-
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ com.wombatnation
+ privateer
+ 0.1.1
+ test
+
+
-
-
- release
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
-
-
- attach-javadocs
-
- jar
-
-
-
-
-
-
-
-
+
+
+
+ org.apache.maven.wagon
+ wagon-webdav
+ 1.0-beta-2
+
+
+
+
+ maven-compiler-plugin
+ 3.6.0
+
+ 1.8
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 2.5.3
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.6
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.0.1
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+
+
+
+
+ release
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+
+
+
diff --git a/src/main/java/org/log4mongo/BsonAppender.java b/src/main/java/org/log4mongo/BsonAppender.java
index 76da620..045c617 100644
--- a/src/main/java/org/log4mongo/BsonAppender.java
+++ b/src/main/java/org/log4mongo/BsonAppender.java
@@ -19,16 +19,15 @@
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
+import org.bson.BSONObject;
-import com.mongodb.DBObject;
/**
- * Abstract Log4J Appender class that stores log events in the BSON format. Concrete
- * implementation classes must implement append(DBObject) to store the BSON
- * representation of a LoggingEvent.
+ * Abstract Log4J Appender class that stores log events in the BSON format. Concrete implementation classes must
+ * implement append(DBObject) to store the BSON representation of a LoggingEvent.
*
* An example BSON structure for a single log entry is as follows:
- *
+ *
*
* {
* "_id" : ObjectId("f1c0895fd5eee04a445deb00"),
@@ -58,7 +57,8 @@
* "method" : "testLogWithChainedExceptions",
* "lineNumber" : 147,
* "class" : {
- * "fullyQualifiedClassName" : "org.log4mongo.TestMongoDbAppender",
+ * "fullyQualifiedClassName" :
+ * "org.log4mongo.TestMongoDbAppender",
* "package" : [ "org", "log4mongo" ],
* "className" : "TestMongoDbAppender"
* }
@@ -67,7 +67,8 @@
* "method" : "invoke0",
* "lineNumber" : -2,
* "class" : {
- * "fullyQualifiedClassName" : "sun.reflect.NativeMethodAccessorImpl",
+ * "fullyQualifiedClassName" :
+ * "sun.reflect.NativeMethodAccessorImpl",
* "package" : [ "sun", "reflect" ],
* "className" : "NativeMethodAccessorImpl"
* }
@@ -95,47 +96,49 @@
* }
*
*
- * @see Log4J Appender Interface
+ * @see Log4J Appender
+ * Interface
* @see MongoDB
*/
public abstract class BsonAppender extends AppenderSkeleton {
- private LoggingEventBsonifier bsonifier = new LoggingEventBsonifierImpl();
-
- /**
- * @see org.apache.log4j.Appender#requiresLayout()
- */
- public boolean requiresLayout() {
- return(false);
- }
- /**
- * @see org.apache.log4j.AppenderSkeleton#append(org.apache.log4j.spi.LoggingEvent)
- */
- @Override
- protected void append(final LoggingEvent loggingEvent) {
- DBObject bson = bsonifier.bsonify(loggingEvent);
- append(bson);
- }
+ private LoggingEventBsonifier bsonifier = new LoggingEventBsonifierImpl();
+
+ /**
+ * @see org.apache.log4j.Appender#requiresLayout()
+ */
+ public boolean requiresLayout() {
+ return ( false );
+ }
+
+ /**
+ * @see org.apache.log4j.AppenderSkeleton#append(org.apache.log4j.spi.LoggingEvent)
+ */
+ @Override
+ protected void append( final LoggingEvent loggingEvent ) {
+ BSONObject bson = bsonifier.bsonify( loggingEvent );
+ append( bson );
+ }
+
+ /**
+ * Method implemented by a concrete class to store the BSON object.
+ *
+ * @param bson The BSON representation of a Logging Event that will be stored
+ */
+ protected abstract void append( BSONObject bson );
- /**
- * Method implemented by a concrete class to store the BSON object.
- *
- * @param bson The BSON representation of a Logging Event that will be stored
- */
- protected abstract void append(DBObject bson);
+ /**
+ * @return Object used to Bsonify LoggingEvent objects
+ */
+ public LoggingEventBsonifier getBsonifier() {
+ return bsonifier;
+ }
- /**
- * @return Object used to Bsonify LoggingEvent objects
- */
- public LoggingEventBsonifier getBsonifier() {
- return bsonifier;
- }
+ /**
+ * @param bsonifier Object used to Bsonify LoggingEvent objects
+ */
+ public void setBsonifier( LoggingEventBsonifier bsonifier ) {
+ this.bsonifier = bsonifier;
+ }
- /**
- * @param bsonifier Object used to Bsonify LoggingEvent objects
- */
- public void setBsonifier(LoggingEventBsonifier bsonifier) {
- this.bsonifier = bsonifier;
- }
-
}
diff --git a/src/main/java/org/log4mongo/ExtendedMongoDbAppender.java b/src/main/java/org/log4mongo/ExtendedMongoDbAppender.java
index 739396d..14e620f 100644
--- a/src/main/java/org/log4mongo/ExtendedMongoDbAppender.java
+++ b/src/main/java/org/log4mongo/ExtendedMongoDbAppender.java
@@ -2,74 +2,77 @@
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
+import org.bson.BSONObject;
import java.util.LinkedHashMap;
import java.util.Map;
+
/**
* This appender is designed so you can add top level elements to each logging
* entry. Users can also extend MongoDbAppender themselves in order to add the
* top level elements.
- *
+ *
* Use case: A desire to use a common appender for unified logs across different
* code bases, such that commonly logged elements be consistent, such as
* application, eventType, etc. This is enabled by adding a property called
* rootLevelProperties with a key=value list of elements to be added to the root
* level log. See log4j.properties.sample for an example.
- *
+ *
* @author Mick Knutson (http://www.baselogic.com)
*/
public class ExtendedMongoDbAppender extends MongoDbAppender {
- private DBObject constants;
+ private DBObject constants;
- private Map rootProperties = new LinkedHashMap();
+ private Map rootProperties = new LinkedHashMap ();
- /**
- * @see org.apache.log4j.AppenderSkeleton#activateOptions()
- */
- @Override
- public void activateOptions() {
- super.activateOptions();
- initTopLevelProperties();
- }
+ /**
+ * @see org.apache.log4j.AppenderSkeleton#activateOptions()
+ */
+ @Override
+ public void activateOptions() {
+ super.activateOptions();
+ initTopLevelProperties();
+ }
- /**
- * Initialize custom top level elements to appear in a log event
- *
- * Allows users to create custom properties to be added to the top level
- * log event.
- */
- public void initTopLevelProperties() {
- constants = new BasicDBObject();
- if (!rootProperties.isEmpty()){
- constants.putAll(rootProperties);
- }
- }
+ /**
+ * Initialize custom top level elements to appear in a log event
+ *
+ * Allows users to create custom properties to be added to the top level
+ * log event.
+ */
+ public void initTopLevelProperties() {
+ constants = new BasicDBObject();
+ if ( !rootProperties.isEmpty() ) {
+ constants.putAll( rootProperties );
+ }
+ }
- /**
- * This will handle spaces and empty values
- * A = minus- & C=equals= & E==F
- * For XML, must escape (&)
- * @param rootLevelProperties
- */
- public void setRootLevelProperties(String rootLevelProperties) {
- for (String keyValue : rootLevelProperties.split(" *& *")) {
- String[] pairs = keyValue.split(" *= *", 2);
- rootProperties.put(pairs[0], pairs.length == 1 ? "" : pairs[1]);
- }
- }
+ /**
+ * This will handle spaces and empty values
+ * A = minus- & C=equals= & E==F
+ * For XML, must escape (&)
+ *
+ * @param rootLevelProperties
+ */
+ public void setRootLevelProperties( String rootLevelProperties ) {
+ for ( String keyValue : rootLevelProperties.split( " *& *" ) ) {
+ String[] pairs = keyValue.split( " *= *", 2 );
+ rootProperties.put( pairs[ 0 ], pairs.length == 1 ? "" : pairs[ 1 ] );
+ }
+ }
- /**
- * @param bson The BSON object to insert into a MongoDB database collection.
- */
- @Override
- public void append(DBObject bson) {
- if (this.isInitialized() && bson != null) {
- if (constants != null) {
- bson.putAll(constants);
- }
- super.append(bson);
- }
- }
+ /**
+ * @param bson The BSON object to insert into a MongoDB database collection.
+ */
+ @Override
+ public void append( BSONObject bson ) {
+ if ( this.isInitialized() && bson != null ) {
+ if ( constants != null ) {
+ bson.putAll( constants );
+ }
+ super.append( bson );
+ }
+ }
}
diff --git a/src/main/java/org/log4mongo/LoggingEventBsonifier.java b/src/main/java/org/log4mongo/LoggingEventBsonifier.java
index 230b4b6..523ce25 100644
--- a/src/main/java/org/log4mongo/LoggingEventBsonifier.java
+++ b/src/main/java/org/log4mongo/LoggingEventBsonifier.java
@@ -18,13 +18,15 @@
package org.log4mongo;
import org.apache.log4j.spi.LoggingEvent;
+import org.bson.BSONObject;
-import com.mongodb.DBObject;
/**
* Interface implemented by classes that create a BSON representation of a Log4J
* LoggingEvent. LoggingEventBsonifierImpl is the default implementation.
*/
public interface LoggingEventBsonifier {
- DBObject bsonify(LoggingEvent loggingEvent);
+
+ BSONObject bsonify( LoggingEvent loggingEvent );
+
}
diff --git a/src/main/java/org/log4mongo/LoggingEventBsonifierImpl.java b/src/main/java/org/log4mongo/LoggingEventBsonifierImpl.java
index 8684eff..237702d 100644
--- a/src/main/java/org/log4mongo/LoggingEventBsonifierImpl.java
+++ b/src/main/java/org/log4mongo/LoggingEventBsonifierImpl.java
@@ -17,6 +17,15 @@
package org.log4mongo;
+import com.mongodb.BasicDBList;
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.spi.LocationInfo;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.log4j.spi.ThrowableInformation;
+import org.bson.BSONObject;
+
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -25,300 +34,301 @@
import java.util.List;
import java.util.Map;
-import org.apache.log4j.helpers.LogLog;
-import org.apache.log4j.spi.LocationInfo;
-import org.apache.log4j.spi.LoggingEvent;
-import org.apache.log4j.spi.ThrowableInformation;
-
-import com.mongodb.BasicDBList;
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBObject;
/**
* Default implementation class for creating a BSON representation of a Log4J LoggingEvent.
*/
public class LoggingEventBsonifierImpl implements LoggingEventBsonifier {
- // Main log event elements
- private static final String KEY_TIMESTAMP = "timestamp";
- private static final String KEY_LEVEL = "level";
- private static final String KEY_THREAD = "thread";
- private static final String KEY_MESSAGE = "message";
- private static final String KEY_LOGGER_NAME = "loggerName";
- // Source code location
- private static final String KEY_FILE_NAME = "fileName";
- private static final String KEY_METHOD = "method";
- private static final String KEY_LINE_NUMBER = "lineNumber";
- private static final String KEY_CLASS = "class";
- // Class info
- private static final String KEY_FQCN = "fullyQualifiedClassName";
- private static final String KEY_PACKAGE = "package";
- private static final String KEY_CLASS_NAME = "className";
- // Exceptions
- private static final String KEY_THROWABLES = "throwables";
- private static final String KEY_EXCEPTION_MESSAGE = "message";
- private static final String KEY_STACK_TRACE = "stackTrace";
- // Host and Process Info
- private static final String KEY_HOST = "host";
- private static final String KEY_PROCESS = "process";
- private static final String KEY_HOSTNAME = "name";
- private static final String KEY_IP = "ip";
- // MDC Properties
- private static final String KEY_MDC_PROPERTIES = "properties";
-
- private final DBObject hostInfo = new BasicDBObject();
-
- public LoggingEventBsonifierImpl() {
- setupNetworkInfo();
- }
-
- private void setupNetworkInfo() {
- hostInfo.put(KEY_PROCESS, ManagementFactory.getRuntimeMXBean().getName());
- try {
- hostInfo.put(KEY_HOSTNAME, InetAddress.getLocalHost().getHostName());
- hostInfo.put(KEY_IP, InetAddress.getLocalHost().getHostAddress());
- } catch (UnknownHostException e) {
- LogLog.warn(e.getMessage());
- }
- }
-
- /**
- * BSONifies a single Log4J LoggingEvent object.
- *
- * @param loggingEvent
- * The LoggingEvent object to BSONify (may be null) .
- * @return The BSONified equivalent of the LoggingEvent object (may be null) .
- */
- public DBObject bsonify(final LoggingEvent loggingEvent) {
- DBObject result = null;
-
- if (loggingEvent != null) {
- result = new BasicDBObject();
-
- result.put(KEY_TIMESTAMP, new Date(loggingEvent.getTimeStamp()));
- nullSafePut(result, KEY_LEVEL, loggingEvent.getLevel().toString());
- nullSafePut(result, KEY_THREAD, loggingEvent.getThreadName());
- nullSafePut(result, KEY_MESSAGE, loggingEvent.getRenderedMessage());
- nullSafePut(result, KEY_LOGGER_NAME, bsonifyClassName(loggingEvent.getLoggerName()));
-
- addMDCInformation(result, loggingEvent.getProperties());
- addLocationInformation(result, loggingEvent.getLocationInformation());
- addThrowableInformation(result, loggingEvent.getThrowableInformation());
- addHostnameInformation(result);
- }
-
- return (result);
- }
-
- /**
- * Adds MDC Properties to the DBObject.
- *
- * @param bson
- * The root DBObject
- * @param props
- * MDC Properties to be logged
- */
- protected void addMDCInformation(DBObject bson, final Map props) {
- if (props != null && props.size() > 0) {
-
- BasicDBObject mdcProperties = new BasicDBObject();
- String key;
- // Copy MDC properties into document
- for (Map.Entry entry : props.entrySet()) {
- key = (entry.getKey().toString().contains("."))
- ? entry.getKey().toString().replaceAll("\\.", "_")
- : entry.getKey().toString();
- nullSafePut(mdcProperties, key, entry.getValue().toString());
- }
- bson.put(KEY_MDC_PROPERTIES, mdcProperties);
- }
- }
-
- /**
- * Adds the LocationInfo object to an existing BSON object.
- *
- * @param bson
- * The BSON object to add the location info to (must not be null) .
- * @param locationInfo
- * The LocationInfo object to add to the BSON object (may be null) .
- */
- protected void addLocationInformation(DBObject bson, final LocationInfo locationInfo) {
- if (locationInfo != null) {
- nullSafePut(bson, KEY_FILE_NAME, locationInfo.getFileName());
- nullSafePut(bson, KEY_METHOD, locationInfo.getMethodName());
- nullSafePut(bson, KEY_LINE_NUMBER, locationInfo.getLineNumber());
- nullSafePut(bson, KEY_CLASS, bsonifyClassName(locationInfo.getClassName()));
- }
- }
-
- /**
- * Adds the ThrowableInformation object to an existing BSON object.
- *
- * @param bson
- * The BSON object to add the throwable info to (must not be null) .
- * @param throwableInfo
- * The ThrowableInformation object to add to the BSON object (may be null) .
- */
- @SuppressWarnings(value = "unchecked")
- protected void addThrowableInformation(DBObject bson, final ThrowableInformation throwableInfo) {
- if (throwableInfo != null) {
- Throwable currentThrowable = throwableInfo.getThrowable();
- List throwables = new BasicDBList();
-
- while (currentThrowable != null) {
- DBObject throwableBson = bsonifyThrowable(currentThrowable);
-
- if (throwableBson != null) {
- throwables.add(throwableBson);
- }
-
- currentThrowable = currentThrowable.getCause();
- }
-
- if (throwables.size() > 0) {
- bson.put(KEY_THROWABLES, throwables);
- }
- }
- }
-
- /**
- * Adds the current process's host name, VM name and IP address
- *
- * @param bson
- * A BSON object containing host name, VM name and IP address
- */
- protected void addHostnameInformation(DBObject bson) {
- nullSafePut(bson, KEY_HOST, hostInfo);
- }
-
- /**
- * BSONifies the given Throwable.
- *
- * @param throwable
- * The throwable object to BSONify (may be null) .
- * @return The BSONified equivalent of the Throwable object (may be null) .
- */
- protected DBObject bsonifyThrowable(final Throwable throwable) {
- DBObject result = null;
-
- if (throwable != null) {
- result = new BasicDBObject();
-
- nullSafePut(result, KEY_EXCEPTION_MESSAGE, throwable.getMessage());
- nullSafePut(result, KEY_STACK_TRACE, bsonifyStackTrace(throwable.getStackTrace()));
- }
-
- return (result);
- }
-
- /**
- * BSONifies the given stack trace.
- *
- * @param stackTrace
- * The stack trace object to BSONify (may be null) .
- * @return The BSONified equivalent of the stack trace object (may be null) .
- */
- protected DBObject bsonifyStackTrace(final StackTraceElement[] stackTrace) {
- BasicDBList result = null;
-
- if (stackTrace != null && stackTrace.length > 0) {
- result = new BasicDBList();
-
- for (StackTraceElement element : stackTrace) {
- DBObject bson = bsonifyStackTraceElement(element);
-
- if (bson != null) {
- result.add(bson);
- }
- }
- }
-
- return (result);
- }
-
- /**
- * BSONifies the given stack trace element.
- *
- * @param element
- * The stack trace element object to BSONify (may be null) .
- * @return The BSONified equivalent of the stack trace element object (may be null) .
- */
- protected DBObject bsonifyStackTraceElement(final StackTraceElement element) {
- DBObject result = null;
-
- if (element != null) {
- result = new BasicDBObject();
-
- nullSafePut(result, KEY_FILE_NAME, element.getFileName());
- nullSafePut(result, KEY_METHOD, element.getMethodName());
- nullSafePut(result, KEY_LINE_NUMBER, element.getLineNumber());
- nullSafePut(result, KEY_CLASS, bsonifyClassName(element.getClassName()));
- }
-
- return (result);
- }
-
- /**
- * BSONifies the given class name.
- *
- * @param className
- * The class name to BSONify (may be null) .
- * @return The BSONified equivalent of the class name (may be null) .
- */
- @SuppressWarnings(value = "unchecked")
- protected DBObject bsonifyClassName(final String className) {
- DBObject result = null;
-
- if (className != null && className.trim().length() > 0) {
- result = new BasicDBObject();
-
- result.put(KEY_FQCN, className);
-
- List packageComponents = new BasicDBList();
- String[] packageAndClassName = className.split("\\.");
-
- packageComponents.addAll(Arrays.asList(packageAndClassName));
- // Requires Java 6
- // packageComponents.addAll(Arrays.asList(Arrays.copyOf(packageAndClassName,
- // packageAndClassName.length - 1)));
-
- if (packageComponents.size() > 0) {
- result.put(KEY_PACKAGE, packageComponents);
- }
-
- result.put(KEY_CLASS_NAME, packageAndClassName[packageAndClassName.length - 1]);
- }
-
- return (result);
- }
-
- /**
- * Adds the given value to the given key, except if it's null (in which case this method does
- * nothing).
- *
- * @param bson
- * The BSON object to add the key/value to (must not be null) .
- * @param key
- * The key of the object (must not be null) .
- * @param value
- * The value of the object (may be null) .
- */
- protected void nullSafePut(DBObject bson, final String key, final Object value) {
- if (value != null) {
- if (value instanceof String) {
- String stringValue = (String) value;
- if (stringValue.trim().length() > 0) {
- bson.put(key, stringValue);
- }
- } else if (value instanceof StringBuffer) {
- String stringValue = ((StringBuffer) value).toString();
- if (stringValue.trim().length() > 0) {
- bson.put(key, stringValue);
- }
- } else {
- bson.put(key, value);
- }
- }
- }
+ // Main log event elements
+ private static final String KEY_TIMESTAMP = "timestamp";
+
+ private static final String KEY_LEVEL = "level";
+
+ private static final String KEY_THREAD = "thread";
+
+ private static final String KEY_MESSAGE = "message";
+
+ private static final String KEY_LOGGER_NAME = "loggerName";
+
+ // Source code location
+ private static final String KEY_FILE_NAME = "fileName";
+
+ private static final String KEY_METHOD = "method";
+
+ private static final String KEY_LINE_NUMBER = "lineNumber";
+
+ private static final String KEY_CLASS = "class";
+
+ // Class info
+ private static final String KEY_FQCN = "fullyQualifiedClassName";
+
+ private static final String KEY_PACKAGE = "package";
+
+ private static final String KEY_CLASS_NAME = "className";
+
+ // Exceptions
+ private static final String KEY_THROWABLES = "throwables";
+
+ private static final String KEY_EXCEPTION_MESSAGE = "message";
+
+ private static final String KEY_STACK_TRACE = "stackTrace";
+
+ // Host and Process Info
+ private static final String KEY_HOST = "host";
+
+ private static final String KEY_PROCESS = "process";
+
+ private static final String KEY_HOSTNAME = "name";
+
+ private static final String KEY_IP = "ip";
+
+ // MDC Properties
+ private static final String KEY_MDC_PROPERTIES = "properties";
+
+ private final DBObject hostInfo = new BasicDBObject();
+
+ public LoggingEventBsonifierImpl() {
+ setupNetworkInfo();
+ }
+
+ private void setupNetworkInfo() {
+ hostInfo.put( KEY_PROCESS, ManagementFactory.getRuntimeMXBean().getName() );
+ try {
+ hostInfo.put( KEY_HOSTNAME, InetAddress.getLocalHost().getHostName() );
+ hostInfo.put( KEY_IP, InetAddress.getLocalHost().getHostAddress() );
+ } catch ( UnknownHostException e ) {
+ LogLog.warn( e.getMessage() );
+ }
+ }
+
+ /**
+ * BSONifies a single Log4J LoggingEvent object.
+ *
+ * @param loggingEvent The LoggingEvent object to BSONify (may be null) .
+ *
+ * @return The BSONified equivalent of the LoggingEvent object (may be null) .
+ */
+ public BSONObject bsonify( final LoggingEvent loggingEvent ) {
+ DBObject result = null;
+
+ if ( loggingEvent != null ) {
+ result = new BasicDBObject();
+
+ result.put( KEY_TIMESTAMP, new Date( loggingEvent.getTimeStamp() ) );
+ nullSafePut( result, KEY_LEVEL, loggingEvent.getLevel().toString() );
+ nullSafePut( result, KEY_THREAD, loggingEvent.getThreadName() );
+ nullSafePut( result, KEY_MESSAGE, loggingEvent.getRenderedMessage() );
+ nullSafePut( result, KEY_LOGGER_NAME, bsonifyClassName( loggingEvent.getLoggerName() ) );
+
+ addMDCInformation( result, loggingEvent.getProperties() );
+ addLocationInformation( result, loggingEvent.getLocationInformation() );
+ addThrowableInformation( result, loggingEvent.getThrowableInformation() );
+ addHostnameInformation( result );
+ }
+
+ return ( result );
+ }
+
+ /**
+ * Adds MDC Properties to the DBObject.
+ *
+ * @param bson The root DBObject
+ * @param props MDC Properties to be logged
+ */
+ protected void addMDCInformation( DBObject bson, final Map props ) {
+ if ( props != null && props.size() > 0 ) {
+
+ BasicDBObject mdcProperties = new BasicDBObject();
+ String key;
+ // Copy MDC properties into document
+ for ( Map.Entry entry : props.entrySet() ) {
+ key = ( entry.getKey().toString().contains( "." ) )
+ ? entry.getKey().toString().replaceAll( "\\.", "_" )
+ : entry.getKey().toString();
+ nullSafePut( mdcProperties, key, entry.getValue().toString() );
+ }
+ bson.put( KEY_MDC_PROPERTIES, mdcProperties );
+ }
+ }
+
+ /**
+ * Adds the LocationInfo object to an existing BSON object.
+ *
+ * @param bson The BSON object to add the location info to (must not be null) .
+ * @param locationInfo The LocationInfo object to add to the BSON object (may be null) .
+ */
+ protected void addLocationInformation( DBObject bson, final LocationInfo locationInfo ) {
+ if ( locationInfo != null ) {
+ nullSafePut( bson, KEY_FILE_NAME, locationInfo.getFileName() );
+ nullSafePut( bson, KEY_METHOD, locationInfo.getMethodName() );
+ nullSafePut( bson, KEY_LINE_NUMBER, locationInfo.getLineNumber() );
+ nullSafePut( bson, KEY_CLASS, bsonifyClassName( locationInfo.getClassName() ) );
+ }
+ }
+
+ /**
+ * Adds the ThrowableInformation object to an existing BSON object.
+ *
+ * @param bson The BSON object to add the throwable info to (must not be null) .
+ * @param throwableInfo The ThrowableInformation object to add to the BSON object (may be null) .
+ */
+ @SuppressWarnings( value = "unchecked" )
+ protected void addThrowableInformation( DBObject bson, final ThrowableInformation throwableInfo ) {
+ if ( throwableInfo != null ) {
+ Throwable currentThrowable = throwableInfo.getThrowable();
+ List throwables = new BasicDBList();
+
+ while ( currentThrowable != null ) {
+ DBObject throwableBson = bsonifyThrowable( currentThrowable );
+
+ if ( throwableBson != null ) {
+ throwables.add( throwableBson );
+ }
+
+ currentThrowable = currentThrowable.getCause();
+ }
+
+ if ( throwables.size() > 0 ) {
+ bson.put( KEY_THROWABLES, throwables );
+ }
+ }
+ }
+
+ /**
+ * Adds the current process's host name, VM name and IP address
+ *
+ * @param bson A BSON object containing host name, VM name and IP address
+ */
+ protected void addHostnameInformation( DBObject bson ) {
+ nullSafePut( bson, KEY_HOST, hostInfo );
+ }
+
+ /**
+ * BSONifies the given Throwable.
+ *
+ * @param throwable The throwable object to BSONify (may be null) .
+ *
+ * @return The BSONified equivalent of the Throwable object (may be null) .
+ */
+ protected DBObject bsonifyThrowable( final Throwable throwable ) {
+ DBObject result = null;
+
+ if ( throwable != null ) {
+ result = new BasicDBObject();
+
+ nullSafePut( result, KEY_EXCEPTION_MESSAGE, throwable.getMessage() );
+ nullSafePut( result, KEY_STACK_TRACE, bsonifyStackTrace( throwable.getStackTrace() ) );
+ }
+
+ return ( result );
+ }
+
+ /**
+ * BSONifies the given stack trace.
+ *
+ * @param stackTrace The stack trace object to BSONify (may be null) .
+ *
+ * @return The BSONified equivalent of the stack trace object (may be null) .
+ */
+ protected DBObject bsonifyStackTrace( final StackTraceElement[] stackTrace ) {
+ BasicDBList result = null;
+
+ if ( stackTrace != null && stackTrace.length > 0 ) {
+ result = new BasicDBList();
+
+ for ( StackTraceElement element : stackTrace ) {
+ DBObject bson = bsonifyStackTraceElement( element );
+
+ if ( bson != null ) {
+ result.add( bson );
+ }
+ }
+ }
+
+ return ( result );
+ }
+
+ /**
+ * BSONifies the given stack trace element.
+ *
+ * @param element The stack trace element object to BSONify (may be null) .
+ *
+ * @return The BSONified equivalent of the stack trace element object (may be null) .
+ */
+ protected DBObject bsonifyStackTraceElement( final StackTraceElement element ) {
+ DBObject result = null;
+
+ if ( element != null ) {
+ result = new BasicDBObject();
+
+ nullSafePut( result, KEY_FILE_NAME, element.getFileName() );
+ nullSafePut( result, KEY_METHOD, element.getMethodName() );
+ nullSafePut( result, KEY_LINE_NUMBER, element.getLineNumber() );
+ nullSafePut( result, KEY_CLASS, bsonifyClassName( element.getClassName() ) );
+ }
+
+ return ( result );
+ }
+
+ /**
+ * BSONifies the given class name.
+ *
+ * @param className The class name to BSONify (may be null) .
+ *
+ * @return The BSONified equivalent of the class name (may be null) .
+ */
+ @SuppressWarnings( value = "unchecked" )
+ protected DBObject bsonifyClassName( final String className ) {
+ DBObject result = null;
+
+ if ( className != null && className.trim().length() > 0 ) {
+ result = new BasicDBObject();
+
+ result.put( KEY_FQCN, className );
+
+ List packageComponents = new BasicDBList();
+ String[] packageAndClassName = className.split( "\\." );
+
+ packageComponents.addAll( Arrays.asList( packageAndClassName ) );
+ // Requires Java 6
+ // packageComponents.addAll(Arrays.asList(Arrays.copyOf(packageAndClassName,
+ // packageAndClassName.length - 1)));
+
+ if ( packageComponents.size() > 0 ) {
+ result.put( KEY_PACKAGE, packageComponents );
+ }
+
+ result.put( KEY_CLASS_NAME, packageAndClassName[ packageAndClassName.length - 1 ] );
+ }
+
+ return ( result );
+ }
+
+ /**
+ * Adds the given value to the given key, except if it's null (in which case this method does
+ * nothing).
+ *
+ * @param bson The BSON object to add the key/value to (must not be null) .
+ * @param key The key of the object (must not be null) .
+ * @param value The value of the object (may be null) .
+ */
+ protected void nullSafePut( DBObject bson, final String key, final Object value ) {
+ if ( value != null ) {
+ if ( value instanceof String ) {
+ String stringValue = (String) value;
+ if ( stringValue.trim().length() > 0 ) {
+ bson.put( key, stringValue );
+ }
+ } else if ( value instanceof StringBuffer ) {
+ String stringValue = ( (StringBuffer) value ).toString();
+ if ( stringValue.trim().length() > 0 ) {
+ bson.put( key, stringValue );
+ }
+ } else {
+ bson.put( key, value );
+ }
+ }
+ }
}
diff --git a/src/main/java/org/log4mongo/MongoDbAppender.java b/src/main/java/org/log4mongo/MongoDbAppender.java
index 76cc4d4..a143810 100644
--- a/src/main/java/org/log4mongo/MongoDbAppender.java
+++ b/src/main/java/org/log4mongo/MongoDbAppender.java
@@ -17,364 +17,370 @@
package org.log4mongo;
-import java.net.UnknownHostException;
+import com.mongodb.*;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import org.apache.log4j.spi.ErrorCode;
+import org.bson.BSONObject;
+import org.bson.Document;
+
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
-import org.apache.log4j.spi.ErrorCode;
-
-import com.mongodb.DB;
-import com.mongodb.DBCollection;
-import com.mongodb.DBObject;
-import com.mongodb.Mongo;
-import com.mongodb.MongoException;
-import com.mongodb.ServerAddress;
-import com.mongodb.WriteConcern;
/**
* Log4J Appender that writes log events into a MongoDB document oriented database. Log events are
* fully parsed and stored as structured records in MongoDB (this appender does not require, nor use
* a Log4J layout).
- *
+ *
* The appender does not create any indexes on the data that's stored - it is assumed that if
* query performance is required, those would be created externally (e.g., in the MongoDB shell or
* other external application).
- *
+ *
* @author Peter Monks (pmonks@gmail.com)
- * @see Log4J
- * Appender Interface
+ * @see Log4J Appender
+ * Interface
* @see MongoDB
*/
public class MongoDbAppender extends BsonAppender {
- private final static String DEFAULT_MONGO_DB_HOSTNAME = "localhost";
- private final static String DEFAULT_MONGO_DB_PORT = "27017";
- private final static String DEFAULT_MONGO_DB_DATABASE_NAME = "log4mongo";
- private final static String DEFAULT_MONGO_DB_COLLECTION_NAME = "logevents";
- private WriteConcern concern;
-
- private String hostname = DEFAULT_MONGO_DB_HOSTNAME;
- private String port = DEFAULT_MONGO_DB_PORT;
- private String databaseName = DEFAULT_MONGO_DB_DATABASE_NAME;
- private String collectionName = DEFAULT_MONGO_DB_COLLECTION_NAME;
- private String userName = null;
- private String password = null;
- private String writeConcern = null;
- private Mongo mongo = null;
- private DBCollection collection = null;
-
- private boolean initialized = false;
-
- /**
- * @see org.apache.log4j.Appender#requiresLayout()
- */
- public boolean requiresLayout() {
- return (false);
- }
-
- /**
- * @see org.apache.log4j.AppenderSkeleton#activateOptions()
- */
- @Override
- public void activateOptions() {
- try {
- // Close previous connections if reactivating
- if (mongo != null) {
- close();
- }
-
- List addresses = getServerAddresses(hostname, port);
- mongo = getMongo(addresses);
-
- DB database = getDatabase(mongo, databaseName);
-
- if (userName != null && userName.trim().length() > 0) {
- if (!database.authenticate(userName, password.toCharArray())) {
- throw new RuntimeException("Unable to authenticate with MongoDB server.");
- }
-
- // Allow password to be GCed
- password = null;
- }
-
- setCollection(database.getCollection(collectionName));
- initialized = true;
- } catch (Exception e) {
- errorHandler.error("Unexpected exception while initialising MongoDbAppender.", e,
- ErrorCode.GENERIC_FAILURE);
- }
- }
-
- /*
- * This method could be overridden to provide the DB instance from an existing connection.
- */
- protected DB getDatabase(Mongo mongo, String databaseName) {
- return mongo.getDB(databaseName);
- }
-
- /*
- * This method could be overridden to provide the Mongo instance from an existing connection.
- */
- protected Mongo getMongo(List addresses) {
- if (addresses.size() < 2) {
- return new Mongo(addresses.get(0));
- } else {
- // Replica set
- return new Mongo(addresses);
- }
- }
-
- /**
- * Note: this method is primarily intended for use by the unit tests.
- *
- * @param collection
- * The MongoDB collection to use when logging events.
- */
- public void setCollection(final DBCollection collection) {
- assert collection != null : "collection must not be null";
-
- this.collection = collection;
- }
-
- /**
- * @see org.apache.log4j.Appender#close()
- */
- public void close() {
- if (mongo != null) {
- collection = null;
- mongo.close();
- }
- }
-
- /**
- * @return The hostname of the MongoDB server (will not be null, empty or blank) .
- */
- public String getHostname() {
- return hostname;
- }
-
- /**
- * @param hostname
- * The MongoDB hostname to set (must not be null, empty or blank) .
- */
- public void setHostname(final String hostname) {
- assert hostname != null : "hostname must not be null";
- assert hostname.trim().length() > 0 : "hostname must not be empty or blank";
-
- this.hostname = hostname;
- }
-
- /**
- * @return The port of the MongoDB server (will be > 0) .
- */
- public String getPort() {
- return port;
- }
-
- /**
- * @param port
- * The port to set (must not be null, empty or blank) .
- */
- public void setPort(final String port) {
- assert port != null : "port must not be null";
- assert port.trim().length() > 0 : "port must not be empty or blank";
-
- this.port = port;
- }
-
- /**
- * @return The database used in the MongoDB server (will not be null, empty or blank) .
- */
- public String getDatabaseName() {
- return databaseName;
- }
-
- /**
- * @param databaseName
- * The database to use in the MongoDB server (must not be null, empty or
- * blank) .
- */
- public void setDatabaseName(final String databaseName) {
- assert databaseName != null : "database must not be null";
- assert databaseName.trim().length() > 0 : "database must not be empty or blank";
-
- this.databaseName = databaseName;
- }
-
- /**
- * @return The collection used within the database in the MongoDB server (will not be null,
- * empty or blank) .
- */
- public String getCollectionName() {
- return collectionName;
- }
-
- /**
- * @param collectionName
- * The collection used within the database in the MongoDB server (must not be
- * null, empty or blank) .
- */
- public void setCollectionName(final String collectionName) {
- assert collectionName != null : "collection must not be null";
- assert collectionName.trim().length() > 0 : "collection must not be empty or blank";
-
- this.collectionName = collectionName;
- }
-
- /**
- * @return The userName used to authenticate with MongoDB (may be null) .
- */
- public String getUserName() {
- return userName;
- }
-
- /**
- * @param userName
- * The userName to use when authenticating with MongoDB (may be null) .
- */
- public void setUserName(final String userName) {
- this.userName = userName;
- }
-
- /**
- * @param password
- * The password to use when authenticating with MongoDB (may be null) .
- */
- public void setPassword(final String password) {
- this.password = password;
- }
-
- /**
- * @return the writeConcern setting for Mongo.
- */
- public String getWriteConcern() {
+
+ private final static String DEFAULT_MONGO_DB_HOSTNAME = "localhost";
+
+ private final static String DEFAULT_MONGO_DB_PORT = "27017";
+
+ private final static String DEFAULT_MONGO_DB_DATABASE_NAME = "log4mongo";
+
+ private final static String DEFAULT_MONGO_DB_COLLECTION_NAME = "logevents";
+
+ private WriteConcern concern;
+
+ private String hostname = DEFAULT_MONGO_DB_HOSTNAME;
+
+ private String port = DEFAULT_MONGO_DB_PORT;
+
+ private String databaseName = DEFAULT_MONGO_DB_DATABASE_NAME;
+
+ private String collectionName = DEFAULT_MONGO_DB_COLLECTION_NAME;
+
+ private String userName = null;
+
+ private String password = null;
+
+ private String writeConcern = null;
+
+ private MongoClient mongo = null;
+
+ private MongoCollection collection = null;
+
+ private boolean initialized = false;
+
+ /**
+ * @see org.apache.log4j.Appender#requiresLayout()
+ */
+ public boolean requiresLayout() {
+ return ( false );
+ }
+
+ /**
+ * @see org.apache.log4j.AppenderSkeleton#activateOptions()
+ */
+ @Override
+ public void activateOptions() {
+ try {
+ // Close previous connections if reactivating
+ if ( mongo != null ) {
+ close();
+ }
+
+ MongoCredential credentials = null;
+ if ( userName != null && userName.trim().length() > 0 ) {
+ credentials = MongoCredential.createCredential( userName, databaseName, password.toCharArray() );
+ password = null;
+ }
+
+ mongo = getMongo( getServerAddresses( hostname, port ), ( credentials != null ) ? Arrays.asList( credentials ) : null );
+
+ MongoDatabase database = getDatabase( mongo, databaseName );
+
+ setCollection( database.getCollection( collectionName ) );
+
+ initialized = true;
+ } catch ( Exception e ) {
+ errorHandler.error( "Unexpected exception while initialising MongoDbAppender.", e,
+ ErrorCode.GENERIC_FAILURE );
+ }
+ }
+
+ /*
+ * This method could be overridden to provide the DB instance from an existing connection.
+ */
+ protected MongoDatabase getDatabase( MongoClient mongo, String databaseName ) {
+ return mongo.getDatabase( databaseName );
+ }
+
+ /*
+ * This method could be overridden to provide the Mongo instance from an existing connection.
+ */
+ protected MongoClient getMongo( List addresses ) {
+ if ( addresses.size() < 2 ) {
+ return new MongoClient( addresses.get( 0 ) );
+ } else {
+ // Replica set
+ return new MongoClient( addresses );
+ }
+ }
+
+ private MongoClient getMongo( List addresses, List credentials ) {
+ if ( credentials == null ) {
+ return this.getMongo( addresses );
+ }
+
+ if ( addresses.size() < 2 ) {
+ return new MongoClient( addresses.get( 0 ), credentials );
+ } else {
+ // Replica set
+ return new MongoClient( addresses, credentials );
+ }
+ }
+
+ /**
+ * Note: this method is primarily intended for use by the unit tests.
+ *
+ * @param collection The MongoDB collection to use when logging events.
+ */
+ public void setCollection( final MongoCollection collection ) {
+ assert collection != null : "collection must not be null";
+
+ this.collection = collection;
+ }
+
+ /**
+ * @see org.apache.log4j.Appender#close()
+ */
+ public void close() {
+ if ( mongo != null ) {
+ collection = null;
+ mongo.close();
+ }
+ }
+
+ /**
+ * @return The hostname of the MongoDB server (will not be null, empty or blank) .
+ */
+ public String getHostname() {
+ return hostname;
+ }
+
+ /**
+ * @param hostname The MongoDB hostname to set (must not be null, empty or blank) .
+ */
+ public void setHostname( final String hostname ) {
+ assert hostname != null : "hostname must not be null";
+ assert hostname.trim().length() > 0 : "hostname must not be empty or blank";
+
+ this.hostname = hostname;
+ }
+
+ /**
+ * @return The port of the MongoDB server (will be > 0) .
+ */
+ public String getPort() {
+ return port;
+ }
+
+ /**
+ * @param port The port to set (must not be null, empty or blank) .
+ */
+ public void setPort( final String port ) {
+ assert port != null : "port must not be null";
+ assert port.trim().length() > 0 : "port must not be empty or blank";
+
+ this.port = port;
+ }
+
+ /**
+ * @return The database used in the MongoDB server (will not be null, empty or blank) .
+ */
+ public String getDatabaseName() {
+ return databaseName;
+ }
+
+ /**
+ * @param databaseName The database to use in the MongoDB server (must not be null, empty or blank) .
+ */
+ public void setDatabaseName( final String databaseName ) {
+ assert databaseName != null : "database must not be null";
+ assert databaseName.trim().length() > 0 : "database must not be empty or blank";
+
+ this.databaseName = databaseName;
+ }
+
+ /**
+ * @return The collection used within the database in the MongoDB server (will not be null, empty or blank) .
+ */
+ public String getCollectionName() {
+ return collectionName;
+ }
+
+ /**
+ * @param collectionName The collection used within the database in the MongoDB server (must not be null, empty
+ * or blank) .
+ */
+ public void setCollectionName( final String collectionName ) {
+ assert collectionName != null : "collection must not be null";
+ assert collectionName.trim().length() > 0 : "collection must not be empty or blank";
+
+ this.collectionName = collectionName;
+ }
+
+ /**
+ * @return The userName used to authenticate with MongoDB (may be null) .
+ */
+ public String getUserName() {
+ return userName;
+ }
+
+ /**
+ * @param userName The userName to use when authenticating with MongoDB (may be null) .
+ */
+ public void setUserName( final String userName ) {
+ this.userName = userName;
+ }
+
+ /**
+ * @param password The password to use when authenticating with MongoDB (may be null) .
+ */
+ public void setPassword( final String password ) {
+ this.password = password;
+ }
+
+ /**
+ * @return the writeConcern setting for Mongo.
+ */
+ public String getWriteConcern() {
return writeConcern;
}
-
- /**
- * @param writeConcern
- * The WriteConcern setting for Mongo.(may be null). If null, set to default of dbCollection's writeConcern.
- */
- public void setWriteConcern(final String writeConcern) {
- this.writeConcern = writeConcern;
- concern = WriteConcern.valueOf(writeConcern);
+
+ /**
+ * @param writeConcern The WriteConcern setting for Mongo.(may be null). If null, set to default of
+ * dbCollection's writeConcern.
+ */
+ public void setWriteConcern( final String writeConcern ) {
+ this.writeConcern = writeConcern;
+ concern = WriteConcern.valueOf( writeConcern );
}
-
- public WriteConcern getConcern() {
- if (concern == null) {
- concern = getCollection().getWriteConcern();
- }
+
+ public WriteConcern getConcern() {
+ if ( concern == null ) {
+ concern = getCollection().getWriteConcern();
+ }
return concern;
}
- /**
- * @param bson
- * The BSON object to insert into a MongoDB database collection.
- */
- @Override
- public void append(DBObject bson) {
- if (initialized && bson != null) {
- try {
- getCollection().insert(bson, getConcern());
- } catch (MongoException e) {
- errorHandler.error("Failed to insert document to MongoDB", e,
- ErrorCode.WRITE_FAILURE);
- }
- }
- }
-
- /**
- * Returns true if appender was successfully initialized. If this method returns false, the
- * appender should not attempt to log events.
- *
- * @return true if appender was successfully initialized
- */
- public boolean isInitialized() {
- return initialized;
- }
-
- /**
- *
- * @return The MongoDB collection to which events are logged.
- */
- protected DBCollection getCollection() {
- return collection;
- }
-
- /**
- * Returns a List of ServerAddress objects for each host specified in the hostname property.
- * Returns an empty list if configuration is detected to be invalid, e.g.:
- *
- * Port property doesn't contain either one port or one port per host
- * After parsing port property to integers, there isn't either one port or one port per host
- *
- *
- *
- * @param hostname
- * Blank space delimited hostnames
- * @param port
- * Blank space delimited ports. Must specify one port for all hosts or a port per
- * host.
- * @return List of ServerAddresses to connect to
- */
- private List getServerAddresses(String hostname, String port) {
- List addresses = new ArrayList();
-
- String[] hosts = hostname.split(" ");
- String[] ports = port.split(" ");
-
- if (ports.length != 1 && ports.length != hosts.length) {
- errorHandler.error(
- "MongoDB appender port property must contain one port or a port per host",
- null, ErrorCode.ADDRESS_PARSE_FAILURE);
- } else {
- List portNums = getPortNums(ports);
- // Validate number of ports again after parsing
- if (portNums.size() != 1 && portNums.size() != hosts.length) {
- errorHandler
- .error("MongoDB appender port property must contain one port or a valid port per host",
- null, ErrorCode.ADDRESS_PARSE_FAILURE);
- } else {
- boolean onePort = (portNums.size() == 1);
-
- int i = 0;
- for (String host : hosts) {
- int portNum = (onePort) ? portNums.get(0) : portNums.get(i);
- try {
- addresses.add(new ServerAddress(host.trim(), portNum));
- } catch (UnknownHostException e) {
- errorHandler.error(
- "MongoDB appender hostname property contains unknown host", e,
- ErrorCode.ADDRESS_PARSE_FAILURE);
- }
- i++;
- }
- }
- }
- return addresses;
- }
-
- private List getPortNums(String[] ports) {
- List portNums = new ArrayList();
-
- for (String port : ports) {
- try {
- Integer portNum = Integer.valueOf(port.trim());
- if (portNum < 0) {
- errorHandler.error(
- "MongoDB appender port property can't contain a negative integer",
- null, ErrorCode.ADDRESS_PARSE_FAILURE);
- } else {
- portNums.add(portNum);
- }
- } catch (NumberFormatException e) {
- errorHandler.error(
- "MongoDB appender can't parse a port property value into an integer", e,
- ErrorCode.ADDRESS_PARSE_FAILURE);
- }
-
- }
-
- return portNums;
- }
+ /**
+ * @param bson The BSON object to insert into a MongoDB database collection.
+ */
+ @Override
+ public void append( BSONObject bson ) {
+ if ( initialized && bson != null ) {
+ try {
+ getCollection().insertOne( new Document( bson.toMap() ) );
+ } catch ( MongoException e ) {
+ errorHandler.error( "Failed to insert document to MongoDB", e,
+ ErrorCode.WRITE_FAILURE );
+ }
+ }
+ }
+
+ /**
+ * Returns true if appender was successfully initialized. If this method returns false, the
+ * appender should not attempt to log events.
+ *
+ * @return true if appender was successfully initialized
+ */
+ public boolean isInitialized() {
+ return initialized;
+ }
+
+ /**
+ * @return The MongoDB collection to which events are logged.
+ */
+ protected MongoCollection getCollection() {
+ if ( concern == null ) {
+ return collection;
+ }
+
+ return collection.withWriteConcern( concern );
+ }
+
+ /**
+ * Returns a List of ServerAddress objects for each host specified in the hostname property.
+ * Returns an empty list if configuration is detected to be invalid, e.g.:
+ *
+ * Port property doesn't contain either one port or one port per host
+ * After parsing port property to integers, there isn't either one port or one port per host
+ *
+ *
+ *
+ * @param hostname Blank space delimited hostnames
+ * @param port Blank space delimited ports. Must specify one port for all hosts or a port per host.
+ *
+ * @return List of ServerAddresses to connect to
+ */
+ private List getServerAddresses( String hostname, String port ) {
+ List addresses = new ArrayList ();
+
+ String[] hosts = hostname.split( " " );
+ String[] ports = port.split( " " );
+
+ if ( ports.length != 1 && ports.length != hosts.length ) {
+ errorHandler.error(
+ "MongoDB appender port property must contain one port or a port per host",
+ null, ErrorCode.ADDRESS_PARSE_FAILURE );
+ } else {
+ List portNums = getPortNumbers( ports );
+ // Validate number of ports again after parsing
+ if ( portNums.size() != 1 && portNums.size() != hosts.length ) {
+ errorHandler
+ .error( "MongoDB appender port property must contain one port or a valid port per host",
+ null, ErrorCode.ADDRESS_PARSE_FAILURE );
+ } else {
+ boolean onePort = ( portNums.size() == 1 );
+
+ int i = 0;
+ for ( String host : hosts ) {
+ int portNum = ( onePort ) ? portNums.get( 0 ) : portNums.get( i );
+ addresses.add( new ServerAddress( host.trim(), portNum ) );
+ i++;
+ }
+ }
+ }
+ return addresses;
+ }
+
+ private List getPortNumbers( String[] ports ) {
+ List portNumbers = new ArrayList <>();
+
+ for ( String port : ports ) {
+ try {
+ Integer portNum = Integer.valueOf( port.trim() );
+ if ( portNum < 0 ) {
+ errorHandler.error(
+ "MongoDB appender port property can't contain a negative integer",
+ null, ErrorCode.ADDRESS_PARSE_FAILURE );
+ } else {
+ portNumbers.add( portNum );
+ }
+ } catch ( NumberFormatException e ) {
+ errorHandler.error(
+ "MongoDB appender can't parse a port property value into an integer", e,
+ ErrorCode.ADDRESS_PARSE_FAILURE );
+ }
+
+ }
+
+ return portNumbers;
+ }
}
diff --git a/src/main/java/org/log4mongo/MongoDbPatternLayout.java b/src/main/java/org/log4mongo/MongoDbPatternLayout.java
index edf5a97..85b1506 100644
--- a/src/main/java/org/log4mongo/MongoDbPatternLayout.java
+++ b/src/main/java/org/log4mongo/MongoDbPatternLayout.java
@@ -22,101 +22,107 @@
import org.apache.log4j.helpers.PatternParser;
import org.apache.log4j.spi.LoggingEvent;
+
/**
* PatternLayout that must be used or extended when logging with MongoDbPatternLayoutAppender.
*
* Much of the PatternLayout functionality needed to be re-implemented, because double quotes and \
* need to be escaped in the formatted String. The formatted String will later be parsed as a JSON
* document, so quotes in the values must be escaped.
- *
+ *
* @author Robert Stewart (robert@wombatnation.com)
*/
public class MongoDbPatternLayout extends PatternLayout {
- private StringBuffer buf = new StringBuffer(BUF_SIZE);
- private StringBuilder builder = new StringBuilder(BUF_SIZE);
- private String conversionPattern;
- private PatternConverter headConverter;
-
- public MongoDbPatternLayout() {
- this(DEFAULT_CONVERSION_PATTERN);
- }
-
- public MongoDbPatternLayout(String pattern) {
- this.conversionPattern = pattern;
- headConverter = createPatternParser(
- (pattern == null) ? DEFAULT_CONVERSION_PATTERN : pattern).parse();
- }
-
- @Override
- public void setConversionPattern(String conversionPattern) {
- this.conversionPattern = conversionPattern;
- headConverter = createPatternParser(conversionPattern).parse();
- }
-
- @Override
- public String getConversionPattern() {
- return conversionPattern;
- }
-
- @Override
- public PatternParser createPatternParser(String pattern) {
- PatternParser parser;
- if (pattern == null)
- parser = new PatternParser(DEFAULT_CONVERSION_PATTERN);
- else
- parser = new PatternParser(pattern);
-
- return parser;
- }
-
- /**
- * Produces a formatted string as specified by the conversion pattern.
- *
- * The PatternConverter expects to append to a StringBuffer. However, for converters other than
- * a LiteralPatternConverter, double quotes need to be escaped in the characters appended to the
- * StringBuffer.
- */
- @Override
- public String format(LoggingEvent event) {
- // Reset working StringBuilder
- if (builder.capacity() > MAX_CAPACITY) {
- builder = new StringBuilder(BUF_SIZE);
- } else {
- builder.setLength(0);
- }
-
- PatternConverter c = headConverter;
-
- while (c != null) {
- if (buf.capacity() > MAX_CAPACITY) {
- buf = new StringBuffer(BUF_SIZE);
- } else {
- buf.setLength(0);
- }
- c.format(buf, event);
-
- // Escape double quotes and \ in String generated by converters
- // other than a LiteralPatternConverter. Can't use "instance of"
- // because class is private.
- if (c.getClass().getSimpleName().equals("LiteralPatternConverter")) {
- builder.append(buf);
- } else {
- char[] chars = buf.toString().toCharArray();
- int pos = 0;
- for (int i = 0; i < chars.length; i++) {
- if (chars[i] == '\"') {
- builder.append(chars, pos, i - pos).append("\\\"");
- pos = i + 1;
- } else if (chars[i] == '\\') {
- builder.append(chars, pos, i - pos).append("\\\\");
- pos = i + 1;
- }
- }
- builder.append(chars, pos, chars.length - pos);
- }
-
- c = c.next;
- }
- return builder.toString();
- }
+
+ private StringBuffer buf = new StringBuffer( BUF_SIZE );
+
+ private StringBuilder builder = new StringBuilder( BUF_SIZE );
+
+ private String conversionPattern;
+
+ private PatternConverter headConverter;
+
+ public MongoDbPatternLayout() {
+ this( DEFAULT_CONVERSION_PATTERN );
+ }
+
+ public MongoDbPatternLayout( String pattern ) {
+ this.conversionPattern = pattern;
+ headConverter = createPatternParser(
+ ( pattern == null ) ? DEFAULT_CONVERSION_PATTERN : pattern ).parse();
+ }
+
+ @Override
+ public void setConversionPattern( String conversionPattern ) {
+ this.conversionPattern = conversionPattern;
+ headConverter = createPatternParser( conversionPattern ).parse();
+ }
+
+ @Override
+ public String getConversionPattern() {
+ return conversionPattern;
+ }
+
+ @Override
+ public PatternParser createPatternParser( String pattern ) {
+ PatternParser parser;
+ if ( pattern == null ) {
+ parser = new PatternParser( DEFAULT_CONVERSION_PATTERN );
+ } else {
+ parser = new PatternParser( pattern );
+ }
+
+ return parser;
+ }
+
+ /**
+ * Produces a formatted string as specified by the conversion pattern.
+ *
+ * The PatternConverter expects to append to a StringBuffer. However, for converters other than
+ * a LiteralPatternConverter, double quotes need to be escaped in the characters appended to the
+ * StringBuffer.
+ */
+ @Override
+ public String format( LoggingEvent event ) {
+ // Reset working StringBuilder
+ if ( builder.capacity() > MAX_CAPACITY ) {
+ builder = new StringBuilder( BUF_SIZE );
+ } else {
+ builder.setLength( 0 );
+ }
+
+ PatternConverter c = headConverter;
+
+ while ( c != null ) {
+ if ( buf.capacity() > MAX_CAPACITY ) {
+ buf = new StringBuffer( BUF_SIZE );
+ } else {
+ buf.setLength( 0 );
+ }
+ c.format( buf, event );
+
+ // Escape double quotes and \ in String generated by converters
+ // other than a LiteralPatternConverter. Can't use "instance of"
+ // because class is private.
+ if ( c.getClass().getSimpleName().equals( "LiteralPatternConverter" ) ) {
+ builder.append( buf );
+ } else {
+ char[] chars = buf.toString().toCharArray();
+ int pos = 0;
+ for ( int i = 0; i < chars.length; i++ ) {
+ if ( chars[ i ] == '\"' ) {
+ builder.append( chars, pos, i - pos ).append( "\\\"" );
+ pos = i + 1;
+ } else if ( chars[ i ] == '\\' ) {
+ builder.append( chars, pos, i - pos ).append( "\\\\" );
+ pos = i + 1;
+ }
+ }
+ builder.append( chars, pos, chars.length - pos );
+ }
+
+ c = c.next;
+ }
+ return builder.toString();
+ }
}
diff --git a/src/main/java/org/log4mongo/MongoDbPatternLayoutAppender.java b/src/main/java/org/log4mongo/MongoDbPatternLayoutAppender.java
index e9521da..f46e339 100644
--- a/src/main/java/org/log4mongo/MongoDbPatternLayoutAppender.java
+++ b/src/main/java/org/log4mongo/MongoDbPatternLayoutAppender.java
@@ -17,12 +17,13 @@
package org.log4mongo;
-import org.apache.log4j.spi.ErrorCode;
-import org.apache.log4j.spi.LoggingEvent;
-
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import com.mongodb.util.JSON;
+import org.apache.log4j.spi.ErrorCode;
+import org.apache.log4j.spi.LoggingEvent;
+import org.bson.Document;
+
/**
* A Log4J Appender that uses a PatternLayout to write log events into a MongoDB database.
@@ -38,50 +39,50 @@
* The appender does not create any indexes on the data that's stored. If query performance
* is required, indexes must be created externally (e.g., in the mongo shell or an external
* reporting application).
- *
+ *
* @author Robert Stewart (robert@wombatnation.com)
- * @see Log4J
- * Appender Interface
+ * @see Log4J Appender
+ * Interface
* @see MongoDB
*/
public class MongoDbPatternLayoutAppender extends MongoDbAppender {
- @Override
- public boolean requiresLayout() {
- return (true);
- }
- /**
- * Inserts a BSON representation of a LoggingEvent into a MongoDB collection. A PatternLayout is
- * used to format a JSON document containing data available in the LoggingEvent and, optionally,
- * additional data returned by custom PatternConverters.
- *
- * The format of the JSON document is specified in the .layout.ConversionPattern property.
- *
- * @param loggingEvent
- * The LoggingEvent that will be formatted and stored in MongoDB
- */
- @Override
- protected void append(final LoggingEvent loggingEvent) {
- if (isInitialized()) {
- DBObject bson = null;
- String json = layout.format(loggingEvent);
+ @Override
+ public boolean requiresLayout() {
+ return ( true );
+ }
+
+ /**
+ * Inserts a BSON representation of a LoggingEvent into a MongoDB collection. A PatternLayout is
+ * used to format a JSON document containing data available in the LoggingEvent and, optionally,
+ * additional data returned by custom PatternConverters.
+ *
+ * The format of the JSON document is specified in the .layout.ConversionPattern property.
+ *
+ * @param loggingEvent The LoggingEvent that will be formatted and stored in MongoDB
+ */
+ @Override
+ protected void append( final LoggingEvent loggingEvent ) {
+ if ( isInitialized() ) {
+ DBObject bson = null;
+ String json = layout.format( loggingEvent );
- if (json.length() > 0) {
- Object obj = JSON.parse(json);
- if (obj instanceof DBObject) {
- bson = (DBObject) obj;
- }
- }
+ if ( json.length() > 0 ) {
+ Object obj = JSON.parse( json );
+ if ( obj instanceof DBObject ) {
+ bson = (DBObject) obj;
+ }
+ }
- if (bson != null) {
- try {
- getCollection().insert(bson);
- } catch (MongoException e) {
- errorHandler.error("Failed to insert document to MongoDB", e,
- ErrorCode.WRITE_FAILURE);
- }
- }
- }
- }
+ if ( bson != null ) {
+ try {
+ getCollection().insertOne( new Document( bson.toMap() ) );
+ } catch ( MongoException e ) {
+ errorHandler.error( "Failed to insert document to MongoDB", e,
+ ErrorCode.WRITE_FAILURE );
+ }
+ }
+ }
+ }
}
diff --git a/src/main/java/org/log4mongo/contrib/HostInfoPatternLayout.java b/src/main/java/org/log4mongo/contrib/HostInfoPatternLayout.java
index a3f46b9..50b6ff4 100644
--- a/src/main/java/org/log4mongo/contrib/HostInfoPatternLayout.java
+++ b/src/main/java/org/log4mongo/contrib/HostInfoPatternLayout.java
@@ -18,25 +18,26 @@
package org.log4mongo.contrib;
import org.apache.log4j.helpers.PatternParser;
-
import org.log4mongo.MongoDbPatternLayout;
+
public class HostInfoPatternLayout extends MongoDbPatternLayout {
- public HostInfoPatternLayout() {
- }
+ public HostInfoPatternLayout() {
+ }
- public HostInfoPatternLayout(String pattern) {
- super(pattern);
- }
+ public HostInfoPatternLayout( String pattern ) {
+ super( pattern );
+ }
- public PatternParser createPatternParser(String pattern) {
- PatternParser parser;
- if (pattern == null)
- parser = new HostInfoPatternParser(DEFAULT_CONVERSION_PATTERN);
- else
- parser = new HostInfoPatternParser(pattern);
+ public PatternParser createPatternParser( String pattern ) {
+ PatternParser parser;
+ if ( pattern == null ) {
+ parser = new HostInfoPatternParser( DEFAULT_CONVERSION_PATTERN );
+ } else {
+ parser = new HostInfoPatternParser( pattern );
+ }
- return parser;
- }
+ return parser;
+ }
}
diff --git a/src/main/java/org/log4mongo/contrib/HostInfoPatternParser.java b/src/main/java/org/log4mongo/contrib/HostInfoPatternParser.java
index 15c97e4..9a30dc5 100644
--- a/src/main/java/org/log4mongo/contrib/HostInfoPatternParser.java
+++ b/src/main/java/org/log4mongo/contrib/HostInfoPatternParser.java
@@ -15,6 +15,11 @@
package org.log4mongo.contrib;
+import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.helpers.PatternConverter;
+import org.apache.log4j.helpers.PatternParser;
+import org.apache.log4j.spi.LoggingEvent;
+
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -22,10 +27,6 @@
import java.util.HashMap;
import java.util.Map;
-import org.apache.log4j.helpers.LogLog;
-import org.apache.log4j.helpers.PatternConverter;
-import org.apache.log4j.helpers.PatternParser;
-import org.apache.log4j.spi.LoggingEvent;
/**
* PatternParser that adds pattern converters for logging useful
@@ -37,115 +38,123 @@
*
*/
public class HostInfoPatternParser extends PatternParser {
- static final char HOST_NAME = 'H';
- static final char VM_NAME = 'V';
- static final char IP_ADDRESS = 'I';
- static final Map converters;
- static {
- Map tmp = new HashMap();
- tmp.put(String.valueOf(HOST_NAME), new HostPatternConverter());
- tmp.put(String.valueOf(VM_NAME), new VMNamePatternConverter());
- tmp.put(String.valueOf(IP_ADDRESS), new IPAddressPatternConverter());
-
- converters = Collections.unmodifiableMap(tmp);
- }
-
- public HostInfoPatternParser(String pattern) {
- super(pattern);
- }
-
- /**
- * This method is called on each pattern converter character while the
- * PatternParser superclass is parsing the pattern. If the character is for
- * a custom converter handled by this PatternParser subclass, this class
- * adds the appropriate converter to a LinkedList of converters. If not, it
- * allows the superclass to handle the converter character.
- *
- * @see org.apache.log4j.helpers.PatternParser#finalizeConverter(char)
- */
- public void finalizeConverter(char formatChar) {
- PatternConverter pc = null;
- switch (formatChar) {
- case HOST_NAME:
- pc = HostInfoPatternParser.converters.get(String.valueOf(HOST_NAME));
- currentLiteral.setLength(0);
- addConverter(pc);
- break;
- case VM_NAME:
- pc = HostInfoPatternParser.converters.get(String.valueOf(VM_NAME));
- currentLiteral.setLength(0);
- addConverter(pc);
- break;
- case IP_ADDRESS:
- pc = HostInfoPatternParser.converters.get(String.valueOf(IP_ADDRESS));
- currentLiteral.setLength(0);
- addConverter(pc);
- break;
-
- default:
- super.finalizeConverter(formatChar);
- }
- }
-
- /**
- * Custom PatternConverter for replacing converter character 'H' with
- * the host name.
- */
- private static class HostPatternConverter extends PatternConverter {
- private String hostname = "";
-
- HostPatternConverter() {
- super();
-
- try {
- hostname = InetAddress.getLocalHost().getHostName();
- } catch (UnknownHostException e) {
- LogLog.warn(e.getMessage());
- }
- }
-
- public String convert(LoggingEvent event) {
- return hostname;
- }
- }
-
- /**
- * Custom PatternConverter for replacing converter character 'V' with
- * the VM name of the JVM, usually formatted as pid@host.
- */
- private static class VMNamePatternConverter extends PatternConverter {
- private String process = "";
-
- VMNamePatternConverter() {
- super();
-
- process = ManagementFactory.getRuntimeMXBean().getName();
- }
-
- public String convert(LoggingEvent event) {
- return process;
- }
- }
-
- /**
- * Custom PatternConverter for replacing converter character 'I' with
- * the IP Address.
- */
- private static class IPAddressPatternConverter extends PatternConverter {
- private String ipaddress = "";
-
- IPAddressPatternConverter() {
- super();
-
- try {
- ipaddress = InetAddress.getLocalHost().getHostAddress();
- } catch (UnknownHostException e) {
- LogLog.warn(e.getMessage());
- }
- }
-
- public String convert(LoggingEvent event) {
- return ipaddress;
- }
- }
+
+ static final char HOST_NAME = 'H';
+
+ static final char VM_NAME = 'V';
+
+ static final char IP_ADDRESS = 'I';
+
+ static final Map converters;
+
+ static {
+ Map tmp = new HashMap ();
+ tmp.put( String.valueOf( HOST_NAME ), new HostPatternConverter() );
+ tmp.put( String.valueOf( VM_NAME ), new VMNamePatternConverter() );
+ tmp.put( String.valueOf( IP_ADDRESS ), new IPAddressPatternConverter() );
+
+ converters = Collections.unmodifiableMap( tmp );
+ }
+
+ public HostInfoPatternParser( String pattern ) {
+ super( pattern );
+ }
+
+ /**
+ * This method is called on each pattern converter character while the
+ * PatternParser superclass is parsing the pattern. If the character is for
+ * a custom converter handled by this PatternParser subclass, this class
+ * adds the appropriate converter to a LinkedList of converters. If not, it
+ * allows the superclass to handle the converter character.
+ *
+ * @see org.apache.log4j.helpers.PatternParser#finalizeConverter(char)
+ */
+ public void finalizeConverter( char formatChar ) {
+ PatternConverter pc = null;
+ switch ( formatChar ) {
+ case HOST_NAME:
+ pc = HostInfoPatternParser.converters.get( String.valueOf( HOST_NAME ) );
+ currentLiteral.setLength( 0 );
+ addConverter( pc );
+ break;
+ case VM_NAME:
+ pc = HostInfoPatternParser.converters.get( String.valueOf( VM_NAME ) );
+ currentLiteral.setLength( 0 );
+ addConverter( pc );
+ break;
+ case IP_ADDRESS:
+ pc = HostInfoPatternParser.converters.get( String.valueOf( IP_ADDRESS ) );
+ currentLiteral.setLength( 0 );
+ addConverter( pc );
+ break;
+
+ default:
+ super.finalizeConverter( formatChar );
+ }
+ }
+
+ /**
+ * Custom PatternConverter for replacing converter character 'H' with
+ * the host name.
+ */
+ private static class HostPatternConverter extends PatternConverter {
+
+ private String hostname = "";
+
+ HostPatternConverter() {
+ super();
+
+ try {
+ hostname = InetAddress.getLocalHost().getHostName();
+ } catch ( UnknownHostException e ) {
+ LogLog.warn( e.getMessage() );
+ }
+ }
+
+ public String convert( LoggingEvent event ) {
+ return hostname;
+ }
+ }
+
+ /**
+ * Custom PatternConverter for replacing converter character 'V' with
+ * the VM name of the JVM, usually formatted as pid@host.
+ */
+ private static class VMNamePatternConverter extends PatternConverter {
+
+ private String process = "";
+
+ VMNamePatternConverter() {
+ super();
+
+ process = ManagementFactory.getRuntimeMXBean().getName();
+ }
+
+ public String convert( LoggingEvent event ) {
+ return process;
+ }
+ }
+
+ /**
+ * Custom PatternConverter for replacing converter character 'I' with
+ * the IP Address.
+ */
+ private static class IPAddressPatternConverter extends PatternConverter {
+
+ private String ipaddress = "";
+
+ IPAddressPatternConverter() {
+ super();
+
+ try {
+ ipaddress = InetAddress.getLocalHost().getHostAddress();
+ } catch ( UnknownHostException e ) {
+ LogLog.warn( e.getMessage() );
+ }
+ }
+
+ public String convert( LoggingEvent event ) {
+ return ipaddress;
+ }
+ }
}
diff --git a/src/test/java/org/log4mongo/CustomPatternLayout.java b/src/test/java/org/log4mongo/CustomPatternLayout.java
index 1f50436..9e8e23d 100644
--- a/src/test/java/org/log4mongo/CustomPatternLayout.java
+++ b/src/test/java/org/log4mongo/CustomPatternLayout.java
@@ -17,24 +17,27 @@
import org.apache.log4j.helpers.PatternParser;
+
/**
* Example PatternLayout that specifies a custom PatternParser.
*/
public class CustomPatternLayout extends MongoDbPatternLayout {
- public CustomPatternLayout() {
- }
-
- public CustomPatternLayout(String pattern) {
- super(pattern);
- }
-
- public PatternParser createPatternParser(String pattern) {
- PatternParser parser;
- if (pattern == null)
- parser = new CustomPatternParser(DEFAULT_CONVERSION_PATTERN);
- else
- parser = new CustomPatternParser(pattern);
-
- return parser;
- }
+
+ public CustomPatternLayout() {
+ }
+
+ public CustomPatternLayout( String pattern ) {
+ super( pattern );
+ }
+
+ public PatternParser createPatternParser( String pattern ) {
+ PatternParser parser;
+ if ( pattern == null ) {
+ parser = new CustomPatternParser( DEFAULT_CONVERSION_PATTERN );
+ } else {
+ parser = new CustomPatternParser( pattern );
+ }
+
+ return parser;
+ }
}
diff --git a/src/test/java/org/log4mongo/CustomPatternParser.java b/src/test/java/org/log4mongo/CustomPatternParser.java
index a557a23..dcbc12c 100644
--- a/src/test/java/org/log4mongo/CustomPatternParser.java
+++ b/src/test/java/org/log4mongo/CustomPatternParser.java
@@ -20,55 +20,58 @@
import org.apache.log4j.helpers.PatternParser;
import org.apache.log4j.spi.LoggingEvent;
+
/**
* Simple PatternParser that adds a single PatternConverter for logging some extra info. The extra
* info returned from convert(LoggingEvent) will replace %e in the pattern when an event is logged
* if the logging style is set to PatternLayout.
*/
public class CustomPatternParser extends PatternParser {
- static final char EXTRA_CHAR = 'e';
- public CustomPatternParser(String pattern) {
- super(pattern);
- }
+ static final char EXTRA_CHAR = 'e';
+
+ public CustomPatternParser( String pattern ) {
+ super( pattern );
+ }
+
+ /**
+ * This method is called on each pattern converter character while the PatternParser superclass
+ * is parsing the pattern. If the character is for a custom converter handled by this
+ * PatternParser subclass, this class adds the appropriate converter to a LinkedList of
+ * converters. If not, it allows the superclass to handle the converter character.
+ *
+ * @see org.apache.log4j.helpers.PatternParser#finalizeConverter(char)
+ */
+ public void finalizeConverter( char formatChar ) {
+ PatternConverter pc = null;
+ switch ( formatChar ) {
+ case EXTRA_CHAR:
+ pc = new ExtraInfoPatternConverter( formattingInfo );
+ currentLiteral.setLength( 0 );
+ addConverter( pc );
+ break;
- /**
- * This method is called on each pattern converter character while the PatternParser superclass
- * is parsing the pattern. If the character is for a custom converter handled by this
- * PatternParser subclass, this class adds the appropriate converter to a LinkedList of
- * converters. If not, it allows the superclass to handle the converter character.
- *
- * @see org.apache.log4j.helpers.PatternParser#finalizeConverter(char)
- */
- public void finalizeConverter(char formatChar) {
- PatternConverter pc = null;
- switch (formatChar) {
- case EXTRA_CHAR:
- pc = new ExtraInfoPatternConverter(formattingInfo);
- currentLiteral.setLength(0);
- addConverter(pc);
- break;
+ default:
+ super.finalizeConverter( formatChar );
+ }
+ }
- default:
- super.finalizeConverter(formatChar);
- }
- }
+ /**
+ * Custom PatternConverter for replacing a converter character (in this case, the character
+ * happens to be 'e') with some additional info. For a real application, this might be a session
+ * ID or some other piece of meaningful info.
+ */
+ private class ExtraInfoPatternConverter extends PatternConverter {
- /**
- * Custom PatternConverter for replacing a converter character (in this case, the character
- * happens to be 'e') with some additional info. For a real application, this might be a session
- * ID or some other piece of meaningful info.
- */
- private class ExtraInfoPatternConverter extends PatternConverter {
- ExtraInfoPatternConverter(FormattingInfo formatInfo) {
- super(formatInfo);
- }
+ ExtraInfoPatternConverter( FormattingInfo formatInfo ) {
+ super( formatInfo );
+ }
- /**
- * Returns the string that will replace %e in the pattern string.
- */
- public String convert(LoggingEvent event) {
- return "useful info";
- }
- }
+ /**
+ * Returns the string that will replace %e in the pattern string.
+ */
+ public String convert( LoggingEvent event ) {
+ return "useful info";
+ }
+ }
}
diff --git a/src/test/java/org/log4mongo/TestExtendedMongoDbAppender.java b/src/test/java/org/log4mongo/TestExtendedMongoDbAppender.java
index 504f31e..247af0a 100644
--- a/src/test/java/org/log4mongo/TestExtendedMongoDbAppender.java
+++ b/src/test/java/org/log4mongo/TestExtendedMongoDbAppender.java
@@ -1,179 +1,192 @@
-/*
- * Copyright (C) 2009 Peter Monks (pmonks@gmail.com)
- *
- * 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.log4mongo;
-
-import com.mongodb.BasicDBObjectBuilder;
-import com.mongodb.DBCollection;
-import com.mongodb.DBObject;
-import com.mongodb.Mongo;
-import org.apache.log4j.Logger;
-import org.apache.log4j.MDC;
-import org.apache.log4j.PropertyConfigurator;
-import org.junit.*;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.*;
-
-/**
- * JUnit unit tests for ExtendedMongoDbAppender.
- *
- * Note: these tests require that a MongoDB server is running, and (by default)
- * assumes that server is listening on the default port (27017) on localhost.
- *
- * @author Mick Knutson (http://www.baselogic.com)
- */
-public class TestExtendedMongoDbAppender {
- private final static Logger log = Logger.getLogger(TestExtendedMongoDbAppender.class);
-
- private final static String TEST_MONGO_SERVER_HOSTNAME = "localhost";
- private final static int TEST_MONGO_SERVER_PORT = 27017;
- private final static String TEST_DATABASE_NAME = "log4mongotest";
- private final static String TEST_COLLECTION_NAME = "logevents";
-
- private final static String MONGODB_APPENDER_NAME = "MongoDB";
-
- private final static String LOG4J_PROPS = "src/test/resources/log4j_extended.properties";
- //private final static String LOG4J_PROPS = "src/test/resources/log4j_extended.xml";
-
- private final Mongo mongo;
- private final ExtendedMongoDbAppender appender;
- private DBCollection collection;
-
- public TestExtendedMongoDbAppender() throws Exception {
- PropertyConfigurator.configure(LOG4J_PROPS);
- mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
- appender = (ExtendedMongoDbAppender) Logger.getRootLogger().getAppender(
- MONGODB_APPENDER_NAME);
- }
-
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- Mongo mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME,
- TEST_MONGO_SERVER_PORT);
- mongo.dropDatabase(TEST_DATABASE_NAME);
- }
-
- @AfterClass
- public static void tearDownAfterClass() throws Exception {
- Mongo mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME,
- TEST_MONGO_SERVER_PORT);
- mongo.dropDatabase(TEST_DATABASE_NAME);
- }
-
- @Before
- public void setUp() throws Exception {
- // Ensure both the appender and the JUnit test use the same collection
- // object - provides consistency across reads (JUnit) & writes (Log4J)
- collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(
- TEST_COLLECTION_NAME);
- collection.drop();
- appender.setCollection(collection);
-
- mongo.getDB(TEST_DATABASE_NAME).requestStart();
- }
-
- @After
- public void tearDown() throws Exception {
- mongo.getDB(TEST_DATABASE_NAME).requestDone();
- }
-
- @Test
- public void testInitialized() throws Exception {
- if (!appender.isInitialized())
- fail();
- }
-
- @Test
- public void testRootLevelProperties() throws Exception {
- assertEquals(0L, countLogEntries());
-
- Map obj = new HashMap() {
- {
- put("key1", "value1");
- put("key2", "value2");
- }
- };
-
- //slf4j style: log.warn("Testing Object in Message: {}", obj);
- log.warn("Testing Object in Message: " + obj);
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("WARN"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("WARN", entry.get("level"));
- assertEquals("Testing Object in Message: {key1=value1, key2=value2}", entry.get("message"));
- }
-
- @Test
- public void testObjectAsMessage() throws Exception {
- assertEquals(0L, countLogEntries());
-
- log.warn("Testing Object in Message");
-
- long appNameCount = countLogEntriesWhere(BasicDBObjectBuilder.start().add("applicationName", "MyProject").get());
-
- assertEquals(1L, appNameCount);
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("Development", entry.get("eventType"));
- }
-
- @Test
- public void testMdcProperties() throws Exception {
- assertEquals(0L, countLogEntries());
-
- MDC.put("uuid", "1000");
- MDC.put("recordAssociation", "xyz");
-
- log.warn("Testing MDC Properties");
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("WARN"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("WARN", entry.get("level"));
- assertEquals("Testing MDC Properties", entry.get("message"));
- assertNotNull(entry.get("properties"));
- DBObject mdcProperties = (DBObject) entry.get("properties");
-
- assertNotNull(mdcProperties.get("uuid"));
- assertNotNull(mdcProperties.get("recordAssociation"));
- }
-
- //-----------------------------------------------------------------------//
- // Private methods
- //-----------------------------------------------------------------------//
- private long countLogEntries() {
- return (collection.getCount());
- }
-
- private long countLogEntriesAtLevel(final String level) {
- return (countLogEntriesWhere(BasicDBObjectBuilder.start().add("level",
- level.toUpperCase()).get()));
- }
-
- private long countLogEntriesWhere(final DBObject whereClause) {
- return collection.getCount(whereClause);
- }
-}
+/*
+ * Copyright (C) 2009 Peter Monks (pmonks@gmail.com)
+ *
+ * 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.log4mongo;
+
+import com.mongodb.DBObject;
+import com.mongodb.Mongo;
+import com.mongodb.MongoClient;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import org.apache.log4j.Logger;
+import org.apache.log4j.MDC;
+import org.apache.log4j.PropertyConfigurator;
+import org.bson.Document;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * JUnit unit tests for ExtendedMongoDbAppender.
+ *
+ * Note: these tests require that a MongoDB server is running, and (by default)
+ * assumes that server is listening on the default port (27017) on localhost.
+ *
+ * @author Mick Knutson (http://www.baselogic.com)
+ */
+public class TestExtendedMongoDbAppender {
+
+ private final static Logger log = Logger.getLogger( TestExtendedMongoDbAppender.class );
+
+ private final static String TEST_MONGO_SERVER_HOSTNAME = "localhost";
+
+ private final static int TEST_MONGO_SERVER_PORT = 27017;
+
+ private final static String TEST_DATABASE_NAME = "log4mongotest";
+
+ private final static String TEST_COLLECTION_NAME = "logevents";
+
+ private final static String MONGODB_APPENDER_NAME = "MongoDB";
+
+ private final static String LOG4J_PROPS = "src/test/resources/log4j_extended.properties";
+ //private final static String LOG4J_PROPS = "src/test/resources/log4j_extended.xml";
+
+ private final MongoClient mongo;
+
+ private final ExtendedMongoDbAppender appender;
+
+ private MongoCollection collection;
+
+ public TestExtendedMongoDbAppender() throws Exception {
+ PropertyConfigurator.configure( LOG4J_PROPS );
+ mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT );
+ appender = (ExtendedMongoDbAppender) Logger.getRootLogger().getAppender(
+ MONGODB_APPENDER_NAME );
+ }
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ Mongo mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME,
+ TEST_MONGO_SERVER_PORT );
+ mongo.dropDatabase( TEST_DATABASE_NAME );
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ Mongo mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME,
+ TEST_MONGO_SERVER_PORT );
+ mongo.dropDatabase( TEST_DATABASE_NAME );
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ // Ensure both the appender and the JUnit test use the same collection
+ // object - provides consistency across reads (JUnit) & writes (Log4J)
+ collection = mongo.getDatabase( TEST_DATABASE_NAME ).getCollection(
+ TEST_COLLECTION_NAME );
+ collection.drop();
+ appender.setCollection( collection );
+ }
+
+ @Test
+ public void testInitialized() throws Exception {
+ if ( !appender.isInitialized() ) {
+ fail();
+ }
+ }
+
+ @Test
+ public void testRootLevelProperties() throws Exception {
+ assertEquals( 0L, countLogEntries() );
+
+ Map obj = new HashMap () {
+
+ {
+ put( "key1", "value1" );
+ put( "key2", "value2" );
+ }
+ };
+
+ //slf4j style: log.warn("Testing Object in Message: {}", obj);
+ log.warn( "Testing Object in Message: " + obj );
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "WARN" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find( DBObject.class );
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "WARN", entry.get( "level" ) );
+ assertEquals( "Testing Object in Message: {key1=value1, key2=value2}", entry.get( "message" ) );
+ }
+ }
+
+ @Test
+ public void testObjectAsMessage() throws Exception {
+ assertEquals( 0L, countLogEntries() );
+
+ log.warn( "Testing Object in Message" );
+
+ long appNameCount = countLogEntriesWhere( Document.parse( "{ 'applicationName' : 'MyProject' }" ) );
+
+ assertEquals( 1L, appNameCount );
+
+ // verify log entry content
+ FindIterable entries = collection.find( DBObject.class );
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "Development", entry.get( "eventType" ) );
+ }
+ }
+
+ @Test
+ public void testMdcProperties() throws Exception {
+ assertEquals( 0L, countLogEntries() );
+
+ MDC.put( "uuid", "1000" );
+ MDC.put( "recordAssociation", "xyz" );
+
+ log.warn( "Testing MDC Properties" );
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "WARN" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find( DBObject.class );
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "WARN", entry.get( "level" ) );
+ assertEquals( "Testing MDC Properties", entry.get( "message" ) );
+ assertNotNull( entry.get( "properties" ) );
+ DBObject mdcProperties = (DBObject) entry.get( "properties" );
+
+ assertNotNull( mdcProperties.get( "uuid" ) );
+ assertNotNull( mdcProperties.get( "recordAssociation" ) );
+ }
+ }
+
+ //-----------------------------------------------------------------------//
+ // Private methods
+ //-----------------------------------------------------------------------//
+ private long countLogEntries() {
+ return ( collection.count() );
+ }
+
+ private long countLogEntriesAtLevel( final String level ) {
+ return ( countLogEntriesWhere( Document.parse( "{ 'level' : '" + level.toUpperCase() + "' }" ) ) );
+ }
+
+ private long countLogEntriesWhere( final Document whereClause ) {
+ return collection.count( whereClause );
+ }
+
+}
diff --git a/src/test/java/org/log4mongo/TestLoggingEventBsonifierImpl.java b/src/test/java/org/log4mongo/TestLoggingEventBsonifierImpl.java
index 1dd56e5..f3b3da2 100644
--- a/src/test/java/org/log4mongo/TestLoggingEventBsonifierImpl.java
+++ b/src/test/java/org/log4mongo/TestLoggingEventBsonifierImpl.java
@@ -1,33 +1,34 @@
package org.log4mongo;
-import static org.junit.Assert.assertEquals;
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import org.junit.Test;
import java.lang.reflect.InvocationTargetException;
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBObject;
public class TestLoggingEventBsonifierImpl {
- @Test
- public void testStringBuffer() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
- LoggingEventBsonifierImplSubclass bsonifier = new LoggingEventBsonifierImplSubclass();
- DBObject bson = new BasicDBObject();
- String key = "thekey";
- StringBuffer sb = new StringBuffer("thevalue");
- bsonifier.publicNullSafePut(bson, key, sb);
- String retrievedValue = (String) bson.get(key);
- assertEquals(sb.toString(), retrievedValue);
- }
-
- // Create a subclass so I can test a protected method
- // Replace this after extending Privateer to support superclasses in method signature
- public class LoggingEventBsonifierImplSubclass extends LoggingEventBsonifierImpl {
- public void publicNullSafePut(DBObject bson, final String key, final Object value) {
- nullSafePut(bson, key, value);
- }
-
- }
+ @Test
+ public void testStringBuffer() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ LoggingEventBsonifierImplSubclass bsonifier = new LoggingEventBsonifierImplSubclass();
+ DBObject bson = new BasicDBObject();
+ String key = "thekey";
+ StringBuffer sb = new StringBuffer( "thevalue" );
+ bsonifier.publicNullSafePut( bson, key, sb );
+ String retrievedValue = (String) bson.get( key );
+ assertEquals( sb.toString(), retrievedValue );
+ }
+
+ // Create a subclass so I can test a protected method
+ // Replace this after extending Privateer to support superclasses in method signature
+ public class LoggingEventBsonifierImplSubclass extends LoggingEventBsonifierImpl {
+
+ public void publicNullSafePut( DBObject bson, final String key, final Object value ) {
+ nullSafePut( bson, key, value );
+ }
+
+ }
}
diff --git a/src/test/java/org/log4mongo/TestMongoDbAppender.java b/src/test/java/org/log4mongo/TestMongoDbAppender.java
index 648fc9c..fb0ed8a 100644
--- a/src/test/java/org/log4mongo/TestMongoDbAppender.java
+++ b/src/test/java/org/log4mongo/TestMongoDbAppender.java
@@ -1,317 +1,320 @@
-/*
- * Copyright (C) 2009 Peter Monks (pmonks@gmail.com)
- *
- * 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.log4mongo;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.lang.management.ManagementFactory;
-import java.net.InetAddress;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.PropertyConfigurator;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.mongodb.BasicDBList;
-import com.mongodb.BasicDBObjectBuilder;
-import com.mongodb.DBCollection;
-import com.mongodb.DBObject;
-import com.mongodb.Mongo;
-
-/**
- * JUnit unit tests for MongoDbAppender.
- *
- * Note: these tests require that a MongoDB server is running, and (by default) assumes that server
- * is listening on the default port (27017) on localhost.
- *
- * @author Peter Monks (pmonks@gmail.com)
- */
-public class TestMongoDbAppender {
- private final static Logger log = Logger.getLogger(TestMongoDbAppender.class);
-
- private final static String TEST_MONGO_SERVER_HOSTNAME = "localhost";
- private final static int TEST_MONGO_SERVER_PORT = 27017;
- private final static String TEST_DATABASE_NAME = "log4mongotest";
- private final static String TEST_COLLECTION_NAME = "logevents";
-
- private final static String MONGODB_APPENDER_NAME = "MongoDB";
-
- private final static String LOG4J_PROPS = "src/test/resources/log4j.properties";
-
- private final Mongo mongo;
- private final MongoDbAppender appender;
- private DBCollection collection;
-
- public TestMongoDbAppender() throws Exception {
- PropertyConfigurator.configure(LOG4J_PROPS);
- mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
- appender = (MongoDbAppender) Logger.getRootLogger().getAppender(MONGODB_APPENDER_NAME);
- }
-
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- Mongo mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
- mongo.dropDatabase(TEST_DATABASE_NAME);
- }
-
- @AfterClass
- public static void tearDownAfterClass() throws Exception {
- Mongo mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
- mongo.dropDatabase(TEST_DATABASE_NAME);
- }
-
- @Before
- public void setUp() throws Exception {
- // Ensure both the appender and the JUnit test use the same collection
- // object - provides consistency across reads (JUnit) & writes (Log4J)
- collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(TEST_COLLECTION_NAME);
- collection.drop();
- appender.setCollection(collection);
-
- mongo.getDB(TEST_DATABASE_NAME).requestStart();
- }
-
- @After
- public void tearDown() throws Exception {
- mongo.getDB(TEST_DATABASE_NAME).requestDone();
- }
-
- @Test
- public void testInitialized() throws Exception {
- if (!appender.isInitialized())
- fail();
- }
-
- @Test
- public void testSingleLogEntry() throws Exception {
- log.trace("Trace entry");
-
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("trace"));
- assertEquals(0L, countLogEntriesAtLevel("debug"));
- assertEquals(0L, countLogEntriesAtLevel("info"));
- assertEquals(0L, countLogEntriesAtLevel("warn"));
- assertEquals(0L, countLogEntriesAtLevel("error"));
- assertEquals(0L, countLogEntriesAtLevel("fatal"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("TRACE", entry.get("level"));
- assertEquals("Trace entry", entry.get("message"));
- }
-
- @Test
- public void testTimestampStoredNatively() throws Exception {
- log.debug("Debug entry");
-
- assertEquals(1L, countLogEntries());
-
- // verify timestamp - presence and data type
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertTrue("Timestamp is not present in logged entry", entry.containsField("timestamp"));
- assertTrue("Timestamp of logged entry is not stored as native date",
- (entry.get("timestamp") instanceof java.util.Date));
- }
-
- @Test
- public void testAllLevels() throws Exception {
- log.trace("Trace entry");
- log.debug("Debug entry");
- log.info("Info entry");
- log.warn("Warn entry");
- log.error("Error entry");
- log.fatal("Fatal entry");
-
- assertEquals(6L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("trace"));
- assertEquals(1L, countLogEntriesAtLevel("debug"));
- assertEquals(1L, countLogEntriesAtLevel("info"));
- assertEquals(1L, countLogEntriesAtLevel("warn"));
- assertEquals(1L, countLogEntriesAtLevel("error"));
- assertEquals(1L, countLogEntriesAtLevel("fatal"));
- }
-
- @Test
- public void testLogWithException() throws Exception {
- log.error("Error entry", new RuntimeException("Here is an exception!"));
-
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("error"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("ERROR", entry.get("level"));
- assertEquals("Error entry", entry.get("message"));
-
- // verify throwable presence and content
- assertTrue("Throwable is not present in logged entry", entry.containsField("throwables"));
- BasicDBList throwables = (BasicDBList) entry.get("throwables");
- assertEquals(1, throwables.size());
-
- DBObject throwableEntry = (DBObject) throwables.get("0");
- assertTrue("Throwable message is not present in logged entry",
- throwableEntry.containsField("message"));
- assertEquals("Here is an exception!", throwableEntry.get("message"));
- }
-
- @Test
- public void testLogWithChainedExceptions() throws Exception {
- Exception rootCause = new RuntimeException("I'm the real culprit!");
-
- log.error("Error entry", new RuntimeException("I'm an innocent bystander.", rootCause));
-
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("error"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("ERROR", entry.get("level"));
- assertEquals("Error entry", entry.get("message"));
-
- // verify throwable presence and content
- assertTrue("Throwable is not present in logged entry", entry.containsField("throwables"));
- BasicDBList throwables = (BasicDBList) entry.get("throwables");
- assertEquals(2, throwables.size());
-
- DBObject rootEntry = (DBObject) throwables.get("0");
- assertTrue("Throwable message is not present in logged entry",
- rootEntry.containsField("message"));
- assertEquals("I'm an innocent bystander.", rootEntry.get("message"));
-
- DBObject chainedEntry = (DBObject) throwables.get("1");
- assertTrue("Throwable message is not present in logged entry",
- chainedEntry.containsField("message"));
- assertEquals("I'm the real culprit!", chainedEntry.get("message"));
- }
-
- @Test
- public void testQuotesInMessage() {
- assertEquals(0L, countLogEntries());
- log.warn("Quotes\" \"embedded");
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("WARN"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("WARN", entry.get("level"));
- assertEquals("Quotes\" \"embedded", entry.get("message"));
- }
-
- @Test
- public void testPerformance() throws Exception {
- // Log one event to minimize start up effects on performance
- log.warn("Warn entry");
-
- long NUM_MESSAGES = 1000;
- long now = System.currentTimeMillis();
- for (long i = 0; i < NUM_MESSAGES; i++) {
- log.warn("Warn entry");
- }
- long dur = System.currentTimeMillis() - now;
- System.out.println("Milliseconds for MongoDbAppender to log " + NUM_MESSAGES + " messages:"
- + dur);
- assertEquals(NUM_MESSAGES + 1, countLogEntries());
- }
-
- @Test
- public void testRegularLoggerRecordsLoggerNameCorrectly() {
- log.info("From an unwrapped logger");
-
- assertEquals(1, countLogEntries());
- assertEquals(1, countLogEntriesAtLevel("info"));
- assertEquals(
- 1,
- countLogEntriesWhere(BasicDBObjectBuilder.start()
- .add("loggerName.className", "TestMongoDbAppender").get()));
- assertEquals(
- 1,
- countLogEntriesWhere(BasicDBObjectBuilder.start()
- .add("class.className", "TestMongoDbAppender").get()));
- }
-
- @Test
- public void testWrappedLoggerRecordsLoggerNameCorrectly() {
- WrappedLogger wrapped = new WrappedLogger(log);
- wrapped.info("From a wrapped logger");
-
- assertEquals(1, countLogEntries());
- assertEquals(1, countLogEntriesAtLevel("info"));
- assertEquals(
- 1,
- countLogEntriesWhere(BasicDBObjectBuilder.start()
- .add("loggerName.className", "TestMongoDbAppender").get()));
- assertEquals(
- 1,
- countLogEntriesWhere(BasicDBObjectBuilder.start()
- .add("class.className", "WrappedLogger").get()));
- }
-
- @Test
- public void testHostInfoRecords() throws Exception {
- assertEquals(0L, countLogEntries());
- log.warn("Testing hostinfo");
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("WARN"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("WARN", entry.get("level"));
- assertEquals("Testing hostinfo", entry.get("message"));
- assertNotNull(entry.get("host"));
- DBObject hostinfo = (DBObject) entry.get("host");
- assertNotNull(hostinfo.get("process"));
- assertEquals(InetAddress.getLocalHost().getHostName(), hostinfo.get("name"));
- assertEquals(ManagementFactory.getRuntimeMXBean().getName(), hostinfo.get("process"));
- }
-
- @Test
- /**
- * Added to verify fix to GitHub issue #24.
- */
- public void testLogObject() throws Exception {
- Object object = new Object();
-
- assertEquals(0L, countLogEntries());
- log.error(object);
- assertEquals(1L, countLogEntries());
- }
-
- private long countLogEntries() {
- return (collection.getCount());
- }
-
- private long countLogEntriesAtLevel(final String level) {
- return (countLogEntriesWhere(BasicDBObjectBuilder.start().add("level", level.toUpperCase())
- .get()));
- }
-
- private long countLogEntriesWhere(final DBObject whereClause) {
- return collection.getCount(whereClause);
- }
-}
+/*
+ * Copyright (C) 2009 Peter Monks (pmonks@gmail.com)
+ *
+ * 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.log4mongo;
+
+import com.mongodb.*;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+import org.bson.Document;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * JUnit unit tests for MongoDbAppender.
+ *
+ * Note: these tests require that a MongoDB server is running, and (by default) assumes that server
+ * is listening on the default port (27017) on localhost.
+ *
+ * @author Peter Monks (pmonks@gmail.com)
+ */
+public class TestMongoDbAppender {
+
+ private final static Logger log = Logger.getLogger( TestMongoDbAppender.class );
+
+ private final static String TEST_MONGO_SERVER_HOSTNAME = "localhost";
+
+ private final static int TEST_MONGO_SERVER_PORT = 27017;
+
+ private final static String TEST_DATABASE_NAME = "log4mongotest";
+
+ private final static String TEST_COLLECTION_NAME = "logevents";
+
+ private final static String MONGODB_APPENDER_NAME = "MongoDB";
+
+ private final static String LOG4J_PROPS = "src/test/resources/log4j.properties";
+
+ private final MongoClient mongo;
+
+ private final MongoDbAppender appender;
+
+ private MongoCollection collection;
+
+ public TestMongoDbAppender() throws Exception {
+ PropertyConfigurator.configure( LOG4J_PROPS );
+ mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT );
+ appender = (MongoDbAppender) Logger.getRootLogger().getAppender( MONGODB_APPENDER_NAME );
+ }
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ MongoClient mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT );
+ mongo.dropDatabase( TEST_DATABASE_NAME );
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ MongoClient mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT );
+ mongo.dropDatabase( TEST_DATABASE_NAME );
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ // Ensure both the appender and the JUnit test use the same collection
+ // object - provides consistency across reads (JUnit) & writes (Log4J)
+ collection = mongo.getDatabase( TEST_DATABASE_NAME ).getCollection( TEST_COLLECTION_NAME );
+ collection.drop();
+ appender.setCollection( collection );
+
+ }
+
+ @Test
+ public void testInitialized() throws Exception {
+ if ( !appender.isInitialized() ) {
+ fail();
+ }
+ }
+
+ @Test
+ public void testSingleLogEntry() throws Exception {
+ log.trace( "Trace entry" );
+
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "trace" ) );
+ assertEquals( 0L, countLogEntriesAtLevel( "debug" ) );
+ assertEquals( 0L, countLogEntriesAtLevel( "info" ) );
+ assertEquals( 0L, countLogEntriesAtLevel( "warn" ) );
+ assertEquals( 0L, countLogEntriesAtLevel( "error" ) );
+ assertEquals( 0L, countLogEntriesAtLevel( "fatal" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find(DBObject.class);
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "TRACE", entry.get( "level" ) );
+ assertEquals( "Trace entry", entry.get( "message" ) );
+ }
+ }
+
+ @Test
+ public void testTimestampStoredNatively() throws Exception {
+ log.debug( "Debug entry" );
+
+ assertEquals( 1L, countLogEntries() );
+
+ // verify timestamp - presence and data type
+ FindIterable entries = collection.find(DBObject.class);
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertTrue( "Timestamp is not present in logged entry", entry.containsField( "timestamp" ) );
+ assertTrue( "Timestamp of logged entry is not stored as native date",
+ ( entry.get( "timestamp" ) instanceof java.util.Date ) );
+ }
+ }
+
+ @Test
+ public void testAllLevels() throws Exception {
+ log.trace( "Trace entry" );
+ log.debug( "Debug entry" );
+ log.info( "Info entry" );
+ log.warn( "Warn entry" );
+ log.error( "Error entry" );
+ log.fatal( "Fatal entry" );
+
+ assertEquals( 6L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "trace" ) );
+ assertEquals( 1L, countLogEntriesAtLevel( "debug" ) );
+ assertEquals( 1L, countLogEntriesAtLevel( "info" ) );
+ assertEquals( 1L, countLogEntriesAtLevel( "warn" ) );
+ assertEquals( 1L, countLogEntriesAtLevel( "error" ) );
+ assertEquals( 1L, countLogEntriesAtLevel( "fatal" ) );
+ }
+
+ @Test
+ public void testLogWithException() throws Exception {
+ log.error( "Error entry", new RuntimeException( "Here is an exception!" ) );
+
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "error" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find(DBObject.class);
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "ERROR", entry.get( "level" ) );
+ assertEquals( "Error entry", entry.get( "message" ) );
+
+ // verify throwable presence and content
+ assertTrue( "Throwable is not present in logged entry", entry.containsField( "throwables" ) );
+ BasicDBList throwables = (BasicDBList) entry.get( "throwables" );
+ assertEquals( 1, throwables.size() );
+
+ DBObject throwableEntry = (DBObject) throwables.get( "0" );
+ assertTrue( "Throwable message is not present in logged entry",
+ throwableEntry.containsField( "message" ) );
+ assertEquals( "Here is an exception!", throwableEntry.get( "message" ) );
+ }
+ }
+
+ @Test
+ public void testLogWithChainedExceptions() throws Exception {
+ Exception rootCause = new RuntimeException( "I'm the real culprit!" );
+
+ log.error( "Error entry", new RuntimeException( "I'm an innocent bystander.", rootCause ) );
+
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "error" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find(DBObject.class);
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "ERROR", entry.get( "level" ) );
+ assertEquals( "Error entry", entry.get( "message" ) );
+
+ // verify throwable presence and content
+ assertTrue( "Throwable is not present in logged entry", entry.containsField( "throwables" ) );
+ BasicDBList throwables = (BasicDBList) entry.get( "throwables" );
+ assertEquals( 2, throwables.size() );
+
+ DBObject rootEntry = (DBObject) throwables.get( "0" );
+ assertTrue( "Throwable message is not present in logged entry",
+ rootEntry.containsField( "message" ) );
+ assertEquals( "I'm an innocent bystander.", rootEntry.get( "message" ) );
+
+ DBObject chainedEntry = (DBObject) throwables.get( "1" );
+ assertTrue( "Throwable message is not present in logged entry",
+ chainedEntry.containsField( "message" ) );
+ assertEquals( "I'm the real culprit!", chainedEntry.get( "message" ) );
+ }
+ }
+
+ @Test
+ public void testQuotesInMessage() {
+ assertEquals( 0L, countLogEntries() );
+ log.warn( "Quotes\" \"embedded" );
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "WARN" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find(DBObject.class);
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "WARN", entry.get( "level" ) );
+ assertEquals( "Quotes\" \"embedded", entry.get( "message" ) );
+ }
+ }
+
+ @Test
+ public void testPerformance() throws Exception {
+ // Log one event to minimize start up effects on performance
+ log.warn( "Warn entry" );
+
+ long NUM_MESSAGES = 1000;
+ long now = System.currentTimeMillis();
+ for ( long i = 0; i < NUM_MESSAGES; i++ ) {
+ log.warn( "Warn entry" );
+ }
+ long dur = System.currentTimeMillis() - now;
+ System.out.println( "Milliseconds for MongoDbAppender to log " + NUM_MESSAGES + " messages:"
+ + dur );
+ assertEquals( NUM_MESSAGES + 1, countLogEntries() );
+ }
+
+ @Test
+ public void testRegularLoggerRecordsLoggerNameCorrectly() {
+ log.info( "From an unwrapped logger" );
+
+ assertEquals( 1, countLogEntries() );
+ assertEquals( 1, countLogEntriesAtLevel( "info" ) );
+ assertEquals(
+ 1,
+ countLogEntriesWhere( Document.parse( "{ 'loggerName.className' : 'TestMongoDbAppender' }" ) ) );
+ assertEquals(
+ 1,
+ countLogEntriesWhere( Document.parse( "{ 'class.className' : 'TestMongoDbAppender' }" ) ) );
+ }
+
+ @Test
+ public void testWrappedLoggerRecordsLoggerNameCorrectly() {
+ WrappedLogger wrapped = new WrappedLogger( log );
+ wrapped.info( "From a wrapped logger" );
+
+ assertEquals( 1, countLogEntries() );
+ assertEquals( 1, countLogEntriesAtLevel( "info" ) );
+ assertEquals(
+ 1,
+ countLogEntriesWhere( Document.parse( "{ 'loggerName.className' : 'TestMongoDbAppender' }" ) ) );
+ assertEquals(
+ 1,
+ countLogEntriesWhere( Document.parse( "{ 'class.className' : 'WrappedLogger' }" ) ) );
+ }
+
+ @Test
+ public void testHostInfoRecords() throws Exception {
+ assertEquals( 0L, countLogEntries() );
+ log.warn( "Testing hostinfo" );
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "WARN" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find(DBObject.class);
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "WARN", entry.get( "level" ) );
+ assertEquals( "Testing hostinfo", entry.get( "message" ) );
+ assertNotNull( entry.get( "host" ) );
+ DBObject hostinfo = (DBObject) entry.get( "host" );
+ assertNotNull( hostinfo.get( "process" ) );
+ assertEquals( InetAddress.getLocalHost().getHostName(), hostinfo.get( "name" ) );
+ assertEquals( ManagementFactory.getRuntimeMXBean().getName(), hostinfo.get( "process" ) );
+ }
+ }
+
+ @Test
+ /**
+ * Added to verify fix to GitHub issue #24.
+ */
+ public void testLogObject() throws Exception {
+ Object object = new Object();
+
+ assertEquals( 0L, countLogEntries() );
+ log.error( object );
+ assertEquals( 1L, countLogEntries() );
+ }
+
+ private long countLogEntries() {
+ return ( collection.count() );
+ }
+
+ private long countLogEntriesAtLevel( final String level ) {
+ return ( countLogEntriesWhere( Document.parse( "{ 'level' : '" + level.toUpperCase() + "' }" ) ) );
+ }
+
+ private long countLogEntriesWhere( final Document whereClause ) {
+ return collection.count( whereClause );
+ }
+}
diff --git a/src/test/java/org/log4mongo/TestMongoDbAppenderAuth.java b/src/test/java/org/log4mongo/TestMongoDbAppenderAuth.java
index b191f3a..6f61d26 100644
--- a/src/test/java/org/log4mongo/TestMongoDbAppenderAuth.java
+++ b/src/test/java/org/log4mongo/TestMongoDbAppenderAuth.java
@@ -15,88 +15,84 @@
package org.log4mongo;
-import org.apache.log4j.PropertyConfigurator;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import com.mongodb.DBCollection;
import com.mongodb.Mongo;
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoCollection;
+import org.apache.log4j.PropertyConfigurator;
+import org.junit.*;
+
/**
* Authentication-related JUnit unit tests for MongoDbAppender.
- *
+ *
* Note: these tests require that a MongoDB server is running, and (by default) assumes that server
* is listening on the default port (27017) on localhost.
- *
+ *
* @author Robert Stewart (robert@wombatnation.com)
*/
public class TestMongoDbAppenderAuth {
- private final static String TEST_MONGO_SERVER_HOSTNAME = "localhost";
- private final static int TEST_MONGO_SERVER_PORT = 27017;
- private final static String TEST_DATABASE_NAME = "log4mongotestauth";
- private final static String TEST_COLLECTION_NAME = "logevents";
-
- private final static String LOG4J_AUTH_PROPS = "src/test/resources/log4j_auth.properties";
-
- private final static String username = "open";
- private final static String password = "sesame";
-
- private final Mongo mongo;
- private DBCollection collection;
-
- public TestMongoDbAppenderAuth() throws Exception {
- mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
- }
-
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- Mongo mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
- mongo.dropDatabase(TEST_DATABASE_NAME);
- }
-
- @AfterClass
- public static void tearDownAfterClass() throws Exception {
- Mongo mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
- mongo.dropDatabase(TEST_DATABASE_NAME);
- }
-
- @Before
- public void setUp() throws Exception {
- // Ensure both the appender and the JUnit test use the same
- // collection object - provides consistency across reads (JUnit) &
- // writes (Log4J)
- collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(TEST_COLLECTION_NAME);
- collection.drop();
-
- mongo.getDB(TEST_DATABASE_NAME).requestStart();
- }
-
- @After
- public void tearDown() throws Exception {
- mongo.getDB(TEST_DATABASE_NAME).requestDone();
- }
-
- /**
- * Catching the RuntimeException thrown when Log4J calls the MongoDbAppender activeOptions()
- * method isn't easy, since it is thrown in another thread.
- */
- @Test(expected = RuntimeException.class)
- @Ignore
- public void testAppenderActivateNoAuth() {
- PropertyConfigurator.configure(LOG4J_AUTH_PROPS);
- }
-
- /**
- * Adds the user to the test database before activating the appender.
- */
- @Test
- public void testAppenderActivateWithAuth() {
- mongo.getDB(TEST_DATABASE_NAME).addUser(username, password.toCharArray());
- PropertyConfigurator.configure(LOG4J_AUTH_PROPS);
- }
+
+ private final static String TEST_MONGO_SERVER_HOSTNAME = "localhost";
+
+ private final static int TEST_MONGO_SERVER_PORT = 27017;
+
+ private final static String TEST_DATABASE_NAME = "log4mongotestauth";
+
+ private final static String TEST_COLLECTION_NAME = "logevents";
+
+ private final static String LOG4J_AUTH_PROPS = "src/test/resources/log4j_auth.properties";
+
+ private final static String username = "open";
+
+ private final static String password = "sesame";
+
+ private final MongoClient mongo;
+
+ private MongoCollection collection;
+
+ public TestMongoDbAppenderAuth() throws Exception {
+ mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT );
+ }
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ MongoClient mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT );
+ mongo.dropDatabase( TEST_DATABASE_NAME );
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ MongoClient mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT );
+ mongo.dropDatabase( TEST_DATABASE_NAME );
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ // Ensure both the appender and the JUnit test use the same
+ // collection object - provides consistency across reads (JUnit) &
+ // writes (Log4J)
+ collection = mongo.getDatabase( TEST_DATABASE_NAME ).getCollection( TEST_COLLECTION_NAME );
+ collection.drop();
+
+ }
+
+ /**
+ * Catching the RuntimeException thrown when Log4J calls the MongoDbAppender activeOptions()
+ * method isn't easy, since it is thrown in another thread.
+ */
+ @Test( expected = RuntimeException.class )
+ @Ignore
+ public void testAppenderActivateNoAuth() {
+ PropertyConfigurator.configure( LOG4J_AUTH_PROPS );
+ }
+
+ /**
+ * Adds the user to the test database before activating the appender.
+ */
+ @Test
+ public void testAppenderActivateWithAuth() {
+ mongo.getDB( TEST_DATABASE_NAME ).addUser( username, password.toCharArray() );
+ PropertyConfigurator.configure( LOG4J_AUTH_PROPS );
+ }
}
diff --git a/src/test/java/org/log4mongo/TestMongoDbAppenderHosts.java b/src/test/java/org/log4mongo/TestMongoDbAppenderHosts.java
index de10c22..420c45b 100644
--- a/src/test/java/org/log4mongo/TestMongoDbAppenderHosts.java
+++ b/src/test/java/org/log4mongo/TestMongoDbAppenderHosts.java
@@ -1,164 +1,167 @@
-/*
- * Copyright (C) 2009 Robert Stewart (robert@wombatnation.com)
- *
- * 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.log4mongo;
-
-import static org.junit.Assert.assertTrue;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.PropertyConfigurator;
-import org.junit.Test;
-
-import com.mongodb.Mongo;
-import com.mongodb.ServerAddress;
-import com.wombatnation.privateer.Privateer;
-
-/**
- * JUnit unit tests for MongoDbAppender to verify proper behavior when setting the hostname and
- * property properties.
- *
- * Note: these tests require that a MongoDB server is running, and (by default) assumes that
- * server is listening on the default port (27017) on localhost.
- *
- * Unless a replica set is configured with mongod instances listening on ports 27017 and 27018,
- * errors will be logged. If a host is not listening on port 27018, testOneHostNonDefaultPort() will
- * fail with an error.
- *
- * To test on localhost with a replica set, do the following (either starting mongod instances in
- * separate terminals or start them with --fork):
- *
- * $ mkdir -p /data/r0
- * $ mkdir -p /data/r1
- * $ mkdir -p /data/r2
- * $ mongod --replSet foo --smallfiles --port 27017 --dbpath /data/r0
- * $ mongod --replSet foo --smallfiles --port 27018 --dbpath /data/r1
- * $ mongod --replSet foo --smallfiles --port 27019 --dbpath /data/r2
- * $ mongo
- * >config = {"_id": "foo", members:[{_id: 0, host: 'localhost:27017'},{_id: 1, host:
- * 'localhost:27018'},{_id: 2, host: 'localhost:27019', arbiterOnly: true}]}
- * >rs.initiate(config)
- * Then wait about a minute until replica set is established. You can run rs.status() and look
- * for direct confirmation.
- *
- * Since the unit tests create and drop databases several times, they run about twice as fast if
- * mongod is started with the --smallfiles argument.
- *
- * @author Robert Stewart (robert@wombatnation.com)
- */
-public class TestMongoDbAppenderHosts {
- private final static String TEST_MONGO_SERVER_HOSTNAME = "localhost";
- private final static int TEST_MONGO_SERVER_PORT = 27017;
- private final static String TEST_DATABASE_NAME = "log4mongotest";
-
- private final static String MONGODB_APPENDER_NAME = "MongoDB";
-
- private final Privateer p = new Privateer();
-
- @Test
- public void testOneHost() throws Exception {
- String hostname = TEST_MONGO_SERVER_HOSTNAME;
- PropertyConfigurator.configure(getDefaultPortProperties(hostname));
-
- MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
- MONGODB_APPENDER_NAME);
- Mongo mongo = (Mongo) p.getField(appender, "mongo");
- assertTrue(mongo.getAddress() != null);
- assertTrue(TEST_MONGO_SERVER_HOSTNAME.equals(mongo.getAddress().getHost()));
- assertTrue(TEST_MONGO_SERVER_PORT == mongo.getAddress().getPort());
-
- appender.close();
- }
-
- @Test
- public void testOneHostNonDefaultPort() throws Exception {
- String hostname = TEST_MONGO_SERVER_HOSTNAME;
- String port = "27018";
- int portNum = Integer.parseInt(port);
- PropertyConfigurator.configure(getNonDefaultPortProperties(hostname, port));
-
- MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
- MONGODB_APPENDER_NAME);
-
- Mongo mongo = (Mongo) p.getField(appender, "mongo");
- assertTrue(mongo.getAddress() != null);
- assertTrue(TEST_MONGO_SERVER_HOSTNAME.equals(mongo.getAddress().getHost()));
- assertTrue(portNum == mongo.getAddress().getPort());
-
- appender.close();
- }
-
- /**
- * If this test is run without a mongod running on localhost port 27018, an error will be logged
- * to the console by the appender.
- *
- * @throws Exception
- */
- @Test
- public void testTwoHostsTwoPorts() throws Exception {
- String hostname = "localhost localhost";
- List hosts = Arrays.asList("localhost", "localhost");
- String port = "27017 27018";
- List ports = Arrays.asList("27017", "27018");
- PropertyConfigurator.configure(getNonDefaultPortProperties(hostname, port));
-
- MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
- MONGODB_APPENDER_NAME);
-
- Mongo mongo = (Mongo) p.getField(appender, "mongo");
- List addresses = mongo.getAllAddress();
- assertTrue(addresses != null);
- for (ServerAddress address : addresses) {
- boolean found = false;
- int i = 0;
- for (String host : hosts) {
- if (host.equals(address.getHost())) {
- String p = String.valueOf(address.getPort());
- if (ports.get(i).equals(p)) {
- found = true;
- break;
- }
- }
- i++;
- }
- assertTrue(found);
- }
-
- appender.close();
- }
-
- private Properties getDefaultPortProperties(String hostname) {
- Properties props = new Properties();
- props.put("log4j.rootLogger", "DEBUG, MongoDB");
- props.put("log4j.appender.MongoDB", "org.log4mongo.MongoDbAppender");
- props.put("log4j.appender.MongoDB.databaseName", TEST_DATABASE_NAME);
- props.put("log4j.appender.MongoDB.hostname", hostname);
- return props;
- }
-
- private Properties getNonDefaultPortProperties(String hostname, String port) {
- Properties props = new Properties();
- props.put("log4j.rootLogger", "DEBUG, MongoDB");
- props.put("log4j.appender.MongoDB", "org.log4mongo.MongoDbAppender");
- props.put("log4j.appender.MongoDB.databaseName", TEST_DATABASE_NAME);
- props.put("log4j.appender.MongoDB.hostname", hostname);
- props.put("log4j.appender.MongoDB.port", port);
- return props;
- }
-}
+/*
+ * Copyright (C) 2009 Robert Stewart (robert@wombatnation.com)
+ *
+ * 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.log4mongo;
+
+import com.mongodb.Mongo;
+import com.mongodb.ServerAddress;
+import com.wombatnation.privateer.Privateer;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import static org.junit.Assert.assertTrue;
+
+
+/**
+ * JUnit unit tests for MongoDbAppender to verify proper behavior when setting the hostname and
+ * property properties.
+ *
+ * Note: these tests require that a MongoDB server is running, and (by default) assumes that
+ * server is listening on the default port (27017) on localhost.
+ *
+ * Unless a replica set is configured with mongod instances listening on ports 27017 and 27018,
+ * errors will be logged. If a host is not listening on port 27018, testOneHostNonDefaultPort() will
+ * fail with an error.
+ *
+ * To test on localhost with a replica set, do the following (either starting mongod instances in
+ * separate terminals or start them with --fork):
+ *
+ * $ mkdir -p /data/r0
+ * $ mkdir -p /data/r1
+ * $ mkdir -p /data/r2
+ * $ mongod --replSet foo --smallfiles --port 27017 --dbpath /data/r0
+ * $ mongod --replSet foo --smallfiles --port 27018 --dbpath /data/r1
+ * $ mongod --replSet foo --smallfiles --port 27019 --dbpath /data/r2
+ * $ mongo
+ * >config = {"_id": "foo", members:[{_id: 0, host: 'localhost:27017'},{_id: 1, host:
+ * 'localhost:27018'},{_id: 2, host: 'localhost:27019', arbiterOnly: true}]}
+ * >rs.initiate(config)
+ * Then wait about a minute until replica set is established. You can run rs.status() and look
+ * for direct confirmation.
+ *
+ * Since the unit tests create and drop databases several times, they run about twice as fast if
+ * mongod is started with the --smallfiles argument.
+ *
+ * @author Robert Stewart (robert@wombatnation.com)
+ */
+public class TestMongoDbAppenderHosts {
+
+ private final static String TEST_MONGO_SERVER_HOSTNAME = "localhost";
+
+ private final static int TEST_MONGO_SERVER_PORT = 27017;
+
+ private final static String TEST_DATABASE_NAME = "log4mongotest";
+
+ private final static String MONGODB_APPENDER_NAME = "MongoDB";
+
+ private final Privateer p = new Privateer();
+
+ @Test
+ public void testOneHost() throws Exception {
+ String hostname = TEST_MONGO_SERVER_HOSTNAME;
+ PropertyConfigurator.configure( getDefaultPortProperties( hostname ) );
+
+ MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
+ MONGODB_APPENDER_NAME );
+ Mongo mongo = (Mongo) p.getField( appender, "mongo" );
+ assertTrue( mongo.getAddress() != null );
+ assertTrue( TEST_MONGO_SERVER_HOSTNAME.equals( mongo.getAddress().getHost() ) );
+ assertTrue( TEST_MONGO_SERVER_PORT == mongo.getAddress().getPort() );
+
+ appender.close();
+ }
+
+ @Test
+ public void testOneHostNonDefaultPort() throws Exception {
+ String hostname = TEST_MONGO_SERVER_HOSTNAME;
+ String port = "27017";
+ int portNum = Integer.parseInt( port );
+ PropertyConfigurator.configure( getNonDefaultPortProperties( hostname, port ) );
+
+ MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
+ MONGODB_APPENDER_NAME );
+
+ Mongo mongo = (Mongo) p.getField( appender, "mongo" );
+ assertTrue( mongo.getAddress() != null );
+ assertTrue( TEST_MONGO_SERVER_HOSTNAME.equals( mongo.getAddress().getHost() ) );
+ assertTrue( portNum == mongo.getAddress().getPort() );
+
+ appender.close();
+ }
+
+ /**
+ * If this test is run without a mongod running on localhost port 27018, an error will be logged
+ * to the console by the appender.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testTwoHostsTwoPorts() throws Exception {
+ String hostname = "technecium technecium";
+ List hosts = Arrays.asList( "localhost", "localhost" );
+ String port = "27017 27017";
+ List ports = Arrays.asList( "27017", "27017" );
+ PropertyConfigurator.configure( getNonDefaultPortProperties( hostname, port ) );
+
+ MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
+ MONGODB_APPENDER_NAME );
+
+ Mongo mongo = (Mongo) p.getField( appender, "mongo" );
+ List addresses = mongo.getAllAddress();
+ assertTrue( addresses != null );
+ for ( ServerAddress address : addresses ) {
+ boolean found = false;
+ int i = 0;
+ for ( String host : hosts ) {
+ if ( host.equals( address.getHost() ) ) {
+ String p = String.valueOf( address.getPort() );
+ if ( ports.get( i ).equals( p ) ) {
+ found = true;
+ break;
+ }
+ }
+ i++;
+ }
+ assertTrue( found );
+ }
+
+ appender.close();
+ }
+
+ private Properties getDefaultPortProperties( String hostname ) {
+ Properties props = new Properties();
+ props.put( "log4j.rootLogger", "DEBUG, MongoDB" );
+ props.put( "log4j.appender.MongoDB", "org.log4mongo.MongoDbAppender" );
+ props.put( "log4j.appender.MongoDB.databaseName", TEST_DATABASE_NAME );
+ props.put( "log4j.appender.MongoDB.hostname", hostname );
+ return props;
+ }
+
+ private Properties getNonDefaultPortProperties( String hostname, String port ) {
+ Properties props = new Properties();
+ props.put( "log4j.rootLogger", "DEBUG, MongoDB" );
+ props.put( "log4j.appender.MongoDB", "org.log4mongo.MongoDbAppender" );
+ props.put( "log4j.appender.MongoDB.databaseName", TEST_DATABASE_NAME );
+ props.put( "log4j.appender.MongoDB.hostname", hostname );
+ props.put( "log4j.appender.MongoDB.port", port );
+ return props;
+ }
+}
diff --git a/src/test/java/org/log4mongo/TestMongoDbPatternLayout.java b/src/test/java/org/log4mongo/TestMongoDbPatternLayout.java
index 287f3d8..c4a0b2d 100644
--- a/src/test/java/org/log4mongo/TestMongoDbPatternLayout.java
+++ b/src/test/java/org/log4mongo/TestMongoDbPatternLayout.java
@@ -1,345 +1,354 @@
-/* Copyright (C) 2010 Robert Stewart (robert@wombatnation.com)
- *
- * 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.log4mongo;
-
-import static org.junit.Assert.*;
-
-import java.net.InetAddress;
-import java.util.Properties;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.PropertyConfigurator;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.mongodb.BasicDBList;
-import com.mongodb.BasicDBObject;
-import com.mongodb.BasicDBObjectBuilder;
-import com.mongodb.DBCollection;
-import com.mongodb.DBObject;
-import com.mongodb.Mongo;
-
-/**
- * JUnit unit tests for PatternLayout style logging.
- *
- * Since tests may depend on different Log4J property settings, each test reconfigures an appender
- * using a Properties object.
- *
- * Note: these tests require that a MongoDB server is running, and (by default) assumes that server
- * is listening on the default port (27017) on localhost.
- *
- * @author Robert Stewart (robert@wombatnation.com)
- */
-public class TestMongoDbPatternLayout {
- private static final Logger log = Logger.getLogger(TestMongoDbPatternLayout.class);
-
- public static final String TEST_MONGO_SERVER_HOSTNAME = "localhost";
- public static final int TEST_MONGO_SERVER_PORT = 27017;
- private static final String TEST_DATABASE_NAME = "log4mongotest";
- private static final String TEST_COLLECTION_NAME = "logeventslayout";
-
- private static final String APPENDER_NAME = "MongoDBPatternLayout";
-
- private final Mongo mongo;
- private DBCollection collection;
-
- public TestMongoDbPatternLayout() throws Exception {
- mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
- }
-
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- Mongo mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
- mongo.dropDatabase(TEST_DATABASE_NAME);
- }
-
- @AfterClass
- public static void tearDownAfterClass() throws Exception {
- Mongo mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
- mongo.dropDatabase(TEST_DATABASE_NAME);
- }
-
- @Before
- public void setUp() throws Exception {
- // Ensure both the appender and the JUnit test use the same collection
- // object - provides consistency across reads (JUnit) & writes (Log4J)
- collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(TEST_COLLECTION_NAME);
- collection.drop();
-
- mongo.getDB(TEST_DATABASE_NAME).requestStart();
- }
-
- @After
- public void tearDown() throws Exception {
- mongo.getDB(TEST_DATABASE_NAME).requestDone();
- }
-
- @Test
- public void testValidPatternLayout() {
- PropertyConfigurator.configure(getValidPatternLayoutProperties());
-
- MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
- APPENDER_NAME);
-
- collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(TEST_COLLECTION_NAME);
- appender.setCollection(collection);
-
- assertEquals(0L, countLogEntries());
- log.warn("Warn entry");
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("WARN"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("WARN", entry.get("level"));
- assertEquals("Warn entry", entry.get("message"));
- // This is the custom info. In the pattern, the field is named "extra".
- assertEquals("useful info", entry.get("extra"));
- }
-
- @Test
- public void testQuotesInMessage() {
- PropertyConfigurator.configure(getValidPatternLayoutProperties());
-
- MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
- APPENDER_NAME);
-
- collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(TEST_COLLECTION_NAME);
- appender.setCollection(collection);
-
- assertEquals(0L, countLogEntries());
- String msg = "\"Quotes\" ' \"embedded\"";
- log.warn(msg);
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("WARN"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("WARN", entry.get("level"));
- assertEquals(msg, entry.get("message"));
- }
-
- @Test
- public void testNestedDoc() {
- PropertyConfigurator.configure(getNestedDocPatternLayoutProperties());
-
- MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
- APPENDER_NAME);
-
- collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(TEST_COLLECTION_NAME);
- appender.setCollection(collection);
-
- assertEquals(0L, countLogEntries());
- String msg = "Nested warning";
- log.warn(msg);
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("WARN"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("WARN", entry.get("level"));
- DBObject nestedDoc = (DBObject) entry.get("nested");
- assertEquals(msg, nestedDoc.get("message"));
- }
-
- /**
- * Tests that the document stored in MongoDB has an array as a value if the conversion pattern
- * specifies an array as a value.
- */
- @Test
- public void testArrayValue() {
- PropertyConfigurator.configure(getArrayPatternLayoutProperties());
-
- MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
- APPENDER_NAME);
-
- collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(TEST_COLLECTION_NAME);
- appender.setCollection(collection);
-
- assertEquals(0L, countLogEntries());
- String msg = "Message in array";
- log.warn(msg);
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("WARN"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("WARN", entry.get("level"));
- BasicDBList list = (BasicDBList) entry.get("array");
- assertEquals(2, list.size());
- assertEquals(this.getClass().getSimpleName(), list.get(0));
- assertEquals(msg, list.get(1));
- }
-
- @Test
- public void testHostInfoPatternLayout() throws Exception {
- PropertyConfigurator.configure(getHostInfoPatternLayoutProperties());
-
- MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
- APPENDER_NAME);
-
- collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(TEST_COLLECTION_NAME);
- appender.setCollection(collection);
-
- assertEquals(0L, countLogEntries());
- String msg = "Message in array";
- log.warn(msg);
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("WARN"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("WARN", entry.get("level"));
- assertNotNull(entry.get("host"));
- DBObject hostinfo = (DBObject) entry.get("host");
- assertNotNull(hostinfo.get("name"));
- assertNotNull(hostinfo.get("ip_address"));
- assertNotNull(hostinfo.get("process"));
- assertEquals(InetAddress.getLocalHost().getHostName(), hostinfo.get("name"));
- assertEquals(InetAddress.getLocalHost().getHostAddress(), hostinfo.get("ip_address"));
- }
-
- @Test
- public void testBackslashInMessage() {
- PropertyConfigurator.configure(getValidPatternLayoutProperties());
-
- MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
- APPENDER_NAME);
-
- collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(TEST_COLLECTION_NAME);
- appender.setCollection(collection);
-
- assertEquals(0L, countLogEntries());
- String msg = "c:\\users\\some_file\\";
- log.warn(msg);
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("WARN"));
-
- String msgDoubleBackslash = "c:\\\\users\\\\some_file\\\\";
- log.info(msgDoubleBackslash);
- assertEquals(2L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("INFO"));
-
- // verify log entry content
- DBObject queryObj = new BasicDBObject();
- queryObj.put("level", "WARN");
- DBObject entry = collection.findOne(queryObj);
- assertNotNull(entry);
- assertEquals("WARN", entry.get("level"));
- assertEquals(msg, entry.get("message"));
-
- queryObj = new BasicDBObject();
- queryObj.put("level", "INFO");
- entry = collection.findOne(queryObj);
- assertNotNull(entry);
- assertEquals("INFO", entry.get("level"));
- assertEquals(msgDoubleBackslash, entry.get("message"));
- }
-
- @Test
- public void testPerformance() {
- PropertyConfigurator.configure(getValidPatternLayoutProperties());
-
- MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
- APPENDER_NAME);
-
- collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(TEST_COLLECTION_NAME);
- appender.setCollection(collection);
-
- int NUM_MESSAGES = 1000;
- long now = System.currentTimeMillis();
- for (int i = 0; i < NUM_MESSAGES; i++) {
- log.warn("Warn entry");
- }
- long dur = System.currentTimeMillis() - now;
- System.out.println("Milliseconds for MongoDbPatternLayoutAppender to log " + NUM_MESSAGES
- + " messages:" + dur);
- assertEquals(NUM_MESSAGES, countLogEntries());
- }
-
- private long countLogEntries() {
- return (collection.getCount());
- }
-
- private long countLogEntriesAtLevel(final String level) {
- return (countLogEntriesWhere(BasicDBObjectBuilder.start().add("level", level.toUpperCase())
- .get()));
- }
-
- private long countLogEntriesWhere(final DBObject whereClause) {
- return collection.getCount(whereClause);
- }
-
- private Properties getValidPatternLayoutProperties() {
- Properties props = new Properties();
- props.put("log4j.rootLogger", "DEBUG, MongoDBPatternLayout");
- props.put("log4j.appender.MongoDBPatternLayout",
- "org.log4mongo.MongoDbPatternLayoutAppender");
- props.put("log4j.appender.MongoDBPatternLayout.databaseName", "log4mongotest");
- props.put("log4j.appender.MongoDBPatternLayout.layout", "org.log4mongo.CustomPatternLayout");
- props.put(
- "log4j.appender.MongoDBPatternLayout.layout.ConversionPattern",
- "{\"extra\":\"%e\",\"timestamp\":\"%d{yyyy-MM-dd'T'HH:mm:ss'Z'}\",\"level\":\"%p\",\"class\":\"%c{1}\",\"message\":\"%m\"}");
- return props;
- }
-
- private Properties getNestedDocPatternLayoutProperties() {
- Properties props = new Properties();
- props.put("log4j.rootLogger", "DEBUG, MongoDBPatternLayout");
- props.put("log4j.appender.MongoDBPatternLayout",
- "org.log4mongo.MongoDbPatternLayoutAppender");
- props.put("log4j.appender.MongoDBPatternLayout.databaseName", "log4mongotest");
- props.put("log4j.appender.MongoDBPatternLayout.layout", "org.log4mongo.CustomPatternLayout");
- props.put(
- "log4j.appender.MongoDBPatternLayout.layout.ConversionPattern",
- "{\"timestamp\":\"%d{yyyy-MM-dd'T'HH:mm:ss'Z'}\",\"level\":\"%p\",\"nested\":{\"class\":\"%c{1}\",\"message\":\"%m\"}}");
- return props;
- }
-
- private Properties getArrayPatternLayoutProperties() {
- Properties props = new Properties();
- props.put("log4j.rootLogger", "DEBUG, MongoDBPatternLayout");
- props.put("log4j.appender.MongoDBPatternLayout",
- "org.log4mongo.MongoDbPatternLayoutAppender");
- props.put("log4j.appender.MongoDBPatternLayout.databaseName", "log4mongotest");
- props.put("log4j.appender.MongoDBPatternLayout.layout", "org.log4mongo.CustomPatternLayout");
- props.put("log4j.appender.MongoDBPatternLayout.layout.ConversionPattern",
- "{\"timestamp\":\"%d{yyyy-MM-dd'T'HH:mm:ss'Z'}\",\"level\":\"%p\",\"array\":[\"%c{1}\",\"%m\"]}");
- return props;
- }
-
- private Properties getHostInfoPatternLayoutProperties() {
- Properties props = new Properties();
- props.put("log4j.rootLogger", "DEBUG, MongoDBPatternLayout");
- props.put("log4j.appender.MongoDBPatternLayout",
- "org.log4mongo.MongoDbPatternLayoutAppender");
- props.put("log4j.appender.MongoDBPatternLayout.databaseName", "log4mongotest");
- props.put("log4j.appender.MongoDBPatternLayout.layout",
- "org.log4mongo.contrib.HostInfoPatternLayout");
- props.put(
- "log4j.appender.MongoDBPatternLayout.layout.ConversionPattern",
- "{\"timestamp\":\"%d{yyyy-MM-dd'T'HH:mm:ss'Z'}\",\"level\":\"%p\",\"array\":[\"%c{1}\",\"%m\"],\"host\":{\"name\":\"%H\", \"process\":\"%V\", \"ip_address\":\"%I\"}}");
- return props;
- }
-}
+/* Copyright (C) 2010 Robert Stewart (robert@wombatnation.com)
+ *
+ * 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.log4mongo;
+
+import com.mongodb.*;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+import org.bson.Document;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.net.InetAddress;
+import java.util.Properties;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+
+/**
+ * JUnit unit tests for PatternLayout style logging.
+ *
+ * Since tests may depend on different Log4J property settings, each test reconfigures an appender
+ * using a Properties object.
+ *
+ * Note: these tests require that a MongoDB server is running, and (by default) assumes that server
+ * is listening on the default port (27017) on localhost.
+ *
+ * @author Robert Stewart (robert@wombatnation.com)
+ */
+public class TestMongoDbPatternLayout {
+
+ private static final Logger log = Logger.getLogger( TestMongoDbPatternLayout.class );
+
+ public static final String TEST_MONGO_SERVER_HOSTNAME = "localhost";
+
+ public static final int TEST_MONGO_SERVER_PORT = 27017;
+
+ private static final String TEST_DATABASE_NAME = "log4mongotest";
+
+ private static final String TEST_COLLECTION_NAME = "logeventslayout";
+
+ private static final String APPENDER_NAME = "MongoDBPatternLayout";
+
+ private final MongoClient mongo;
+
+ private MongoCollection collection;
+
+ public TestMongoDbPatternLayout() throws Exception {
+ mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT );
+ }
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ MongoClient mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT );
+ mongo.dropDatabase( TEST_DATABASE_NAME );
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ MongoClient mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT );
+ mongo.dropDatabase( TEST_DATABASE_NAME );
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ // Ensure both the appender and the JUnit test use the same collection
+ // object - provides consistency across reads (JUnit) & writes (Log4J)
+ collection = mongo.getDatabase( TEST_DATABASE_NAME ).getCollection( TEST_COLLECTION_NAME );
+ collection.drop();
+ }
+
+ @Test
+ public void testValidPatternLayout() {
+ PropertyConfigurator.configure( getValidPatternLayoutProperties() );
+
+ MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
+ APPENDER_NAME );
+
+ collection = mongo.getDatabase( TEST_DATABASE_NAME ).getCollection( TEST_COLLECTION_NAME );
+ appender.setCollection( collection );
+
+ assertEquals( 0L, countLogEntries() );
+ log.warn( "Warn entry" );
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "WARN" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find( DBObject.class );
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "WARN", entry.get( "level" ) );
+ assertEquals( "Warn entry", entry.get( "message" ) );
+ // This is the custom info. In the pattern, the field is named "extra".
+ assertEquals( "useful info", entry.get( "extra" ) );
+ }
+ }
+
+ @Test
+ public void testQuotesInMessage() {
+ PropertyConfigurator.configure( getValidPatternLayoutProperties() );
+
+ MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
+ APPENDER_NAME );
+
+ collection = mongo.getDatabase( TEST_DATABASE_NAME ).getCollection( TEST_COLLECTION_NAME );
+ appender.setCollection( collection );
+
+ assertEquals( 0L, countLogEntries() );
+ String msg = "\"Quotes\" ' \"embedded\"";
+ log.warn( msg );
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "WARN" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find( DBObject.class );
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "WARN", entry.get( "level" ) );
+ assertEquals( msg, entry.get( "message" ) );
+ }
+ }
+
+ @Test
+ public void testNestedDoc() {
+ PropertyConfigurator.configure( getNestedDocPatternLayoutProperties() );
+
+ MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
+ APPENDER_NAME );
+
+ collection = mongo.getDatabase( TEST_DATABASE_NAME ).getCollection( TEST_COLLECTION_NAME );
+ appender.setCollection( collection );
+
+ assertEquals( 0L, countLogEntries() );
+ String msg = "Nested warning";
+ log.warn( msg );
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "WARN" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find( DBObject.class );
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "WARN", entry.get( "level" ) );
+ DBObject nestedDoc = (DBObject) entry.get( "nested" );
+ assertEquals( msg, nestedDoc.get( "message" ) );
+ }
+ }
+
+ /**
+ * Tests that the document stored in MongoDB has an array as a value if the conversion pattern
+ * specifies an array as a value.
+ */
+ @Test
+ public void testArrayValue() {
+ PropertyConfigurator.configure( getArrayPatternLayoutProperties() );
+
+ MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
+ APPENDER_NAME );
+
+ collection = mongo.getDatabase( TEST_DATABASE_NAME ).getCollection( TEST_COLLECTION_NAME );
+ appender.setCollection( collection );
+
+ assertEquals( 0L, countLogEntries() );
+ String msg = "Message in array";
+ log.warn( msg );
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "WARN" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find(DBObject.class);
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "WARN", entry.get( "level" ) );
+ BasicDBList list = (BasicDBList) entry.get( "array" );
+ assertEquals( 2, list.size() );
+ assertEquals( this.getClass().getSimpleName(), list.get( 0 ) );
+ assertEquals( msg, list.get( 1 ) );
+ }
+ }
+
+ @Test
+ public void testHostInfoPatternLayout() throws Exception {
+ PropertyConfigurator.configure( getHostInfoPatternLayoutProperties() );
+
+ MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
+ APPENDER_NAME );
+
+ collection = mongo.getDatabase( TEST_DATABASE_NAME ).getCollection( TEST_COLLECTION_NAME );
+ appender.setCollection( collection );
+
+ assertEquals( 0L, countLogEntries() );
+ String msg = "Message in array";
+ log.warn( msg );
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "WARN" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find(DBObject.class);
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "WARN", entry.get( "level" ) );
+ assertNotNull( entry.get( "host" ) );
+ DBObject hostinfo = (DBObject) entry.get( "host" );
+ assertNotNull( hostinfo.get( "name" ) );
+ assertNotNull( hostinfo.get( "ip_address" ) );
+ assertNotNull( hostinfo.get( "process" ) );
+ assertEquals( InetAddress.getLocalHost().getHostName(), hostinfo.get( "name" ) );
+ assertEquals( InetAddress.getLocalHost().getHostAddress(), hostinfo.get( "ip_address" ) );
+ }
+ }
+
+ @Test
+ public void testBackslashInMessage() {
+ PropertyConfigurator.configure( getValidPatternLayoutProperties() );
+
+ MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
+ APPENDER_NAME );
+
+ collection = mongo.getDatabase( TEST_DATABASE_NAME ).getCollection( TEST_COLLECTION_NAME );
+ appender.setCollection( collection );
+
+ assertEquals( 0L, countLogEntries() );
+ String msg = "c:\\users\\some_file\\";
+ log.warn( msg );
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "WARN" ) );
+
+ String msgDoubleBackslash = "c:\\\\users\\\\some_file\\\\";
+ log.info( msgDoubleBackslash );
+ assertEquals( 2L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "INFO" ) );
+
+ // verify log entry content
+ DBObject queryObj = new BasicDBObject();
+ queryObj.put( "level", "WARN" );
+ FindIterable entries = collection.find(DBObject.class).limit(1);
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "WARN", entry.get( "level" ) );
+ assertEquals( msg, entry.get( "message" ) );
+ }
+
+ queryObj = new BasicDBObject();
+ queryObj.put( "level", "INFO" );
+ entries = collection.find(DBObject.class).skip( 1 );
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "INFO", entry.get( "level" ) );
+ assertEquals( msgDoubleBackslash, entry.get( "message" ) );
+ }
+ }
+
+ @Test
+ public void testPerformance() {
+ PropertyConfigurator.configure( getValidPatternLayoutProperties() );
+
+ MongoDbAppender appender = (MongoDbAppender) Logger.getRootLogger().getAppender(
+ APPENDER_NAME );
+
+ collection = mongo.getDatabase( TEST_DATABASE_NAME ).getCollection( TEST_COLLECTION_NAME );
+ appender.setCollection( collection );
+
+ int NUM_MESSAGES = 1000;
+ long now = System.currentTimeMillis();
+ for ( int i = 0; i < NUM_MESSAGES; i++ ) {
+ log.warn( "Warn entry" );
+ }
+ long dur = System.currentTimeMillis() - now;
+ System.out.println( "Milliseconds for MongoDbPatternLayoutAppender to log " + NUM_MESSAGES
+ + " messages:" + dur );
+ assertEquals( NUM_MESSAGES, countLogEntries() );
+ }
+
+ private long countLogEntries() {
+ return ( collection.count() );
+ }
+
+ private long countLogEntriesAtLevel( final String level ) {
+ return ( countLogEntriesWhere( Document.parse( "{ 'level' : '" + level.toUpperCase() + "' }" ) ) );
+ }
+
+ private long countLogEntriesWhere( final Document whereClause ) {
+ return collection.count( whereClause );
+ }
+
+ private Properties getValidPatternLayoutProperties() {
+ Properties props = new Properties();
+ props.put( "log4j.rootLogger", "DEBUG, MongoDBPatternLayout" );
+ props.put( "log4j.appender.MongoDBPatternLayout",
+ "org.log4mongo.MongoDbPatternLayoutAppender" );
+ props.put( "log4j.appender.MongoDBPatternLayout.databaseName", "log4mongotest" );
+ props.put( "log4j.appender.MongoDBPatternLayout.layout", "org.log4mongo.CustomPatternLayout" );
+ props.put(
+ "log4j.appender.MongoDBPatternLayout.layout.ConversionPattern",
+ "{\"extra\":\"%e\",\"timestamp\":\"%d{yyyy-MM-dd'T'HH:mm:ss'Z'}\",\"level\":\"%p\",\"class\":\"%c{1}\",\"message\":\"%m\"}" );
+ return props;
+ }
+
+ private Properties getNestedDocPatternLayoutProperties() {
+ Properties props = new Properties();
+ props.put( "log4j.rootLogger", "DEBUG, MongoDBPatternLayout" );
+ props.put( "log4j.appender.MongoDBPatternLayout",
+ "org.log4mongo.MongoDbPatternLayoutAppender" );
+ props.put( "log4j.appender.MongoDBPatternLayout.databaseName", "log4mongotest" );
+ props.put( "log4j.appender.MongoDBPatternLayout.layout", "org.log4mongo.CustomPatternLayout" );
+ props.put(
+ "log4j.appender.MongoDBPatternLayout.layout.ConversionPattern",
+ "{\"timestamp\":\"%d{yyyy-MM-dd'T'HH:mm:ss'Z'}\",\"level\":\"%p\",\"nested\":{\"class\":\"%c{1}\",\"message\":\"%m\"}}" );
+ return props;
+ }
+
+ private Properties getArrayPatternLayoutProperties() {
+ Properties props = new Properties();
+ props.put( "log4j.rootLogger", "DEBUG, MongoDBPatternLayout" );
+ props.put( "log4j.appender.MongoDBPatternLayout",
+ "org.log4mongo.MongoDbPatternLayoutAppender" );
+ props.put( "log4j.appender.MongoDBPatternLayout.databaseName", "log4mongotest" );
+ props.put( "log4j.appender.MongoDBPatternLayout.layout", "org.log4mongo.CustomPatternLayout" );
+ props.put( "log4j.appender.MongoDBPatternLayout.layout.ConversionPattern",
+ "{\"timestamp\":\"%d{yyyy-MM-dd'T'HH:mm:ss'Z'}\",\"level\":\"%p\",\"array\":[\"%c{1}\",\"%m\"]}" );
+ return props;
+ }
+
+ private Properties getHostInfoPatternLayoutProperties() {
+ Properties props = new Properties();
+ props.put( "log4j.rootLogger", "DEBUG, MongoDBPatternLayout" );
+ props.put( "log4j.appender.MongoDBPatternLayout",
+ "org.log4mongo.MongoDbPatternLayoutAppender" );
+ props.put( "log4j.appender.MongoDBPatternLayout.databaseName", "log4mongotest" );
+ props.put( "log4j.appender.MongoDBPatternLayout.layout",
+ "org.log4mongo.contrib.HostInfoPatternLayout" );
+ props.put(
+ "log4j.appender.MongoDBPatternLayout.layout.ConversionPattern",
+ "{\"timestamp\":\"%d{yyyy-MM-dd'T'HH:mm:ss'Z'}\",\"level\":\"%p\",\"array\":[\"%c{1}\",\"%m\"],\"host\":{\"name\":\"%H\", \"process\":\"%V\", \"ip_address\":\"%I\"}}" );
+ return props;
+ }
+}
diff --git a/src/test/java/org/log4mongo/TestWriteConcern.java b/src/test/java/org/log4mongo/TestWriteConcern.java
index 2ba21d9..09d24c8 100644
--- a/src/test/java/org/log4mongo/TestWriteConcern.java
+++ b/src/test/java/org/log4mongo/TestWriteConcern.java
@@ -1,311 +1,317 @@
-/*
- * Copyright (C) 2009 Peter Monks (pmonks@gmail.com)
- *
- * 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.log4mongo;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.lang.management.ManagementFactory;
-import java.net.InetAddress;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.PropertyConfigurator;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.mongodb.BasicDBList;
-import com.mongodb.BasicDBObjectBuilder;
-import com.mongodb.DBCollection;
-import com.mongodb.DBObject;
-import com.mongodb.Mongo;
-
-/**
- * JUnit unit tests for using write concerns with MongoDbAppender.
- *
- * When using FSYNCED, logging is well over a magnitude slower than UNACKNOWLEDGED.
- *
- * Note: these tests require that a MongoDB server is running, and (by default) assumes that server
- * is listening on the default port (27017) on localhost.
- */
-public class TestWriteConcern {
- private final static Logger log = Logger.getLogger(TestWriteConcern.class);
-
- private final static String TEST_MONGO_SERVER_HOSTNAME = "localhost";
- private final static int TEST_MONGO_SERVER_PORT = 27017;
- private final static String TEST_DATABASE_NAME = "log4mongotest";
- private final static String TEST_COLLECTION_NAME = "logevents";
-
- private final static String MONGODB_APPENDER_NAME = "MongoDB";
-
- private final static String LOG4J_PROPS = "src/test/resources/log4j_write_concern.properties";
-
- private final Mongo mongo;
- private final MongoDbAppender appender;
- private DBCollection collection;
-
- public TestWriteConcern() throws Exception {
- PropertyConfigurator.configure(LOG4J_PROPS);
- mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
- appender = (MongoDbAppender) Logger.getRootLogger().getAppender(MONGODB_APPENDER_NAME);
- }
-
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- Mongo mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
- mongo.dropDatabase(TEST_DATABASE_NAME);
- }
-
- @AfterClass
- public static void tearDownAfterClass() throws Exception {
- Mongo mongo = new Mongo(TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT);
- mongo.dropDatabase(TEST_DATABASE_NAME);
- }
-
- @Before
- public void setUp() throws Exception {
- // Ensure both the appender and the JUnit test use the same collection
- // object - provides consistency across reads (JUnit) & writes (Log4J)
- collection = mongo.getDB(TEST_DATABASE_NAME).getCollection(TEST_COLLECTION_NAME);
- collection.drop();
- appender.setCollection(collection);
-
- mongo.getDB(TEST_DATABASE_NAME).requestStart();
- }
-
- @After
- public void tearDown() throws Exception {
- mongo.getDB(TEST_DATABASE_NAME).requestDone();
- }
-
- @Test
- public void testInitialized() throws Exception {
- if (!appender.isInitialized())
- fail();
- }
-
- @Test
- public void testWriteConcern() throws Exception {
- testInitialized();
- assertEquals(appender.getWriteConcern(), "FSYNCED");
- }
-
- @Test
- public void testSingleLogEntry() throws Exception {
- log.trace("Trace entry");
-
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("trace"));
- assertEquals(0L, countLogEntriesAtLevel("debug"));
- assertEquals(0L, countLogEntriesAtLevel("info"));
- assertEquals(0L, countLogEntriesAtLevel("warn"));
- assertEquals(0L, countLogEntriesAtLevel("error"));
- assertEquals(0L, countLogEntriesAtLevel("fatal"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("TRACE", entry.get("level"));
- assertEquals("Trace entry", entry.get("message"));
- }
-
- @Test
- public void testTimestampStoredNatively() throws Exception {
- log.debug("Debug entry");
-
- assertEquals(1L, countLogEntries());
-
- // verify timestamp - presence and data type
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertTrue("Timestamp is not present in logged entry", entry.containsField("timestamp"));
- assertTrue("Timestamp of logged entry is not stored as native date",
- (entry.get("timestamp") instanceof java.util.Date));
- }
-
- @Test
- public void testAllLevels() throws Exception {
- log.trace("Trace entry");
- log.debug("Debug entry");
- log.info("Info entry");
- log.warn("Warn entry");
- log.error("Error entry");
- log.fatal("Fatal entry");
-
- assertEquals(6L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("trace"));
- assertEquals(1L, countLogEntriesAtLevel("debug"));
- assertEquals(1L, countLogEntriesAtLevel("info"));
- assertEquals(1L, countLogEntriesAtLevel("warn"));
- assertEquals(1L, countLogEntriesAtLevel("error"));
- assertEquals(1L, countLogEntriesAtLevel("fatal"));
- }
-
- @Test
- public void testLogWithException() throws Exception {
- log.error("Error entry", new RuntimeException("Here is an exception!"));
-
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("error"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("ERROR", entry.get("level"));
- assertEquals("Error entry", entry.get("message"));
-
- // verify throwable presence and content
- assertTrue("Throwable is not present in logged entry", entry.containsField("throwables"));
- BasicDBList throwables = (BasicDBList) entry.get("throwables");
- assertEquals(1, throwables.size());
-
- DBObject throwableEntry = (DBObject) throwables.get("0");
- assertTrue("Throwable message is not present in logged entry",
- throwableEntry.containsField("message"));
- assertEquals("Here is an exception!", throwableEntry.get("message"));
- }
-
- @Test
- public void testLogWithChainedExceptions() throws Exception {
- Exception rootCause = new RuntimeException("I'm the real culprit!");
-
- log.error("Error entry", new RuntimeException("I'm an innocent bystander.", rootCause));
-
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("error"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("ERROR", entry.get("level"));
- assertEquals("Error entry", entry.get("message"));
-
- // verify throwable presence and content
- assertTrue("Throwable is not present in logged entry", entry.containsField("throwables"));
- BasicDBList throwables = (BasicDBList) entry.get("throwables");
- assertEquals(2, throwables.size());
-
- DBObject rootEntry = (DBObject) throwables.get("0");
- assertTrue("Throwable message is not present in logged entry",
- rootEntry.containsField("message"));
- assertEquals("I'm an innocent bystander.", rootEntry.get("message"));
-
- DBObject chainedEntry = (DBObject) throwables.get("1");
- assertTrue("Throwable message is not present in logged entry",
- chainedEntry.containsField("message"));
- assertEquals("I'm the real culprit!", chainedEntry.get("message"));
- }
-
- @Test
- public void testQuotesInMessage() {
- assertEquals(0L, countLogEntries());
- log.warn("Quotes\" \"embedded");
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("WARN"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("WARN", entry.get("level"));
- assertEquals("Quotes\" \"embedded", entry.get("message"));
- }
-
- @Test
- public void testPerformance() throws Exception {
- // Log one event to minimize start up effects on performance
- log.warn("Warn entry");
-
- long NUM_MESSAGES = 100;
- long now = System.currentTimeMillis();
- for (long i = 0; i < NUM_MESSAGES; i++) {
- log.warn("Warn entry");
- }
- long dur = System.currentTimeMillis() - now;
- System.out.println("Milliseconds for MongoDbAppender with write concern "
- + appender.getWriteConcern() + " to log " + NUM_MESSAGES + " messages:" + dur);
- assertEquals(NUM_MESSAGES + 1, countLogEntries());
- }
-
- @Test
- public void testRegularLoggerRecordsLoggerNameCorrectly() {
- log.info("From an unwrapped logger");
-
- assertEquals(1, countLogEntries());
- assertEquals(1, countLogEntriesAtLevel("info"));
- assertEquals(
- 1,
- countLogEntriesWhere(BasicDBObjectBuilder.start()
- .add("loggerName.className", "TestWriteConcern").get()));
- assertEquals(
- 1,
- countLogEntriesWhere(BasicDBObjectBuilder.start()
- .add("class.className", "TestWriteConcern").get()));
- }
-
- @Test
- public void testWrappedLoggerRecordsLoggerNameCorrectly() {
- WrappedLogger wrapped = new WrappedLogger(log);
- wrapped.info("From a wrapped logger");
-
- assertEquals(1, countLogEntries());
- assertEquals(1, countLogEntriesAtLevel("info"));
- assertEquals(
- 1,
- countLogEntriesWhere(BasicDBObjectBuilder.start()
- .add("loggerName.className", "TestWriteConcern").get()));
- assertEquals(
- 1,
- countLogEntriesWhere(BasicDBObjectBuilder.start()
- .add("class.className", "WrappedLogger").get()));
- }
-
- @Test
- public void testHostInfoRecords() throws Exception {
- assertEquals(0L, countLogEntries());
- log.warn("Testing hostinfo");
- assertEquals(1L, countLogEntries());
- assertEquals(1L, countLogEntriesAtLevel("WARN"));
-
- // verify log entry content
- DBObject entry = collection.findOne();
- assertNotNull(entry);
- assertEquals("WARN", entry.get("level"));
- assertEquals("Testing hostinfo", entry.get("message"));
- assertNotNull(entry.get("host"));
- DBObject hostinfo = (DBObject) entry.get("host");
- assertNotNull(hostinfo.get("process"));
- assertEquals(InetAddress.getLocalHost().getHostName(), hostinfo.get("name"));
- assertEquals(ManagementFactory.getRuntimeMXBean().getName(), hostinfo.get("process"));
- }
-
- private long countLogEntries() {
- return (collection.getCount());
- }
-
- private long countLogEntriesAtLevel(final String level) {
- return (countLogEntriesWhere(BasicDBObjectBuilder.start().add("level", level.toUpperCase())
- .get()));
- }
-
- private long countLogEntriesWhere(final DBObject whereClause) {
- return collection.getCount(whereClause);
- }
-}
+/*
+ * Copyright (C) 2009 Peter Monks (pmonks@gmail.com)
+ *
+ * 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.log4mongo;
+
+import com.mongodb.BasicDBList;
+import com.mongodb.BasicDBObjectBuilder;
+import com.mongodb.DBObject;
+import com.mongodb.MongoClient;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+import org.bson.Document;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * JUnit unit tests for using write concerns with MongoDbAppender.
+ *
+ * When using FSYNCED, logging is well over a magnitude slower than UNACKNOWLEDGED.
+ *
+ * Note: these tests require that a MongoDB server is running, and (by default) assumes that server
+ * is listening on the default port (27017) on localhost.
+ */
+public class TestWriteConcern {
+
+ private final static Logger log = Logger.getLogger( TestWriteConcern.class );
+
+ private final static String TEST_MONGO_SERVER_HOSTNAME = "localhost";
+
+ private final static int TEST_MONGO_SERVER_PORT = 27017;
+
+ private final static String TEST_DATABASE_NAME = "log4mongotest";
+
+ private final static String TEST_COLLECTION_NAME = "logevents";
+
+ private final static String MONGODB_APPENDER_NAME = "MongoDB";
+
+ private final static String LOG4J_PROPS = "src/test/resources/log4j_write_concern.properties";
+
+ private final MongoClient mongo;
+
+ private final MongoDbAppender appender;
+
+ private MongoCollection collection;
+
+ public TestWriteConcern() throws Exception {
+ PropertyConfigurator.configure( LOG4J_PROPS );
+ mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT );
+ appender = (MongoDbAppender) Logger.getRootLogger().getAppender( MONGODB_APPENDER_NAME );
+ }
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ MongoClient mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT );
+ mongo.dropDatabase( TEST_DATABASE_NAME );
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ MongoClient mongo = new MongoClient( TEST_MONGO_SERVER_HOSTNAME, TEST_MONGO_SERVER_PORT );
+ mongo.dropDatabase( TEST_DATABASE_NAME );
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ // Ensure both the appender and the JUnit test use the same collection
+ // object - provides consistency across reads (JUnit) & writes (Log4J)
+ collection = mongo.getDatabase( TEST_DATABASE_NAME ).getCollection( TEST_COLLECTION_NAME );
+ collection.drop();
+ appender.setCollection( collection );
+ }
+
+ @Test
+ public void testInitialized() throws Exception {
+ if ( !appender.isInitialized() ) {
+ fail();
+ }
+ }
+
+ @Test
+ public void testWriteConcern() throws Exception {
+ testInitialized();
+ assertEquals( appender.getWriteConcern(), "FSYNCED" );
+ }
+
+ @Test
+ public void testSingleLogEntry() throws Exception {
+ log.trace( "Trace entry" );
+
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "trace" ) );
+ assertEquals( 0L, countLogEntriesAtLevel( "debug" ) );
+ assertEquals( 0L, countLogEntriesAtLevel( "info" ) );
+ assertEquals( 0L, countLogEntriesAtLevel( "warn" ) );
+ assertEquals( 0L, countLogEntriesAtLevel( "error" ) );
+ assertEquals( 0L, countLogEntriesAtLevel( "fatal" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find( DBObject.class );
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "TRACE", entry.get( "level" ) );
+ assertEquals( "Trace entry", entry.get( "message" ) );
+ }
+ }
+
+ @Test
+ public void testTimestampStoredNatively() throws Exception {
+ log.debug( "Debug entry" );
+
+ assertEquals( 1L, countLogEntries() );
+
+ // verify timestamp - presence and data type
+ FindIterable entries = collection.find( DBObject.class );
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertTrue( "Timestamp is not present in logged entry", entry.containsField( "timestamp" ) );
+ assertTrue( "Timestamp of logged entry is not stored as native date",
+ ( entry.get( "timestamp" ) instanceof java.util.Date ) );
+ }
+ }
+
+ @Test
+ public void testAllLevels() throws Exception {
+ log.trace( "Trace entry" );
+ log.debug( "Debug entry" );
+ log.info( "Info entry" );
+ log.warn( "Warn entry" );
+ log.error( "Error entry" );
+ log.fatal( "Fatal entry" );
+
+ assertEquals( 6L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "trace" ) );
+ assertEquals( 1L, countLogEntriesAtLevel( "debug" ) );
+ assertEquals( 1L, countLogEntriesAtLevel( "info" ) );
+ assertEquals( 1L, countLogEntriesAtLevel( "warn" ) );
+ assertEquals( 1L, countLogEntriesAtLevel( "error" ) );
+ assertEquals( 1L, countLogEntriesAtLevel( "fatal" ) );
+ }
+
+ @Test
+ public void testLogWithException() throws Exception {
+ log.error( "Error entry", new RuntimeException( "Here is an exception!" ) );
+
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "error" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find(DBObject.class);
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "ERROR", entry.get( "level" ) );
+ assertEquals( "Error entry", entry.get( "message" ) );
+
+ // verify throwable presence and content
+ assertTrue( "Throwable is not present in logged entry", entry.containsField( "throwables" ) );
+ BasicDBList throwables = (BasicDBList) entry.get( "throwables" );
+ assertEquals( 1, throwables.size() );
+
+ DBObject throwableEntry = (DBObject) throwables.get( "0" );
+ assertTrue( "Throwable message is not present in logged entry",
+ throwableEntry.containsField( "message" ) );
+ assertEquals( "Here is an exception!", throwableEntry.get( "message" ) );
+ }
+ }
+
+ @Test
+ public void testLogWithChainedExceptions() throws Exception {
+ Exception rootCause = new RuntimeException( "I'm the real culprit!" );
+
+ log.error( "Error entry", new RuntimeException( "I'm an innocent bystander.", rootCause ) );
+
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "error" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find(DBObject.class);
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "ERROR", entry.get( "level" ) );
+ assertEquals( "Error entry", entry.get( "message" ) );
+
+ // verify throwable presence and content
+ assertTrue( "Throwable is not present in logged entry", entry.containsField( "throwables" ) );
+ BasicDBList throwables = (BasicDBList) entry.get( "throwables" );
+ assertEquals( 2, throwables.size() );
+
+ DBObject rootEntry = (DBObject) throwables.get( "0" );
+ assertTrue( "Throwable message is not present in logged entry",
+ rootEntry.containsField( "message" ) );
+ assertEquals( "I'm an innocent bystander.", rootEntry.get( "message" ) );
+
+ DBObject chainedEntry = (DBObject) throwables.get( "1" );
+ assertTrue( "Throwable message is not present in logged entry",
+ chainedEntry.containsField( "message" ) );
+ assertEquals( "I'm the real culprit!", chainedEntry.get( "message" ) );
+ }
+ }
+
+ @Test
+ public void testQuotesInMessage() {
+ assertEquals( 0L, countLogEntries() );
+ log.warn( "Quotes\" \"embedded" );
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "WARN" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find(DBObject.class);
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "WARN", entry.get( "level" ) );
+ assertEquals( "Quotes\" \"embedded", entry.get( "message" ) );
+ }
+ }
+
+ @Test
+ public void testPerformance() throws Exception {
+ // Log one event to minimize start up effects on performance
+ log.warn( "Warn entry" );
+
+ long NUM_MESSAGES = 100;
+ long now = System.currentTimeMillis();
+ for ( long i = 0; i < NUM_MESSAGES; i++ ) {
+ log.warn( "Warn entry" );
+ }
+ long dur = System.currentTimeMillis() - now;
+ System.out.println( "Milliseconds for MongoDbAppender with write concern "
+ + appender.getWriteConcern() + " to log " + NUM_MESSAGES + " messages:" + dur );
+ assertEquals( NUM_MESSAGES + 1, countLogEntries() );
+ }
+
+ @Test
+ public void testRegularLoggerRecordsLoggerNameCorrectly() {
+ log.info( "From an unwrapped logger" );
+
+ assertEquals( 1, countLogEntries() );
+ assertEquals( 1, countLogEntriesAtLevel( "info" ) );
+ assertEquals(
+ 1,
+ countLogEntriesWhere( Document.parse( "{ 'loggerName.className' : 'TestWriteConcern' }" ) ) );
+ assertEquals(
+ 1,
+ countLogEntriesWhere( Document.parse( "{ 'class.className' : 'TestWriteConcern' }" ) ) );
+ }
+
+ @Test
+ public void testWrappedLoggerRecordsLoggerNameCorrectly() {
+ WrappedLogger wrapped = new WrappedLogger( log );
+ wrapped.info( "From a wrapped logger" );
+
+ assertEquals( 1, countLogEntries() );
+ assertEquals( 1, countLogEntriesAtLevel( "info" ) );
+ assertEquals(
+ 1,
+ countLogEntriesWhere( Document.parse( "{ 'loggerName.className' : 'TestWriteConcern' }" ) ) );
+ assertEquals(
+ 1,
+ countLogEntriesWhere( Document.parse( "{ 'class.className' : 'WrappedLogger' }" ) ) );
+ }
+
+ @Test
+ public void testHostInfoRecords() throws Exception {
+ assertEquals( 0L, countLogEntries() );
+ log.warn( "Testing hostinfo" );
+ assertEquals( 1L, countLogEntries() );
+ assertEquals( 1L, countLogEntriesAtLevel( "WARN" ) );
+
+ // verify log entry content
+ FindIterable entries = collection.find(DBObject.class);
+ for ( DBObject entry : entries ) {
+ assertNotNull( entry );
+ assertEquals( "WARN", entry.get( "level" ) );
+ assertEquals( "Testing hostinfo", entry.get( "message" ) );
+ assertNotNull( entry.get( "host" ) );
+ DBObject hostinfo = (DBObject) entry.get( "host" );
+ assertNotNull( hostinfo.get( "process" ) );
+ assertEquals( InetAddress.getLocalHost().getHostName(), hostinfo.get( "name" ) );
+ assertEquals( ManagementFactory.getRuntimeMXBean().getName(), hostinfo.get( "process" ) );
+ }
+ }
+
+ private long countLogEntries() {
+ return ( collection.count() );
+ }
+
+ private long countLogEntriesAtLevel( final String level ) {
+ return ( countLogEntriesWhere( Document.parse( "{ 'level' : '" + level.toUpperCase() + "' }" ) ) );
+ }
+
+ private long countLogEntriesWhere( final Document whereClause ) {
+ return collection.count( whereClause );
+ }
+
+}
diff --git a/src/test/java/org/log4mongo/WrappedLogger.java b/src/test/java/org/log4mongo/WrappedLogger.java
index a7bc61b..f8c8413 100644
--- a/src/test/java/org/log4mongo/WrappedLogger.java
+++ b/src/test/java/org/log4mongo/WrappedLogger.java
@@ -20,195 +20,196 @@
import java.text.MessageFormat;
+
/**
*
*/
public class WrappedLogger {
- private final Logger delegate;
-
- public WrappedLogger(Logger logger) {
- this.delegate = logger;
- }
-
- /**
- * @see org.apache.log4j.Category#fatal(java.lang.Object, java.lang.Throwable)
- */
- public void fatal(Object message, Throwable t) {
- delegate.fatal(message, t);
- }
-
- /**
- * @see org.apache.log4j.Category#fatal(java.lang.Object)
- */
- public void fatal(Object message) {
- delegate.fatal(message);
- }
-
- public void fatal(String format, Object... params) {
- // fatal is always enabled
- if (params[params.length - 1] instanceof Throwable) {
- delegate.fatal(generateFormattedMessage(format, params),
- (Throwable) params[params.length - 1]);
- } else {
- delegate.fatal(generateFormattedMessage(format, params));
- }
- }
-
- public boolean isErrorEnabled() {
- return delegate.isEnabledFor(Level.ERROR);
- }
-
- /**
- * @see org.apache.log4j.Category#error(java.lang.Object, java.lang.Throwable)
- */
- public void error(Object message, Throwable t) {
- delegate.error(message, t);
- }
-
- /**
- * @see org.apache.log4j.Category#error(java.lang.Object)
- */
- public void error(Object message) {
- delegate.error(message);
- }
-
- public void error(String format, Object... params) {
- // skip isErrorEnabled() check here since more than likely it is.
- // Log4j checks anyway, so...
- if (params[params.length - 1] instanceof Throwable) {
- final String message = generateFormattedMessage(format, params);
- delegate.error(message, (Throwable) params[params.length - 1]);
- } else {
- delegate.error(generateFormattedMessage(format, params));
- }
- }
-
- public boolean isWarnEnabled() {
- return delegate.isEnabledFor(Level.WARN);
- }
-
- /**
- * @see org.apache.log4j.Category#warn(java.lang.Object, java.lang.Throwable)
- */
- public void warn(Object message, Throwable t) {
- delegate.warn(message, t);
- }
-
- /**
- * @see org.apache.log4j.Category#warn(java.lang.Object)
- */
- public void warn(Object message) {
- delegate.warn(message);
- }
-
- public void warn(String format, Object... params) {
- if (params[params.length - 1] instanceof Throwable) {
- delegate.warn(generateFormattedMessage(format, params),
- (Throwable) params[params.length - 1]);
- } else {
- delegate.warn(generateFormattedMessage(format, params));
- }
- }
-
- /**
- * @see org.apache.log4j.Category#isInfoEnabled()
- */
- public boolean isInfoEnabled() {
- return delegate.isInfoEnabled();
- }
-
- /**
- * @see org.apache.log4j.Category#info(java.lang.Object, java.lang.Throwable)
- */
- public void info(Object message, Throwable t) {
- delegate.info(message, t);
- }
-
- /**
- * @see org.apache.log4j.Category#info(java.lang.Object)
- */
- public void info(Object message) {
- delegate.info(message);
- }
-
- public void info(String format, Object... params) {
- if (isInfoEnabled()) {
- if (params[params.length - 1] instanceof Throwable) {
- delegate.info(generateFormattedMessage(format, params),
- (Throwable) params[params.length - 1]);
- } else {
- delegate.info(generateFormattedMessage(format, params));
- }
- }
- }
-
- /**
- * @see org.apache.log4j.Category#isDebugEnabled()
- */
- public boolean isDebugEnabled() {
- return delegate.isDebugEnabled();
- }
-
- /**
- * @see org.apache.log4j.Category#debug(java.lang.Object, java.lang.Throwable)
- */
- public void debug(Object message, Throwable t) {
- delegate.debug(message, t);
- }
-
- /**
- * @see org.apache.log4j.Category#debug(java.lang.Object)
- */
- public void debug(Object message) {
- delegate.debug(message);
- }
-
- public void debug(String format, Object... params) {
- if (isDebugEnabled()) {
- if (params[params.length - 1] instanceof Throwable) {
- delegate.debug(generateFormattedMessage(format, params),
- (Throwable) params[params.length - 1]);
- } else {
- delegate.debug(generateFormattedMessage(format, params));
- }
- }
- }
-
- private String generateFormattedMessage(String format, Object... params) {
- return MessageFormat.format(format, params);
- }
-
- /**
- * @see org.apache.log4j.Logger#isTraceEnabled()
- */
- public boolean isTraceEnabled() {
- return delegate.isTraceEnabled();
- }
-
- /**
- * @see org.apache.log4j.Logger#trace(java.lang.Object, java.lang.Throwable)
- */
- public void trace(Object message, Throwable t) {
- delegate.trace(message, t);
- }
-
- /**
- * @see org.apache.log4j.Logger#trace(java.lang.Object)
- */
- public void trace(Object message) {
- delegate.trace(message);
- }
-
- public void trace(String format, Object... params) {
- if (isTraceEnabled()) {
- if (params[params.length - 1] instanceof Throwable) {
- delegate.trace(generateFormattedMessage(format, params),
- (Throwable) params[params.length - 1]);
- } else {
- delegate.trace(generateFormattedMessage(format, params));
- }
- }
- }
+ private final Logger delegate;
+
+ public WrappedLogger( Logger logger ) {
+ this.delegate = logger;
+ }
+
+ /**
+ * @see org.apache.log4j.Category#fatal(java.lang.Object, java.lang.Throwable)
+ */
+ public void fatal( Object message, Throwable t ) {
+ delegate.fatal( message, t );
+ }
+
+ /**
+ * @see org.apache.log4j.Category#fatal(java.lang.Object)
+ */
+ public void fatal( Object message ) {
+ delegate.fatal( message );
+ }
+
+ public void fatal( String format, Object... params ) {
+ // fatal is always enabled
+ if ( params[ params.length - 1 ] instanceof Throwable ) {
+ delegate.fatal( generateFormattedMessage( format, params ),
+ (Throwable) params[ params.length - 1 ] );
+ } else {
+ delegate.fatal( generateFormattedMessage( format, params ) );
+ }
+ }
+
+ public boolean isErrorEnabled() {
+ return delegate.isEnabledFor( Level.ERROR );
+ }
+
+ /**
+ * @see org.apache.log4j.Category#error(java.lang.Object, java.lang.Throwable)
+ */
+ public void error( Object message, Throwable t ) {
+ delegate.error( message, t );
+ }
+
+ /**
+ * @see org.apache.log4j.Category#error(java.lang.Object)
+ */
+ public void error( Object message ) {
+ delegate.error( message );
+ }
+
+ public void error( String format, Object... params ) {
+ // skip isErrorEnabled() check here since more than likely it is.
+ // Log4j checks anyway, so...
+ if ( params[ params.length - 1 ] instanceof Throwable ) {
+ final String message = generateFormattedMessage( format, params );
+ delegate.error( message, (Throwable) params[ params.length - 1 ] );
+ } else {
+ delegate.error( generateFormattedMessage( format, params ) );
+ }
+ }
+
+ public boolean isWarnEnabled() {
+ return delegate.isEnabledFor( Level.WARN );
+ }
+
+ /**
+ * @see org.apache.log4j.Category#warn(java.lang.Object, java.lang.Throwable)
+ */
+ public void warn( Object message, Throwable t ) {
+ delegate.warn( message, t );
+ }
+
+ /**
+ * @see org.apache.log4j.Category#warn(java.lang.Object)
+ */
+ public void warn( Object message ) {
+ delegate.warn( message );
+ }
+
+ public void warn( String format, Object... params ) {
+ if ( params[ params.length - 1 ] instanceof Throwable ) {
+ delegate.warn( generateFormattedMessage( format, params ),
+ (Throwable) params[ params.length - 1 ] );
+ } else {
+ delegate.warn( generateFormattedMessage( format, params ) );
+ }
+ }
+
+ /**
+ * @see org.apache.log4j.Category#isInfoEnabled()
+ */
+ public boolean isInfoEnabled() {
+ return delegate.isInfoEnabled();
+ }
+
+ /**
+ * @see org.apache.log4j.Category#info(java.lang.Object, java.lang.Throwable)
+ */
+ public void info( Object message, Throwable t ) {
+ delegate.info( message, t );
+ }
+
+ /**
+ * @see org.apache.log4j.Category#info(java.lang.Object)
+ */
+ public void info( Object message ) {
+ delegate.info( message );
+ }
+
+ public void info( String format, Object... params ) {
+ if ( isInfoEnabled() ) {
+ if ( params[ params.length - 1 ] instanceof Throwable ) {
+ delegate.info( generateFormattedMessage( format, params ),
+ (Throwable) params[ params.length - 1 ] );
+ } else {
+ delegate.info( generateFormattedMessage( format, params ) );
+ }
+ }
+ }
+
+ /**
+ * @see org.apache.log4j.Category#isDebugEnabled()
+ */
+ public boolean isDebugEnabled() {
+ return delegate.isDebugEnabled();
+ }
+
+ /**
+ * @see org.apache.log4j.Category#debug(java.lang.Object, java.lang.Throwable)
+ */
+ public void debug( Object message, Throwable t ) {
+ delegate.debug( message, t );
+ }
+
+ /**
+ * @see org.apache.log4j.Category#debug(java.lang.Object)
+ */
+ public void debug( Object message ) {
+ delegate.debug( message );
+ }
+
+ public void debug( String format, Object... params ) {
+ if ( isDebugEnabled() ) {
+ if ( params[ params.length - 1 ] instanceof Throwable ) {
+ delegate.debug( generateFormattedMessage( format, params ),
+ (Throwable) params[ params.length - 1 ] );
+ } else {
+ delegate.debug( generateFormattedMessage( format, params ) );
+ }
+ }
+ }
+
+ private String generateFormattedMessage( String format, Object... params ) {
+ return MessageFormat.format( format, params );
+ }
+
+ /**
+ * @see org.apache.log4j.Logger#isTraceEnabled()
+ */
+ public boolean isTraceEnabled() {
+ return delegate.isTraceEnabled();
+ }
+
+ /**
+ * @see org.apache.log4j.Logger#trace(java.lang.Object, java.lang.Throwable)
+ */
+ public void trace( Object message, Throwable t ) {
+ delegate.trace( message, t );
+ }
+
+ /**
+ * @see org.apache.log4j.Logger#trace(java.lang.Object)
+ */
+ public void trace( Object message ) {
+ delegate.trace( message );
+ }
+
+ public void trace( String format, Object... params ) {
+ if ( isTraceEnabled() ) {
+ if ( params[ params.length - 1 ] instanceof Throwable ) {
+ delegate.trace( generateFormattedMessage( format, params ),
+ (Throwable) params[ params.length - 1 ] );
+ } else {
+ delegate.trace( generateFormattedMessage( format, params ) );
+ }
+ }
+ }
}