什么是布局?

如果你想知道,布局与佛罗里达州的大型庄园无关。

布局是负责将传入事件转换为String的回溯组件。

Layout接口中的format()方法接受一个表示事件(任何类型)的对象并返回一个String。

Layout界面的概要如下所示。

public interface Layout<E> extends ContextAware, LifeCycle {

  String doLayout(E event);
  String getFileHeader();
  String getPresentationHeader();
  String getFileFooter();
  String getPresentationFooter();
  String getContentType();
}

自定义布局

MyLayout

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.LayoutBase;

/**
 * @author binbin.hou
 * @date 2018/11/22
 */
public class MyLayout extends LayoutBase<ILoggingEvent> {

    public String doLayout(ILoggingEvent event) {
        StringBuffer sbuf = new StringBuffer(128);
        sbuf.append("myLayout ");
        sbuf.append(event.getTimeStamp() - event.getLoggerContextVO().getBirthTime());
        sbuf.append(" ");
        sbuf.append(event.getLevel());
        sbuf.append(" [");
        sbuf.append(event.getThreadName());
        sbuf.append("] ");
        sbuf.append(event.getLoggerName());
        sbuf.append(" - ");
        sbuf.append(event.getFormattedMessage());
        sbuf.append("\n");
        return sbuf.toString();
    }

}
  • 配置文件
<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="com.github.houbb.logback.learn.layout.custom.MyLayout" />
        </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
  • 日志输出
myLayout 293 INFO [main] com.github.houbb.logback.learn.layout.AutoConfigDemo - Entering application.
myLayout 296 DEBUG [main] com.github.houbb.logback.learn.layout.AutoConfigDemo - Debug info...
myLayout 296 INFO [main] com.github.houbb.logback.learn.layout.AutoConfigDemo - Exiting application.

PatternLayout

Logback经典船舶具有灵活的布局,称为PatternLayout。与所有布局一样,PatternLayout接受日志记录事件并返回String。但是,可以通过调整PatternLayout的转换模式来自定义此String。

PatternLayout的转换模式与C编程语言中printf()函数的转换模式密切相关。

转换模式由文字文本和称为转换说明符的格式控制表达式组成。您可以在转换模式中插入任何文字文本。

每个转换说明符都以百分号’%’开头,后跟可选的格式修饰符,转换字和大括号之间的可选参数。

转换字控制要转换的数据字段,例如,记录器名称,级别,日期或线程名称。格式修饰符控制字段宽度,填充和左对齐或右对齐。

正如已经多次提到的那样,FileAppender和子类需要一个编码器。

因此,当与FileAppender或其子类一起使用时,PatternLayout必须包含在编码器中。

鉴于FileAppender / PatternLayout组合如此常见,logback附带了一个名为PatternLayoutEncoder的编码器,该编码器仅用于包装PatternLayout实例,以便可以将其视为编码器。

下面是一个以编程方式使用PatternLayoutEncoder配置ConsoleAppender的示例:

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.ConsoleAppender;
import org.slf4j.LoggerFactory;

/**
 * @author binbin.hou
 * @date 2018/11/22
 */
public class PatternLayoutEncoderDemo {

    public static void main(String[] args) {
        Logger rootLogger = (Logger)LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
        LoggerContext loggerContext = rootLogger.getLoggerContext();
        // we are not interested in auto-configuration
        loggerContext.reset();

        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        encoder.setContext(loggerContext);
        encoder.setPattern("%-5level [%thread]: %message%n");
        encoder.start();

        ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<ILoggingEvent>();
        appender.setContext(loggerContext);
        appender.setEncoder(encoder);
        appender.start();

        rootLogger.addAppender(appender);

        rootLogger.debug("Message 1");
        rootLogger.warn("Message 2");
    }
}
  • 日志信息
DEBUG [main]: Message 1
WARN  [main]: Message 2

格式修饰符

默认情况下,相关信息按原样输出。但是,借助格式修饰符,可以更改每个数据字段的最小和最大宽度以及理由。

可选的格式修饰符位于百分号和转换字符或单词之间。

第一个可选的格式修饰符是左对齐标志,它只是减号( - )字符。然后是可选的最小字段宽度修改器。这是一个十进制常量,表示要输出的最小字符数。如果数据项包含较少的字符,则会在左侧或右侧填充,直到达到最小宽度。默认设置是在左侧填充(右对齐),但您可以使用左对齐标志指定右填充。填充字符是空格。如果数据项大于最小字段宽度,则扩展该字段以容纳数据。该值永远不会被截断。

可以使用最大字段宽度修饰符更改此行为,该修饰符由句点后跟十进制常量指定。如果数据项长于最大字段,则从数据项的开头删除多余的字符。

例如,如果最大字段宽度为8且数据项长度为十个字符,则删除数据项的前两个字符。此行为偏离C中的printf函数,其中截断是从末尾完成的。

可以通过在句点之后添加减号字符来结束截断。在这种情况下,如果最大字段宽度为8且数据项长度为10个字符,则删除数据项的最后两个字符。

转换字选项

转换说明符后面可以跟选项。总是在大括号之间声明。我们已经看到了一些选项提供的可能性,

例如与MDC转换说明符一起使用,如:%mdc {someKey}

转换说明符可能有多个选项。

例如,使用评估程序的转换说明符(将很快介绍)可以将评估程序名称添加到选项列表中,如下所示:

<pattern>%-4relative [%thread] %-5level - %msg%n \
  %caller{2, DISP_CALLER_EVAL, OTHER_EVAL_NAME, THIRD_EVAL_NAME}</pattern>

如果该选项包含特殊字符(如大括号,空格或逗号),则可以将其括在单引号或双引号之间。

例如,考虑下一个模式。

<pattern>%-5level - %replace(%msg){'\d{14,16}', 'XXXX'}%n</pattern>

我们将选项\d {16}和XXXX传递给替换转换字。

它用XXXX替换消息中包含的任何14,15或16位数字序列,有效地模糊信用卡号码。请注意“\d”是正则表达式中单个数字的简写。

“{14,16 \}”被解释为“{14,16}”,即重复前一项至少14次但最多16次。

参考资料

https://logback.qos.ch/manual/encoders.html