sp; <pattern>%-4relative [%thread] %-5level %lo{35} - %msg%n</pattern>
</encoder>
</appender>
<!-- 异步输出 -->
<appender name ="ASYNC" class= "ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>256</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref ="ROLLING-FILE-1"/>
</appender>
<logger name="java" additivity="false" />
<logger name="java.lang" level="DEBUG">
<appender-ref ref="ASYNC" />
</logger>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
即,我们引入了一个AsyncAppender,先说一下AsyncAppender的原理,再说一下几个参数:
当我们配置了AsyncAppender,系统启动时会初始化一条名为"AsyncAppender-Worker-ASYNC"的线程
当Logging Event进入AsyncAppender后,AsyncAppender会调用appender方法,appender方法中再将event填入Buffer(使用的Buffer为BlockingQueue,具体实现为ArrayBlockingQueye)前,会先判断当前Buffer的容量以及丢弃日志特性是否开启,当消费能力不如生产能力时,AsyncAppender会将超出Buffer容量的Logging Event的级别进行丢弃,作为消费速度一旦跟不上生产速度导致Buffer溢出处理的一种方式。
上面的线程的作用,就是从Buffer中取出Event,交给对应的appender进行后面的日志推送
从上面的描述我们可以看出,AsyncAppender并不处理日志,只是将日志缓冲到一个BlockingQueue里面去,并在内部创建一个工作线程从队列头部获取日志,之后将获取的日志循环记录到附加的其他appender上去,从而达到不阻塞主线程的效果。因此AsyncAppender仅仅充当的是事件转发器,必须引用另外一个appender来做事。
从上述原理,我们就能比较清晰地理解几个参数的作用了:
<encoder>
<encoder>节点负责两件事情:
目前PatternLayoutEncoder是唯一有用的且默认的encoder,有一个<pattern>节点,就像上面演示的,用来设置日志的输入格式,使用“%+转换符"的方式,如果要输出"%"则必须使用"\%"对"%"进行转义。
<encoder>的一些可用参数用表格表示一下:
看到最后一列是"是否避免使用",这是因为这些信息是无法直接拿到的(比如请求行号、调用方法名),logback必须通过一些特殊手段去获取这些数据(比如在日志打印出产生一个堆栈信息),这种操作会比较影响效率,因此除非必要,否则不建议打印这些数据。
Filter
最后来看一下<filter>,<filter>是<appender>的一个子节点,表示在当前给到的日志级别下再进行一次过滤,最基本的Filter有ch.qos.logback.classic.filter.LevelFilter和ch.qos.logback.classic.filter.ThresholdFilter,首先看一下LevelFilter:
<configuration scan="false" scanPeriod="60000" debug="false">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
&nbs