文章目录
一、前言
上一篇文章介绍过, 在OutputStreamAppender
中可以注入Encoder
和layout
, Layout 主要用于格式化日志文本(如 PatternLayout),适用于 控制台日志输出。Encoder 负责将日志编码(通常是字符或二进制),适用于 文件、远程日志 等场景。
下面是OutputStreamAppender
对Encoder
和layout
的注入方法
public void setEncoder(Encoder<E> encoder) {
this.encoder = encoder;
}
public void setLayout(Layout<E> layout) {
addWarn("This appender no longer admits a layout as a sub-component, set an encoder instead.");
addWarn("To ensure compatibility, wrapping your layout in LayoutWrappingEncoder.");
addWarn("See also " + CODES_URL + "#layoutInsteadOfEncoder for details");
LayoutWrappingEncoder<E> lwe = new LayoutWrappingEncoder<E>();
lwe.setLayout(layout);
lwe.setContext(context);
this.encoder = lwe;
}
可以看出设置的layout实际也是被包装到endoer中了(LayoutWrappingEncoder), 整体看也就是只需一个encoder
就行了
二、源码解读
Layout
public interface Layout<E> extends ContextAware, LifeCycle {
/**
* 将事件转为字符串, 这个事件一般是日志对象
*/
String doLayout(E event);
/**
* 获取文件头部内容, 可以为空
*/
String getFileHeader();
/**
* 返回日志事件格式化的头部内容, 可以为空
*/
String getPresentationHeader();
/**
* 返回日志事件格式化的尾部内容, 可以为空
*/
String getPresentationFooter();
/**
* 返回文件的尾部内容, 可以为空
*/
String getFileFooter();
/**
* 获取日志内容类型
*/
String getContentType();
}
LayoutBase
abstract public class LayoutBase<E> extends ContextAwareBase implements Layout<E> {
protected boolean started;
String fileHeader;
String fileFooter;
String presentationHeader;
String presentationFooter;
public String getContentType() {
return "text/plain";
}
// ... 省略部分代码
}
这个类比较简单, 定义了头部、尾部、格式化头部、格式化头部以及生命周期的start字段, 默认日志内容是文本格式
PatternLayoutBase
abstract public class PatternLayoutBase<E> extends LayoutBase<E> {
/**
* 日志格式转换器链
*/
Converter<E> head;
/**
* 日志格式
*/
String pattern;
/** 获取默认的转换器 */
protected abstract Map<String, Supplier<DynamicConverter>> getDefaultConverterSupplierMap();
/**
* 获取有效的转换器
*/
public Map<String, Supplier<DynamicConverter>> getEffectiveConverterMap