Encoder

Encoder 是什么

编码器负责将事件转换为字节数组,并将该字节数组写入OutputStream。编码器在logback版本0.9.19中引入。在以前的版本中,大多数appender依靠布局将事件转换为字符串并使用java.io.Writer将其写出来。在以前版本的logback中,用户可以在FileAppender中嵌套PatternLayout。由于logback 0.9.19,FileAppender和子类需要一个编码器而不再采用布局。

为什么突破变化?

如下一章中详细讨论的,布局只能将事件转换为字符串。此外,由于布局无法控制何时写出事件,因此布局无法将事件聚合成批处理。将此与编码器进行对比,编码器不仅可以完全控制写出的字节格式,还可以控制何时(以及是否)写出这些字节。

目前,PatternLayoutEncoder是唯一真正有用的编码器。它只包装了一个完成大部分工作的PatternLayout。因此,除了不必要的复杂性之外,编码器看起来并没有带来太大的影响。但是,我们希望随着新的强大编码器的出现,这种印象会发生变化。

编码器接口

编码器负责将传入事件转换为字节数组,并将生成的字节数组写入适当的OutputStream。

因此,编码器完全控制将字节写入由拥有的appender维护的OutputStream的内容和时间。

这是编码器接口:

public interface Encoder<E> extends ContextAware, LifeCycle {

   /**
   * This method is called when the owning appender starts or whenever output
   * needs to be directed to a new OutputStream, for instance as a result of a
   * rollover.
   */
  void init(OutputStream os) throws IOException;

  /**
   * Encode and write an event to the appropriate {@link OutputStream}.
   * Implementations are free to defer writing out of the encoded event and
   * instead write in batches.
   */
  void doEncode(E event) throws IOException;


  /**
   * This method is called prior to the closing of the underling
   * {@link OutputStream}. Implementations MUST not close the underlying
   * {@link OutputStream} which is the responsibility of the owning appender.
   */
  void close() throws IOException;
}

LayoutWrappingEncoder

在回溯版本0.9.19之前,许多appender依赖于Layout实例来控制日志输出的格式。

由于存在大量基于布局界面的代码,我们需要一种编码器与布局互操作的方法。

LayoutWrappingEncoder填补了编码器和布局之间的空白。

它实现了编码器接口并包装了一个布局,它将委托转换为字符串的工作。

下面是LayoutWrappingEncoder类的摘录,说明了如何完成对包装布局实例的委派。

public class LayoutWrappingEncoder<E> extends EncoderBase<E> {

  protected Layout<E> layout;
  private Charset charset;
 
   // encode a given event as a byte[]
   public byte[] encode(E event) {
     String txt = layout.doLayout(event);
     return convertToBytes(txt);
  }

  private byte[] convertToBytes(String s) {
    if (charset == null) {
      return s.getBytes();
    } else {
      return s.getBytes(charset);
    }
  } 
}

doEncode() 方法首先让包装的布局将传入的事件转换为字符串。根据用户选择的字符集编码将生成的文本字符串转换为字节。

PatternLayoutEncoder

鉴于PatternLayout是最常用的布局,logback适用于PatternLayoutEncoder的这种常见用例,LayoutWrappingEncoder的扩展仅限于包装PatternLayout的实例。

从logback版本0.9.19开始,只要FileAppender或其子类之一配置了PatternLayout,就必须使用PatternLayoutEncoder。这在logback错误代码的相关条目中进行了解释。

属性

  • immediateFlush

从LOGBACK 1.2.0开始,immediateFlush属性是封闭的Appender的一部分。

  • outputPatternAsHeader

输出模式字符串作为标题

为了便于解析日志文件,logback可以在日志文件的顶部插入用于日志输出的模式。

默认情况下禁用此功能。可以通过将相关PatternLayoutEncoder的outputPatternAsHeader属性设置为“true”来启用它。

这是一个例子:

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d %-5level [%thread] %logger{0}: %msg%n</pattern>
        <outputPatternAsHeader>true</outputPatternAsHeader>
    </encoder>
</appender>

日志输出如下:

#logback.classic pattern: %d %-5level [%thread] %logger{0}: %msg%n
2018-11-22 15:54:17,768 INFO  [main] AutoConfigDemo: Entering application.
2018-11-22 15:54:17,772 DEBUG [main] AutoConfigDemo: Debug info...
2018-11-22 15:54:17,772 INFO  [main] AutoConfigDemo: Exiting application.

参考资料

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