Update to version 4.x and update to SLF4J 2.x and Logback 1.4

This commit is contained in:
Stephan Schnabel 2022-09-13 14:13:01 +02:00
parent eb22b5a309
commit 73ea6c7b60
Signed by: stephan.schnabel
GPG key ID: E07AF5BA239FE543
11 changed files with 121 additions and 53 deletions

View file

@ -17,6 +17,8 @@ Include in your `pom.xml`:
## Features ## Features
* Version [3.x](https://github.com/kokuwaio/micronaut-logging/tree/3.x) is based on SLF4J 1.7 & Logback 1.2
* Version [4.x](https://github.com/kokuwaio/micronaut-logging/tree/main) is based on SLF4J 2.0 & Logback 1.4
* [set log level based on MDC values](docs/features/logback_mdc_level.md) * [set log level based on MDC values](docs/features/logback_mdc_level.md)
* [add default xml](docs/features/logback_default.md) * [add default xml](docs/features/logback_default.md)
* [preconfigured appender for different environments](docs/features/logback_appender.md) * [preconfigured appender for different environments](docs/features/logback_appender.md)
@ -33,5 +35,3 @@ Include in your `pom.xml`:
* configure mdc on refresh event * configure mdc on refresh event
* read **serviceName** and **serviceVersion** from yaml * read **serviceName** and **serviceVersion** from yaml
* support auto select appender with custom `logback.xml`
* add maven site with jacoco / dependency updates for snapshot build

View file

@ -2,7 +2,7 @@
## Available Appender ## Available Appender
* console with jansi for developers * console for developers
* gcp logging format (with support for error reporting) * gcp logging format (with support for error reporting)
* json * json
@ -12,5 +12,3 @@
2. if GCP is detected gcp appender will be used 2. if GCP is detected gcp appender will be used
3. if Kubernetes is detected json appender will be used 3. if Kubernetes is detected json appender will be used
4. console appender else 4. console appender else
*IMPORTENT*: only works without custom `logback.xml`

View file

@ -4,14 +4,12 @@ If no `logback.xml` by user is provided a default [logback.xml](../../src/main/r
```xml ```xml
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true" scan="false"> <configuration debug="false" scan="false">
<include resource="io/kokuwa/logback/base.xml" />
<logger name="io.micronaut.logging.PropertiesLoggingLevelsConfigurer" levels="WARN" /> <logger name="io.micronaut.logging.PropertiesLoggingLevelsConfigurer" levels="WARN" />
<root level="INFO"> <root level="INFO">
<appender-ref ref="${LOGBACK_APPENDER:-CONSOLE}" /> <autoAppender />
</root> </root>
</configuration> </configuration>

13
pom.xml
View file

@ -4,7 +4,7 @@
<groupId>io.kokuwa.micronaut</groupId> <groupId>io.kokuwa.micronaut</groupId>
<artifactId>micronaut-logging</artifactId> <artifactId>micronaut-logging</artifactId>
<version>3.0.6-SNAPSHOT</version> <version>4.0.0-SNAPSHOT</version>
<name>Logging Support for Micronaut</name> <name>Logging Support for Micronaut</name>
<description>Enhanced logging using MDC or request header.</description> <description>Enhanced logging using MDC or request header.</description>
@ -105,9 +105,10 @@
<!-- dependencies --> <!-- dependencies -->
<version.ch.qos.logback>1.2.11</version.ch.qos.logback> <version.ch.qos.logback>1.4.0</version.ch.qos.logback>
<version.ch.qos.logback.contrib>0.1.5</version.ch.qos.logback.contrib> <version.ch.qos.logback.contrib>0.1.5</version.ch.qos.logback.contrib>
<version.io.micronaut>3.6.1</version.io.micronaut> <version.io.micronaut>3.6.1</version.io.micronaut>
<version.org.slf4j.api>2.0.0</version.org.slf4j.api>
</properties> </properties>
@ -123,6 +124,13 @@
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<!-- slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${version.org.slf4j.api}</version>
</dependency>
<!-- logback --> <!-- logback -->
<dependency> <dependency>
<groupId>ch.qos.logback</groupId> <groupId>ch.qos.logback</groupId>
@ -193,7 +201,6 @@
<dependency> <dependency>
<groupId>ch.qos.logback.contrib</groupId> <groupId>ch.qos.logback.contrib</groupId>
<artifactId>logback-jackson</artifactId> <artifactId>logback-jackson</artifactId>
<scope>runtime</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View file

@ -14,12 +14,12 @@ import ch.qos.logback.core.spi.ContextAwareBase;
public class DefaultConfigurator extends ContextAwareBase implements Configurator { public class DefaultConfigurator extends ContextAwareBase implements Configurator {
@Override @Override
public void configure(LoggerContext loggerContext) { public ExecutionStatus configure(LoggerContext loggerContext) {
var base = DefaultConfigurator.class.getResource("/io/kokuwa/logback/logback-default.xml"); var base = DefaultConfigurator.class.getResource("/io/kokuwa/logback/logback-default.xml");
if (base == null) { if (base == null) {
addError("Failed to find logback.xml from io.kokuwa:micronaut-logging"); addError("Failed to find logback.xml from io.kokuwa:micronaut-logging");
return; return ExecutionStatus.NEUTRAL;
} }
try { try {
@ -29,8 +29,10 @@ public class DefaultConfigurator extends ContextAwareBase implements Configurato
configurator.doConfigure(base); configurator.doConfigure(base);
} catch (JoranException e) { } catch (JoranException e) {
addError("Failed to load logback.xml from io.kokuwa:micronaut-logging", e); addError("Failed to load logback.xml from io.kokuwa:micronaut-logging", e);
return ExecutionStatus.NEUTRAL;
} }
loggerContext.getLogger("io.micronaut.logging.PropertiesLoggingLevelsConfigurer").setLevel(Level.WARN); loggerContext.getLogger("io.micronaut.logging.PropertiesLoggingLevelsConfigurer").setLevel(Level.WARN);
return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY;
} }
} }

View file

@ -12,8 +12,8 @@ import ch.qos.logback.core.joran.spi.RuleStore;
public class MicronautJoranConfigurator extends JoranConfigurator { public class MicronautJoranConfigurator extends JoranConfigurator {
@Override @Override
public void addInstanceRules(RuleStore rs) { public void addElementSelectorAndActionAssociations(RuleStore rs) {
super.addInstanceRules(rs); super.addElementSelectorAndActionAssociations(rs);
rs.addRule(new ElementSelector("configuration/root/autoAppender"), new RootAutoSelectAppenderAction()); rs.addRule(new ElementSelector("configuration/root/autoAppender"), () -> new RootAutoSelectAppenderAction());
} }
} }

View file

@ -1,16 +1,21 @@
package io.kokuwa.micronaut.logging.configurator; package io.kokuwa.micronaut.logging.configurator;
import java.util.Map; import java.util.Optional;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender; import ch.qos.logback.contrib.jackson.JacksonJsonFormatter;
import ch.qos.logback.contrib.json.classic.JsonLayout;
import ch.qos.logback.core.ConsoleAppender;
import ch.qos.logback.core.Layout;
import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.action.Action;
import ch.qos.logback.core.joran.action.ActionConst; import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext;
import ch.qos.logback.core.joran.spi.InterpretationContext; import io.kokuwa.micronaut.logging.layout.GcpJsonLayout;
import io.micronaut.core.util.StringUtils; import io.micronaut.core.util.StringUtils;
/** /**
@ -27,9 +32,16 @@ public class RootAutoSelectAppenderAction extends Action {
private static final String APPENDER_JSON = "JSON"; private static final String APPENDER_JSON = "JSON";
private static final String APPENDER_GCP = "GCP"; private static final String APPENDER_GCP = "GCP";
private static final String LOGBACK_APPENDER = "LOGBACK_APPENDER"; private static final String LOGBACK_APPENDER = "LOGBACK_APPENDER";
private static final String LOGBACK_PATTERN = "LOGBACK_PATTERN";
private static final String LOGBACK_PATTERN_DEFAULT = "%cyan(%d{HH:mm:ss.SSS})"
+ " %gray(%-6.6thread)"
+ " %highlight(%-5level)"
+ " %magenta(%32logger{32})"
+ " %mdc"
+ " %msg%n}";
@Override @Override
public void begin(InterpretationContext ic, String name, Attributes attributes) { public void begin(SaxEventInterpretationContext ic, String name, Attributes attributes) {
var rootLogger = LoggerContext.class.cast(context).getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); var rootLogger = LoggerContext.class.cast(context).getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
var rootLoggerAppenders = rootLogger.iteratorForAppenders(); var rootLoggerAppenders = rootLogger.iteratorForAppenders();
@ -38,36 +50,95 @@ public class RootAutoSelectAppenderAction extends Action {
return; return;
} }
var envAppender = System.getenv(LOGBACK_APPENDER); var envAppender = env(LOGBACK_APPENDER, null);
if (envAppender != null && setAppender(ic, rootLogger, envAppender)) { if (envAppender != null) {
setAppender(rootLogger, envAppender);
return; return;
} }
if (IS_KUBERNETES && setAppender(ic, rootLogger, APPENDER_JSON)) { if (IS_KUBERNETES) {
setAppender(rootLogger, APPENDER_JSON);
return; return;
} }
if (IS_GCP && setAppender(ic, rootLogger, APPENDER_GCP)) { if (IS_GCP) {
setAppender(rootLogger, APPENDER_GCP);
return; return;
} }
setAppender(ic, rootLogger, APPENDER_CONSOLE); setAppender(rootLogger, APPENDER_CONSOLE);
} }
@Override @Override
public void end(InterpretationContext ic, String name) {} public void end(SaxEventInterpretationContext ic, String name) {}
private boolean setAppender(InterpretationContext ic, Logger rootLogger, String appenderName) { private void setAppender(Logger rootLogger, String appenderName) {
addInfo("Use appender: " + appenderName);
@SuppressWarnings("unchecked") Layout<ILoggingEvent> layout;
var appenderBag = (Map<String, Appender<ILoggingEvent>>) ic.getObjectMap().get(ActionConst.APPENDER_BAG); switch (appenderName) {
var appender = appenderBag.get(appenderName); case APPENDER_JSON:
if (appender == null) { layout = json();
addError("Could not find an appender named [" + appenderName break;
+ "]. Did you define it below instead of above in the configuration file?"); case APPENDER_GCP:
return false; layout = gcp();
break;
case APPENDER_CONSOLE:
layout = console();
break;
default:
addError("Appender " + appenderName + " not found. Using console ...");
layout = console();
}
layout.start();
var encoder = new LayoutWrappingEncoder<ILoggingEvent>();
encoder.setContext(context);
encoder.setLayout(layout);
encoder.start();
var appender = new ConsoleAppender<ILoggingEvent>();
appender.setContext(context);
appender.setName(appenderName);
appender.setEncoder(encoder);
appender.start();
rootLogger.addAppender(appender);
} }
addInfo("Use appender: " + appenderName); private Layout<ILoggingEvent> console() {
rootLogger.addAppender(appender); var layout = new PatternLayout();
return true; layout.setContext(context);
layout.setPattern(env(LOGBACK_PATTERN, LOGBACK_PATTERN_DEFAULT));
return layout;
}
private Layout<ILoggingEvent> json() {
var layout = new GcpJsonLayout();
layout.setContext(context);
layout.setJsonFormatter(new JacksonJsonFormatter());
layout.setAppendLineSeparator(true);
layout.setIncludeContextName(false);
layout.setServiceName(env("SERVICE_NAME", null));
layout.setServiceVersion(env("SERVICE_VERSION", null));
return layout;
}
private Layout<ILoggingEvent> gcp() {
var layout = new JsonLayout();
layout.setContext(context);
layout.setJsonFormatter(new JacksonJsonFormatter());
layout.setAppendLineSeparator(true);
layout.setIncludeContextName(false);
return layout;
}
private String env(String name, String defaultValue) {
var envValue = Optional.ofNullable(System.getenv(name)).map(String::trim).filter(String::isEmpty);
var finalValue = envValue.orElse(defaultValue);
if (envValue.isPresent()) {
addInfo("Use provided config: " + name + "=" + finalValue);
} else {
addInfo("Use default config: " + name + "=" + finalValue);
}
return finalValue;
} }
} }

View file

@ -2,8 +2,8 @@
<included> <included>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<withJansi>${CONSOLE_LOG_JANSI:-true}</withJansi> <withJansi>${CONSOLE_LOG_JANSI:-false}</withJansi>
<encoder> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<pattern>${CONSOLE_LOG_PATTERN:-%cyan(%d{HH:mm:ss.SSS}) %gray(%-6.6thread) %highlight(%-5level) %magenta(%32logger{32}) %mdc %msg%n}</pattern> <pattern>${CONSOLE_LOG_PATTERN:-%cyan(%d{HH:mm:ss.SSS}) %gray(%-6.6thread) %highlight(%-5level) %magenta(%32logger{32}) %mdc %msg%n}</pattern>
<charset>${CONSOLE_LOG_CHARSET:-default}</charset> <charset>${CONSOLE_LOG_CHARSET:-default}</charset>
</encoder> </encoder>

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<included>
<include resource="io/kokuwa/logback/appender-console.xml" />
<include resource="io/kokuwa/logback/appender-json.xml" />
<include resource="io/kokuwa/logback/appender-gcp.xml" />
</included>

View file

@ -1,8 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="false"> <configuration debug="false" scan="false">
<include resource="io/kokuwa/logback/base.xml" />
<logger name="io.micronaut.logging.PropertiesLoggingLevelsConfigurer" levels="WARN" /> <logger name="io.micronaut.logging.PropertiesLoggingLevelsConfigurer" levels="WARN" />
<root level="INFO"> <root level="INFO">

View file

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true" scan="false"> <configuration debug="true" scan="false">
<include resource="io/kokuwa/logback/base.xml" /> <include resource="io/kokuwa/logback/appender-console.xml" />
<include resource="io/kokuwa/logback/appender-json.xml" />
<include resource="io/kokuwa/logback/appender-gcp.xml" />
<logger name="io.micronaut.logging.PropertiesLoggingLevelsConfigurer" levels="WARN" /> <logger name="io.micronaut.logging.PropertiesLoggingLevelsConfigurer" levels="WARN" />