logback源码阅读-Encoder

Posted lqblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了logback源码阅读-Encoder相关的知识,希望对你有一定的参考价值。

类图

技术图片

 

 

 配置文件

 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <Encoder>
            <pattern><pattern>|%p|%d{yyyy-MM-dd HH:mm:ss.SSS}|%t|%logger{10}:%line%n   %m%n%n</pattern></pattern>
            <charset>utf-8</charset>
        </Encoder>
    </appender>

encoder主要负责输出格式和编码的处理

ch.qos.logback.core.OutputStreamAppender#subAppend

 protected void subAppend(E event) {
        if (this.isStarted()) {
            try {
                if (event instanceof DeferredProcessingAware) {
                    ((DeferredProcessingAware)event).prepareForDeferredProcessing();
                }
                //这里encode是PatternLayoutEncoder
                byte[] byteArray = this.encoder.encode(event);
                this.writeBytes(byteArray);
            } catch (IOException var3) {
                this.started = false;
                this.addStatus(new ErrorStatus("IO failure in appender", this, var3));
            }

        }
    }

LayoutWrappingEncoder

encode

ch.qos.logback.core.OutputStreamAppender#subAppend

->

ch.qos.logback.core.encoder.LayoutWrappingEncoder#encode

   public byte[] encode(E event) {
       //可以发现内部又委托给了layout
        String txt = this.layout.doLayout(event);
       //负责编码处理
        return this.convertToBytes(txt);
    }
private byte[] convertToBytes(String s) {
        return this.charset == null ? s.getBytes() : s.getBytes(this.charset);
    }

 

layout在start方法初始化

public class PatternLayoutEncoder extends PatternLayoutEncoderBase<ILoggingEvent> {
    public PatternLayoutEncoder() {
    }
    //start也实现了LifeCycle 标签解析结束就会调用start
    public void start() {
        PatternLayout patternLayout = new PatternLayout();
        patternLayout.setContext(this.context);
        patternLayout.setPattern(this.getPattern());
        patternLayout.setOutputPatternAsHeader(this.outputPatternAsHeader);
        patternLayout.start();
        this.layout = patternLayout;
        super.start();
    }
}

PatternLayout

类图

技术图片

 

 

 

doLayout

ch.qos.logback.core.OutputStreamAppender#subAppend

->

ch.qos.logback.core.encoder.LayoutWrappingEncoder#encode

->

ch.qos.logback.classic.PatternLayout#doLayout

 public String doLayout(ILoggingEvent event) {
        //判断是否开启  调用父类的格式化方法
        return !this.isStarted() ? "" : this.writeLoopOnConverters(event);
    }

ch.qos.logback.core.OutputStreamAppender#subAppend

->

ch.qos.logback.core.encoder.LayoutWrappingEncoder#encode

->

ch.qos.logback.classic.PatternLayout#doLayout

->

ch.qos.logback.core.pattern.PatternLayoutBase#writeLoopOnConverters

  protected String writeLoopOnConverters(E event) {
        StringBuilder strBuilder = new StringBuilder(256);

        /**
         * 将我们配置的输出格式表达式 进行转换处理
         *  <pattern><pattern>|%p|%d{yyyy-MM-dd HH:mm:ss.SSS}|%t|%logger{10}:%line%n   %m%n%n</pattern></pattern>
         */
        for(Converter c = this.head; c != null; c = c.getNext()) {
            c.write(strBuilder, event);
        }
        //返回最终输出的数据
        return strBuilder.toString();
    }

Converter

public abstract class Converter<E> {
    Converter<E> next;

    public Converter() {
    }

    public abstract String convert(E var1);

    public void write(StringBuilder buf, E event) {
        buf.append(this.convert(event));
    }

    public final void setNext(Converter<E> next) {
        if (this.next != null) {
            throw new IllegalStateException("Next converter has been already set");
        } else {
            this.next = next;
        }
    }

    public final Converter<E> getNext() {
        return this.next;
    }
}

