Skip to content

Commit

Permalink
implement putAll and putAllCloseable
Browse files Browse the repository at this point in the history
Implements putAll and putAllCloseable described in SLF4J-387

Signed-off-by: Nikolas Grottendieck <git@nikolasgrottendieck.com>
  • Loading branch information
Okeanos committed Jan 10, 2022
1 parent 7c62cf8 commit 35adca4
Show file tree
Hide file tree
Showing 5 changed files with 375 additions and 1 deletion.
74 changes: 73 additions & 1 deletion slf4j-api/src/main/java/org/slf4j/MDC.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
package org.slf4j;

import java.io.Closeable;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.slf4j.helpers.BasicMDCAdapter;
import org.slf4j.helpers.NOPMDCAdapter;
Expand Down Expand Up @@ -72,13 +74,25 @@ public class MDC {
*/
public static class MDCCloseable implements Closeable {
private final String key;
private final Set<String> keys;

private MDCCloseable(String key) {
this.key = key;
this.keys = null;
}

private MDCCloseable(Set<String> keys) {
this.key = null;
this.keys = new HashSet<>(keys);
}

public void close() {
MDC.remove(this.key);
if (this.key != null) {
MDC.remove(this.key);
}
if (this.keys != null) {
this.keys.forEach(MDC::remove);
}
}
}

Expand Down Expand Up @@ -121,6 +135,31 @@ public static void put(String key, String val) throws IllegalArgumentException {
mdcAdapter.put(key, val);
}

/**
* Put a diagnostic context map (the <code>entries</code> parameter) as identified with each
* <code>key</code> into the current thread's diagnostic context map. The
* <code>entries</code> parameter and its <code>keys</code> cannot be null. The
* <code>value</code> of each entry can be null only if the underlying implementation
* supports it.
*
* <p>
* This method delegates all work to the MDC of the underlying logging system.
*
* @param entries entries to put in the map
*
* @throws IllegalArgumentException
* in case the "entries" parameter is null
*/
public static void putAll(Map<String, String> entries) throws IllegalArgumentException {
if (entries == null) {
throw new IllegalArgumentException("entries parameter cannot be null");
}
if (mdcAdapter == null) {
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
}
entries.forEach((k,v) -> mdcAdapter.put(k, v));
}

/**
* Put a diagnostic context value (the <code>val</code> parameter) as identified with the
* <code>key</code> parameter into the current thread's diagnostic context map. The
Expand Down Expand Up @@ -154,6 +193,39 @@ public static MDCCloseable putCloseable(String key, String val) throws IllegalAr
return new MDCCloseable(key);
}

/**
* Put a diagnostic context map (the <code>entries</code> parameter) as identified with each
* <code>key</code> into the current thread's diagnostic context map. The
* <code>entries</code> parameter and its <code>keys</code> cannot be null. The
* <code>value</code> of each entry can be null only if the underlying implementation
* supports it.
*
* <p>
* This method delegates all work to the MDC of the underlying logging system.
* <p>
* This method returns a <code>Closeable</code> object which can remove all <code>keys</code>
* that are part of the <code>entries</code> when <code>close</code> is called.
*
* <p>
* Useful with Java 9 for example :
* <code>
* try(MDC.MDCCloseable closeable = MDC.putAllCloseable(Map.of(key1, value, key2, value2)) {
* ....
* }
* </code>
*
* @param entries entries to put in the map
* @return a <code>Closeable</code> who can remove all originally supplied <code>keys</code>
* when <code>close</code> is called.
*
* @throws IllegalArgumentException
* in case the "entries" parameter is null
*/
public static MDCCloseable putAllCloseable(Map<String, String> entries) throws IllegalArgumentException {
MDC.putAll(entries);
return new MDCCloseable(entries.keySet());
}

/**
* Get the diagnostic context identified by the <code>key</code> parameter. The
* <code>key</code> parameter cannot be null.
Expand Down
123 changes: 123 additions & 0 deletions slf4j-jdk14/src/test/java/org/slf4j/jul/InvocationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import org.junit.Test;
import org.slf4j.*;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
Expand Down Expand Up @@ -170,6 +172,127 @@ public void testMDC() {
}
}

@Test
public void testMDCContextMapValues() {
Map<String, String> map = new HashMap<>();
map.put("ka", "va");
map.put("kb", "vb");

MDC.put("k", "v");
assertEquals("v", MDC.get("k"));
MDC.setContextMap(map);
assertNull(MDC.get("k"));
assertEquals("va", MDC.get("ka"));
assertEquals("vb", MDC.get("kb"));
}


@Test
public void testMDCPutAll() {
Map<String, String> values = new HashMap<>();
values.put("k1", "v1");
values.put("k2", "v2");

MDC.put("k", "v");
MDC.putAll(values);

assertNotNull(MDC.get("k"));
assertNotNull(MDC.get("k1"));
assertNotNull(MDC.get("k2"));
MDC.remove("k1");
MDC.remove("k2");
assertNotNull(MDC.get("k"));
assertNull(MDC.get("k1"));
assertNull(MDC.get("k2"));
MDC.clear();
}

@Test
public void testMDCCloseable() {
MDC.put("pre", "v");
try(MDC.MDCCloseable mdcCloseable = MDC.putCloseable("try-with", "v")) {
assertNotNull(MDC.get("pre"));
assertNotNull(MDC.get("try-with"));
assertNull(MDC.get("post"));
}
MDC.put("post", "v");
assertNotNull(MDC.get("pre"));
assertNull(MDC.get("try-with"));
assertNotNull(MDC.get("post"));
MDC.clear();
}

@Test
public void testMDCCloseableOverwrites() {
MDC.put("pre", "v");
try(MDC.MDCCloseable mdcCloseable = MDC.putCloseable("pre", "v2")) {
assertNotNull(MDC.get("pre"));
assertEquals("v2", MDC.get("pre"));
assertNull(MDC.get("post"));
}
MDC.put("post", "v");
assertNull(MDC.get("pre"));
assertNotNull(MDC.get("post"));
MDC.clear();
}

@Test
public void testMDCCloseablePutAll() {
Map<String, String> values = new HashMap<>();
values.put("try-with", "v");

MDC.put("pre", "v");
try(MDC.MDCCloseable mdcCloseable = MDC.putAllCloseable(values)) {
assertNotNull(MDC.get("pre"));
assertNotNull(MDC.get("try-with"));
assertNull(MDC.get("post"));
}
MDC.put("post", "v");
assertNotNull(MDC.get("pre"));
assertNull(MDC.get("try-with"));
assertNotNull(MDC.get("post"));
MDC.clear();
}

@Test
public void testMDCCloseablePutAllOverwrites() {
Map<String, String> values = new HashMap<>();
values.put("pre", "v2");
values.put("try-with", "v");

MDC.put("pre", "v");
try(MDC.MDCCloseable mdcCloseable = MDC.putAllCloseable(values)) {
assertNotNull(MDC.get("pre"));
assertEquals("v2", MDC.get("pre"));
assertNotNull(MDC.get("try-with"));
assertNull(MDC.get("post"));
}
MDC.put("post", "v");
assertNull(MDC.get("pre"));
assertNull(MDC.get("try-with"));
assertNotNull(MDC.get("post"));
MDC.clear();
}

@Test
public void testMDCCloseablePutAllImmutable() {
Map<String, String> values = new HashMap<>();
values.put("try-with", "v");

MDC.put("pre", "v");
try(MDC.MDCCloseable mdcCloseable = MDC.putAllCloseable(values)) {
values.remove("try-with");
assertNotNull(MDC.get("pre"));
assertNotNull(MDC.get("try-with"));
assertNull(MDC.get("post"));
}
MDC.put("post", "v");
assertNotNull(MDC.get("pre"));
assertNull(MDC.get("try-with"));
assertNotNull(MDC.get("post"));
MDC.clear();
}

private void assertLogMessage(String expected, int index) {
LogRecord logRecord = listHandler.recordList.get(index);
Assert.assertNotNull(logRecord);
Expand Down
106 changes: 106 additions & 0 deletions slf4j-log4j12/src/test/java/org/slf4j/log4j12/InvocationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,112 @@ public void testMDCContextMapValues() {
assertEquals("vb", MDC.get("kb"));
}

@Test
public void testMDCPutAll() {
Map<String, String> values = new HashMap<>();
values.put("k1", "v1");
values.put("k2", "v2");

MDC.put("k", "v");
MDC.putAll(values);

assertNotNull(MDC.get("k"));
assertNotNull(MDC.get("k1"));
assertNotNull(MDC.get("k2"));
MDC.remove("k1");
MDC.remove("k2");
assertNotNull(MDC.get("k"));
assertNull(MDC.get("k1"));
assertNull(MDC.get("k2"));
MDC.clear();
}

@Test
public void testMDCCloseable() {
MDC.put("pre", "v");
try(MDC.MDCCloseable mdcCloseable = MDC.putCloseable("try-with", "v")) {
assertNotNull(MDC.get("pre"));
assertNotNull(MDC.get("try-with"));
assertNull(MDC.get("post"));
}
MDC.put("post", "v");
assertNotNull(MDC.get("pre"));
assertNull(MDC.get("try-with"));
assertNotNull(MDC.get("post"));
MDC.clear();
}

@Test
public void testMDCCloseableOverwrites() {
MDC.put("pre", "v");
try(MDC.MDCCloseable mdcCloseable = MDC.putCloseable("pre", "v2")) {
assertNotNull(MDC.get("pre"));
assertEquals("v2", MDC.get("pre"));
assertNull(MDC.get("post"));
}
MDC.put("post", "v");
assertNull(MDC.get("pre"));
assertNotNull(MDC.get("post"));
MDC.clear();
}

@Test
public void testMDCCloseablePutAllImmutable() {
Map<String, String> values = new HashMap<>();
values.put("try-with", "v");

MDC.put("pre", "v");
try(MDC.MDCCloseable mdcCloseable = MDC.putAllCloseable(values)) {
values.remove("try-with");
assertNotNull(MDC.get("pre"));
assertNotNull(MDC.get("try-with"));
assertNull(MDC.get("post"));
}
MDC.put("post", "v");
assertNotNull(MDC.get("pre"));
assertNull(MDC.get("try-with"));
assertNotNull(MDC.get("post"));
MDC.clear();
}

@Test
public void testMDCCloseablePutAll() {
Map<String, String> values = new HashMap<>();
values.put("try-with", "v");

MDC.put("pre", "v");
try(MDC.MDCCloseable mdcCloseable = MDC.putAllCloseable(values)) {
assertNotNull(MDC.get("pre"));
assertNotNull(MDC.get("try-with"));
assertNull(MDC.get("post"));
}
MDC.put("post", "v");
assertNotNull(MDC.get("pre"));
assertNull(MDC.get("try-with"));
assertNotNull(MDC.get("post"));
MDC.clear();
}

@Test
public void testMDCCloseablePutAllOverwrites() {
Map<String, String> values = new HashMap<>();
values.put("pre", "v2");
values.put("try-with", "v");

MDC.put("pre", "v");
try(MDC.MDCCloseable mdcCloseable = MDC.putAllCloseable(values)) {
assertNotNull(MDC.get("pre"));
assertEquals("v2", MDC.get("pre"));
assertNotNull(MDC.get("try-with"));
assertNull(MDC.get("post"));
}
MDC.put("post", "v");
assertNull(MDC.get("pre"));
assertNull(MDC.get("try-with"));
assertNotNull(MDC.get("post"));
MDC.clear();
}

@Test
public void testCallerInfo() {
Logger logger = LoggerFactory.getLogger("testMarker");
Expand Down

0 comments on commit 35adca4

Please sign in to comment.