- logback无缝衔接SLF4J(也是Ceki Gülcü的作品,日志门面)
- 项目中需要包含对
slf4j-api-*.jar的依赖 - 项目中需要包含对
logback-core.jar和logback-classic.jar的依赖 使用方法还是千篇一律的写法
package chapters.introduction;
// 这里并没有引入logback相关文件,在记录日志时也是只使用SLF4j提供的接口
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld1 {
public static void main(String[] args) {
// 这句话会根据classpath下的引用查找SLF4j的具体实现类,可参照上一篇
Logger logger = LoggerFactory.getLogger("chapters.introduction.HelloWorld1");
logger.debug("Hello world.");
}
}
由三大组件构成
- logback-core:核心组件,为其他两个提供支撑
- logback-classic:扩展Logback-core,而且是日志功能的真实实现,可理解为log4j的进阶版本
- logback-access:可结合logback-core用于http容器的日志功能,如tomcat,不常用
由三大主类构成
- Logger:在logback-classic中实现,日志记录器
- Appender :在logback-core中实现,打印到什么地方
- Layout.:在logback-core中实现,设置打印格式
Logger介绍
获取Logger
通过LoggerFactory.getLogger(A)获取Logger,如果A相同,Logger始终是同一个对象
// 那么:aLogger和bLogger引用完全相同的Logger对象。
Logger aLogger = LoggerFactory.getLogger("com.foo");
Logger bLogger = LoggerFactory.getLogger("com.foo");
日志记录等级及关系: TRACE < DEBUG < INFO < WARN < ERROR
日志记录等级有2个用处:
- 在代码逻辑中输出日志时,需要明确等级,如
logger.info("打印普通日志"),明确了等级=info - 日志全局配置中需要指定真实打印日志的等级,如
logging.level=warn,只有大于>warn的日志等级才会真实被打印,上面的info不会被打印
Logger的继承关系
为什么会存在继承关系? 比如在使用logger的时候并没有配置level,怎么办? 这时候就是根据继承关系向上查找,直到找到后生效。 如果都没有设置怎么办? 不会发生这种情况,因为根记录器提供一个默认的level,并设为debug,也就是保底的配置。 如何继承?看一个示例:
//ROOT_LOGGER_NAME固定为ROOT,是所有日志记录器的根(Root)
Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
Logger faLogger = LoggerFactory.getLogger("com.foo");
Logger chLogger = LoggerFactory.getLogger("com.foo.bar");
只要缺省了某一个配置,就会沿着继承关系逐级向上查找,直到找到为止!
- Level的继承关系:如果自身设置了level,则使用自身的生效;否则向上查找;
- Appender的继承关系:默认是累加的,即自身和父级的都会生效(这种累加会一直向上查找,直到遇到附加flag=false的为止),当然可以设置flag=false禁用累加方式,Appender比较复杂,见下表:
| Logger | 设置Appender | 附加Flag | 最终输出目标 | 备注 |
|---|---|---|---|---|
| root | A1 | 不适用 | A1 | 根日志记录器不需要设置Flag |
| x | A-x1, A-x2 | true | A1, A-x1, A-x2 | 其中A1是继承了root |
| x.y | none | true | A1, A-x1, A-x2 | 继承了root和x |
| x.y.z | A-xyz1 | true | A1, A-x1, A-x2, A-xyz1 | 继承了root、x和x.y |
| security | A-sec | false | A-sec | 不继承父级 |
| security.access | none | true | A-sec | 只继承security,因为security设置了false,所以不再继续继承祖先 |
Appender
一个Logger可以被打印到多个Appender指定的位置,如同时打印到文件或console。
Layout
用来控制打印到Appender的输出格式,比如%-4relative [%thread] %-5level %logger{32} - %msg%n输出以下格式:
176 [main] DEBUG manual.architecture.HelloWorld2 - Hello world.
推荐写法
通常,记录日志的写法如下:
logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
无论该日志是否打印,日志内容中的+都会执行解析,增加了开销,所以更推荐以下写法:
Object entry = new SomeObject();
//只有需要打印`debug`级别的日志时,才会解析日志内容,平时无开销
logger.debug("The entry is {}.", entry);