映射关系在PatternLayout 的static方法

  static {
        defaultConverterMap.putAll(Parser.DEFAULT_COMPOSITE_CONVERTER_MAP);
        defaultConverterMap.put("d", DateConverter.class.getName());
        defaultConverterMap.put("date", DateConverter.class.getName());
        defaultConverterMap.put("r", RelativeTimeConverter.class.getName());
        defaultConverterMap.put("relative", RelativeTimeConverter.class.getName());
        defaultConverterMap.put("level", LevelConverter.class.getName());
        defaultConverterMap.put("le", LevelConverter.class.getName());
        defaultConverterMap.put("p", LevelConverter.class.getName());
        defaultConverterMap.put("t", ThreadConverter.class.getName());
        defaultConverterMap.put("thread", ThreadConverter.class.getName());
        defaultConverterMap.put("lo", LoggerConverter.class.getName());
        defaultConverterMap.put("logger", LoggerConverter.class.getName());
        defaultConverterMap.put("c", LoggerConverter.class.getName());
        defaultConverterMap.put("m", MessageConverter.class.getName());
        defaultConverterMap.put("msg", MessageConverter.class.getName());
        defaultConverterMap.put("message", MessageConverter.class.getName());
        defaultConverterMap.put("C", ClassOfCallerConverter.class.getName());
        defaultConverterMap.put("class", ClassOfCallerConverter.class.getName());
        defaultConverterMap.put("M", MethodOfCallerConverter.class.getName());
        defaultConverterMap.put("method", MethodOfCallerConverter.class.getName());
        defaultConverterMap.put("L", LineOfCallerConverter.class.getName());
        defaultConverterMap.put("line", LineOfCallerConverter.class.getName());
        defaultConverterMap.put("F", FileOfCallerConverter.class.getName());
        defaultConverterMap.put("file", FileOfCallerConverter.class.getName());
        defaultConverterMap.put("X", MDCConverter.class.getName());
        defaultConverterMap.put("mdc", MDCConverter.class.getName());
        defaultConverterMap.put("ex", ThrowableProxyConverter.class.getName());
        defaultConverterMap.put("exception", ThrowableProxyConverter.class.getName());
        defaultConverterMap.put("rEx", RootCauseFirstThrowableProxyConverter.class.getName());
        defaultConverterMap.put("rootException", RootCauseFirstThrowableProxyConverter.class.getName());
        defaultConverterMap.put("throwable", ThrowableProxyConverter.class.getName());
        defaultConverterMap.put("xEx", ExtendedThrowableProxyConverter.class.getName());
        defaultConverterMap.put("xException", ExtendedThrowableProxyConverter.class.getName());
        defaultConverterMap.put("xThrowable", ExtendedThrowableProxyConverter.class.getName());
        defaultConverterMap.put("nopex", NopThrowableInformationConverter.class.getName());
        defaultConverterMap.put("nopexception", NopThrowableInformationConverter.class.getName());
        defaultConverterMap.put("cn", ContextNameConverter.class.getName());
        defaultConverterMap.put("contextName", ContextNameConverter.class.getName());
        defaultConverterMap.put("caller", CallerDataConverter.class.getName());
        defaultConverterMap.put("marker", MarkerConverter.class.getName());
        defaultConverterMap.put("property", PropertyConverter.class.getName());
        defaultConverterMap.put("n", LineSeparatorConverter.class.getName());
        defaultConverterMap.put("black", BlackCompositeConverter.class.getName());
        defaultConverterMap.put("red", RedCompositeConverter.class.getName());
        defaultConverterMap.put("green", GreenCompositeConverter.class.getName());
        defaultConverterMap.put("yellow", YellowCompositeConverter.class.getName());
        defaultConverterMap.put("blue", BlueCompositeConverter.class.getName());
        defaultConverterMap.put("magenta", MagentaCompositeConverter.class.getName());
        defaultConverterMap.put("cyan", CyanCompositeConverter.class.getName());
        defaultConverterMap.put("white", WhiteCompositeConverter.class.getName());
        defaultConverterMap.put("gray", GrayCompositeConverter.class.getName());
        defaultConverterMap.put("boldRed", BoldRedCompositeConverter.class.getName());
        defaultConverterMap.put("boldGreen", BoldGreenCompositeConverter.class.getName());
        defaultConverterMap.put("boldYellow", BoldYellowCompositeConverter.class.getName());
        defaultConverterMap.put("boldBlue", BoldBlueCompositeConverter.class.getName());
        defaultConverterMap.put("boldMagenta", BoldMagentaCompositeConverter.class.getName());
        defaultConverterMap.put("boldCyan", BoldCyanCompositeConverter.class.getName());
        defaultConverterMap.put("boldWhite", BoldWhiteCompositeConverter.class.getName());
        defaultConverterMap.put("highlight", HighlightingCompositeConverter.class.getName());
        defaultConverterMap.put("lsn", LocalSequenceNumberConverter.class.getName());
    }

我们可以进行扩展自己的convert 如参考LevelConverter

public class LevelConverter extends ClassicConverter {
    public LevelConverter() {
    }

    public String convert(ILoggingEvent le) {
        return le.getLevel().toString();
    }
}

总结

1.appender输出文件是给encoder

2.encoder再委托给layout

3.如果是PatternLayout  patternLayout支持输出格式定义 输出格式定义是根据Converter来的 我们可以自定义convert 比如TraceIdConvert

以上是关于logback源码阅读-Encoder的主要内容,如果未能解决你的问题,请参考以下文章

java.lang.ClassNotFoundException:net.logstash.logback.encoder.LogstashEncoder

logback源码阅读-配置文件解析过程

logback源码阅读-Appender

用SLF4j/Logback打印日志-2

logback

logback 集成 logstash