Logback输出日志到控制台的配置方法和源码分析

1,配置方法

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder charset="UTF-8">
        <pattern>[%-5level] %date --%thread-- [%logger] %msg %n</pattern>
    </encoder>
</appender>

2,源码

当调用Logger.info()方法时,会执行ConsoleAppender类的append方法。

具体调用过程可以看这里:http://blog.youkuaiyun.com/lkforce/article/details/76637071

ConsoleAppender的append方法在他的父类OutputStreamAppender中:

  protected void append(E eventObject) {
    if (!isStarted()) {
      return;
    }

    subAppend(eventObject);
  }
然后subAppend方法:

  /**
   * Actual writing occurs here.
   * <p>
   * Most subclasses of <code>WriterAppender</code> will need to override this
   * method.
   * 
   * @since 0.9.0
   */
  protected void subAppend(E event) {
    if (!isStarted()) {
      return;
    }
    try {
      // this step avoids LBCLASSIC-139
      if (event instanceof DeferredProcessingAware) {
        ((DeferredProcessingAware) event).prepareForDeferredProcessing();
      }
      // the synchronization prevents the OutputStream from being closed while we
      // are writing. It also prevents multiple threads from entering the same
      // converter. Converters assume that they are in a synchronized block.
      lock.lock();
      try {
        writeOut(event);
      } finally {
        lock.unlock();
      }
    } catch (IOException ioe) {
      // as soon as an exception occurs, move to non-started state
      // and add a single ErrorStatus to the SM.
      this.started = false;
      addStatus(new ErrorStatus("IO failure in appender", this, ioe));
    }
  }
这里用到了一个锁:ReentrantLock,输出日志之前加锁,finally里面解锁。

writeOut方法是这样的:

  protected void writeOut(E event) throws IOException {
    this.encoder.doEncode(event);
  }
这里的encoder使用的是LayoutWrappingEncoder,是在setLayout方法里指定的:

  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;
  }
LayoutWrappingEncoder的doEncode方法:

  public void doEncode(E event) throws IOException {
    String txt = layout.doLayout(event);
    outputStream.write(convertToBytes(txt));
    if (immediateFlush)
      outputStream.flush();
  }
用输出流把日志写到磁盘上,最后如果immediateFlush是true,则立即flush。immediateFlush可以在logback的配置文件中配置,默认是true。

这样写日志的流程就结束了。


另外,这种输出日志到控制台的方式是有可能导致线程阻塞甚至死锁的,貌似在压力比较大的情况可能会出现,跟控制台还有子线程的一些设定有关,我还没有具体研究。

log死锁还是挺严重的,所有线程都会卡在Logger.info()上,然后线程爆满,内存溢出都可能会出现。

除非必要,还是不要往控制台输出日志比较好。


要使用 Logback控制台输出的所有日志存到日志文件,可参考以下方法。 ### 1. 导入相关依赖 在项目的 `pom.xml` 中添加 Logback 相关依赖: ```xml <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </dependency> ``` 此依赖配置可确保项目能正常使用 Logback 日志框架[^3]。 ### 2. 配置 logback.xml 在 `src/main/resources` 目录下创建 `logback.xml` 文件,并进行如下配置: ```xml <configuration> <!-- 控制台输出配置 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- 输出模板 --> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4relative [%thread] %-5level %logger{35} - %msg %n</pattern> </encoder> </appender> <!-- 文件输出配置 --> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <!-- 日志文件路径 --> <file>logs/application.log</file> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4relative [%thread] %-5level %logger{35} - %msg %n</pattern> </encoder> </appender> <root level="DEBUG"> <!-- 同时输出控制台文件 --> <appender-ref ref="STDOUT" /> <appender-ref ref="FILE" /> </root> </configuration> ``` 该配置文件定义了两个 `appender`,一个用于控制台输出(`STDOUT`),另一个用于文件输出(`FILE`)。`root` 元素将日志级别设为 `DEBUG`,并将日志同时输出控制台文件[^1]。 ### 3. 运行项目 配置完成后,运行项目,日志就会同时输出控制台指定的日志文件(`logs/application.log`)中。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值