diff --git a/pom.xml b/pom.xml
index f9c321b..2322017 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,34 +41,39 @@
net.logstash.logback
logstash-logback-encoder
- 7.4
+ 8.0
org.projectlombok
lombok
- 1.18.30
+ 1.18.36
provided
org.slf4j
slf4j-api
- 2.0.9
+ 2.0.16
ch.qos.logback
logback-classic
- 1.4.14
+ 1.5.11
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jdk8
+ 2.18.2
org.springframework
spring-core
- 6.1.1
+ 6.1.14
true
org.springframework.boot
spring-boot
- 3.2.0
+ 3.4.0
true
compile
@@ -77,31 +82,31 @@
org.springframework.boot
spring-boot-starter-test
- 3.2.0
+ 3.4.0
test
org.junit.jupiter
junit-jupiter-engine
- 5.10.1
+ 5.10.5
test
org.junit.jupiter
junit-jupiter-api
- 5.10.1
+ 5.10.5
test
org.assertj
assertj-core
- 3.24.2
+ 3.25.3
test
org.mockito
mockito-core
- 5.8.0
+ 5.11.0
test
@@ -118,7 +123,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.11.0
+ 3.13.0
${java.version}
${java.version}
@@ -130,7 +135,7 @@
org.apache.maven.plugins
maven-checkstyle-plugin
- 3.3.1
+ 3.6.0
checkstyle.xml
true
@@ -141,7 +146,7 @@
com.puppycrawl.tools
checkstyle
- 10.12.5
+ 10.20.1
@@ -157,12 +162,12 @@
org.apache.maven.plugins
maven-surefire-plugin
- 3.2.2
+ 3.5.2
org.apache.maven.plugins
maven-release-plugin
- 3.0.1
+ 3.1.1
@{project.version}
@@ -170,7 +175,7 @@
org.sonatype.plugins
nexus-staging-maven-plugin
- 1.6.13
+ 1.7.0
true
ossrh
@@ -192,12 +197,12 @@
org.apache.maven.plugins
maven-source-plugin
- 3.3.0
+ 3.3.1
org.apache.maven.plugins
maven-javadoc-plugin
- 3.6.3
+ 3.11.1
${java.version}
${encoding}
@@ -222,7 +227,7 @@
org.apache.maven.plugins
maven-gpg-plugin
- 3.1.0
+ 3.2.7
sign-artifacts
@@ -296,5 +301,12 @@
scm:git:ssh://git@github.com/dm-drogeriemarkt/structured-logging.git
http://github.com/dm-drogeriemarkt/structured-logging/tree/master
+
+
+ maven_central
+ Maven Central
+ https://repo.maven.apache.org/maven2/
+
+
diff --git a/src/main/java/de/dm/prom/structuredlogging/MdcContext.java b/src/main/java/de/dm/prom/structuredlogging/MdcContext.java
index 8728d22..7a1bce7 100644
--- a/src/main/java/de/dm/prom/structuredlogging/MdcContext.java
+++ b/src/main/java/de/dm/prom/structuredlogging/MdcContext.java
@@ -3,6 +3,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
@@ -29,28 +30,34 @@
*/
@Slf4j
public final class MdcContext implements java.io.Closeable {
- private final String oldValue; //MDC value outside this context
- private final String key;
-
private static final ObjectMapper DEFAULT_OBJECT_MAPPER = new ObjectMapper();
private static Optional customObjectMapper = Optional.empty();
static {
SimpleModule module = new SimpleModule();
- module.addSerializer(Instant.class, new ToStringSerializer());
- module.addSerializer(LocalDate.class, new ToStringSerializer());
- module.addSerializer(LocalDateTime.class, new ToStringSerializer());
- module.addSerializer(OffsetDateTime.class, new ToStringSerializer());
- module.addSerializer(OffsetTime.class, new ToStringSerializer());
- module.addSerializer(Period.class, new ToStringSerializer());
- module.addSerializer(ZonedDateTime.class, new ToStringSerializer());
- module.addSerializer(LocalTime.class, new ToStringSerializer());
- module.addSerializer(Duration.class, new ToStringSerializer());
- module.addSerializer(MonthDay.class, new ToStringSerializer());
- module.addSerializer(Year.class, new ToStringSerializer());
- module.addSerializer(YearMonth.class, new ToStringSerializer());
+ module.addSerializer(Instant.class, ToStringSerializer.instance);
+ module.addSerializer(LocalDate.class, ToStringSerializer.instance);
+ module.addSerializer(LocalDateTime.class, ToStringSerializer.instance);
+ module.addSerializer(OffsetDateTime.class, ToStringSerializer.instance);
+ module.addSerializer(OffsetTime.class, ToStringSerializer.instance);
+ module.addSerializer(Period.class, ToStringSerializer.instance);
+ module.addSerializer(ZonedDateTime.class, ToStringSerializer.instance);
+ module.addSerializer(LocalTime.class, ToStringSerializer.instance);
+ module.addSerializer(Duration.class, ToStringSerializer.instance);
+ module.addSerializer(MonthDay.class, ToStringSerializer.instance);
+ module.addSerializer(Year.class, ToStringSerializer.instance);
+ module.addSerializer(YearMonth.class, ToStringSerializer.instance);
DEFAULT_OBJECT_MAPPER.registerModule(module);
+ DEFAULT_OBJECT_MAPPER.registerModule(new Jdk8Module());
+ }
+
+ private final String oldValue; //MDC value outside this context
+ private final String key;
+
+ private MdcContext(String key, Object value) {
+ this.key = key;
+ oldValue = putToMDCwithOverwriteWarning(key, toJson(value));
}
/**
@@ -288,20 +295,6 @@ public static void update(Object mdcValue) {
updateMdcContent(mdcValue.getClass().getSimpleName(), toJson(mdcValue));
}
- private MdcContext(String key, Object value) {
- this.key = key;
- oldValue = putToMDCwithOverwriteWarning(key, toJson(value));
- }
-
- @Override
- public void close() {
- if (oldValue == null) {
- MDC.remove(key);
- } else {
- MDC.put(key, oldValue);
- }
- }
-
private static String toJson(Object object) {
String objectToJson = "{\"json_error\":\"Unserializable Object.\"}";
//needs to be an object, not a string, for Kibana. Otherwise, Kibana will throw away the log entry because the field has the wrong type.
@@ -355,4 +348,13 @@ private static void logFailedUpdate(String key) {
log.warn("Cannot update content of MDC key {} in {}.{}({}:{}) because it does not exist.",
key, caller.getClassName(), caller.getMethodName(), caller.getFileName(), caller.getLineNumber());
}
+
+ @Override
+ public void close() {
+ if (oldValue == null) {
+ MDC.remove(key);
+ } else {
+ MDC.put(key, oldValue);
+ }
+ }
}
diff --git a/src/test/java/de/dm/prom/structuredlogging/ExampleBean.java b/src/test/java/de/dm/prom/structuredlogging/ExampleBean.java
index 646a3a6..aa646de 100644
--- a/src/test/java/de/dm/prom/structuredlogging/ExampleBean.java
+++ b/src/test/java/de/dm/prom/structuredlogging/ExampleBean.java
@@ -19,6 +19,7 @@
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
+import java.util.Optional;
import static java.time.DayOfWeek.MONDAY;
import static java.time.Month.JANUARY;
@@ -42,6 +43,8 @@ class ExampleBean {
private MonthDay monthDay;
private Year year;
private YearMonth yearMonth;
+ private Optional emptyOptional;
+ private Optional nonEmptyOptional;
static ExampleBean getExample() {
LocalDateTime importantTime = LocalDateTime.of(2019, JANUARY, 1, 13, 37);
@@ -63,6 +66,8 @@ static ExampleBean getExample() {
.monthDay(MonthDay.of(12, 24))
.year(Year.of(1984))
.yearMonth(YearMonth.of(2000, 8))
+ .emptyOptional(Optional.empty())
+ .nonEmptyOptional(Optional.of("Hello"))
.build();
}
}
diff --git a/src/test/java/de/dm/prom/structuredlogging/MdcContextUnitTest.java b/src/test/java/de/dm/prom/structuredlogging/MdcContextUnitTest.java
index 64f85c1..9ff2c15 100644
--- a/src/test/java/de/dm/prom/structuredlogging/MdcContextUnitTest.java
+++ b/src/test/java/de/dm/prom/structuredlogging/MdcContextUnitTest.java
@@ -25,32 +25,184 @@
@Slf4j
class MdcContextUnitTest {
- private static final String SAMPLE_BEAN_JSON = "{\"name\":\"John Doe\"," +
- "\"age\":35," +
- "\"importantTime\":\"2019-01-01T13:37\"," +
- "\"importantOffsetTime\":\"2019-01-01T13:37+01:00\"," +
- "\"instant\":\"1970-01-01T00:00:01Z\"," +
- "\"localDate\":\"2020-01-01\"," +
- "\"offsetTime\":\"13:37+01:00\"," +
- "\"period\":\"P42D\"," +
- "\"zonedDateTime\":\"2019-01-01T13:37Z[UTC]\"," +
- "\"localTime\":\"13:37\"," +
- "\"duration\":\"PT42M\"," +
- "\"dayOfWeek\":\"MONDAY\"," +
- "\"month\":\"JANUARY\"," +
- "\"monthDay\":\"--12-24\"," +
- "\"year\":\"1984\"," +
- "\"yearMonth\":\"2000-08\"" +
- "}";
+ private static final String SAMPLE_BEAN_JSON = """
+ {
+ "name":"John Doe",
+ "age":35,
+ "importantTime":"2019-01-01T13:37",
+ "importantOffsetTime":"2019-01-01T13:37+01:00",
+ "instant":"1970-01-01T00:00:01Z",
+ "localDate":"2020-01-01",
+ "offsetTime":"13:37+01:00",
+ "period":"P42D",
+ "zonedDateTime":"2019-01-01T13:37Z[UTC]",
+ "localTime":"13:37",
+ "duration":"PT42M",
+ "dayOfWeek":"MONDAY",
+ "month":"JANUARY",
+ "monthDay":"--12-24",
+ "year":"1984",
+ "yearMonth":"2000-08",
+ "emptyOptional" : null,
+ "nonEmptyOptional" : "Hello"
+ }
+ """;
@RegisterExtension
public LogCapture logCapture = LogCapture.forCurrentPackage();
+ private static void throwIOException() throws IOException {
+ throw new IOException("not really an IOException, just an example");
+ }
+
@AfterEach
void resetMdc() {
MdcContext.resetGlobalObjectMapper();
}
+ @Test
+ void customObjectMapperIsUsedAndReset() throws IOException {
+ ObjectMapper customObjectMapper = mock(ObjectMapper.class);
+ ExampleBean objectToSerialize = ExampleBean.getExample();
+ String expectedCustomJson = "{\"content\": \"custom json string\"}";
+
+ when(customObjectMapper.writeValueAsString(objectToSerialize)).thenReturn(expectedCustomJson);
+
+ try (MdcContext c = MdcContext.of(objectToSerialize)) {
+ assertMdcFieldContentIsCorrect("ExampleBean", SAMPLE_BEAN_JSON);
+ }
+
+ MdcContext.setGlobalObjectMapper(customObjectMapper);
+
+ try (MdcContext c = MdcContext.of(objectToSerialize)) {
+ assertMdcFieldContentIsCorrect("ExampleBean", expectedCustomJson);
+ }
+
+ MdcContext.resetGlobalObjectMapper();
+
+ try (MdcContext c = MdcContext.of(objectToSerialize)) {
+ assertMdcFieldContentIsCorrect("ExampleBean", SAMPLE_BEAN_JSON);
+ }
+ }
+
+ @Test
+ void exceptionsThrownByObjectMapperAreCaughtAndLogged() throws IOException {
+ ObjectMapper customObjectMapper = mock(ObjectMapper.class);
+ String objectToSerialize = "I have a toString method";
+
+ when(customObjectMapper.writeValueAsString(objectToSerialize)).thenThrow(new RuntimeException("something terrible happened"));
+
+ MdcContext.setGlobalObjectMapper(customObjectMapper);
+ try (MdcContext c = MdcContext.of(objectToSerialize)) {
+ log.info("something happened");
+ }
+
+ logCapture.assertLogged(error("Object cannot be serialized\\: \"I have a toString method\"", exception().expectedMessageRegex("something terrible happened").build()));
+ }
+
+ private void assertMdcFieldContentIsCorrect(String mdcFieldName, String expectedJson) throws JsonProcessingException {
+ String jsonStringFromMdc = MDC.get(mdcFieldName);
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ JsonNode sampleBeanTree = objectMapper.readTree(expectedJson);
+
+ assertThat(jsonStringFromMdc).startsWith(JSON_PREFIX);
+ String actualJson = jsonStringFromMdc.replaceFirst(JSON_PREFIX, "");
+ JsonNode treeFromMDC = objectMapper.readTree(actualJson);
+
+ assertThat(treeFromMDC.toPrettyString())
+ .isEqualTo(sampleBeanTree.toPrettyString());
+ }
+
+ @Test
+ void putSomethingToMDCUpdateAndRemoveWhenDone() {
+ String mdcKey = new StringKeySupplier().getMdcKey();
+ String mdcValue = "test value"; //JSON strings are expected at this point
+ String updatedValue = "updated value";
+ try (MdcContext c = MdcContext.of(StringKeySupplier.class, mdcValue)) {
+ assertThat(MDC.get(mdcKey)).isEqualTo(String.format("%s\"%s\"", JSON_PREFIX, mdcValue));
+ MdcContext.update(StringKeySupplier.class, updatedValue);
+ assertThat(MDC.get(mdcKey)).isEqualTo(String.format("%s\"%s\"", JSON_PREFIX, updatedValue));
+ }
+ assertThat(MDC.get(mdcKey)).isNull();
+ }
+
+ @Test
+ void withSuppliedStringAsKey() throws Exception {
+ ExampleBean exampleBean = ExampleBean.getExample();
+ String mdcKey = "custom_key";
+
+ try (MdcContext c = MdcContext.of(mdcKey, exampleBean)) {
+ assertMdcFieldContentIsCorrect(mdcKey, SAMPLE_BEAN_JSON);
+ String updatedName = "Jack Frost";
+ exampleBean.setName(updatedName);
+ MdcContext.update(mdcKey, exampleBean);
+ assertMdcFieldContentIsCorrect(mdcKey, SAMPLE_BEAN_JSON.replace("John Doe", updatedName));
+ }
+ assertThat(MDC.get(mdcKey)).isNull();
+ }
+
+ @Test
+ void withSimpleNameAsKey() throws Exception {
+ ExampleBean exampleBean = ExampleBean.getExample();
+ String mdcKey = "ExampleBean";
+
+ try (MdcContext c = MdcContext.of(exampleBean)) {
+ assertMdcFieldContentIsCorrect(mdcKey, SAMPLE_BEAN_JSON);
+ String updatedName = "Jack Frost";
+ exampleBean.setName(updatedName);
+ MdcContext.update(exampleBean);
+ assertMdcFieldContentIsCorrect(mdcKey, SAMPLE_BEAN_JSON.replace("John Doe", updatedName));
+ }
+ assertThat(MDC.get(mdcKey)).isNull();
+ }
+
+ @Test
+ void failedUpdate() {
+ MdcContext.update(ExampleBean.getExample());
+
+ logCapture.assertLogged(warn("^Cannot update content of MDC key ExampleBean in .*\\.failedUpdate\\(MdcContextUnitTest.java:[0-9]+\\) because it does not exist.$"));
+ }
+
+ @Test
+ void accidentallyOverwriteMDCValue() {
+ String someValue = "some value";
+ String someValueJson = JSON_PREFIX + "\"" + someValue + "\"";
+ String otherValue = "other value";
+ String otherValueJson = JSON_PREFIX + "\"" + otherValue + "\"";
+
+ String mdcKey = new StringKeySupplier().getMdcKey();
+
+ try (MdcContext c = MdcContext.of(StringKeySupplier.class, someValue)) {
+ assertThat(MDC.get(mdcKey)).isEqualTo(someValueJson);
+ try (MdcContext inner = MdcContext.of(StringKeySupplier.class, someValue)) {
+ assertThat(MDC.get(mdcKey)).isEqualTo(someValueJson);
+ try (MdcContext sameIdWithDifferentValue = MdcContext.of(StringKeySupplier.class, otherValue)) {
+ assertThat(MDC.get(mdcKey)).isEqualTo(otherValueJson);
+ }
+ assertThat(MDC.get(mdcKey)).isEqualTo(someValueJson);
+ }
+ assertThat(MDC.get(mdcKey)).isEqualTo(someValueJson);
+ }
+ assertThat(MDC.get(mdcKey)).isNull();
+
+ logCapture.assertLoggedInOrder(warn("^Overwriting MDC key string_sample in .*\\.accidentallyOverwriteMDCValue\\(MdcContextUnitTest.java:[0-9]+\\) " +
+ "- a context with a certain key should never contain another context with the same one. " +
+ "The value is overwritten with the same value. This is superfluous and should be removed."),
+ error("^Overwriting MDC key string_sample in .*\\.accidentallyOverwriteMDCValue\\(MdcContextUnitTest.java:[0-9]+\\) " +
+ "- a context with a certain key should never contain another context with the same one. " +
+ "The old value differs from new value. This should never happen, because it messes up the MDC context. " +
+ "Old value: MDC_JSON_VALUE:\"some value\" - new value: MDC_JSON_VALUE:\"other value\""));
+ }
+
+ // useful for this test: ObjectMapper is not needed for comparison of serialized JSON
+ public static final class StringKeySupplier implements MdcKeySupplier {
+ @Override
+ public String getMdcKey() {
+ return "string_sample";
+ }
+ }
+
@Nested
class ContextId {
@Test
@@ -206,153 +358,4 @@ void withThrowingSupplier() {
}
}
}
-
- private static void throwIOException() throws IOException {
- throw new IOException("not really an IOException, just an example");
- }
-
-
- @Test
- void customObjectMapperIsUsedAndReset() throws IOException {
- ObjectMapper customObjectMapper = mock(ObjectMapper.class);
- ExampleBean objectToSerialize = ExampleBean.getExample();
- String expectedCustomJson = "{\"content\": \"custom json string\"}";
-
- when(customObjectMapper.writeValueAsString(objectToSerialize)).thenReturn(expectedCustomJson);
-
- try (MdcContext c = MdcContext.of(objectToSerialize)) {
- assertMdcFieldContentIsCorrect("ExampleBean", SAMPLE_BEAN_JSON);
- }
-
- MdcContext.setGlobalObjectMapper(customObjectMapper);
-
- try (MdcContext c = MdcContext.of(objectToSerialize)) {
- assertMdcFieldContentIsCorrect("ExampleBean", expectedCustomJson);
- }
-
- MdcContext.resetGlobalObjectMapper();
-
- try (MdcContext c = MdcContext.of(objectToSerialize)) {
- assertMdcFieldContentIsCorrect("ExampleBean", SAMPLE_BEAN_JSON);
- }
- }
-
- @Test
- void exceptionsThrownByObjectMapperAreCaughtAndLogged() throws IOException {
- ObjectMapper customObjectMapper = mock(ObjectMapper.class);
- String objectToSerialize = "I have a toString method";
-
- when(customObjectMapper.writeValueAsString(objectToSerialize)).thenThrow(new RuntimeException("something terrible happened"));
-
- MdcContext.setGlobalObjectMapper(customObjectMapper);
- try (MdcContext c = MdcContext.of(objectToSerialize)) {
- log.info("something happened");
- }
-
- logCapture.assertLogged(error("Object cannot be serialized\\: \"I have a toString method\"", exception().expectedMessageRegex("something terrible happened").build()));
- }
-
- private void assertMdcFieldContentIsCorrect(String mdcFieldName, String expectedJson) throws JsonProcessingException {
- String jsonStringFromMdc = MDC.get(mdcFieldName);
-
- ObjectMapper objectMapper = new ObjectMapper();
- JsonNode sampleBeanTree = objectMapper.readTree(expectedJson);
-
- assertThat(jsonStringFromMdc).startsWith(JSON_PREFIX);
- String actualJson = jsonStringFromMdc.replaceFirst(JSON_PREFIX, "");
- JsonNode treeFromMDC = objectMapper.readTree(actualJson);
-
- assertThat(treeFromMDC).as("Expecting:\n<%s>\nto be equal to:\n<%s>\nbut was not.\n\n\n",
- treeFromMDC.toPrettyString(), sampleBeanTree.toPrettyString())
- .isEqualTo(sampleBeanTree);
- }
-
- @Test
- void putSomethingToMDCUpdateAndRemoveWhenDone() {
- String mdcKey = new StringKeySupplier().getMdcKey();
- String mdcValue = "test value"; //JSON strings are expected at this point
- String updatedValue = "updated value";
- try (MdcContext c = MdcContext.of(StringKeySupplier.class, mdcValue)) {
- assertThat(MDC.get(mdcKey)).isEqualTo(String.format("%s\"%s\"", JSON_PREFIX, mdcValue));
- MdcContext.update(StringKeySupplier.class, updatedValue);
- assertThat(MDC.get(mdcKey)).isEqualTo(String.format("%s\"%s\"", JSON_PREFIX, updatedValue));
- }
- assertThat(MDC.get(mdcKey)).isNull();
- }
-
- @Test
- void withSuppliedStringAsKey() throws Exception {
- ExampleBean exampleBean = ExampleBean.getExample();
- String mdcKey = "custom_key";
-
- try (MdcContext c = MdcContext.of(mdcKey, exampleBean)) {
- assertMdcFieldContentIsCorrect(mdcKey, SAMPLE_BEAN_JSON);
- String updatedName = "Jack Frost";
- exampleBean.setName(updatedName);
- MdcContext.update(mdcKey, exampleBean);
- assertMdcFieldContentIsCorrect(mdcKey, SAMPLE_BEAN_JSON.replace("John Doe", updatedName));
- }
- assertThat(MDC.get(mdcKey)).isNull();
- }
-
- @Test
- void withSimpleNameAsKey() throws Exception {
- ExampleBean exampleBean = ExampleBean.getExample();
- String mdcKey = "ExampleBean";
-
- try (MdcContext c = MdcContext.of(exampleBean)) {
- assertMdcFieldContentIsCorrect(mdcKey, SAMPLE_BEAN_JSON);
- String updatedName = "Jack Frost";
- exampleBean.setName(updatedName);
- MdcContext.update(exampleBean);
- assertMdcFieldContentIsCorrect(mdcKey, SAMPLE_BEAN_JSON.replace("John Doe", updatedName));
- }
- assertThat(MDC.get(mdcKey)).isNull();
- }
-
- @Test
- void failedUpdate() {
- MdcContext.update(ExampleBean.getExample());
-
- logCapture.assertLogged(warn("^Cannot update content of MDC key ExampleBean in .*\\.failedUpdate\\(MdcContextUnitTest.java:[0-9]+\\) because it does not exist.$"));
- }
-
- @Test
- void accidentallyOverwriteMDCValue() {
- String someValue = "some value";
- String someValueJson = JSON_PREFIX + "\"" + someValue + "\"";
- String otherValue = "other value";
- String otherValueJson = JSON_PREFIX + "\"" + otherValue + "\"";
-
- String mdcKey = new StringKeySupplier().getMdcKey();
-
- try (MdcContext c = MdcContext.of(StringKeySupplier.class, someValue)) {
- assertThat(MDC.get(mdcKey)).isEqualTo(someValueJson);
- try (MdcContext inner = MdcContext.of(StringKeySupplier.class, someValue)) {
- assertThat(MDC.get(mdcKey)).isEqualTo(someValueJson);
- try (MdcContext sameIdWithDifferentValue = MdcContext.of(StringKeySupplier.class, otherValue)) {
- assertThat(MDC.get(mdcKey)).isEqualTo(otherValueJson);
- }
- assertThat(MDC.get(mdcKey)).isEqualTo(someValueJson);
- }
- assertThat(MDC.get(mdcKey)).isEqualTo(someValueJson);
- }
- assertThat(MDC.get(mdcKey)).isNull();
-
- logCapture.assertLoggedInOrder(warn("^Overwriting MDC key string_sample in .*\\.accidentallyOverwriteMDCValue\\(MdcContextUnitTest.java:[0-9]+\\) " +
- "- a context with a certain key should never contain another context with the same one. " +
- "The value is overwritten with the same value. This is superfluous and should be removed."),
- error("^Overwriting MDC key string_sample in .*\\.accidentallyOverwriteMDCValue\\(MdcContextUnitTest.java:[0-9]+\\) " +
- "- a context with a certain key should never contain another context with the same one. " +
- "The old value differs from new value. This should never happen, because it messes up the MDC context. " +
- "Old value: MDC_JSON_VALUE:\"some value\" - new value: MDC_JSON_VALUE:\"other value\""));
- }
-
- // useful for this test: ObjectMapper is not needed for comparison of serialized JSON
- public static final class StringKeySupplier implements MdcKeySupplier {
- @Override
- public String getMdcKey() {
- return "string_sample";
- }
- }
}
diff --git a/src/test/java/de/dm/prom/structuredlogging/StructuredMdcJsonProviderUnitTest.java b/src/test/java/de/dm/prom/structuredlogging/StructuredMdcJsonProviderUnitTest.java
index b31e7dc..1bf376b 100644
--- a/src/test/java/de/dm/prom/structuredlogging/StructuredMdcJsonProviderUnitTest.java
+++ b/src/test/java/de/dm/prom/structuredlogging/StructuredMdcJsonProviderUnitTest.java
@@ -27,30 +27,37 @@
// LogCapture is not applicable here because the actual output format of the log is relevant
@Slf4j
class StructuredMdcJsonProviderUnitTest {
- private static final String SAMPLE_LOGSTASH_JSON_LOG = "{\"@version\":\"1\"," +
- "\"message\":\"something in which the ExampleBean context is relevant\"," +
- "\"logger_name\":\"de.dm.prom.structuredlogging.StructuredMdcJsonProviderUnitTest\"," +
- "\"thread_name\":\"main\"," +
- "\"level\":\"INFO\"," +
- "\"level_value\":20000," +
- "\"an_unmanaged_mdc_field\":\"some value\"," +
- "\"example_bean\":" +
- "{\"name\":\"John Doe\"," +
- "\"age\":35," +
- "\"importantTime\":\"2019-01-01T13:37\"," +
- "\"importantOffsetTime\":\"2019-01-01T13:37+01:00\"," +
- "\"instant\":\"1970-01-01T00:00:01Z\"," +
- "\"localDate\":\"2020-01-01\"," +
- "\"offsetTime\":\"13:37+01:00\"," +
- "\"period\":\"P42D\"," +
- "\"localTime\":\"13:37\"," +
- "\"duration\":\"PT42M\"," +
- "\"dayOfWeek\":\"MONDAY\"," +
- "\"month\":\"JANUARY\"," +
- "\"monthDay\":\"--12-24\"," +
- "\"year\":\"1984\"," +
- "\"yearMonth\":\"2000-08\"," +
- "\"zonedDateTime\":\"2019-01-01T13:37Z[UTC]\"}}";
+ private static final String SAMPLE_LOGSTASH_JSON_LOG = """
+ {
+ "@version":"1",
+ "message":"something in which the ExampleBean context is relevant",
+ "logger_name":"de.dm.prom.structuredlogging.StructuredMdcJsonProviderUnitTest",
+ "thread_name":"main",
+ "level":"INFO",
+ "level_value":20000,
+ "an_unmanaged_mdc_field":"some value",
+ "example_bean": {
+ "name":"John Doe",
+ "age":35,
+ "importantTime":"2019-01-01T13:37",
+ "importantOffsetTime":"2019-01-01T13:37+01:00",
+ "instant":"1970-01-01T00:00:01Z",
+ "localDate":"2020-01-01",
+ "offsetTime":"13:37+01:00",
+ "period":"P42D",
+ "zonedDateTime":"2019-01-01T13:37Z[UTC]",
+ "localTime":"13:37",
+ "duration":"PT42M",
+ "dayOfWeek":"MONDAY",
+ "month":"JANUARY",
+ "monthDay":"--12-24",
+ "year":"1984",
+ "yearMonth":"2000-08",
+ "emptyOptional" : null,
+ "nonEmptyOptional" : "Hello"
+ }
+ }
+ """;
private final Logger rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
@@ -85,7 +92,7 @@ void logTest(CapturedOutput output) throws IOException {
((ObjectNode) actualJson).remove("@timestamp"); //because only ObjectNode provides .remove(...)
- Assertions.assertThat(actualJson).isEqualTo(expectedJson);
+ Assertions.assertThat(actualJson.toPrettyString()).isEqualTo(expectedJson.toPrettyString());
}
}
}