美文网首页
Logback进阶

Logback进阶

作者: Tinyspot | 来源:发表于2022-07-15 10:17 被阅读0次

    2. Logback 源码分析

    // log.info("user:{}", "tinyspot");
    
    // slf4j
    public void info(String format, Object arg);
    
    // logback 实现:ch.qos.logback.classic.Logger#info
    public void info(String format, Object arg) {
      this.filterAndLog_1(FQCN, (Marker)null, Level.INFO, format, arg, (Throwable)null);
    }
    
    private void buildLoggingEventAndAppend(String localFQCN, Marker marker, Level level, String msg, Object[] params, Throwable t) {
      LoggingEvent le = new LoggingEvent(localFQCN, this, level, msg, t, params);
      le.setMarker(marker);
      this.callAppenders(le);
    }
    

    2.1 callAppenders(ILoggingEvent event)

    • appendLoopOnAppenders()
    • ch.qos.logback.core.Appender#doAppend
    public void callAppenders(ILoggingEvent event) {
        int writes = 0;
        for (Logger l = this; l != null; l = l.parent) {
            // Invoke all the appenders of this logger
            writes += l.appendLoopOnAppenders(event);
            if (!l.additive) {
                // 如果子logger 和 父logger 都绑定了同样的 appender, 日志会重复记录;如果不想重复记录,指定additivity="false"
                break;
            }
        }
        if (writes == 0) {
            loggerContext.noAppenderDefinedWarning(this);
        }
    }
    
    public int appendLoopOnAppenders(E e) {
        // ...
        for (int i = 0; i < len; i++) {
            appenderArray[i].doAppend(e);
            size++;
        }
    }
    

    ch.qos.logback.core.UnsynchronizedAppenderBase#doAppend

    public void prepareForDeferredProcessing() {
        // format message
        this.getFormattedMessage();
        this.getThreadName();
        this.getMDCPropertyMap();
    }
    

    6. 动态构造 logger 对象

    import ch.qos.logback.classic.Logger;
    import ch.qos.logback.classic.LoggerContext;
    import org.slf4j.LoggerFactory;
    
    @Test
    public void test() {
        // LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
        // StatusPrinter.print(context);
        getLogger("org.demo").info("this is my custom logger");
    }
    
    public static Logger getLogger(String name) {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        if (loggerContext.exists(name) == null) {
            Logger logger = loggerContext.getLogger(name);
            RollingFileAppender rollingFileAppender = new RollingFileAppender();
            rollingFileAppender.setName(name);
            rollingFileAppender.setContext(loggerContext);
    
            TimeBasedRollingPolicy rollingPolicy = new TimeBasedRollingPolicy();
            rollingPolicy.setFileNamePattern("/log/" + name + ".%d{yyyy-MM-dd}.log");
            rollingPolicy.setParent(rollingFileAppender);
            rollingPolicy.setContext(loggerContext);
            rollingPolicy.start();
    
            PatternLayoutEncoder encoder = new PatternLayoutEncoder();
            encoder.setCharset(StandardCharsets.UTF_8);
            encoder.setPattern("%m%n");
            encoder.setContext(loggerContext);
            encoder.start();
    
            rollingFileAppender.setRollingPolicy(rollingPolicy);
            rollingFileAppender.setEncoder(encoder);
            rollingFileAppender.start();
    
            logger.addAppender(rollingFileAppender);
            logger.setAdditive(false);
            logger.setLevel(Level.INFO);
            return logger;
        }
        return null;
    }
    

    8. Logback 的 MDC 解析

    • 多线程间应用
    • Mapped Diagnostic Context, 一个线程安全的存放诊断日志的容器
    • 使用 MDC 之前需要在配置文件加上 %X{REQUEST}
    • MDC, MDCAdapter, LogbackMDCAdapter
    • 用处
      • 在日志中记录用户IP, 请求URL,统计耗时等
      • 在MDC中填充 REQUEST ID 追踪单个请求的执行轨迹
      • 微服务场景下,使用 MDC埋点,做到链路跟踪,多个系统日志的拼接

    相关文章

      网友评论

          本文标题:Logback进阶

          本文链接:https://www.haomeiwen.com/subject/bntxirtx.html