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())); + } +}
