• 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();
                    }
                    //<1>这里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

    <1>encode

    ch.qos.logback.core.OutputStreamAppender#subAppend

    ->

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

       public byte[] encode(E event) {
           //<2>可以发现内部又委托给了layout 初始化处:<4>
            String txt = this.layout.doLayout(event);
           //<3>负责编码处理
            return this.convertToBytes(txt);
        }

    <3>

    private byte[] convertToBytes(String s) {
            return this.charset == null ? s.getBytes() : s.getBytes(this.charset);
        }

    <4>

    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

    类图

    <2>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) {
            //<5>判断是否开启  调用父类的格式化方法
            return !this.isStarted() ? "" : this.writeLoopOnConverters(event);
        }

    <5>

    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

  • 相关阅读:
    java_day20_Servlet
    前端_day08_定位
    前端_day07_浮动和清除浮动
    前端_day06_CSS选择器
    前端_day05_HTML常见标签
    数据库_day06_多表查询,子查询,事务,sql注入
    java_day19_MVC和配置文件
    chrome更新flash player失败
    jar打包命令使用
    win7开启远程桌面服务
  • 原文地址:https://www.cnblogs.com/LQBlog/p/12164918.html
Copyright © 2020-2023  润新知