既然使用Logback,应该对它多些了解(三)

1. AsyncAppender 异步记录日志

AsyncAppender仅仅是做为一个日志分发器存在,因此,它必须绑定到其它的Appender上面。
AsyncAppender会将日志缓存在一个BlockingQueue之中,然后启动一个线程从队列中取日志输出。默认情况下,缓存队列的长度是256。如果缓存占了队列的80%的时候,AsyncAppender就会丢弃trace,debug,info级别的日志。如果不想丢掉日志,可以配置AsyncAppender的discardingThreshold为0。

因为缓存的存在,在应用退出的时候,需要等待将缓存的日志写到日志文件中,否则就有可能日志丢失。可以使用下面的代码关闭日志:

        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
        context.stop();

在写入日志的时候,会有一个超时时间,默认是1000ms,如果这个时间太短,可以通过AsyncAppender的maxFlushTime配置这个超时时间。
另外也可以在logback的配置文件中添加jvm的关闭时的回调钩子:


   
 
  .... 

这样,当jvm通过命令exit退出的时候,logback会自动关闭所有的appender,关把缓存在队列中的日志输出到日志文件里面。需要注意的一点是,如果在jvm中添加多个回调钩子,它们是并行执行的,没有顺序性。如果在logback中配置了shutdownHook,有可能提前关闭了日志,其它钩子如果有日志打印就不会输出了,不可以配置logback的关闭钩子的延迟执行时间,

    
        5000
    

下面是一个异步日志的输出配置方式:


  
    myapp.log
    
      %logger{35} - %msg%n
    
  

  
    
  

  
    
  

2. 自定义Appender

通过继承AppenderBase可以自定义自己的Appender。它只需要实现一个方法:append(Object eventObject)。下面是一个例子,用来限制日志的输出数据,当日志数量达到限制之后就不再输出了:

package chapters.appenders;

import java.io.IOException;

import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;


public class CountingConsoleAppender extends AppenderBase {
  static int DEFAULT_LIMIT = 10;
  int counter = 0;
  int limit = DEFAULT_LIMIT;
  
  PatternLayoutEncoder encoder;
  
  public void setLimit(int limit) {
    this.limit = limit;
  }

  public int getLimit() {
    return limit;
  }
  
  @Override
  public void start() {
    if (this.encoder == null) {
      addError("No encoder set for the appender named ["+ name +"].");
      return;
    }
    
    try {
      encoder.init(System.out);
    } catch (IOException e) {
    }
    super.start();
  }

  public void append(ILoggingEvent event) {
    if (counter >= limit) {//达到限制了,不再输出日志
      return;
    }
    // output the events as formatted by our layout
    try {
      this.encoder.doEncode(event);
    } catch (IOException e) {
    }

    // prepare for next event
    counter++;
  }

  public PatternLayoutEncoder getEncoder() {
    return encoder;
  }

  public void setEncoder(PatternLayoutEncoder encoder) {
    this.encoder = encoder;
  }
}

在类中的成员变量,只要有getter/setter方法,就可以像配置其它Appender一样,在logback配置文件中配置。
start()方法一般用来初始化。

3. Encoder

Encoder负责将日志事件转化为byte[]并写入到OutputStream之中。因此,Encoder决定了何时写入OutputSteam,以及写入什么。
目前最常用的Encoder是PatternLayoutEncoder,它取代了以前版本的Layout。

4. 日志过滤组件-Filters

logback有两种不同类型的filters,一个是Regular filters,一个是turbo filters。最常用的是Regular Filters。

Regular Filters 有一个decide方法,它的参数是ILogingEvent,多个filter是按顺序执行的,decide方法返回一个枚举类型:DENY,NETURAL,ACCEPT。如果返回的是DENY,日志事件就会被立刻丢弃,并且不会再执行剩下的Filters,如果返回的是NETURAL,日志事件会被传到下一个filter,如果返回的是ACCEPT,日志将会被处理,并且不会再执行剩下的filters。
Filters可以配置到Appender之中,可以配置多个,你可以在filter中添加任意的条件。

4.1 自定义Filter

自定义的Filter需要继承实现Filter,如下所示:

package chapters.filters;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;

public class SampleFilter extends Filter {

  @Override
  public FilterReply decide(ILoggingEvent event) {    
    if (event.getMessage().contains("sample")) {
      return FilterReply.ACCEPT;
    } else {
      return FilterReply.NEUTRAL;
    }
  }
}

然后可以这样配置:

View as .groovy

  

    

    
      
        %-4relative [%thread] %-5level %logger - %msg%n
      
    
  
        
  
    
  

4.2 LevelFilter

LevelFitler是根据日志的级别进行判断的,配置如下:

View as .groovy

  
    
      INFO
      ACCEPT
      DENY
    
    
      
        %-4relative [%thread] %-5level %logger{30} - %msg%n
      
    
  
  
    
  

这表示,如果日志是INFO级别,就会被接收处理,如果不是,就拒绝并丢弃。

4.3 ThresholdFilter

这个Filter需要设置一个临界值,大于等于这个临界值会被接收,小于这个临界值被拒绝。

View as .groovy

  
    
    
      INFO
    
    
      
        %-4relative [%thread] %-5level %logger{30} - %msg%n
      
    
  
  
    
  

像trace,debug小于info级别的日志会被拒绝,而info,warn,error会被接收处理。
既然使用Logback,应该对它多些了解(三)_第1张图片

你可能感兴趣的:(Java游戏服务端开发)