This is an automated email from the ASF dual-hosted git repository.

pkarwasz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 1003c9a3605416256e47c089fd55ba645304a103
Author: Piotr P. Karwasz <[email protected]>
AuthorDate: Sun Aug 28 13:14:14 2022 +0200

    [LOG4J2-2975] Implements the SLF4J LoggingEventBuilder
    
    This PR implements the SLF4J 2.0 `LoggingEventBuilder`, taking care of
    preserving the caller information.
---
 .../java/org/apache/logging/log4j/BridgeAware.java |  34 +++++
 .../logging/log4j/internal/DefaultLogBuilder.java  |  11 +-
 log4j-slf4j20-impl/pom.xml                         |   3 +-
 .../apache/logging/slf4j/Log4jEventBuilder.java    | 151 +++++++++++++++++++++
 .../java/org/apache/logging/slf4j/Log4jLogger.java | 130 ++++++++++++------
 .../apache/logging/slf4j/Log4jMarkerFactory.java   |  18 ++-
 .../logging/slf4j/CallerInformationTest.java       |  12 +-
 .../logging/slf4j/Log4jEventBuilderTest.java       |  67 +++++++++
 8 files changed, 379 insertions(+), 47 deletions(-)

diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/BridgeAware.java 
b/log4j-api/src/main/java/org/apache/logging/log4j/BridgeAware.java
new file mode 100644
index 0000000000..fc3b8fd929
--- /dev/null
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/BridgeAware.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * Extended interface to allow bridges between logging systems to convey the
+ * correct location information.
+ *
+ */
+public interface BridgeAware {
+
+    /**
+     * Fully qualified class name of the entry point to the logging system. 
This
+     * class will not appear in the location information.
+     * 
+     * @param fqcn
+     * @return this
+     */
+    public void setEntryPoint(final String fqcn);
+}
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/internal/DefaultLogBuilder.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/internal/DefaultLogBuilder.java
index 5f672612c3..75915c52ee 100644
--- 
a/log4j-api/src/main/java/org/apache/logging/log4j/internal/DefaultLogBuilder.java
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/internal/DefaultLogBuilder.java
@@ -16,6 +16,7 @@
  */
 package org.apache.logging.log4j.internal;
 
+import org.apache.logging.log4j.BridgeAware;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.LogBuilder;
 import org.apache.logging.log4j.Logger;
@@ -32,7 +33,7 @@ import org.apache.logging.log4j.util.Supplier;
 /**
  * Collects data for a log event and then logs it. This class should be 
considered private.
  */
