diff --git a/README.md b/README.md
index a72e0cb..a9c998a 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,21 @@ Structured logging utility.
* Works with log consumers that can digest JSON logs, like the **ELK Stack** or **Datadog**.
* Framework agnostic (works well with **Spring**, because Spring Boot uses logback out of the box)
+**Table of Contents**
+
+* [Why use this?](#why-use-this)
+* [Example](#example)
+* [Changes](#changes)
+ * [1.0.3](#103)
+* [Usage](#usage)
+ * [Add structured-logging as a dependency](#add-structured-logging-as-a-dependency)
+ * [Define how Objects should be named in MDC](#define-how-objects-should-be-named-in-mdc)
+ * [Put Objects into MDC](#put-objects-into-mdc)
+ * [Excluding properties from serialization](#excluding-properties-from-serialization)
+ * [Configure Logback for Logstash](#configure-logback-for-logstash)
+ * [Configure a Task Decorator in Spring](#configure-a-task-decorator-in-spring)
+ * [Test your logging](#test-your-logging)
+
## Why use this?
If you use your logs for monitoring, alerting or visualization, you want them to have structured information so you can properly build your monitoring/alerting/visualizations on that.
@@ -42,6 +57,19 @@ If there are log messages that happen in the context of an order, you may want t
}
```
+## Changes
+
+### 1.0.3
+
+* Added proper serialization for further JSR310 types. Now properly serializes
+ * Instant (new)
+ * LocalDate (new)
+ * LocalDateTime
+ * OffsetDateTime
+ * OffsetTime (new)
+ * Period (new)
+ * ZonedDateTime (new)
+
## Usage
To use this, you need to:
@@ -62,7 +90,7 @@ If you use maven, add this to your pom.xml:
de.dm.infrastructure
structured-logging
- 1.0.2
+ 1.0.3
test
```
diff --git a/pom.xml b/pom.xml
index ddef34c..dd5b170 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
de.dm.infrastructure
structured-logging
- 1.0.3-SNAPSHOT
+ 1.0.4-SNAPSHOT
structured-logging
Structured logging and log testing
diff --git a/src/main/java/de/dm/prom/structuredlogging/MdcContext.java b/src/main/java/de/dm/prom/structuredlogging/MdcContext.java
index 52237d6..aa0b640 100644
--- a/src/main/java/de/dm/prom/structuredlogging/MdcContext.java
+++ b/src/main/java/de/dm/prom/structuredlogging/MdcContext.java
@@ -7,8 +7,14 @@
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
+import java.lang.reflect.InvocationTargetException;
+import java.time.Instant;
+import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.Period;
+import java.time.ZonedDateTime;
/**
* a context that can be used to wrap MDC information in a try-with-resources block.
@@ -56,14 +62,15 @@ private MdcContext(String key, String value) {
public void close() {
if (oldValue == null) {
MDC.remove(key);
- }
- else {
+ } 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.
+ 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.
+
try {
objectToJson = getObjectMapper().writeValueAsString(object);
} catch (JsonProcessingException e) {
@@ -73,10 +80,16 @@ private static String toJson(Object object) {
}
private static ObjectMapper getObjectMapper() {
- ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
- module.addSerializer(OffsetDateTime.class, new ToStringSerializer());
+ 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());
+
+ ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
return objectMapper;
}
@@ -98,8 +111,7 @@ private static void logOverwriting(String key, String value, String oldValue) {
if (!oldValue.equals(value)) {
log.error("{} The old value differs from new value. This should never happen, because it messes up the MDC context. Old value: {} - new value: {}",
message, oldValue, value);
- }
- else {
+ } else {
log.warn("{} The value is overwritten with the same value. This is superfluous and should be removed.", message);
}
}
diff --git a/src/test/java/de/dm/prom/structuredlogging/ExampleBean.java b/src/test/java/de/dm/prom/structuredlogging/ExampleBean.java
index 94f0345..7eeb50b 100644
--- a/src/test/java/de/dm/prom/structuredlogging/ExampleBean.java
+++ b/src/test/java/de/dm/prom/structuredlogging/ExampleBean.java
@@ -3,10 +3,17 @@
import lombok.Builder;
import lombok.Data;
+import java.time.Instant;
+import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.time.LocalTime;
import java.time.Month;
import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.Period;
+import java.time.ZoneId;
import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
@Data
@Builder
@@ -15,6 +22,11 @@ class ExampleBean {
private int age;
private LocalDateTime importantTime;
private OffsetDateTime importantOffsetTime;
+ private Instant instant;
+ private LocalDate localDate;
+ private OffsetTime offsetTime;
+ private Period period;
+ private ZonedDateTime zonedDateTime;
static ExampleBean getExample() {
LocalDateTime importantTime = LocalDateTime.of(2019, Month.JANUARY, 1, 13, 37);
@@ -24,6 +36,11 @@ static ExampleBean getExample() {
.age(35)
.importantTime(importantTime)
.importantOffsetTime(OffsetDateTime.of(importantTime, ZoneOffset.of("+01:00")))
+ .instant(Instant.ofEpochMilli(1000))
+ .localDate(LocalDate.of(2020, 1, 1))
+ .offsetTime(OffsetTime.of(LocalTime.of(13, 37), ZoneOffset.of("+01:00")))
+ .period(Period.ofDays(42))
+ .zonedDateTime(ZonedDateTime.of(importantTime, ZoneId.of("UTC")))
.build();
}
}
diff --git a/src/test/java/de/dm/prom/structuredlogging/MdcContextUnitTest.java b/src/test/java/de/dm/prom/structuredlogging/MdcContextUnitTest.java
index 2a81d34..f0efb76 100644
--- a/src/test/java/de/dm/prom/structuredlogging/MdcContextUnitTest.java
+++ b/src/test/java/de/dm/prom/structuredlogging/MdcContextUnitTest.java
@@ -16,7 +16,15 @@
@Slf4j
public 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\"}";
+ 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]\"}";
@Rule
public LogCapture logCapture = LogCapture.forUnitTest();
diff --git a/src/test/java/de/dm/prom/structuredlogging/StructuredMdcJsonProviderUnitTest.java b/src/test/java/de/dm/prom/structuredlogging/StructuredMdcJsonProviderUnitTest.java
index 5a9f545..81661bf 100644
--- a/src/test/java/de/dm/prom/structuredlogging/StructuredMdcJsonProviderUnitTest.java
+++ b/src/test/java/de/dm/prom/structuredlogging/StructuredMdcJsonProviderUnitTest.java
@@ -23,7 +23,24 @@
@Slf4j
public class StructuredMdcJsonProviderUnitTest {
- private static 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\"}}";
+ private static 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]\"}}";
+
private Logger rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
@Rule