From 049254a8205b7f78a896613b615cb8d91ebb62b2 Mon Sep 17 00:00:00 2001 From: Stephan Schnabel Date: Tue, 16 May 2023 14:30:05 +0200 Subject: [PATCH] Remove unmaintained `logback-contrib` and replace by direct jackson --- pom.xml | 32 +-- src/it/log-gcp-with-service/postbuild.bsh | 2 +- .../logging/layout/GcpJsonLayout.java | 4 +- .../micronaut/logging/layout/JsonLayout.java | 182 ++++++++++++++++++ .../io/kokuwa/logback/appender-gcp.xml | 4 - .../io/kokuwa/logback/appender-json.xml | 7 +- 6 files changed, 194 insertions(+), 37 deletions(-) create mode 100644 src/main/java/io/kokuwa/micronaut/logging/layout/JsonLayout.java diff --git a/pom.xml b/pom.xml index 59a4286..7e0c704 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.kokuwa.micronaut micronaut-logging - 3.1.1-SNAPSHOT + 3.2.0-SNAPSHOT Logging Support for Micronaut Enhanced logging using MDC or request header. @@ -101,8 +101,8 @@ 1.2.12 - 0.1.5 - 3.1.1-SNAPSHOT + 2.15.0 + 3.2.0-SNAPSHOT 3.9.1 3.11.0 1.7.36 @@ -138,19 +138,9 @@ ${version.ch.qos.logback} - ch.qos.logback.contrib - logback-json-classic - ${version.ch.qos.logback.contrib} - - - ch.qos.logback.contrib - logback-json-core - ${version.ch.qos.logback.contrib} - - - ch.qos.logback.contrib - logback-jackson - ${version.ch.qos.logback.contrib} + com.fasterxml.jackson.core + jackson-databind + ${version.com.fasterxml.jackson} @@ -217,13 +207,9 @@ logback-classic - ch.qos.logback.contrib - logback-json-classic - - - ch.qos.logback.contrib - logback-jackson - runtime + com.fasterxml.jackson.core + jackson-databind + provided diff --git a/src/it/log-gcp-with-service/postbuild.bsh b/src/it/log-gcp-with-service/postbuild.bsh index 7ba1cab..6264c10 100644 --- a/src/it/log-gcp-with-service/postbuild.bsh +++ b/src/it/log-gcp-with-service/postbuild.bsh @@ -1,6 +1,6 @@ // verify log -String expected = "^\\{\"time\":\"202[3-9]-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{0,3}Z\",\"severity\":\"INFO\",\"thread\":\"main\",\"logger\":\"io.kokuwa.micronaut.logging.LoggingTest\",\"message\":\"test-output-marker\",\"raw-message\":\"test-output-marker\",\"serviceContext\":\\{\"version\":\"0.1.2\",\"service\":\"test-service\"}}$"; +String expected = "^\\{\"time\":\"202[3-9]-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{0,3}Z\",\"severity\":\"INFO\",\"thread\":\"main\",\"logger\":\"io.kokuwa.micronaut.logging.LoggingTest\",\"message\":\"test-output-marker\",\"raw-message\":\"test-output-marker\",\"serviceContext\":\\{\"service\":\"test-service\",\"version\":\"0.1.2\"}}$"; String[] logs = org.codehaus.plexus.util.FileUtils.fileRead(basedir + "/build.log").split("\n"); for (String log : logs) { diff --git a/src/main/java/io/kokuwa/micronaut/logging/layout/GcpJsonLayout.java b/src/main/java/io/kokuwa/micronaut/logging/layout/GcpJsonLayout.java index 139607c..524601c 100644 --- a/src/main/java/io/kokuwa/micronaut/logging/layout/GcpJsonLayout.java +++ b/src/main/java/io/kokuwa/micronaut/logging/layout/GcpJsonLayout.java @@ -1,12 +1,10 @@ package io.kokuwa.micronaut.logging.layout; import java.time.Instant; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.contrib.json.classic.JsonLayout; import io.micronaut.core.util.StringUtils; /** @@ -44,7 +42,7 @@ public class GcpJsonLayout extends JsonLayout { private void addServiceContext(Map map) { if (serviceContext == null) { - serviceContext = new HashMap<>(2); + serviceContext = new LinkedHashMap<>(2); if (StringUtils.isNotEmpty(serviceName) && !serviceName.endsWith(UNDEFINED)) { serviceContext.put("service", serviceName); } diff --git a/src/main/java/io/kokuwa/micronaut/logging/layout/JsonLayout.java b/src/main/java/io/kokuwa/micronaut/logging/layout/JsonLayout.java new file mode 100644 index 0000000..9617549 --- /dev/null +++ b/src/main/java/io/kokuwa/micronaut/logging/layout/JsonLayout.java @@ -0,0 +1,182 @@ +package io.kokuwa.micronaut.logging.layout; + +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 io.micronaut.http.MediaType; + +public class JsonLayout extends LayoutBase { + + public static final String TIMESTAMP_ATTR_NAME = "timestamp"; + public static final String LEVEL_ATTR_NAME = "level"; + public static final String THREAD_ATTR_NAME = "thread"; + public static final String MDC_ATTR_NAME = "mdc"; + public static final String LOGGER_ATTR_NAME = "logger"; + public static final String FORMATTED_MESSAGE_ATTR_NAME = "message"; + public static final String MESSAGE_ATTR_NAME = "raw-message"; + 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; + protected boolean includeLoggerName = true; + protected boolean includeFormattedMessage = true; + protected boolean includeMessage = true; + protected boolean includeException = true; + protected boolean includeContextName = false; + protected boolean includeTimestamp = true; + private String timestampFormat; + private String timestampFormatTimezoneId; + private ThrowableHandlingConverter throwableHandlingConverter = new ThrowableProxyConverter(); + + @Override + public String getContentType() { + return MediaType.APPLICATION_JSON; + } + + @Override + public void start() { + this.throwableHandlingConverter.start(); + super.start(); + } + + @Override + public void stop() { + super.stop(); + this.throwableHandlingConverter.stop(); + } + + @Override + public String doLayout(ILoggingEvent event) { + var map = toJsonMap(event); + try { + return mapper.writeValueAsString(map) + CoreConstants.LINE_SEPARATOR; + } catch (JsonProcessingException e) { + addError("Failed to write json from event " + event + " and map " + map, e); + return null; + } + } + + protected Map toJsonMap(ILoggingEvent event) { + var map = new LinkedHashMap(); + addTimestamp(TIMESTAMP_ATTR_NAME, includeTimestamp, event.getTimeStamp(), map); + add(LEVEL_ATTR_NAME, includeLevel, String.valueOf(event.getLevel()), map); + add(THREAD_ATTR_NAME, includeThreadName, event.getThreadName(), map); + addMap(MDC_ATTR_NAME, includeMDC, event.getMDCPropertyMap(), map); + add(LOGGER_ATTR_NAME, includeLoggerName, event.getLoggerName(), map); + add(FORMATTED_MESSAGE_ATTR_NAME, includeFormattedMessage, event.getFormattedMessage(), map); + add(MESSAGE_ATTR_NAME, includeMessage, event.getMessage(), map); + add(CONTEXT_ATTR_NAME, includeContextName, event.getLoggerContextVO().getName(), map); + addThrowableInfo(EXCEPTION_ATTR_NAME, includeException, event, map); + return map; + } + + protected void addThrowableInfo(String fieldName, boolean field, ILoggingEvent value, Map map) { + if (field && value != null) { + var throwableProxy = value.getThrowableProxy(); + if (throwableProxy != null) { + var ex = throwableHandlingConverter.convert(value); + if (ex != null && !ex.equals("")) { + map.put(fieldName, ex); + } + } + } + } + + protected void addMap(String key, boolean field, Map mapValue, Map map) { + if (field && mapValue != null && !mapValue.isEmpty()) { + map.put(key, mapValue); + } + } + + protected void addTimestamp(String key, boolean field, long timeStamp, Map map) { + if (field) { + var formatted = formatTimestamp(timeStamp); + if (formatted != null) { + map.put(key, formatted); + } + } + } + + protected void add(String fieldName, boolean field, String value, Map map) { + if (field && value != null) { + map.put(fieldName, value); + } + } + + protected String formatTimestamp(long timestamp) { + if (timestampFormat == null || timestamp < 0) { + return String.valueOf(timestamp); + } + var date = new Date(timestamp); + var format = new SimpleDateFormat(timestampFormat); + if (timestampFormatTimezoneId != null) { + format.setTimeZone(TimeZone.getTimeZone(timestampFormatTimezoneId)); + } + return format.format(date); + } + + // setter + + public void setIncludeLevel(boolean includeLevel) { + this.includeLevel = includeLevel; + } + + public void setIncludeThreadName(boolean includeThreadName) { + this.includeThreadName = includeThreadName; + } + + public void setIncludeMDC(boolean includeMDC) { + this.includeMDC = includeMDC; + } + + public void setIncludeLoggerName(boolean includeLoggerName) { + this.includeLoggerName = includeLoggerName; + } + + public void setIncludeFormattedMessage(boolean includeFormattedMessage) { + this.includeFormattedMessage = includeFormattedMessage; + } + + public void setIncludeMessage(boolean includeMessage) { + this.includeMessage = includeMessage; + } + + public void setIncludeException(boolean includeException) { + this.includeException = includeException; + } + + public void setIncludeContextName(boolean includeContextName) { + this.includeContextName = includeContextName; + } + + public void setIncludeTimestamp(boolean includeTimestamp) { + this.includeTimestamp = includeTimestamp; + } + + public void setTimestampFormat(String timestampFormat) { + this.timestampFormat = timestampFormat; + } + + public void setTimestampFormatTimezoneId(String timestampFormatTimezoneId) { + this.timestampFormatTimezoneId = timestampFormatTimezoneId; + } + + public void setThrowableHandlingConverter(ThrowableHandlingConverter throwableHandlingConverter) { + this.throwableHandlingConverter = throwableHandlingConverter; + } +} diff --git a/src/main/resources/io/kokuwa/logback/appender-gcp.xml b/src/main/resources/io/kokuwa/logback/appender-gcp.xml index e847d99..a36210d 100644 --- a/src/main/resources/io/kokuwa/logback/appender-gcp.xml +++ b/src/main/resources/io/kokuwa/logback/appender-gcp.xml @@ -6,10 +6,6 @@ ${SERVICE_NAME} ${SERVICE_VERSION} - - true - true - false diff --git a/src/main/resources/io/kokuwa/logback/appender-json.xml b/src/main/resources/io/kokuwa/logback/appender-json.xml index b850ac7..e0034e4 100644 --- a/src/main/resources/io/kokuwa/logback/appender-json.xml +++ b/src/main/resources/io/kokuwa/logback/appender-json.xml @@ -3,12 +3,7 @@ - - - true - true - false - + -- 2.47.2