I am using logback with slf4j and I need to change the pattern for a specific logger but keep the appenders same.
Here's my configuration:logback.xml
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %class{36}:%L - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${logFile}</file>
<append>false</append>
<!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %class{36}:%L - %msg%n</pattern>
</encoder>
</appender>
<!-- We want error logging from this logger to go to an extra appender It still inherits CONSOLE STDOUT from the root logger -->
<logger name="${log.name:-com.mycompany}" level="${log.level:-INFO}">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</logger>
<logger name="completion-logger" level="${log.level:-INFO}">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</logger>
</configuration>
I would like to use a different pattern for 'completion-logger'. Is this possible?
Key Difference Between Log4j vs LogbackAs logback is improved, version log4j and versions log4j2 and logback have no difference in terms of performance or any features. Therefore log4j is the most used logging utility before the logback newer versions were invented.
You can now use -Dlogback. debug=true to enable debugging of the logback setup. Unfortunately, there is no way to enable debugging via a System property. You have to use <configuration debug="true"> in the logback.
properties file will be defined as properties in the logback. xml file.
I have created a custom multi-layout pattern class. The custom encoder has main two parts that root layout and custom layouts by logger names. You can change the class position and update com.example.demo.MultiLayoutPattern
in logback.xml
.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="com.example.demo.MultiLayoutPattern">
<pattern>ROOT %d{HH:mm:ss.SSS} [%thread] %-5level %class{36}:%L - %msg%n</pattern>
<rule>
<logger>com.example.demo</logger>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %class{36}:%L - %msg%n</pattern>
</rule>
<rule>
<logger>com.example.demo.TestService</logger>
<pattern>SRV: %d{HH:mm:ss.SSS} [%thread] %class{36}:%L - %msg%n</pattern>
</rule>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
Source Code:
package com.example.demo;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.Layout;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MultiLayoutPattern extends PatternLayoutEncoder {
private List<Rule> rules = new ArrayList<>();
private Map<String, Layout<ILoggingEvent>> layoutMap = new HashMap<>();
public void addRule(Rule rule) {
this.rules.add(rule);
rule.start(context);
}
public byte[] encode(ILoggingEvent event) {
Layout<ILoggingEvent> layout = getLayout(event.getLoggerName());
String txt = layout.doLayout(event);
return convertToBytes(txt);
}
private byte[] convertToBytes(String s) {
Charset charset = getCharset();
if (charset == null) {
return s.getBytes();
} else {
return s.getBytes(charset);
}
}
private Layout<ILoggingEvent> getLayout(final String name) {
if (name == null) {
throw new IllegalArgumentException("name argument cannot be null");
}
// if we are asking for the root logger, then let us return it without
// wasting time
if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) {
return this.getLayout();
}
if (layoutMap.containsKey(name)) {
return layoutMap.get(name);
}
// split package and class names
String[] nameParts = name.split("[.]");
// get root layout
Layout<ILoggingEvent> layout = getLayout();
// it is used for best match rule
int bestMatch = 0;
for (Rule rule : rules) {
String[] loggerParts = rule.getLoggerParts();
int i = 0;
// match parts
while (i < loggerParts.length && i < nameParts.length && nameParts[i].equals(loggerParts[i])) {
i++;
}
if (i == loggerParts.length && i > bestMatch) {
bestMatch = i;
layout = rule.getPatternLayoutEncoder().getLayout();
}
}
// save layout with logger
layoutMap.put(name, layout);
return layout;
}
@Override
public void start() {
super.start();
}
public static class Rule {
private String logger;
private String[] loggerParts;
private String pattern;
private PatternLayoutEncoder patternLayoutEncoder;
private boolean outputPatternAsHeader = false;
public String getLogger() {
return logger;
}
public void setLogger(String logger) {
this.logger = logger;
this.loggerParts = logger.split("[.]");
}
public String[] getLoggerParts() {
return loggerParts;
}
public String getPattern() {
return pattern;
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
public boolean isOutputPatternAsHeader() {
return outputPatternAsHeader;
}
public void setOutputPatternAsHeader(boolean outputPatternAsHeader) {
this.outputPatternAsHeader = outputPatternAsHeader;
}
public PatternLayoutEncoder getPatternLayoutEncoder() {
return patternLayoutEncoder;
}
public void start(Context context) {
patternLayoutEncoder = new PatternLayoutEncoder();
patternLayoutEncoder.setPattern(pattern);
patternLayoutEncoder.setContext(context);
patternLayoutEncoder.setOutputPatternAsHeader(outputPatternAsHeader);
patternLayoutEncoder.start();
}
}
}
Output (Console)
ROOT 03:29:14.435 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext:289 - Root WebApplicationContext: initialization completed in 705 ms
SRV: 03:29:14.465 [main] com.example.demo.TestService:13 - Test service initialized
ROOT 03:29:14.541 [main] INFO o.s.s.c.ExecutorConfigurationSupport:181 - Initializing ExecutorService 'applicationTaskExecutor'
ROOT 03:29:14.642 [main] INFO org.apache.juli.logging.DirectJDKLog:173 - Starting ProtocolHandler ["http-nio-8080"]
ROOT 03:29:14.660 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer:220 - Tomcat started on port(s): 8080 (http) with context path ''
03:29:14.668 [main] INFO o.s.boot.StartupInfoLogger:61 - Started DemoApplication in 1.26 seconds (JVM running for 2.538)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With