Logback
是由log4j
创始人Ceki Gülcü设计的又一个开源日志组件。根据logback
官网上的说明:
Logback is intended as a successor to the popular log4j project, picking up where log4j leaves off.
logback
旨在替代log4j
成为最通用的日志框架。相比log4j
,Ceki重写了log4j
的内核形成了logback
,这使得在一些关键执行路径上logback
的性能相比log4j
提升10倍以上。而且logback
的初始化内存加载也更小了。
总所周知slf4j
是一个标准的日志接口,而logback
则是非常标准的实现。以至于未来替换掉logback
非常容易。
这里来看看logback的几个组件。
appender
appender
是logback中定义输出位置的组件,它明确了日志输出的位置,是控制台、文件还是数据库等等。
logback
中两个最经典的实现就是ConsoleAppender
和FileAppender
了。除此之外还有很多非常实用的实现,例如:等等。
如果所有现有的实现都不能满足我们的需求也不要紧,logback作为slf4j的实现框架,为我们提供了非常好的扩展。
如果我们需要自己实现一个appender,那么我们就新写一个类,继承AppenderBase
就可以了。
public class CountingConsoleAppender extends AppenderBase<ILoggingEvent> {
public void append(ILoggingEvent event) {
// export the log to custom place
}
}
Encoder
appender
负责告诉logback把日志送到哪里去,那么怎么显示就需要接下来介绍的一些列组件了,其中Encoder
组件负责将日志事件转换成二进制流的形式传递到相应的位置上。
配置中默认使用的Encoder
类型是ch.qos.logback.classic.encoder.PatternLayoutEncoder
。
layout
Encoder
负责传递日志流,而layout
则负责将一条条日志根据我们的习惯转换成可以阅读的文字。这也是我们在配置logback
中最需要自定义的部分了。
最常见的场景就是我们使用ch.qos.logback.classic.PatternLayout
这个类了。
平时我们在配置中使用的配置pattern
标签使用的就是这个类。
<pattern>
%d{yyyy-MM-dd HH:mm:ss} |-%-5level ${PID:- } in %-50(%logger[%thread]) : %msg%n
</pattern>
配置中具体的模板转换词可以参考logback的说明(http://logback.qos.ch/manual/layouts.html#conversionWord)。
filter
在logback中,我们可以根据自己的需求定制出相对应的规则,过滤掉一些日志,减少排查时候的错误信息。完成这个过滤规则定制的组件就是filter
。
每个过滤器都会实现一个decide()
方法,这个方法会返回一个FilterReply
枚举类对象,FilterReply
中有DENY,NEUTRAL,ACCEPT三种类型:
- DENY:日志将立即被抛弃不再经过其他过滤器
- NEUTRAL:有序列表里的下个过滤器过接着处理日志
- ACCEPT:日志会被立即处理,不再经过剩余过滤器
filter
中最常用的可能就是LevelFilter
了。LevelFilter
可以帮助过滤指定的日志的等级。
举个栗子,比如我在一个APPENDER
组件中放入两个filter
:
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
这个上面这个配置中,每条日志都会被检查是不是INFO等级的日志,如果是则被接受,如果不是就被丢给下一个filter
,第二个filter
开始检查是不是ERROR等级,如果等级是日志则被打印,否则日志就被丢弃。
如果我们自己想去实现一个filter
,可以定义一个继承ch.qos.logback.classic.filter.Filter
的类。在decide()
类中去写自己的规则就可以了。
如果我们希望自己定义的filter
也能像LevelFilter
一样使用onMatch
和onMismatch
两个标签,可以选择继承ch.qos.logback.classic.filter.AbstractMatcherFilter
这个类。
Spring Boot和logback
Spring Boot
借助成熟的Spring
体系,已经在Java生态中大红大紫了,Spring Boot
也将logback
作为了自己的默认日志处理框架。
一般情况下logback
的配置文件会被取成logback.xml
,但是Spring Boot中如果需要使用SpringBoot的一些插件,那么需要将插件的配置文件文件名称设置成logback-spring.xml
,因为logback.xml
加载的时机太早了,以至于Spring还没有启动logback的配置以及完成了。
Spring Boot
主要解决的问题就是配置问题,在logback
中原先要读取配置是比较麻烦的。
而Spring Boot
提供了一个插件springProperty
:
<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
<remoteHost>${fluentHost}</remoteHost>
...
</appender>
这样配置文件会自动从application.properties
文件中读取相应的配置,并在logback
中使用这些变量。
针对Spring Boot
一个jar,四处运行 的宗旨,Spring Boot
还提供了一个springProfile
的插件:
<springProfile name="staging">
<!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>
<springProfile name="dev, staging">
<!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>
<springProfile name="!production">
<!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>
这样logback
就会根据Spring Boot
当时所处的环境,切换到对应的配置上。