Skip to content

Commit b1c8d63

Browse files
committed
Pass key-value properties into events in slf4j-reload4j.
Merge MDC and fluent key-value properties together in slf4j-reload4j, so the fluent API can be used with an appropriate Layout. Signed-off-by: Joseph Walton <[email protected]>
1 parent 8c4ea8f commit b1c8d63

File tree

2 files changed

+133
-1
lines changed

2 files changed

+133
-1
lines changed

slf4j-reload4j/src/main/java/org/slf4j/reload4j/Reload4jLoggerAdapter.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,21 @@
2727
import static org.slf4j.event.EventConstants.NA_SUBST;
2828

2929
import java.io.Serializable;
30+
import java.util.Collections;
31+
import java.util.HashMap;
32+
import java.util.Hashtable;
33+
import java.util.List;
34+
import java.util.Map;
35+
import java.util.stream.Collectors;
3036

3137
import org.apache.log4j.Level;
38+
import org.apache.log4j.MDC;
3239
import org.apache.log4j.spi.LocationInfo;
3340
import org.apache.log4j.spi.ThrowableInformation;
3441
import org.slf4j.Logger;
3542
import org.slf4j.Marker;
3643
import org.slf4j.event.DefaultLoggingEvent;
44+
import org.slf4j.event.KeyValuePair;
3745
import org.slf4j.event.LoggingEvent;
3846
import org.slf4j.event.SubstituteLoggingEvent;
3947
import org.slf4j.helpers.LegacyAbstractLogger;
@@ -175,8 +183,25 @@ private org.apache.log4j.spi.LoggingEvent event2Log4jEvent(LoggingEvent event, L
175183
defaultLoggingEvent.setTimeStamp(System.currentTimeMillis());
176184
}
177185

186+
Map<String, Object> properties;
187+
188+
Hashtable mdcContext = MDC.getContext();
189+
if (mdcContext != null) {
190+
properties = mdcContext;
191+
} else {
192+
properties = Collections.emptyMap();
193+
}
194+
195+
List<KeyValuePair> keyValuePairs = event.getKeyValuePairs();
196+
if (keyValuePairs != null) {
197+
Map<String, Object> newProperties = new HashMap<>(properties);
198+
properties = event.getKeyValuePairs().stream().collect(
199+
Collectors.toMap(kvp -> kvp.key, kvp -> kvp.value, (a, b) -> b, () -> newProperties)
200+
);
201+
}
202+
178203
org.apache.log4j.spi.LoggingEvent log4jEvent = new org.apache.log4j.spi.LoggingEvent(fqcn, logger, event.getTimeStamp(), log4jLevel, formattedMessage,
179-
event.getThreadName(), ti, null, locationInfo, null);
204+
event.getThreadName(), ti, null, locationInfo, properties);
180205

181206
return log4jEvent;
182207
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package org.slf4j.reload4j;
2+
3+
import org.apache.log4j.AppenderSkeleton;
4+
import org.apache.log4j.Logger;
5+
import org.apache.log4j.MDC;
6+
import org.junit.Test;
7+
import org.slf4j.event.DefaultLoggingEvent;
8+
import org.slf4j.event.Level;
9+
import org.slf4j.event.LoggingEvent;
10+
11+
import java.util.ArrayList;
12+
import java.util.HashMap;
13+
import java.util.List;
14+
import java.util.Map;
15+
16+
import static org.junit.Assert.assertEquals;
17+
import static java.util.Collections.emptyMap;
18+
import static java.util.Collections.singletonMap;
19+
20+
public class Reload4jLoggerAdapterTest {
21+
static Map<String, Object> propertiesFromConvertedEvent(LoggingEvent event) {
22+
List<org.apache.log4j.spi.LoggingEvent> capturedEvents = new ArrayList<>();
23+
24+
Logger logger = Logger.getRootLogger();
25+
logger.removeAllAppenders();
26+
logger.addAppender(new AppenderSkeleton() {
27+
@Override
28+
public void close() {
29+
}
30+
31+
@Override
32+
public boolean requiresLayout() {
33+
return false;
34+
}
35+
36+
@Override
37+
protected void append(org.apache.log4j.spi.LoggingEvent loggingEvent) {
38+
capturedEvents.add(loggingEvent);
39+
}
40+
});
41+
Reload4jLoggerAdapter adapter = new Reload4jLoggerAdapter(logger);
42+
43+
adapter.log(event);
44+
45+
if (capturedEvents.size() != 1) {
46+
throw new IllegalStateException();
47+
}
48+
return capturedEvents.get(0).getProperties();
49+
}
50+
51+
@Test
52+
public void propertiesAreEmptyWhenNotProvided() {
53+
LoggingEvent event = new DefaultLoggingEvent(Level.INFO, null);
54+
55+
assertEquals(emptyMap(), propertiesFromConvertedEvent(event));
56+
}
57+
58+
@Test
59+
public void mdcContentsArePresentInEventProperties() {
60+
try {
61+
MDC.put("mdc-key", "value");
62+
LoggingEvent event = new DefaultLoggingEvent(Level.INFO, null);
63+
assertEquals(singletonMap("mdc-key", "value"), propertiesFromConvertedEvent(event));
64+
} finally {
65+
MDC.remove("mdc-key");
66+
}
67+
}
68+
69+
@Test
70+
public void keyValuesArePlacedInEventProperties() {
71+
DefaultLoggingEvent event = new DefaultLoggingEvent(Level.INFO, null);
72+
event.addKeyValue("kv-key", "value");
73+
74+
assertEquals(singletonMap("kv-key", "value"), propertiesFromConvertedEvent(event));
75+
}
76+
77+
@Test
78+
public void mdcAndKeyValuesAreMergedInEventProperties() {
79+
try {
80+
MDC.put("mdc-key", "value");
81+
DefaultLoggingEvent event = new DefaultLoggingEvent(Level.INFO, null);
82+
event.addKeyValue("kv-key", "value");
83+
Map<String, String> expectedProperties = new HashMap<>();
84+
expectedProperties.put("mdc-key", "value");
85+
expectedProperties.put("kv-key", "value");
86+
87+
assertEquals(expectedProperties,
88+
propertiesFromConvertedEvent(event));
89+
} finally {
90+
MDC.remove("mdc-key");
91+
}
92+
}
93+
94+
@Test
95+
public void keyValuePropertiesOverrideMdc() {
96+
try {
97+
MDC.put("clashing-key", "mdc-value");
98+
DefaultLoggingEvent event = new DefaultLoggingEvent(Level.INFO, null);
99+
event.addKeyValue("clashing-key", "kv-value");
100+
assertEquals(
101+
singletonMap("clashing-key", "kv-value"),
102+
propertiesFromConvertedEvent(event));
103+
} finally {
104+
MDC.remove("clashing-key");
105+
}
106+
}
107+
}

0 commit comments

Comments
 (0)