Skip to content

Commit

Permalink
Pass key-value properties into events in slf4j-reload4j.
Browse files Browse the repository at this point in the history
Merge MDC and fluent key-value properties together in slf4j-reload4j, so
the fluent API can be used with an appropriate Layout.
  • Loading branch information
josephw committed Feb 5, 2024
1 parent 8c4ea8f commit 2ac1439
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -175,8 +183,25 @@ private org.apache.log4j.spi.LoggingEvent event2Log4jEvent(LoggingEvent event, L
defaultLoggingEvent.setTimeStamp(System.currentTimeMillis());
}

Map<String, Object> properties;

Hashtable mdcContext = MDC.getContext();
if (mdcContext != null) {
properties = mdcContext;
} else {
properties = Collections.emptyMap();
}

List<KeyValuePair> keyValuePairs = event.getKeyValuePairs();
if (keyValuePairs != null) {
Map<String, Object> 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;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String, Object> propertiesFromConvertedEvent(LoggingEvent event) {
List<org.apache.log4j.spi.LoggingEvent> 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<String, String> 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");
}
}
}

0 comments on commit 2ac1439

Please sign in to comment.