diff --git a/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerAdapter.java b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerAdapter.java index 90a305d3e..17a20f1a8 100644 --- a/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerAdapter.java +++ b/slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerAdapter.java @@ -27,13 +27,21 @@ import static org.slf4j.event.EventConstants.NA_SUBST; import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import org.apache.log4j.Level; +import org.apache.log4j.MDC; import org.apache.log4j.spi.LocationInfo; import org.apache.log4j.spi.ThrowableInformation; import org.slf4j.Logger; import org.slf4j.Marker; import org.slf4j.event.DefaultLoggingEvent; +import org.slf4j.event.KeyValuePair; import org.slf4j.event.LoggingEvent; import org.slf4j.event.SubstituteLoggingEvent; import org.slf4j.helpers.LegacyAbstractLogger; @@ -175,8 +183,25 @@ private org.apache.log4j.spi.LoggingEvent event2Log4jEvent(LoggingEvent event, L defaultLoggingEvent.setTimeStamp(System.currentTimeMillis()); } + Map properties; + + Hashtable mdcContext = MDC.getContext(); + if (mdcContext != null) { + properties = mdcContext; + } else { + properties = Collections.emptyMap(); + } + + List keyValuePairs = event.getKeyValuePairs(); + if (keyValuePairs != null) { + Map newProperties = new HashMap<>(properties); + properties = event.getKeyValuePairs().stream().collect( + Collectors.toMap(kvp -> kvp.key, kvp -> kvp.value, (a, b) -> b, () -> newProperties) + ); + } + org.apache.log4j.spi.LoggingEvent log4jEvent = new org.apache.log4j.spi.LoggingEvent(fqcn, logger, event.getTimeStamp(), log4jLevel, formattedMessage, - event.getThreadName(), ti, null, locationInfo, null); + event.getThreadName(), ti, null, locationInfo, properties); return log4jEvent; } diff --git a/slf4j-reload4j/src/test/java/org/slf4j/reload4j/Reload4jLoggerAdapterTest.java b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/Reload4jLoggerAdapterTest.java new file mode 100644 index 000000000..dfcf6fc18 --- /dev/null +++ b/slf4j-reload4j/src/test/java/org/slf4j/reload4j/Reload4jLoggerAdapterTest.java @@ -0,0 +1,107 @@ +package org.slf4j.reload4j; + +import org.apache.log4j.AppenderSkeleton; +import org.apache.log4j.Logger; +import org.apache.log4j.MDC; +import org.junit.Test; +import org.slf4j.event.DefaultLoggingEvent; +import org.slf4j.event.Level; +import org.slf4j.event.LoggingEvent; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; + +public class Reload4jLoggerAdapterTest { + static Map propertiesFromConvertedEvent(LoggingEvent event) { + List capturedEvents = new ArrayList<>(); + + Logger logger = Logger.getRootLogger(); + logger.removeAllAppenders(); + logger.addAppender(new AppenderSkeleton() { + @Override + public void close() { + } + + @Override + public boolean requiresLayout() { + return false; + } + + @Override + protected void append(org.apache.log4j.spi.LoggingEvent loggingEvent) { + capturedEvents.add(loggingEvent); + } + }); + Reload4jLoggerAdapter adapter = new Reload4jLoggerAdapter(logger); + + adapter.log(event); + + if (capturedEvents.size() != 1) { + throw new IllegalStateException(); + } + return capturedEvents.get(0).getProperties(); + } + + @Test + public void propertiesAreEmptyWhenNotProvided() { + LoggingEvent event = new DefaultLoggingEvent(Level.INFO, null); + + assertEquals(emptyMap(), propertiesFromConvertedEvent(event)); + } + + @Test + public void mdcContentsArePresentInEventProperties() { + try { + MDC.put("mdc-key", "value"); + LoggingEvent event = new DefaultLoggingEvent(Level.INFO, null); + assertEquals(singletonMap("mdc-key", "value"), propertiesFromConvertedEvent(event)); + } finally { + MDC.remove("mdc-key"); + } + } + + @Test + public void keyValuesArePlacedInEventProperties() { + DefaultLoggingEvent event = new DefaultLoggingEvent(Level.INFO, null); + event.addKeyValue("kv-key", "value"); + + assertEquals(singletonMap("kv-key", "value"), propertiesFromConvertedEvent(event)); + } + + @Test + public void mdcAndKeyValuesAreMergedInEventProperties() { + try { + MDC.put("mdc-key", "value"); + DefaultLoggingEvent event = new DefaultLoggingEvent(Level.INFO, null); + event.addKeyValue("kv-key", "value"); + Map expectedProperties = new HashMap<>(); + expectedProperties.put("mdc-key", "value"); + expectedProperties.put("kv-key", "value"); + + assertEquals(expectedProperties, + propertiesFromConvertedEvent(event)); + } finally { + MDC.remove("mdc-key"); + } + } + + @Test + public void keyValuePropertiesOverrideMdc() { + try { + MDC.put("clashing-key", "mdc-value"); + DefaultLoggingEvent event = new DefaultLoggingEvent(Level.INFO, null); + event.addKeyValue("clashing-key", "kv-value"); + assertEquals( + singletonMap("clashing-key", "kv-value"), + propertiesFromConvertedEvent(event)); + } finally { + MDC.remove("clashing-key"); + } + } +}