我正在使用slf4j的logback,我需要更改特定记录器的模式,但保持appender相同。
这是我的配置: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>
我想为完成记录程序使用不同的模式&#39;。这可能吗?
答案 0 :(得分:5)
我创建了一个自定义的多布局模式类。自定义编码器有两个主要部分,即根布局和按记录器名称自定义布局。您可以更改班级位置并更新 com.example.demo.MultiLayoutPattern
中的 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>
源代码:
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();
}
}
}
输出(控制台)
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)