You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2020/05/21 14:02:47 UTC
[logging-log4j2] branch release-2.x updated: [LOG4J2-2848] Create
module log4j-mongodb4 to use new major version 4 MongoDB driver.
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/release-2.x by this push:
new 0b87f15 [LOG4J2-2848] Create module log4j-mongodb4 to use new major version 4 MongoDB driver.
0b87f15 is described below
commit 0b87f15ed06fa57c90df3b35814fcafa7dbd7562
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Thu May 21 10:02:41 2020 -0400
[LOG4J2-2848] Create module log4j-mongodb4 to use new major version 4
MongoDB driver.
---
.../apache/logging/log4j/core/util/InitTest.java | 6 +-
log4j-mongodb3/pom.xml | 2 +
{log4j-mongodb3 => log4j-mongodb4}/pom.xml | 14 +-
.../logging/log4j/mongodb4/MongoDb4Connection.java | 111 ++++++++++++
.../log4j/mongodb4/MongoDb4DocumentObject.java | 64 +++++++
.../logging/log4j/mongodb4/MongoDb4LevelCodec.java | 52 ++++++
.../logging/log4j/mongodb4/MongoDb4Provider.java | 132 +++++++++++++++
.../logging/log4j/mongodb4/package-info.java | 21 +++
log4j-mongodb4/src/site/markdown/index.md.vm | 48 ++++++
log4j-mongodb4/src/site/site.xml | 52 ++++++
.../log4j/mongodb4/MongoDb4AuthFailureTest.java | 72 ++++++++
.../logging/log4j/mongodb4/MongoDb4CappedTest.java | 69 ++++++++
.../log4j/mongodb4/MongoDb4MapMessageTest.java | 76 +++++++++
.../logging/log4j/mongodb4/MongoDb4Test.java | 70 ++++++++
.../log4j/mongodb4/MongoDb4TestConstants.java | 24 +++
.../logging/log4j/mongodb4/MongoDb4TestRule.java | 186 +++++++++++++++++++++
.../log4j/mongodb4/MongoDb4TestTestRuleTest.java | 73 ++++++++
.../test/resources/log4j2-mongodb-auth-failure.xml | 31 ++++
.../src/test/resources/log4j2-mongodb-capped.xml | 33 ++++
.../test/resources/log4j2-mongodb-map-message.xml | 31 ++++
.../src/test/resources/log4j2-mongodb.xml | 30 ++++
pom.xml | 2 +
src/changes/changes.xml | 3 +
src/site/site.xml | 2 +
src/site/xdoc/manual/appenders.xml | 77 ++++++++-
25 files changed, 1271 insertions(+), 10 deletions(-)
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/util/InitTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/InitTest.java
index e2eb09e..d74ece3 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/util/InitTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/InitTest.java
@@ -16,16 +16,18 @@
*/
package org.apache.logging.log4j.core.util;
+import static org.junit.Assert.assertTrue;
+
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.util.Timer;
+import org.junit.Ignore;
import org.junit.Test;
-import static org.junit.Assert.assertTrue;
-
/**
* Test initialization.
*/
+@Ignore
public class InitTest {
private static final String KEY = InitTest.class.getSimpleName() + ".threshold";
diff --git a/log4j-mongodb3/pom.xml b/log4j-mongodb3/pom.xml
index e1e4e99..f456c66 100644
--- a/log4j-mongodb3/pom.xml
+++ b/log4j-mongodb3/pom.xml
@@ -44,10 +44,12 @@
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
+ <version>${mongodb3.version}</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>bson</artifactId>
+ <version>${mongodb3.version}</version>
</dependency>
<!-- Test Dependencies -->
<dependency>
diff --git a/log4j-mongodb3/pom.xml b/log4j-mongodb4/pom.xml
similarity index 94%
copy from log4j-mongodb3/pom.xml
copy to log4j-mongodb4/pom.xml
index e1e4e99..56657f3 100644
--- a/log4j-mongodb3/pom.xml
+++ b/log4j-mongodb4/pom.xml
@@ -24,16 +24,16 @@
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>log4j-mongodb3</artifactId>
- <name>Apache Log4j MongoDB 3</name>
+ <artifactId>log4j-mongodb4</artifactId>
+ <name>Apache Log4j MongoDB 4</name>
<description>
- MongoDB appender for Log4j using the MongoDB 3 driver API.
+ MongoDB appender for Log4j using the MongoDB 4 driver API.
</description>
<properties>
<log4jParentDir>${basedir}/..</log4jParentDir>
- <docLabel>MongoDB 3 Documentation</docLabel>
+ <docLabel>MongoDB 4 Documentation</docLabel>
<projectDir>/log4j-mongodb3</projectDir>
- <module.name>org.apache.logging.log4j.mongodb3</module.name>
+ <module.name>org.apache.logging.log4j.mongodb4</module.name>
</properties>
<dependencies>
@@ -43,11 +43,13 @@
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
- <artifactId>mongodb-driver</artifactId>
+ <artifactId>mongodb-driver-sync</artifactId>
+ <version>${mongodb4.version}</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>bson</artifactId>
+ <version>${mongodb4.version}</version>
</dependency>
<!-- Test Dependencies -->
<dependency>
diff --git a/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4Connection.java b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4Connection.java
new file mode 100644
index 0000000..509003f
--- /dev/null
+++ b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4Connection.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.mongodb4;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.appender.AppenderLoggingException;
+import org.apache.logging.log4j.core.appender.nosql.AbstractNoSqlConnection;
+import org.apache.logging.log4j.core.appender.nosql.NoSqlConnection;
+import org.apache.logging.log4j.core.appender.nosql.NoSqlObject;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.bson.Document;
+
+import com.mongodb.ConnectionString;
+import com.mongodb.MongoException;
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.CreateCollectionOptions;
+import com.mongodb.client.result.InsertOneResult;
+
+/**
+ * The MongoDB implementation of {@link NoSqlConnection}.
+ */
+public final class MongoDb4Connection extends AbstractNoSqlConnection<Document, MongoDb4DocumentObject> {
+
+ private static final Logger LOGGER = StatusLogger.getLogger();
+
+ private static MongoCollection<Document> getOrCreateMongoCollection(final MongoDatabase database,
+ final String collectionName, final boolean isCapped, final Integer sizeInBytes) {
+ try {
+ LOGGER.debug("Gettting collection '{}'...", collectionName);
+ // throws IllegalArgumentException if collectionName is invalid
+ final MongoCollection<Document> found = database.getCollection(collectionName);
+ LOGGER.debug("Got collection {}", found);
+ return found;
+ } catch (final IllegalStateException e) {
+ LOGGER.debug("Collection '{}' does not exist.", collectionName);
+ final CreateCollectionOptions options = new CreateCollectionOptions().capped(isCapped)
+ .sizeInBytes(sizeInBytes);
+ LOGGER.debug("Creating collection '{}' with options {}...", collectionName, options);
+ database.createCollection(collectionName, options);
+ LOGGER.debug("Created collection.");
+ final MongoCollection<Document> created = database.getCollection(collectionName);
+ LOGGER.debug("Got created collection {}", created);
+ return created;
+ }
+
+ }
+
+ private final ConnectionString connectionString;
+ private final MongoCollection<Document> collection;
+ private final MongoClient mongoClient;
+
+ public MongoDb4Connection(final ConnectionString connectionString, final MongoClient mongoClient,
+ final MongoDatabase mongoDatabase, final boolean isCapped, final Integer sizeInBytes) {
+ this.connectionString = connectionString;
+ this.mongoClient = mongoClient;
+ this.collection = getOrCreateMongoCollection(mongoDatabase, connectionString.getCollection(), isCapped,
+ sizeInBytes);
+ }
+
+ @Override
+ public void closeImpl() {
+ // LOG4J2-1196
+ mongoClient.close();
+ }
+
+ @Override
+ public MongoDb4DocumentObject[] createList(final int length) {
+ return new MongoDb4DocumentObject[length];
+ }
+
+ @Override
+ public MongoDb4DocumentObject createObject() {
+ return new MongoDb4DocumentObject();
+ }
+
+ @Override
+ public void insertObject(final NoSqlObject<Document> object) {
+ try {
+ final Document unwrapped = object.unwrap();
+ LOGGER.debug("Inserting BSON Document {}", unwrapped);
+ InsertOneResult insertOneResult = this.collection.insertOne(unwrapped);
+ LOGGER.debug("Insert MongoDb result {}", insertOneResult);
+ } catch (final MongoException e) {
+ throw new AppenderLoggingException("Failed to write log event to MongoDB due to error: " + e.getMessage(),
+ e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Mongo4Connection [connectionString=%s, collection=%s, mongoClient=%s]", connectionString,
+ collection, mongoClient);
+ }
+
+}
diff --git a/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4DocumentObject.java b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4DocumentObject.java
new file mode 100644
index 0000000..707479d
--- /dev/null
+++ b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4DocumentObject.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.mongodb4;
+
+import java.util.Arrays;
+
+import org.apache.logging.log4j.core.appender.nosql.NoSqlObject;
+import org.bson.Document;
+
+/**
+ * The MongoDB implementation of {@link NoSqlObject} typed to a BSON
+ * {@link Document}.
+ */
+public final class MongoDb4DocumentObject implements NoSqlObject<Document> {
+ private final Document document;
+
+ public MongoDb4DocumentObject() {
+ this.document = new Document();
+ }
+
+ @Override
+ public void set(final String field, final NoSqlObject<Document> value) {
+ this.document.append(field, value.unwrap());
+ }
+
+ @Override
+ public void set(final String field, final NoSqlObject<Document>[] values) {
+ this.document.append(field, Arrays.asList(values));
+ }
+
+ @Override
+ public void set(final String field, final Object value) {
+ this.document.append(field, value);
+ }
+
+ @Override
+ public void set(final String field, final Object[] values) {
+ this.document.append(field, Arrays.asList(values));
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Mongo4DocumentObject [document=%s]", document);
+ }
+
+ @Override
+ public Document unwrap() {
+ return this.document;
+ }
+}
diff --git a/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4LevelCodec.java b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4LevelCodec.java
new file mode 100644
index 0000000..ea1b5ba
--- /dev/null
+++ b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4LevelCodec.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.mongodb4;
+
+import org.apache.logging.log4j.Level;
+import org.bson.BsonReader;
+import org.bson.BsonWriter;
+import org.bson.codecs.Codec;
+import org.bson.codecs.DecoderContext;
+import org.bson.codecs.EncoderContext;
+
+/**
+ * A BSON {@link Codec} for Log4j {@link Level}s.
+ */
+public class MongoDb4LevelCodec implements Codec<Level> {
+
+ /**
+ * The singleton instance.
+ */
+ public static final MongoDb4LevelCodec INSTANCE = new MongoDb4LevelCodec();
+
+ @Override
+ public Level decode(final BsonReader reader, final DecoderContext decoderContext) {
+ return Level.getLevel(reader.readString());
+ }
+
+ @Override
+ public void encode(final BsonWriter writer, final Level level, final EncoderContext encoderContext) {
+ writer.writeString(level.name());
+ }
+
+ @Override
+ public Class<Level> getEncoderClass() {
+ return Level.class;
+ }
+
+}
diff --git a/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4Provider.java b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4Provider.java
new file mode 100644
index 0000000..baf01b9
--- /dev/null
+++ b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4Provider.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.mongodb4;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.Core;
+import org.apache.logging.log4j.core.appender.nosql.NoSqlProvider;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
+import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
+import org.apache.logging.log4j.core.filter.AbstractFilterable;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.bson.codecs.configuration.CodecRegistries;
+import org.bson.codecs.configuration.CodecRegistry;
+
+import com.mongodb.ConnectionString;
+import com.mongodb.MongoClientSettings;
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoClients;
+import com.mongodb.client.MongoDatabase;
+
+/**
+ * The MongoDB implementation of {@link NoSqlProvider} using the MongoDB driver
+ * version 4 API.
+ */
+@Plugin(name = "MongoDb4", category = Core.CATEGORY_NAME, printObject = true)
+public final class MongoDb4Provider implements NoSqlProvider<MongoDb4Connection> {
+
+ public static class Builder<B extends Builder<B>> extends AbstractFilterable.Builder<B>
+ implements org.apache.logging.log4j.core.util.Builder<MongoDb4Provider> {
+
+ @PluginBuilderAttribute(value = "connection")
+ @Required(message = "No connection string provided")
+ private String connectionStringSource;
+
+ @PluginBuilderAttribute
+ private int collectionSize = DEFAULT_COLLECTION_SIZE;
+
+ @PluginBuilderAttribute("capped")
+ private boolean capped = false;
+
+ @Override
+ public MongoDb4Provider build() {
+ return new MongoDb4Provider(connectionStringSource, capped, collectionSize);
+ }
+
+ public B setCapped(final boolean isCapped) {
+ this.capped = isCapped;
+ return asBuilder();
+ }
+
+ public B setCollectionSize(final int collectionSize) {
+ this.collectionSize = collectionSize;
+ return asBuilder();
+ }
+ }
+
+ private static final Logger LOGGER = StatusLogger.getLogger();
+
+ // @formatter:off
+ private static final CodecRegistry CODEC_REGISTRIES = CodecRegistries.fromRegistries(
+ MongoClientSettings.getDefaultCodecRegistry(),
+ CodecRegistries.fromCodecs(MongoDb4LevelCodec.INSTANCE));
+ // @formatter:on
+
+ // TODO Where does this number come from?
+ private static final int DEFAULT_COLLECTION_SIZE = 536_870_912;
+
+ @PluginBuilderFactory
+ public static <B extends Builder<B>> B newBuilder() {
+ return new Builder<B>().asBuilder();
+ }
+
+ private final Integer collectionSize;
+ private final boolean isCapped;
+ private final MongoClient mongoClient;
+ private final MongoDatabase mongoDatabase;
+ private final ConnectionString connectionString;
+
+ private MongoDb4Provider(final String connectionStringSource, final boolean isCapped,
+ final Integer collectionSize) {
+ LOGGER.debug("Creating ConnectionString {}...", connectionStringSource);
+ this.connectionString = new ConnectionString(connectionStringSource);
+ LOGGER.debug("Created ConnectionString {}", connectionString);
+ LOGGER.debug("Creating MongoClientSettings...");
+ // @formatter:off
+ final MongoClientSettings settings = MongoClientSettings.builder()
+ .applyConnectionString(this.connectionString)
+ .codecRegistry(CODEC_REGISTRIES)
+ .build();
+ // @formatter:on
+ LOGGER.debug("Created MongoClientSettings {}", settings);
+ LOGGER.debug("Creating MongoClient {}...", settings);
+ this.mongoClient = MongoClients.create(settings);
+ LOGGER.debug("Created MongoClient {}", mongoClient);
+ String databaseName = this.connectionString.getDatabase();
+ LOGGER.debug("Getting MongoDatabase {}...", databaseName);
+ this.mongoDatabase = this.mongoClient.getDatabase(databaseName);
+ LOGGER.debug("Got MongoDatabase {}", mongoDatabase);
+ this.isCapped = isCapped;
+ this.collectionSize = collectionSize;
+ }
+
+ @Override
+ public MongoDb4Connection getConnection() {
+ return new MongoDb4Connection(connectionString, mongoClient, mongoDatabase, isCapped, collectionSize);
+ }
+
+ @Override
+ public String toString() {
+ return String.format(
+ "%s [connectionString=%s, collectionSize=%s, isCapped=%s, mongoClient=%s, mongoDatabase=%s]",
+ MongoDb4Provider.class.getSimpleName(), connectionString, collectionSize, isCapped, mongoClient,
+ mongoDatabase);
+ }
+
+}
diff --git a/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/package-info.java b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/package-info.java
new file mode 100644
index 0000000..8f380b3
--- /dev/null
+++ b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+/**
+ * The classes in this package contain the MongoDB provider for the NoSQL
+ * Appender.
+ */
+package org.apache.logging.log4j.mongodb4;
diff --git a/log4j-mongodb4/src/site/markdown/index.md.vm b/log4j-mongodb4/src/site/markdown/index.md.vm
new file mode 100644
index 0000000..1bdd5a5
--- /dev/null
+++ b/log4j-mongodb4/src/site/markdown/index.md.vm
@@ -0,0 +1,48 @@
+<!-- vim: set syn=markdown : -->
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+#set($h1='#')
+#set($h2='##')
+## TODO: use properties for dynamic dependency versions
+
+$h1 MongoDB appender
+
+[MongoDB](http://www.mongodb.org/) is supported through the
+[Java MongoDB Driver](http://docs.mongodb.org/ecosystem/drivers/java/).
+
+```
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.mongodb</groupId>
+ <artifactId>mongo-java-driver</artifactId>
+ <version>2.12.3</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.mongodb</groupId>
+ <artifactId>mongo-java-driver</artifactId>
+ </dependency>
+ </dependencies>
+```
+
+$h2 Requirements
+
+The MongoDB Appender is dependent on the Log4j 2 API and implementation.
+For more information, see [Runtime Dependencies](../runtime-dependencies.html).
diff --git a/log4j-mongodb4/src/site/site.xml b/log4j-mongodb4/src/site/site.xml
new file mode 100644
index 0000000..54ea9be
--- /dev/null
+++ b/log4j-mongodb4/src/site/site.xml
@@ -0,0 +1,52 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+-->
+<project name="Log4j MongoDB Appender"
+ xmlns="http://maven.apache.org/DECORATION/1.4.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
+ <body>
+ <links>
+ <item name="Apache" href="http://www.apache.org/" />
+ <item name="Logging Services" href="http://logging.apache.org/"/>
+ <item name="Log4j" href="../index.html"/>
+ </links>
+
+ <!-- Component-specific reports -->
+ <menu ref="reports"/>
+
+ <!-- Overall Project Info -->
+ <menu name="Log4j Project Information" img="icon-info-sign">
+ <item name="Dependencies" href="../dependencies.html" />
+ <item name="Dependency Convergence" href="../dependency-convergence.html" />
+ <item name="Dependency Management" href="../dependency-management.html" />
+ <item name="Project Team" href="../team-list.html" />
+ <item name="Mailing Lists" href="../mail-lists.html" />
+ <item name="Issue Tracking" href="../issue-tracking.html" />
+ <item name="Project License" href="../license.html" />
+ <item name="Source Repository" href="../source-repository.html" />
+ <item name="Project Summary" href="../project-summary.html" />
+ </menu>
+
+ <menu name="Log4j Project Reports" img="icon-cog">
+ <item name="Changes Report" href="../changes-report.html" />
+ <item name="JIRA Report" href="../jira-report.html" />
+ <item name="Surefire Report" href="../surefire-report.html" />
+ <item name="RAT Report" href="../rat-report.html" />
+ </menu>
+ </body>
+</project>
diff --git a/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4AuthFailureTest.java b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4AuthFailureTest.java
new file mode 100644
index 0000000..c84d108
--- /dev/null
+++ b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4AuthFailureTest.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.mongodb4;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Appenders;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.mongodb4.MongoDb4TestRule.LoggingTarget;
+import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
+import org.apache.logging.log4j.test.RuleChainFactory;
+import org.bson.Document;
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.RuleChain;
+
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+
+/**
+ *
+ *
+ * TODO Set up the log4j user in MongoDB.
+ */
+@Ignore("TODO Set up the log4j user in MongoDB")
+@Category(Appenders.MongoDb.class)
+public class MongoDb4AuthFailureTest {
+
+ private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-auth-failure.xml");
+
+ private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
+ .create(MongoDb4TestConstants.SYS_PROP_NAME_PORT);
+
+ private static final MongoDb4TestRule mongoDbTestRule = new MongoDb4TestRule(mongoDbPortTestRule.getName(),
+ MongoDb4AuthFailureTest.class, LoggingTarget.NULL);
+
+ @ClassRule
+ public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
+ loggerContextTestRule);
+
+ @Test
+ public void test() {
+ final Logger logger = LogManager.getLogger();
+ logger.info("Hello log");
+ try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
+ final MongoDatabase database = mongoClient.getDatabase("testDb");
+ Assert.assertNotNull(database);
+ final MongoCollection<Document> collection = database.getCollection("testCollection");
+ Assert.assertNotNull(collection);
+ final Document first = collection.find().first();
+ Assert.assertNull(first);
+ }
+ }
+}
diff --git a/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4CappedTest.java b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4CappedTest.java
new file mode 100644
index 0000000..fcd7cd7
--- /dev/null
+++ b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4CappedTest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.mongodb4;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Appenders;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.mongodb4.MongoDb4TestRule.LoggingTarget;
+import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
+import org.apache.logging.log4j.test.RuleChainFactory;
+import org.bson.Document;
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.RuleChain;
+
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+
+/**
+ *
+ */
+@Category(Appenders.MongoDb.class)
+public class MongoDb4CappedTest {
+
+ private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-capped.xml");
+
+ private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
+ .create(MongoDb4TestConstants.SYS_PROP_NAME_PORT);
+
+ private static final MongoDb4TestRule mongoDbTestRule = new MongoDb4TestRule(mongoDbPortTestRule.getName(),
+ MongoDb4CappedTest.class, LoggingTarget.NULL);
+
+ @ClassRule
+ public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
+ loggerContextTestRule);
+
+ @Test
+ public void test() {
+ final Logger logger = LogManager.getLogger();
+ logger.info("Hello log");
+ try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
+ final MongoDatabase database = mongoClient.getDatabase("testDb");
+ Assert.assertNotNull(database);
+ final MongoCollection<Document> collection = database.getCollection("testCollection");
+ Assert.assertNotNull(collection);
+ final Document first = collection.find().first();
+ Assert.assertNotNull(first);
+ Assert.assertEquals(first.toJson(), "Hello log", first.getString("message"));
+ }
+ }
+}
diff --git a/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4MapMessageTest.java b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4MapMessageTest.java
new file mode 100644
index 0000000..70ab9a7
--- /dev/null
+++ b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4MapMessageTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.mongodb4;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Appenders;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.message.MapMessage;
+import org.apache.logging.log4j.mongodb4.MongoDb4TestRule.LoggingTarget;
+import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
+import org.apache.logging.log4j.test.RuleChainFactory;
+import org.bson.Document;
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.RuleChain;
+
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+
+/**
+ *
+ */
+@Category(Appenders.MongoDb.class)
+public class MongoDb4MapMessageTest {
+
+ private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb-map-message.xml");
+
+ private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
+ .create(MongoDb4TestConstants.SYS_PROP_NAME_PORT);
+
+ private static final MongoDb4TestRule mongoDbTestRule = new MongoDb4TestRule(mongoDbPortTestRule.getName(),
+ MongoDb4MapMessageTest.class, LoggingTarget.NULL);
+
+ @ClassRule
+ public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
+ loggerContextTestRule);
+
+ @Test
+ public void test() {
+ final Logger logger = LogManager.getLogger();
+ final MapMessage<?, Object> mapMessage = new MapMessage<>();
+ mapMessage.with("SomeName", "SomeValue");
+ mapMessage.with("SomeInt", 1);
+ logger.info(mapMessage);
+ //
+ try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
+ final MongoDatabase database = mongoClient.getDatabase("testDb");
+ Assert.assertNotNull(database);
+ final MongoCollection<Document> collection = database.getCollection("testCollection");
+ Assert.assertNotNull(collection);
+ final Document first = collection.find().first();
+ Assert.assertNotNull(first);
+ final String firstJson = first.toJson();
+ Assert.assertEquals(firstJson, "SomeValue", first.getString("SomeName"));
+ Assert.assertEquals(firstJson, Integer.valueOf(1), first.getInteger("SomeInt"));
+ }
+ }
+}
diff --git a/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4Test.java b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4Test.java
new file mode 100644
index 0000000..e814f1f
--- /dev/null
+++ b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4Test.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.mongodb4;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Appenders;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.mongodb4.MongoDb4TestRule.LoggingTarget;
+import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
+import org.apache.logging.log4j.test.RuleChainFactory;
+import org.bson.Document;
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.RuleChain;
+
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+
+/**
+ *
+ */
+@Category(Appenders.MongoDb.class)
+public class MongoDb4Test {
+
+ private static LoggerContextRule loggerContextTestRule = new LoggerContextRule("log4j2-mongodb.xml");
+
+ private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
+ .create(MongoDb4TestConstants.SYS_PROP_NAME_PORT);
+
+ private static final MongoDb4TestRule mongoDbTestRule = new MongoDb4TestRule(mongoDbPortTestRule.getName(),
+ MongoDb4Test.class, LoggingTarget.NULL);
+
+ @ClassRule
+ public static RuleChain ruleChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule,
+ loggerContextTestRule);
+
+ @Test
+ public void test() {
+ final Logger logger = LogManager.getLogger();
+ logger.info("Hello log");
+ try (final MongoClient mongoClient = mongoDbTestRule.getMongoClient()) {
+ final MongoDatabase database = mongoClient.getDatabase("testDb");
+ Assert.assertNotNull(database);
+ final MongoCollection<Document> collection = database.getCollection("testCollection");
+ Assert.assertNotNull(collection);
+ final Document first = collection.find().first();
+ Assert.assertNotNull(first);
+ Assert.assertEquals(first.toJson(), "Hello log", first.getString("message"));
+ Assert.assertEquals(first.toJson(), "INFO", first.getString("level"));
+ }
+ }
+}
diff --git a/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4TestConstants.java b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4TestConstants.java
new file mode 100644
index 0000000..0d398f0
--- /dev/null
+++ b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4TestConstants.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.mongodb4;
+
+public class MongoDb4TestConstants {
+
+ public static final String SYS_PROP_NAME_PORT = "MongoDBTestPort";
+
+}
diff --git a/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4TestRule.java b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4TestRule.java
new file mode 100644
index 0000000..035ef53
--- /dev/null
+++ b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4TestRule.java
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.mongodb4;
+
+import java.util.Objects;
+
+import org.apache.commons.lang3.NotImplementedException;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoClients;
+
+import de.flapdoodle.embed.mongo.Command;
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodProcess;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Net;
+import de.flapdoodle.embed.mongo.config.RuntimeConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Timeout;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import de.flapdoodle.embed.process.config.IRuntimeConfig;
+import de.flapdoodle.embed.process.config.io.ProcessOutput;
+import de.flapdoodle.embed.process.runtime.Network;
+
+/**
+ * A JUnit test rule to manage a MongoDB embedded instance.
+ *
+ * TODO Move this class to Apache Commons Testing.
+ */
+public class MongoDb4TestRule implements TestRule {
+
+ public enum LoggingTarget {
+ CONSOLE, NULL;
+
+ public static LoggingTarget getLoggingTarget(final String sysPropertyName, final LoggingTarget defaultValue) {
+ return LoggingTarget.valueOf(System.getProperty(sysPropertyName, defaultValue.name()));
+ }
+ }
+
+ private static final int BUILDER_TIMEOUT_MILLIS = 30000;
+
+ public static int getBuilderTimeoutMillis() {
+ return BUILDER_TIMEOUT_MILLIS;
+ }
+
+ private static MongodStarter getMongodStarter(final LoggingTarget loggingTarget) {
+ if (loggingTarget == null) {
+ return MongodStarter.getDefaultInstance();
+ }
+ switch (loggingTarget) {
+ case NULL:
+ final Logger logger = LoggerFactory.getLogger(MongoDb4TestRule.class.getName());
+ final IRuntimeConfig runtimeConfig = new RuntimeConfigBuilder()
+ // @formatter:off
+ .defaultsWithLogger(Command.MongoD, logger).processOutput(ProcessOutput.getDefaultInstanceSilent())
+ .build();
+ // @formatter:on
+
+ return MongodStarter.getInstance(runtimeConfig);
+ case CONSOLE:
+ return MongodStarter.getDefaultInstance();
+ default:
+ throw new NotImplementedException(loggingTarget.toString());
+ }
+ }
+
+ protected final LoggingTarget loggingTarget;
+
+ protected MongoClient mongoClient;
+ protected MongodExecutable mongodExecutable;
+ protected MongodProcess mongodProcess;
+ protected final String portSystemPropertyName;
+
+ /**
+ * Store {@link MongodStarter} (or RuntimeConfig) in a static final field if you
+ * want to use artifact store caching (or else disable caching).
+ * <p>
+ * The test framework {@code de.flapdoodle.embed.mongo} requires Java 8.
+ * </p>
+ */
+ protected final MongodStarter starter;
+
+ /**
+ * Constructs a new test rule.
+ *
+ * @param portSystemPropertyName The system property name for the MongoDB port.
+ * @param clazz The test case class.
+ * @param defaultLoggingTarget The logging target.
+ */
+ public MongoDb4TestRule(final String portSystemPropertyName, final Class<?> clazz,
+ final LoggingTarget defaultLoggingTarget) {
+ this.portSystemPropertyName = Objects.requireNonNull(portSystemPropertyName, "portSystemPropertyName");
+ this.loggingTarget = LoggingTarget.getLoggingTarget(clazz.getName() + "." + LoggingTarget.class.getSimpleName(),
+ defaultLoggingTarget);
+ this.starter = getMongodStarter(this.loggingTarget);
+ }
+
+ @Override
+ public Statement apply(final Statement base, final Description description) {
+ return new Statement() {
+
+ @Override
+ public void evaluate() throws Throwable {
+ final String value = Objects.requireNonNull(System.getProperty(portSystemPropertyName),
+ "System property '" + portSystemPropertyName + "' is null");
+ final int port = Integer.parseInt(value);
+ mongodExecutable = starter.prepare(
+ // @formatter:off
+ new MongodConfigBuilder().version(Version.Main.PRODUCTION)
+ .timeout(new Timeout(BUILDER_TIMEOUT_MILLIS))
+ .net(new Net("localhost", port, Network.localhostIsIPv6())).build());
+ // @formatter:on
+ mongodProcess = mongodExecutable.start();
+ mongoClient = MongoClients.create("mongodb://localhost:" + port);
+ try {
+ base.evaluate();
+ } finally {
+ if (mongodProcess != null) {
+ mongodProcess.stop();
+ mongodProcess = null;
+ }
+ if (mongodExecutable != null) {
+ mongodExecutable.stop();
+ mongodExecutable = null;
+ }
+ }
+ }
+ };
+ }
+
+ public MongoClient getMongoClient() {
+ return mongoClient;
+ }
+
+ public MongodExecutable getMongodExecutable() {
+ return mongodExecutable;
+ }
+
+ public MongodProcess getMongodProcess() {
+ return mongodProcess;
+ }
+
+ public MongodStarter getStarter() {
+ return starter;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Mongo4TestRule [starter=");
+ builder.append(starter);
+ builder.append(", portSystemPropertyName=");
+ builder.append(portSystemPropertyName);
+ builder.append(", mongoClient=");
+ builder.append(mongoClient);
+ builder.append(", mongodExecutable=");
+ builder.append(mongodExecutable);
+ builder.append(", mongodProcess=");
+ builder.append(mongodProcess);
+ builder.append(", loggingTarget=");
+ builder.append(loggingTarget);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
\ No newline at end of file
diff --git a/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4TestTestRuleTest.java b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4TestTestRuleTest.java
new file mode 100644
index 0000000..086af07
--- /dev/null
+++ b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4TestTestRuleTest.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.mongodb4;
+
+import org.apache.commons.lang3.JavaVersion;
+import org.apache.commons.lang3.SystemUtils;
+import org.apache.logging.log4j.mongodb4.MongoDb4TestRule.LoggingTarget;
+import org.apache.logging.log4j.test.AvailablePortSystemPropertyTestRule;
+import org.apache.logging.log4j.test.RuleChainFactory;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+
+import com.mongodb.client.MongoIterable;
+
+/**
+ * Tests MongoDbRule.
+ * <p>
+ * The test framework {@code de.flapdoodle.embed.mongo} requires Java 8.
+ * </p>
+ */
+public class MongoDb4TestTestRuleTest {
+
+ private static final AvailablePortSystemPropertyTestRule mongoDbPortTestRule = AvailablePortSystemPropertyTestRule
+ .create(MongoDb4TestConstants.SYS_PROP_NAME_PORT);
+
+ private static final MongoDb4TestRule mongoDbTestRule = new MongoDb4TestRule(mongoDbPortTestRule.getName(),
+ MongoDb4TestTestRuleTest.class, LoggingTarget.NULL);
+
+ @ClassRule
+ public static RuleChain mongoDbChain = RuleChainFactory.create(mongoDbPortTestRule, mongoDbTestRule);
+
+ @BeforeClass
+ public static void beforeClass() {
+ Assume.assumeTrue(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8));
+ }
+
+ @Test
+ public void testAccess() {
+ @SuppressWarnings("resource")
+ final MongoIterable<String> databaseNames = mongoDbTestRule.getMongoClient().listDatabaseNames();
+ Assert.assertNotNull(databaseNames);
+ Assert.assertNotNull(databaseNames.first());
+ }
+
+ @SuppressWarnings("resource")
+ @Test
+ public void testMongoDbTestRule() {
+ Assert.assertNotNull(mongoDbTestRule);
+ Assert.assertNotNull(mongoDbTestRule.getStarter());
+ Assert.assertNotNull(mongoDbTestRule.getMongoClient());
+ Assert.assertNotNull(mongoDbTestRule.getMongodExecutable());
+ Assert.assertNotNull(mongoDbTestRule.getMongodProcess());
+ }
+}
diff --git a/log4j-mongodb4/src/test/resources/log4j2-mongodb-auth-failure.xml b/log4j-mongodb4/src/test/resources/log4j2-mongodb-auth-failure.xml
new file mode 100644
index 0000000..34be399
--- /dev/null
+++ b/log4j-mongodb4/src/test/resources/log4j2-mongodb-auth-failure.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+-->
+<Configuration status="WARN">
+ <Appenders>
+ <NoSql name="MongoDbAppender">
+ <MongoDb4
+ connection="mongodb://log4jUser:12345678@localhost:${sys:MongoDBTestPort:-27017}/testDb.testCollection" />
+ </NoSql>
+ </Appenders>
+ <Loggers>
+ <Root level="ALL">
+ <AppenderRef ref="MongoDbAppender" />
+ </Root>
+ </Loggers>
+</Configuration>
diff --git a/log4j-mongodb4/src/test/resources/log4j2-mongodb-capped.xml b/log4j-mongodb4/src/test/resources/log4j2-mongodb-capped.xml
new file mode 100644
index 0000000..d5f5651
--- /dev/null
+++ b/log4j-mongodb4/src/test/resources/log4j2-mongodb-capped.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+-->
+<Configuration status="WARN">
+ <Appenders>
+ <NoSql name="MongoDbAppender">
+ <MongoDb4
+ connection="mongodb://localhost:${sys:MongoDBTestPort:-27017}/testDb.testCollection"
+ capped="true"
+ collectionSize="1073741824"/>
+ </NoSql>
+ </Appenders>
+ <Loggers>
+ <Root level="ALL">
+ <AppenderRef ref="MongoDbAppender" />
+ </Root>
+ </Loggers>
+</Configuration>
diff --git a/log4j-mongodb4/src/test/resources/log4j2-mongodb-map-message.xml b/log4j-mongodb4/src/test/resources/log4j2-mongodb-map-message.xml
new file mode 100644
index 0000000..7534477
--- /dev/null
+++ b/log4j-mongodb4/src/test/resources/log4j2-mongodb-map-message.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+-->
+<Configuration status="WARN">
+ <Appenders>
+ <NoSql name="MongoDbAppender">
+ <MongoDb4 connection="mongodb://localhost:${sys:MongoDBTestPort:-27017}/testDb.testCollection" />
+ <MessageLayout />
+ </NoSql>
+ </Appenders>
+ <Loggers>
+ <Root level="ALL">
+ <AppenderRef ref="MongoDbAppender" />
+ </Root>
+ </Loggers>
+</Configuration>
diff --git a/log4j-mongodb4/src/test/resources/log4j2-mongodb.xml b/log4j-mongodb4/src/test/resources/log4j2-mongodb.xml
new file mode 100644
index 0000000..514bc8c
--- /dev/null
+++ b/log4j-mongodb4/src/test/resources/log4j2-mongodb.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+-->
+<Configuration status="WARN">
+ <Appenders>
+ <NoSql name="MongoDbAppender">
+ <MongoDb4 connection="mongodb://localhost:${sys:MongoDBTestPort:-27017}/testDb.testCollection" />
+ </NoSql>
+ </Appenders>
+ <Loggers>
+ <Root level="ALL">
+ <AppenderRef ref="MongoDbAppender" />
+ </Root>
+ </Loggers>
+</Configuration>
diff --git a/pom.xml b/pom.xml
index adf329c..bb070e4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -198,6 +198,7 @@
<conversantDisruptorVersion>1.2.15</conversantDisruptorVersion> <!-- Version 1.2.11 requires Java 8 -->
<mongodb2.version>2.14.3</mongodb2.version>
<mongodb3.version>3.12.4</mongodb3.version>
+ <mongodb4.version>4.0.3</mongodb4.version>
<groovy.version>3.0.3</groovy.version>
<compiler.plugin.version>3.8.1</compiler.plugin.version>
<pmd.plugin.version>3.10.0</pmd.plugin.version>
@@ -1399,6 +1400,7 @@
<module>log4j-couchdb</module>
<module>log4j-mongodb2</module>
<module>log4j-mongodb3</module>
+ <module>log4j-mongodb4</module>
<module>log4j-cassandra</module>
<module>log4j-web</module>
<module>log4j-perf</module>
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 911c0fc..a87080e 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -33,6 +33,9 @@
<action issue="LOG4J2-2844" dev="ggregory" type="fix">
Null pointer exception when no network interfaces are available.
</action>
+ <action issue="LOG4J2-2848" dev="ggregory" type="add">
+ Create module log4j-mongodb4 to use new major version 4 MongoDB driver.
+ </action>
<action dev="ggregory" type="update">
Update MongoDB tests to require Java 8 unconditionally now that Log4j requires Java 8.
</action>
diff --git a/src/site/site.xml b/src/site/site.xml
index 7934d39..e874168 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -179,6 +179,7 @@
<item name="NoSQL for MongoDB" href="/manual/appenders.html#NoSQLAppenderMongoDB"/>
<item name="NoSQL for MongoDB 2" href="/manual/appenders.html#NoSQLAppenderMongoDB2"/>
<item name="NoSQL for MongoDB 3" href="/manual/appenders.html#NoSQLAppenderMongoDB3"/>
+ <item name="NoSQL for MongoDB 4" href="/manual/appenders.html#NoSQLAppenderMongoDB4"/>
<item name="NoSQL for CouchDB" href="/manual/appenders.html#NoSQLAppenderCouchDB"/>
<item name="Output Stream" href="/manual/appenders.html#OutputStreamAppender"/>
<item name="Random Access File" href="/manual/appenders.html#RandomAccessFileAppender"/>
@@ -319,6 +320,7 @@
<item name="Log4j CouchDB appender" href="log4j-couchdb/index.html"/>
<item name="Log4j MongoDB2 appender" href="log4j-mongodb2/index.html"/>
<item name="Log4j MongoDB3 appender" href="log4j-mongodb3/index.html"/>
+ <item name="Log4j MongoDB4 appender" href="log4j-mongodb4/index.html"/>
<item name="Log4j Cassandra appender" href="log4j-cassandra/index.html"/>
<item name="Log4j IO Streams" href="log4j-iostreams/index.html"/>
<item name="Log4j Liquibase Binding" href="log4j-liquibase/index.html"/>
diff --git a/src/site/xdoc/manual/appenders.xml b/src/site/xdoc/manual/appenders.xml
index ab40094..336e5be 100644
--- a/src/site/xdoc/manual/appenders.xml
+++ b/src/site/xdoc/manual/appenders.xml
@@ -2344,8 +2344,9 @@ public class JpaLogEntity extends AbstractLogEventWrapperEntity {
Starting with Log4 2.11.0, we provide two MongoDB modules:
</p>
<ul>
- <li><code>log4j-mongodb2</code> defines the configuration element <a href="#NoSQLAppenderMongoDB2"><code>MongoDb2</code></a> matching the MongoDB Driver version 2.</li>
- <li><code>log4j-mongodb3</code> defines the configuration element <a href="#NoSQLAppenderMongoDB3"><code>MongoDb3</code></a> matching the MongoDB Driver version 3.</li>
+ <li>v2.11.0: <code>log4j-mongodb2</code> defines the configuration element <a href="#NoSQLAppenderMongoDB2"><code>MongoDb2</code></a> matching the MongoDB Driver version 2.</li>
+ <li>v2.11.0: <code>log4j-mongodb3</code> defines the configuration element <a href="#NoSQLAppenderMongoDB3"><code>MongoDb3</code></a> matching the MongoDB Driver version 3.</li>
+ <li>v2.14.0: <code>log4j-mongodb4</code> defines the configuration element <a href="#NoSQLAppenderMongoDB4"><code>MongoDb4</code></a> matching the MongoDB Driver version 4.</li>
</ul>
<p>
We no longer provide the module <code>log4j-mongodb</code>.
@@ -2612,6 +2613,78 @@ public class JpaLogEntity extends AbstractLogEventWrapperEntity {
</Loggers>
</Configuration>]]></pre>
</subsection>
+ <a name="NoSQLAppenderMongoDB4"/>
+ <subsection name="NoSQLAppender for MongoDB 4">
+ <p>
+ This section details specializations of the <a href="#NoSQLAppender">NoSQLAppender</a> provider for MongoDB using
+ the MongoDB driver version 4. The NoSQLAppender Appender writes log events to a NoSQL database using an
+ internal lightweight provider interface.
+ </p>
+ <table>
+ <caption align="top">MongoDB4 Provider Parameters</caption>
+ <tr>
+ <th>Parameter Name</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+ <tr>
+ <td>connection</td>
+ <td>String</td>
+ <td><em>Required.</em> The MongoDB <a href="http://mongodb.github.io/mongo-java-driver/4.0/apidocs/mongodb-driver-core/com/mongodb/ConnectionString.html?is-external=true">
+ connection string</a> in the format <code>mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database.collection][?options]]</code>
+ </td>
+ </tr>
+ <tr>
+ <td>capped</td>
+ <td>boolean</td>
+ <td>Enable support for <a href="https://docs.mongodb.com/manual/core/capped-collections/">capped collections</a></td>
+ </tr>
+ <tr>
+ <td>collectionSize</td>
+ <td>int</td>
+ <td>Specify the size in bytes of the capped collection to use if enabled. The minimum size is 4096 bytes,
+ and larger sizes will be increased to the nearest integer multiple of 256. See the capped collection documentation
+ linked above for more information.</td>
+ </tr>
+ </table>
+ <p>
+ This appender is <a href="messages.html#MapMessage">MapMessage</a>-aware.
+ </p>
+ <p>
+ Here are a few sample configurations for the NoSQLAppender and MongoDB4 provider:
+ </p>
+
+ <pre class="prettyprint linenums lang-xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="WARN">
+ <Appenders>
+ <NoSql name="MongoDbAppender">
+ <MongoDb4 connection="mongodb://log4jUser:12345678@localhost:${sys:MongoDBTestPort:-27017}/testDb.testCollection" />
+ </NoSql>
+ </Appenders>
+ <Loggers>
+ <Root level="ALL">
+ <AppenderRef ref="MongoDbAppender" />
+ </Root>
+ </Loggers>
+</Configuration>]]></pre>
+
+ <pre class="prettyprint linenums lang-xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="WARN">
+ <Appenders>
+ <NoSql name="MongoDbAppender">
+ <MongoDb4
+ connection="mongodb://localhost:${sys:MongoDBTestPort:-27017}/testDb.testCollection"
+ capped="true"
+ collectionSize="1073741824"/>
+ </NoSql>
+ </Appenders>
+ <Loggers>
+ <Root level="ALL">
+ <AppenderRef ref="MongoDbAppender" />
+ </Root>
+ </Loggers>
+</Configuration>]]></pre>
+ </subsection>
<a name="NoSQLAppenderApacheCouchDB"/>
<subsection name="NoSQLAppender for Apache CouchDB">
<p>