-public class DefaultLogBuilder implements LogBuilder {
+public class DefaultLogBuilder implements BridgeAware, LogBuilder {
 
     private static final String FQCN = DefaultLogBuilder.class.getName();
     private static final Logger LOGGER = StatusLogger.getLogger();
@@ -45,6 +46,7 @@ public class DefaultLogBuilder implements LogBuilder {
     private StackTraceElement location;
     private volatile boolean inUse;
     private final long threadId;
+    private String fqcn = FQCN;
 
     public DefaultLogBuilder(final Logger logger, final Level level) {
         this.logger = logger;
@@ -59,6 +61,11 @@ public class DefaultLogBuilder implements LogBuilder {
         this.threadId = Thread.currentThread().getId();
     }
 
+    @Override
+    public void setEntryPoint(String fqcn) {
+        this.fqcn = fqcn;
+    }
+
     /**
      * This method should be considered internal. It is used to reset the 
LogBuilder for a new log message.
      * @param level The logging level for this event.
@@ -228,7 +235,7 @@ public class DefaultLogBuilder implements LogBuilder {
 
     private void logMessage(final Message message) {
         try {
-            logger.logMessage(level, marker, FQCN, location, message, 
throwable);
+            logger.logMessage(level, marker, fqcn, location, message, 
throwable);
         } finally {
             inUse = false;
         }
diff --git a/log4j-slf4j20-impl/pom.xml b/log4j-slf4j20-impl/pom.xml
index d52ee1b592..7777a9c991 100644
--- a/log4j-slf4j20-impl/pom.xml
+++ b/log4j-slf4j20-impl/pom.xml
@@ -53,7 +53,7 @@
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-core</artifactId>
-      <scope>runtime</scope>
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
@@ -131,6 +131,7 @@
               <includes>
                 <include>**/OverflowTest.java</include>
               </includes>
+              <includeJUnit5Engines>junit-vintage</includeJUnit5Engines>
             </configuration>
           </execution>
           <execution>
diff --git 
a/log4j-slf4j20-impl/src/main/java/org/apache/logging/slf4j/Log4jEventBuilder.java
 
b/log4j-slf4j20-impl/src/main/java/org/apache/logging/slf4j/Log4jEventBuilder.java
new file mode 100644
index 0000000000..2d50d10747
--- /dev/null
+++ 
b/log4j-slf4j20-impl/src/main/java/org/apache/logging/slf4j/Log4jEventBuilder.java
@@ -0,0 +1,151 @@
+/*
+ * 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.slf4j;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
+
+import org.apache.logging.log4j.BridgeAware;
+import org.apache.logging.log4j.CloseableThreadContext;
+import org.apache.logging.log4j.CloseableThreadContext.Instance;
+import org.apache.logging.log4j.LogBuilder;
+import org.slf4j.Marker;
+import org.slf4j.spi.LoggingEventBuilder;
+
+public class Log4jEventBuilder implements LoggingEventBuilder {
+
+    private static final String FQCN = Log4jEventBuilder.class.getName();
+
+    private final Log4jMarkerFactory markerFactory;
+    private final LogBuilder logBuilder;
+    private final List<Object> arguments = new ArrayList<>();
+    private String message = null;
+    private Map<String, String> keyValuePairs = null;
+
+    public Log4jEventBuilder(final Log4jMarkerFactory markerFactory, final 
LogBuilder logBuilder) {
+        this.markerFactory = markerFactory;
+        this.logBuilder = logBuilder;
+        if (logBuilder instanceof BridgeAware) {
+            ((BridgeAware) logBuilder).setEntryPoint(FQCN);
+        }
+    }
+
+    @Override
+    public LoggingEventBuilder setCause(Throwable cause) {
+        logBuilder.withThrowable(cause);
+        return this;
+    }
+
+    @Override
+    public LoggingEventBuilder addMarker(Marker marker) {
+        logBuilder.withMarker(markerFactory.getLog4jMarker(marker));
+        return this;
+    }
+
+    @Override
+    public LoggingEventBuilder addArgument(Object p) {
+        arguments.add(p);
+        return this;
+    }
+
+    @Override
+    public LoggingEventBuilder addArgument(Supplier<?> objectSupplier) {
+        arguments.add(objectSupplier.get());
+        return this;
+    }
+
+    @Override
+    public LoggingEventBuilder addKeyValue(String key, Object value) {
+        if (keyValuePairs == null) {
+            keyValuePairs = new HashMap<>();
+        }
+        keyValuePairs.put(key, String.valueOf(value));
+        return this;
+    }
+
+    @Override
+    public LoggingEventBuilder addKeyValue(String key, Supplier<Object> 
valueSupplier) {
+        if (keyValuePairs == null) {
+            keyValuePairs = new HashMap<>();
+        }
+        keyValuePairs.put(key, String.valueOf(valueSupplier.get()));
+        return this;
+    }
+
+    @Override
+    public LoggingEventBuilder setMessage(String message) {
+        this.message = message;
+        return this;
+    }
+
+    @Override
+    public LoggingEventBuilder setMessage(Supplier<String> messageSupplier) {
+        this.message = messageSupplier.get();
+        return this;
+    }
+
+    @Override
+    public void log() {
+        if (keyValuePairs == null || keyValuePairs.isEmpty()) {
+            logBuilder.log(message, arguments.toArray());
+        } else {
+            try (Instance c = CloseableThreadContext.putAll(keyValuePairs)) {
+                logBuilder.log(message, arguments.toArray());
+            }
+        }
+    }
+
+    @Override
+    public void log(String message) {
+        setMessage(message);
+        log();
+    }
+
+    @Override
+    public void log(String message, Object arg) {
+        setMessage(message);
+        addArgument(arg);
+        log();
+    }
+
+    @Override
+    public void log(String message, Object arg0, Object arg1) {
+        setMessage(message);
+        addArgument(arg0);
+        addArgument(arg1);
+        log();
+    }
+
+    @Override
+    public void log(String message, Object... args) {
+        setMessage(message);
+        for (final Object arg : args) {
+            addArgument(arg);
+        }
+        log();
+    }
+
+    @Override
+    public void log(Supplier<String> messageSupplier) {
+        setMessage(messageSupplier);
+        log();
+    }
+
+}
diff --git 
a/log4j-slf4j20-impl/src/main/java/org/apache/logging/slf4j/Log4jLogger.java 
b/log4j-slf4j20-impl/src/main/java/org/apache/logging/slf4j/Log4jLogger.java
index fd42f361fc..2b601be0ee 100644
--- a/log4j-slf4j20-impl/src/main/java/org/apache/logging/slf4j/Log4jLogger.java
+++ b/log4j-slf4j20-impl/src/main/java/org/apache/logging/slf4j/Log4jLogger.java
@@ -29,6 +29,8 @@ import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.spi.ExtendedLogger;
 import org.slf4j.Marker;
 import org.slf4j.spi.LocationAwareLogger;
+import org.slf4j.spi.LoggingEventBuilder;
+import org.slf4j.spi.NOPLoggingEventBuilder;
 
 /**
  * SLF4J logger implementation that uses Log4j.
@@ -80,32 +82,32 @@ public class Log4jLogger implements LocationAwareLogger, 
Serializable {
 
     @Override
     public boolean isTraceEnabled(final Marker marker) {
-        return logger.isEnabled(Level.TRACE, getMarker(marker), null);
+        return logger.isEnabled(Level.TRACE, 
markerFactory.getLog4jMarker(marker), null);
     }
 
     @Override
     public void trace(final Marker marker, final String s) {
-        logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s);
+        logger.logIfEnabled(FQCN, Level.TRACE, 
markerFactory.getLog4jMarker(marker), s);
     }
 
     @Override
     public void trace(final Marker marker, final String s, final Object o) {
-        logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, o);
+        logger.logIfEnabled(FQCN, Level.TRACE, 
markerFactory.getLog4jMarker(marker), s, o);
     }
 
     @Override
     public void trace(final Marker marker, final String s, final Object o, 
final Object o1) {
-        logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, o, o1);
+        logger.logIfEnabled(FQCN, Level.TRACE, 
markerFactory.getLog4jMarker(marker), s, o, o1);
     }
 
     @Override
     public void trace(final Marker marker, final String s, final Object... 
objects) {
-        logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, objects);
+        logger.logIfEnabled(FQCN, Level.TRACE, 
markerFactory.getLog4jMarker(marker), s, objects);
     }
 
     @Override
     public void trace(final Marker marker, final String s, final Throwable 
throwable) {
-        logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, 
throwable);
+        logger.logIfEnabled(FQCN, Level.TRACE, 
markerFactory.getLog4jMarker(marker), s, throwable);
     }
 
     @Override
@@ -140,32 +142,32 @@ public class Log4jLogger implements LocationAwareLogger, 
Serializable {
 
     @Override
     public boolean isDebugEnabled(final Marker marker) {
-        return logger.isEnabled(Level.DEBUG, getMarker(marker), null);
+        return logger.isEnabled(Level.DEBUG, 
markerFactory.getLog4jMarker(marker), null);
     }
 
     @Override
     public void debug(final Marker marker, final String s) {
-        logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s);
+        logger.logIfEnabled(FQCN, Level.DEBUG, 
markerFactory.getLog4jMarker(marker), s);
     }
 
     @Override
     public void debug(final Marker marker, final String s, final Object o) {
-        logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, o);
+        logger.logIfEnabled(FQCN, Level.DEBUG, 
markerFactory.getLog4jMarker(marker), s, o);
     }
 
     @Override
     public void debug(final Marker marker, final String s, final Object o, 
final Object o1) {
-        logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, o, o1);
+        logger.logIfEnabled(FQCN, Level.DEBUG, 
markerFactory.getLog4jMarker(marker), s, o, o1);
     }
 
     @Override
     public void debug(final Marker marker, final String s, final Object... 
objects) {
-        logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, objects);
+        logger.logIfEnabled(FQCN, Level.DEBUG, 
markerFactory.getLog4jMarker(marker), s, objects);
     }
 
     @Override
     public void debug(final Marker marker, final String s, final Throwable 
throwable) {
-        logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, 
throwable);
+        logger.logIfEnabled(FQCN, Level.DEBUG, 
markerFactory.getLog4jMarker(marker), s, throwable);
     }
 
     @Override
@@ -200,32 +202,32 @@ public class Log4jLogger implements LocationAwareLogger, 
Serializable {
 
     @Override
     public boolean isInfoEnabled(final Marker marker) {
-        return logger.isEnabled(Level.INFO, getMarker(marker), null);
+        return logger.isEnabled(Level.INFO, 
markerFactory.getLog4jMarker(marker), null);
     }
 
     @Override
     public void info(final Marker marker, final String s) {
-        logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s);
+        logger.logIfEnabled(FQCN, Level.INFO, 
markerFactory.getLog4jMarker(marker), s);
     }
 
     @Override
     public void info(final Marker marker, final String s, final Object o) {
-        logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, o);
+        logger.logIfEnabled(FQCN, Level.INFO, 
markerFactory.getLog4jMarker(marker), s, o);
     }
 
     @Override
     public void info(final Marker marker, final String s, final Object o, 
final Object o1) {
-        logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, o, o1);
+        logger.logIfEnabled(FQCN, Level.INFO, 
markerFactory.getLog4jMarker(marker), s, o, o1);
     }
 
     @Override
     public void info(final Marker marker, final String s, final Object... 
objects) {
-        logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, objects);
+        logger.logIfEnabled(FQCN, Level.INFO, 
markerFactory.getLog4jMarker(marker), s, objects);
     }
 
     @Override
     public void info(final Marker marker, final String s, final Throwable 
throwable) {
-        logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, throwable);
+        logger.logIfEnabled(FQCN, Level.INFO, 
markerFactory.getLog4jMarker(marker), s, throwable);
     }
 
     @Override
@@ -260,32 +262,32 @@ public class Log4jLogger implements LocationAwareLogger, 
Serializable {
 
     @Override
     public boolean isWarnEnabled(final Marker marker) {
-        return logger.isEnabled(Level.WARN, getMarker(marker), null);
+        return logger.isEnabled(Level.WARN, 
markerFactory.getLog4jMarker(marker), null);
     }
 
     @Override
     public void warn(final Marker marker, final String s) {
-        logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s);
+        logger.logIfEnabled(FQCN, Level.WARN, 
markerFactory.getLog4jMarker(marker), s);
     }
 
     @Override
     public void warn(final Marker marker, final String s, final Object o) {
-        logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, o);
+        logger.logIfEnabled(FQCN, Level.WARN, 
markerFactory.getLog4jMarker(marker), s, o);
     }
 
     @Override
     public void warn(final Marker marker, final String s, final Object o, 
final Object o1) {
-        logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, o, o1);
+        logger.logIfEnabled(FQCN, Level.WARN, 
markerFactory.getLog4jMarker(marker), s, o, o1);
     }
 
     @Override
     public void warn(final Marker marker, final String s, final Object... 
objects) {
-        logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, objects);
+        logger.logIfEnabled(FQCN, Level.WARN, 
markerFactory.getLog4jMarker(marker), s, objects);
     }
 
     @Override
     public void warn(final Marker marker, final String s, final Throwable 
throwable) {
-        logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, throwable);
+        logger.logIfEnabled(FQCN, Level.WARN, 
markerFactory.getLog4jMarker(marker), s, throwable);
     }
 
     @Override
@@ -320,38 +322,38 @@ public class Log4jLogger implements LocationAwareLogger, 
Serializable {
 
     @Override
     public boolean isErrorEnabled(final Marker marker) {
-        return logger.isEnabled(Level.ERROR, getMarker(marker), null);
+        return logger.isEnabled(Level.ERROR, 
markerFactory.getLog4jMarker(marker), null);
     }
 
     @Override
     public void error(final Marker marker, final String s) {
-        logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s);
+        logger.logIfEnabled(FQCN, Level.ERROR, 
markerFactory.getLog4jMarker(marker), s);
     }
 
     @Override
     public void error(final Marker marker, final String s, final Object o) {
-        logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, o);
+        logger.logIfEnabled(FQCN, Level.ERROR, 
markerFactory.getLog4jMarker(marker), s, o);
     }
 
     @Override
     public void error(final Marker marker, final String s, final Object o, 
final Object o1) {
-        logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, o, o1);
+        logger.logIfEnabled(FQCN, Level.ERROR, 
markerFactory.getLog4jMarker(marker), s, o, o1);
     }
 
     @Override
     public void error(final Marker marker, final String s, final Object... 
objects) {
-        logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, objects);
+        logger.logIfEnabled(FQCN, Level.ERROR, 
markerFactory.getLog4jMarker(marker), s, objects);
     }
 
     @Override
     public void error(final Marker marker, final String s, final Throwable 
throwable) {
-        logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, 
throwable);
+        logger.logIfEnabled(FQCN, Level.ERROR, 
markerFactory.getLog4jMarker(marker), s, throwable);
     }
 
     @Override
     public void log(final Marker marker, final String fqcn, final int level, 
final String message, final Object[] params, final Throwable throwable) {
         final Level log4jLevel = getLevel(level);
-        final org.apache.logging.log4j.Marker log4jMarker = getMarker(marker);
+        final org.apache.logging.log4j.Marker log4jMarker = 
markerFactory.getLog4jMarker(marker);
 
         if (!logger.isEnabled(log4jLevel, log4jMarker, message, params)) {
             return;
@@ -368,16 +370,6 @@ public class Log4jLogger implements LocationAwareLogger, 
Serializable {
         logger.logMessage(fqcn, log4jLevel, log4jMarker, msg, actualThrowable);
     }
 
-    private org.apache.logging.log4j.Marker getMarker(final Marker marker) {
-        if (marker == null) {
-            return null;
-        } else if (marker instanceof Log4jMarker) {
-            return ((Log4jMarker) marker).getLog4jMarker();
-        } else {
-            return ((Log4jMarker) 
markerFactory.getMarker(marker)).getLog4jMarker();
-        }
-    }
-
     @Override
     public String getName() {
         return name;
@@ -417,4 +409,60 @@ public class Log4jLogger implements LocationAwareLogger, 
Serializable {
         }
         return Level.ERROR;
     }
+
+    @Override
+    public LoggingEventBuilder makeLoggingEventBuilder(org.slf4j.event.Level 
level) {
+        final Level log4jLevel = getLevel(level.toInt());
+        if (logger.isEnabled(log4jLevel)) {
+            return new Log4jEventBuilder(markerFactory, 
logger.atLevel(log4jLevel));
+        }
+        return NOPLoggingEventBuilder.singleton();
+    }
+
+    @Override
+    public LoggingEventBuilder atTrace() {
+        if (logger.isTraceEnabled()) {
+            return new Log4jEventBuilder(markerFactory, logger.atTrace());
+        }
+        return NOPLoggingEventBuilder.singleton();
+    }
+
+    @Override
+    public LoggingEventBuilder atDebug() {
+        if (logger.isDebugEnabled()) {
+            return new Log4jEventBuilder(markerFactory, logger.atDebug());
+        }
+        return NOPLoggingEventBuilder.singleton();
+    }
+
+    @Override
+    public LoggingEventBuilder atInfo() {
+        if (logger.isInfoEnabled()) {
+            return new Log4jEventBuilder(markerFactory, logger.atInfo());
+        }
+        return NOPLoggingEventBuilder.singleton();
+    }
+
+    @Override
+    public LoggingEventBuilder atWarn() {
+        if (logger.isWarnEnabled()) {
+            return new Log4jEventBuilder(markerFactory, logger.atWarn());
+        }
+        return NOPLoggingEventBuilder.singleton();
+    }
+
+    @Override
+    public LoggingEventBuilder atError() {
+        if (logger.isErrorEnabled()) {
+            return new Log4jEventBuilder(markerFactory, logger.atError());
+        }
+        return NOPLoggingEventBuilder.singleton();
+    }
+
+    @Override
+    public boolean isEnabledForLevel(org.slf4j.event.Level level) {
+        return logger.isEnabled(getLevel(level.toInt()));
+    }
+
+    
 }
diff --git 
a/log4j-slf4j20-impl/src/main/java/org/apache/logging/slf4j/Log4jMarkerFactory.java
 
b/log4j-slf4j20-impl/src/main/java/org/apache/logging/slf4j/Log4jMarkerFactory.java
index 69ea94b33c..9073fa9242 100644
--- 
a/log4j-slf4j20-impl/src/main/java/org/apache/logging/slf4j/Log4jMarkerFactory.java
+++ 
b/log4j-slf4j20-impl/src/main/java/org/apache/logging/slf4j/Log4jMarkerFactory.java
@@ -78,7 +78,23 @@ public class Log4jMarkerFactory implements IMarkerFactory {
         return addMarkerIfAbsent(marker.getName(), convertMarker(marker));
     }
 
-    private static org.apache.logging.log4j.Marker convertMarker(final Marker 
original) {
+    /**
+     * Gets the Log4j2 marker associated to this SLF4J marker or creates a new 
one.
+     * 
+     * @param marker a SLF4J marker
+     * @return a Log4j2 marker
+     */
+    org.apache.logging.log4j.Marker getLog4jMarker(final Marker marker) {
+        if (marker == null) {
+            return null;
+        } else if (marker instanceof Log4jMarker) {
+            return ((Log4jMarker) marker).getLog4jMarker();
+        } else {
+            return ((Log4jMarker) getMarker(marker)).getLog4jMarker();
+        }
+    }
+
+    static org.apache.logging.log4j.Marker convertMarker(final Marker 
original) {
         if (original == null) {
             throw new IllegalArgumentException("Marker must not be null");
         }
diff --git 
a/log4j-slf4j20-impl/src/test/java/org/apache/logging/slf4j/CallerInformationTest.java
 
b/log4j-slf4j20-impl/src/test/java/org/apache/logging/slf4j/CallerInformationTest.java
index 7efc0e5090..ea399b2b1a 100644
--- 
a/log4j-slf4j20-impl/src/test/java/org/apache/logging/slf4j/CallerInformationTest.java
+++ 
b/log4j-slf4j20-impl/src/test/java/org/apache/logging/slf4j/CallerInformationTest.java
@@ -42,8 +42,11 @@ public class CallerInformationTest {
         logger.info("Ignored message contents.");
         logger.warn("Verifying the caller class is still correct.");
         logger.error("Hopefully nobody breaks me!");
+        logger.atInfo().log("Ignored message contents.");
+        logger.atWarn().log("Verifying the caller class is still correct.");
+        logger.atError().log("Hopefully nobody breaks me!");
         final List<String> messages = app.getMessages();
-        assertEquals("Incorrect number of messages.", 3, messages.size());
+        assertEquals("Incorrect number of messages.", 6, messages.size());
         for (final String message : messages) {
             assertEquals("Incorrect caller class name.", 
this.getClass().getName(), message);
         }
@@ -58,8 +61,13 @@ public class CallerInformationTest {
         logger.error("ZOMBIES!!!");
         logger.warn("brains~~~");
         logger.info("Itchy. Tasty.");
+        logger.atInfo().log("More messages.");
+        logger.atWarn().log("CATASTROPHE INCOMING!");
+        logger.atError().log("ZOMBIES!!!");
+        logger.atWarn().log("brains~~~");
+        logger.atInfo().log("Itchy. Tasty.");
         final List<String> messages = app.getMessages();
-        assertEquals("Incorrect number of messages.", 5, messages.size());
+        assertEquals("Incorrect number of messages.", 10, messages.size());
         for (final String message : messages) {
             assertEquals("Incorrect caller method name.", "testMethodLogger", 
message);
         }
diff --git 
a/log4j-slf4j20-impl/src/test/java/org/apache/logging/slf4j/Log4jEventBuilderTest.java
 
b/log4j-slf4j20-impl/src/test/java/org/apache/logging/slf4j/Log4jEventBuilderTest.java
new file mode 100644
index 0000000000..64a9696155
--- /dev/null
+++ 
b/log4j-slf4j20-impl/src/test/java/org/apache/logging/slf4j/Log4jEventBuilderTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.slf4j;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.junit.LoggerContextSource;
+import org.apache.logging.log4j.junit.Named;
+import org.apache.logging.log4j.test.appender.ListAppender;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+// Config from `log4j-core` test jar.
+@LoggerContextSource("log4j2-config.xml")
+public class Log4jEventBuilderTest {
+
+    private final Logger logger;
+    private final ListAppender appender;
+
+    public Log4jEventBuilderTest(@Named("List") Appender appender) {
+        logger = 
LoggerFactory.getLogger("org.apache.test.Log4jEventBuilderTest");
+        this.appender = (ListAppender) appender;
+    }
+
+    @BeforeEach
+    public void setUp() {
+        appender.clear();
+    }
+
+    @Test
+    public void testKeyValuePairs() {
+        logger.atDebug().addKeyValue("testKeyValuePairs", "ok").log();
+        final List<LogEvent> events = appender.getEvents();
+        assertThat(events).hasSize(1);
+        
assertThat(events.get(0).getContextMap()).containsEntry("testKeyValuePairs", 
"ok");
+    }
+
+    @Test
+    public void testArguments() {
+        
logger.atDebug().setMessage("{}-{}").addArgument("a").addArgument("b").log();
+        logger.atDebug().log("{}-{}", "a", "b");
+        logger.atDebug().addArgument("a").log("{}-{}", "b");
+        logger.atDebug().log("{}-{}", new Object[] {"a", "b"});
+        assertThat(appender.getEvents()).hasSize(4)
+        .allMatch(event -> 
"a-b".equals(event.getMessage().getFormattedMessage()));
+    }
+}

Reply via email to