Logback is intended as a successor to the popular log4j project.
上述引用来自官网的介绍,大意是说Logback旨在替代log4j项目。他比现有的日志框架更加小巧且快速,而且还有一些独特的功能。
logback的文档十分详尽,所以本文主要参考官方的文档。
快速开始
首先我们既然要使用Logback那就要通过maven引入这个框架的jar包。(这里我们暂时只讨论1.X,2.0版本目前还是alpha版本)
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
当我们引入了logback-classic
之后我们可以通过idea的show dependencies
功能查看依赖图表,可以发现logback-core
和slf4j-api
都会被引入到项目中,因为logback-core
是logback-classic
实现的基础,我们的日志框架也是基于slf4j-api
接口实现的,所以这两个被引入也不用奇怪。
如果你看过了我的上一篇关于slf4j的介绍那么我们可以很自然知道,打印一个日志其实很简单
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloLog.class);
logger.info("Hello World");
}
只需要通过调用slf4j的getLogger
方法获取一个实例,再调用定义的info等等方法就会在控制台打印出日志,当然如果我们的项目部署在机器上肯定是不能像我们在本地调试一样打印在控制台,需要打印在日志文件中记录下来,可能还要按照一些规则进行一些分类等等。这些都跟logback日志的配置想关,我们稍后再提。
上述的例子就会在我们的控制台打出
15:27:00.070 [main] INFO com.exercise.HelloLog - Hello World
Logback可以使用内置状态系统报告有关其内部状态的信息。 可以通过StatusManager
组件来访问在回溯这期间发生的重要事件。现在让我们通过调用StatusPrinter
类的print()
方法来指示logback打印其内部状态。
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloLog.class);
logger.info("Hello World");
// print internal state
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
StatusPrinter.print(lc);
}
控制台输出:
15:29:23.586 [main] INFO com.exercise.HelloLog - Hello World
15:29:23,545 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
15:29:23,545 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
15:29:23,546 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml]
15:29:23,548 |-INFO in ch.qos.logback.classic.BasicConfigurator@51565ec2 - Setting up default configuration.
打印的信息表明,logback没有找到这些配置文件,所以调用了默认的配置,即打印在控制台里。因此,如果遇到了logback相关的问题,我们可以调用 StatusPrinter.print()
方法来输出他的内部状态信息,借助这个方法可以帮助我们解决问题。
使用logback记录的三个必要步骤:
1.配置logback环境,具体的下面讲到配置再说;
2.在每个你希望打印日志的类中,通过调用org.slf4j.LoggerFactory
类的getLogger()
方法检索Logger实例,并将当前类名称或该类本身作为参数传递。
3.通过调用其记录方法(即debug(),info(),warn()和error()方法)使用这些方法记录日志。这将在配置的附加程序上生成日志记录输出。
Logback组成
logback由三个主要类组成:Logger
, Appender
和Layout
。这三个类型的组件一起工作,能够让我们根据信息的类型和等级来记录日志,以及在运行期间控制输出的日志信息格式以及输出位置。
Logger
这部分是在logback-classic,Appender
和Layout
是在logback-core中,作为通用模块,logback-core没有logger的概念。
日志级别
TRACE <DEBUG < INFO < WARN < ERROR
第一列代表日志的打印级别,第二列代表我们设置的logger 的有效级别
看一段官方的示例:
public static void main(String[] args) {
// get a logger instance named "com.foo". Let us further assume that the
// logger is of type ch.qos.logback.classic.Logger so that we can
// set its level
ch.qos.logback.classic.Logger logger =
(ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.exercise");
//set its Level to INFO. The setLevel() method requires a logback logger
logger.setLevel(Level. INFO);
Logger barlogger = LoggerFactory.getLogger("com.exercise.LogbackUsage");
// This request is enabled, because WARN >= INFO
logger.warn("Low fuel level.");
// This request is disabled, because DEBUG < INFO.
logger.debug("Starting search for nearest gas station.");
// The logger instance barlogger, named "com.foo.Bar",
// will inherit its level from the logger named
// "com.foo" Thus, the following request is enabled
// because INFO >= INFO.
barlogger.info("Located nearest gas station.");
// This request is disabled, because DEBUG < INFO.
barlogger.debug("Exiting gas station search");
}
由上例子可知,我们能够打印日志的条件是我们调用的日志等级必须是大于或等于设置的日志等级。
通过 LoggerFactory.getLogger()
可以获取到具体的 logger 实例,名字相同则返回的 logger 实例也相同。
Logger x = LoggerFactory.getLogger("wombat");
Logger y = LoggerFactory.getLogger("wombat");
x,y 是同一个 logger 对象。
可以通过配置一个 logger,然后在其它地方获取,而不需要传递引用。父级 logger 总是优于子级 logger,并且父级 logger 会自动寻找并关联子级 logger,即使父级 logger 在子级 logger 之后实例化。
logback 环境的配置会在应用初始化的时候完成。最优的方式是通过读取配置文件。
在每个类里面通过指定全限定类名为 logger 的名字来实例化一个 logger 是最好也是最简单的方式。因为日志能够输出这个 logger 的名字,所以这个命名策略能够看出日志的来源是哪里。虽然这是命名 logger 常见的策略,但是 logback 不会严格限制 logger 的命名,你可以随意命名~
Appender 与 Layout
有选择的启用或者禁用日志的输出只是 logger 的一部分功能。logback 允许日志在多个地方进行输出。站在 logback 的角度来说,输出目标叫做 appender。appender 包括console、file、remote socket server、MySQL、PostgreSQL、Oracle 或者其它的数据库、JMS、remote UNIX Syslog daemons 中。
一个 logger 可以有多个 appender。
logger 通过 addAppender
方法来新增一个 appender。对于给定的 logger,每一个允许输出的日志都会被转发到该 logger 的所有 appender 中去。换句话说,appender 从 logger 的层级结构中去继承叠加性。例如:如果 root logger 添加了一个 console appender,所有允许输出的日志至少会在控制台打印出来。如果再给一个叫做 L 的 logger 添加了一个 file appender,那么 L 以及 L 的子级 logger 都可以在文件和控制台打印日志。可以通过设置 additivity = false 来改写默认的设置,这样 appender 将不再具有叠加性。
appender 的叠加性规则如下:
appender 的叠加性
logger L 的日志输出语句会遍历 L 和它的子级中所有的 appender。这就是所谓的 appender 叠加性(appender additivity)
如果 L 的某个上级 logger 为 P,且 P 设置了 additivity = false,那么 L 的日志会在层级在 L 到 P 之间的所有 logger 的 appender,包括 P 本身的 appender 中输出,但是不会在 P 的上级 appender 中输出。
logger 默认设置 additivity = true。