探索Appenders

官网

Appender的设计思路

logback将日志事件的输出委托给的组件称为appender,appender都必须实现ch.qos.logback.core.Appender接口,Appender重要的接口方法如下:

package ch.qos.logback.core;
import ch.qos.logback.core.spi.ContextAware;
import ch.qos.logback.core.spi.FilterAttachable;
import ch.qos.logback.core.spi.LifeCycle;

public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachable {
  public String getName();
  public void setName(String name);
  void doAppend(E event);
}

Appender接口扩展了FilterAttachable接口。因此,可以将一个或多个过滤器附加到Appender实例。

Appender最终负责输出日志记录事件。但是,他们可以将事件的实际格式委托给Layout或Encoder对象。每个布局/编码器都与一个且只有一个Appender相关联。

AppenderBase

Appender的一个基础子类是AppenderBase类,如下

public synchronized void doAppend(E eventObject) {
  // prevent re-entry.
  if (guard) {
    return;
  }

  try {
    guard = true;

    if (!this.started) {
      if (statusRepeatCount++ < ALLOWED_REPEATS) {
        addStatus(new WarnStatus(
            "Attempted to append to non started appender [" + name + "].",this));
      }
      return;
    }

    if (getFilterChainDecision(eventObject) == FilterReply.DENY) {
      return;
    }
    
    // ok, we now invoke the derived class's implementation of append
    this.append(eventObject);

  } finally {
    guard = false;
  }
}

doAppend()方法要做的第一件事是检查防护措施是否设置为true。如果是,它将立即退出。如果未设置防护,则在下一条语句中将其设置为true。防护措施确保doAppend()方法不会递归调用自身。试想一下,如果append()方法内部又调用到doAppend()方法,会导致无限循环和堆栈溢出。

在下面的语句中,我们检查启动字段是否为true。如果不是,则doAppend()将发送警告消息并返回。换句话说,一旦关闭了附加器,就无法对其进行写入。 Appender对象实现LifeCycle接口,这意味着它们实现了start(),stop()和isStarted()方法。设置附加程序的所有属性后,logback的配置框架Joran调用start()方法来向附加程序发出信号以激活其属性。根据其种类,如果缺少某些属性或由于各种属性之间的干扰,追加程序可能无法启动。例如,假设文件创建依赖于截断模式,则FileAppender在确定地知道Append选项的值之前,不能对其File选项的值起作用。显式激活步骤可确保在知道属性值后,附加程序对其属性进行操作。

如果追加器无法启动或已停止,则将通过logback的内部状态管理系统发出警告消息。进行几次尝试后,为了避免内部状态系统被相同警告消息的副本淹没,doAppend()方法将停止发出这些警告。

下一个if语句检查附加过滤器的结果。根据过滤器链做出的决定,事件可以被拒绝或明确接受。如果过滤器链没有做出决定,则默认情况下会接受事件。

然后,doAppend()方法调用派生类对append()方法的实现。此方法完成了将事件附加到适当设备的实际工作。

最后,释放防护,以允许其他线程随后调用doAppend()方法。

类图

类图

ConsoleAppender

logback-Console.xml

<configuration>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

java -Dlogback.configurationFile=logback-console.xml ConsoleAppenderUse

在这里插入图片描述

FileAppender

logback-fileAppender.xml

<configuration>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>testFile.log</file>
    <append>true</append>
    <!-- set immediateFlush to false for much higher logging throughput -->
    <immediateFlush>true</immediateFlush>
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>
        
  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

测试程序

public class FileAppenderUse {
    private static final Logger logger = LoggerFactory.getLogger(ConsoleAppenderUse.class);
    //设置系统属性logback.configurationFile指定配置文件
    //java -Dlogback.configurationFile=logback-fileAppender.xml FileAppenderUse
    public static void main(String[] args) {
        logger.info("ConsoleAppenderUse");
    }
}

与时间关联的日志文件名

<configuration>

  <!-- Insert the current time formatted as "yyyyMMdd'T'HHmmss" under
       the key "bySecond" into the logger context. This value will be
       available to all subsequent configuration elements. -->
  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>

  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <!-- use the previously created timestamp to create a uniquely
         named log file -->
    <file>log-${bySecond}.txt</file>
    <encoder>
      <pattern>%logger{35} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

上面的日志中表明,解析配置文件的时候会生成一个日志文件,文件名跟解析时间息息相关。
timestamp标签还有一个可选timeReference="contextBirth"属性可以设置,表示时间值取context生成的时间,大多数场景下,这两种时间相差无几。

RollingFileAppender

在这里插入图片描述
rollingPolicy主要控制归档策略, triggeringPolicy主要控制归档时间。

RollingFileAppender必须包含一个rollingPolicy和一个triggeringPolicy
当然,如果RollingPolicy 已经实现了TriggeringPolicy接口,那么只需要rollingPolicy标签就够了。

TimeBasedRollingPolicy

看一个基于TimeBasedRollingPolicy归档策略的例子

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logFile.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- daily rollover -->
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>

      <!-- keep 30 days' worth of history capped at 3GB total size -->
      <maxHistory>30</maxHistory>
      <totalSizeCap>3GB</totalSizeCap>

    </rollingPolicy>

    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender> 

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

SizeAndTimeBasedRollingPolicy

看一个基于时间和单文件大小进行归档的例子

<configuration>
  <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>mylog.txt</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <!-- rollover daily -->
      <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
       <!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
       <maxFileSize>100MB</maxFileSize>    
       <maxHistory>60</maxHistory>
       <totalSizeCap>20GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>


  <root level="DEBUG">
    <appender-ref ref="ROLLING" />
  </root>

</configuration>

FixedWindowRollingPolicy

基于固定大小窗口的文件归档策略,只保留固定的日志文件个数。
在这里插入图片描述

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>test.log</file>

    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <fileNamePattern>tests.%i.log.zip</fileNamePattern>
      <minIndex>1</minIndex>
      <maxIndex>3</maxIndex>
    </rollingPolicy>

    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <maxFileSize>5MB</maxFileSize>
    </triggeringPolicy>
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>
        
  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值