diff --git a/README.md b/README.md
index 2d20fba..94b617e 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,12 @@ Include in your `pom.xml`:
${version.io.kokuwa.micronaut.logging}
runtime
+
+
+ io.micronaut.serde
+ micronaut-serde-jsonp
+ runtime
+
```
## Features
diff --git a/pom.xml b/pom.xml
index 005e3a9..d43a9b2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -114,6 +114,10 @@
micronaut-security
provided
+
+ io.micronaut.serde
+ micronaut-serde-api
+
io.micronaut.test
micronaut-test-junit5
diff --git a/src/it/log-gcp-from-env/pom.xml b/src/it/log-gcp-from-env/pom.xml
index 1c56178..0859f9a 100644
--- a/src/it/log-gcp-from-env/pom.xml
+++ b/src/it/log-gcp-from-env/pom.xml
@@ -9,4 +9,11 @@
@project.artifactId@-it-log-gcp-from-env
+
+
+
+ io.micronaut.serde
+ micronaut-serde-jsonp
+
+
diff --git a/src/it/log-gcp-from-gcloud/pom.xml b/src/it/log-gcp-from-gcloud/pom.xml
index 0030546..8de1353 100644
--- a/src/it/log-gcp-from-gcloud/pom.xml
+++ b/src/it/log-gcp-from-gcloud/pom.xml
@@ -9,4 +9,11 @@
@project.artifactId@-it-log-gcp-from-gcloud
+
+
+
+ io.micronaut.serde
+ micronaut-serde-jsonp
+
+
diff --git a/src/it/log-gcp-with-service/pom.xml b/src/it/log-gcp-with-service/pom.xml
index f13550f..af3eadc 100644
--- a/src/it/log-gcp-with-service/pom.xml
+++ b/src/it/log-gcp-with-service/pom.xml
@@ -9,4 +9,11 @@
@project.artifactId@-it-log-gcp-with-service
+
+
+
+ io.micronaut.serde
+ micronaut-serde-jsonp
+
+
diff --git a/src/it/log-json-from-env/invoker.properties b/src/it/log-json-from-env-serde-jackson/invoker.properties
similarity index 100%
rename from src/it/log-json-from-env/invoker.properties
rename to src/it/log-json-from-env-serde-jackson/invoker.properties
diff --git a/src/it/log-json-from-env-serde-jackson/pom.xml b/src/it/log-json-from-env-serde-jackson/pom.xml
new file mode 100644
index 0000000..66fb890
--- /dev/null
+++ b/src/it/log-json-from-env-serde-jackson/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+
+
+ @project.groupId@
+ @project.artifactId@-it
+ LOCAL-SNAPSHOT
+
+
+ @project.artifactId@-it-log-json-from-env-serde-jackson
+
+
+
+ io.micronaut.serde
+ micronaut-serde-jackson
+
+
+
diff --git a/src/it/log-json-from-env/postbuild.bsh b/src/it/log-json-from-env-serde-jackson/postbuild.bsh
similarity index 100%
rename from src/it/log-json-from-env/postbuild.bsh
rename to src/it/log-json-from-env-serde-jackson/postbuild.bsh
diff --git a/src/it/log-json-from-env-serde-jsonp/invoker.properties b/src/it/log-json-from-env-serde-jsonp/invoker.properties
new file mode 100644
index 0000000..08de0de
--- /dev/null
+++ b/src/it/log-json-from-env-serde-jsonp/invoker.properties
@@ -0,0 +1 @@
+invoker.environmentVariables.LOGBACK_APPENDER=JSON
diff --git a/src/it/log-json-from-env-serde-jsonp/pom.xml b/src/it/log-json-from-env-serde-jsonp/pom.xml
new file mode 100644
index 0000000..23ad54c
--- /dev/null
+++ b/src/it/log-json-from-env-serde-jsonp/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+
+
+ @project.groupId@
+ @project.artifactId@-it
+ LOCAL-SNAPSHOT
+
+
+ @project.artifactId@-it-log-json-from-env-serde-jsonp
+
+
+
+ io.micronaut.serde
+ micronaut-serde-jsonp
+
+
+
diff --git a/src/it/log-json-from-env-serde-jsonp/postbuild.bsh b/src/it/log-json-from-env-serde-jsonp/postbuild.bsh
new file mode 100644
index 0000000..0693fe0
--- /dev/null
+++ b/src/it/log-json-from-env-serde-jsonp/postbuild.bsh
@@ -0,0 +1,21 @@
+// verify log
+
+String expected = "^\\{\"timestamp\":\"[0-9]{13}\",\"level\":\"INFO\",\"thread\":\"main\",\"logger\":\"io.kokuwa.micronaut.logging.LoggingTest\",\"message\":\"test-output-marker\",\"raw-message\":\"test-output-marker\"}$";
+String[] logs = org.codehaus.plexus.util.FileUtils.fileRead(basedir + "/build.log").split("\n");
+
+for (String log : logs) {
+ if (!log.contains("test-output-marker")) {
+ continue;
+ }
+ if (java.util.regex.Pattern.matches(expected, log)) {
+ return true;
+ } else {
+ System.out.println("marker found, but formatting invalid:");
+ System.out.println("[EXPECTED] " + expected);
+ System.out.println("[ACTUAL] " + log);
+ return false;
+ }
+}
+
+System.out.println("marker not found");
+return false;
diff --git a/src/it/log-json-from-env-serde-missing/invoker.properties b/src/it/log-json-from-env-serde-missing/invoker.properties
new file mode 100644
index 0000000..08de0de
--- /dev/null
+++ b/src/it/log-json-from-env-serde-missing/invoker.properties
@@ -0,0 +1 @@
+invoker.environmentVariables.LOGBACK_APPENDER=JSON
diff --git a/src/it/log-json-from-env/pom.xml b/src/it/log-json-from-env-serde-missing/pom.xml
similarity index 84%
rename from src/it/log-json-from-env/pom.xml
rename to src/it/log-json-from-env-serde-missing/pom.xml
index 1ae3e61..68b86a0 100644
--- a/src/it/log-json-from-env/pom.xml
+++ b/src/it/log-json-from-env-serde-missing/pom.xml
@@ -8,5 +8,5 @@
LOCAL-SNAPSHOT
- @project.artifactId@-it-log-json-from-env
+ @project.artifactId@-it-log-json-from-env-serde-missing
diff --git a/src/it/log-json-from-env-serde-missing/postbuild.bsh b/src/it/log-json-from-env-serde-missing/postbuild.bsh
new file mode 100644
index 0000000..465b88c
--- /dev/null
+++ b/src/it/log-json-from-env-serde-missing/postbuild.bsh
@@ -0,0 +1,5 @@
+// verify log
+
+return org.codehaus.plexus.util.FileUtils
+ .fileRead(basedir + "/build.log")
+ .contains("Failed to get object mapper from micronaut, please check your classpath");
diff --git a/src/it/log-json-from-kubernetes/pom.xml b/src/it/log-json-from-kubernetes/pom.xml
index 885bc3b..812ac1f 100644
--- a/src/it/log-json-from-kubernetes/pom.xml
+++ b/src/it/log-json-from-kubernetes/pom.xml
@@ -9,4 +9,11 @@
@project.artifactId@-it-log-json-from-kubernetes
+
+
+
+ io.micronaut.serde
+ micronaut-serde-jsonp
+
+
diff --git a/src/main/java/io/kokuwa/micronaut/logging/layout/JsonLayout.java b/src/main/java/io/kokuwa/micronaut/logging/layout/JsonLayout.java
index 48677e2..4665494 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/layout/JsonLayout.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/layout/JsonLayout.java
@@ -1,20 +1,23 @@
package io.kokuwa.micronaut.logging.layout;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TimeZone;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
import ch.qos.logback.classic.pattern.ThrowableHandlingConverter;
import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.LayoutBase;
+import ch.qos.logback.core.status.OnConsoleStatusListener;
+import ch.qos.logback.core.status.StatusUtil;
+import ch.qos.logback.core.util.StatusListenerConfigHelper;
import io.micronaut.http.MediaType;
+import io.micronaut.json.JsonMapper;
public class JsonLayout extends LayoutBase {
@@ -28,8 +31,6 @@ public class JsonLayout extends LayoutBase {
public static final String EXCEPTION_ATTR_NAME = "exception";
public static final String CONTEXT_ATTR_NAME = "context";
- private final ObjectMapper mapper = new ObjectMapper();
-
protected boolean includeLevel = true;
protected boolean includeThreadName = true;
protected boolean includeMDC = true;
@@ -42,6 +43,7 @@ public class JsonLayout extends LayoutBase {
private String timestampFormat;
private String timestampFormatTimezoneId;
private ThrowableHandlingConverter throwableHandlingConverter = new ThrowableProxyConverter();
+ private JsonMapper mapper;
@Override
public String getContentType() {
@@ -63,9 +65,22 @@ public class JsonLayout extends LayoutBase {
@Override
public String doLayout(ILoggingEvent event) {
var map = toJsonMap(event);
+
+ if (mapper == null) {
+ try {
+ mapper = JsonMapper.createDefault();
+ } catch (IllegalStateException e) {
+ if (!StatusUtil.contextHasStatusListener(context)) {
+ addError("Failed to get object mapper from micronaut, please check your classpath");
+ StatusListenerConfigHelper.addOnConsoleListenerInstance(context, new OnConsoleStatusListener());
+ }
+ return map.toString() + CoreConstants.LINE_SEPARATOR;
+ }
+ }
+
try {
- return mapper.writeValueAsString(map) + CoreConstants.LINE_SEPARATOR;
- } catch (JsonProcessingException e) {
+ return new String(mapper.writeValueAsBytes(map), StandardCharsets.UTF_8) + CoreConstants.LINE_SEPARATOR;
+ } catch (IOException e) {
addError("Failed to write json from event " + event + " and map " + map, e);
return null;
}