Logback指南 - 第三节:配置详解
来源:logback.qos.ch/manual/conf… 作者:Ceki Gülcü,Sébastien Pennec,Carl Harris 版权所有 © 2000-2022 QOS.ch Sarl 本文档采用 知识共享署名 - 非商业性使用 - 相同方式共享 2.5 许可协议 授权。
In symbols one observes an advantage in discovery which is greatest when they express the exact nature of a thing briefly and, as it were, picture it; then indeed the labor of thought is wonderfully diminished.
在符号中,我们观察到发现的优势,当它们简明地表达事物的确切本质并且像图片一样时,思维的工作量会大大减少。
——戈特弗里德·威廉·莱布尼茨
我们首先介绍了配置 logback 的方法,并提供了许多示例配置脚本。logback 依赖于的配置框架 Joran 将在 后面的章节 中介绍。
初始化时的配置
在应用程序代码中插入日志记录请求需要进行一定的规划和努力。观察表明,大约有四分之一的代码专门用于日志记录。因此,即使是一个中等规模的应用程序也将包含数千个嵌入在其代码中的日志记录语句。鉴于其数量,我们需要工具来管理这些日志记录语句。
Logback 可以通过编程方式或使用 XML、Groovy 或序列化模型格式的配置脚本进行配置。顺便说一下,现有的 log4j 用户可以使用我们的 PropertiesTranslator 网络应用程序将它们的 log4j.properties 文件转换为 logback.xml。
让我们首先讨论 logback 遵循的初始化步骤来尝试配置自身:
-
Logback 将使用 服务提供者加载机制 搜索任何自定义的 Configurator 提供程序。如果找到任何此类自定义提供程序,则它们优先于 logback 自己的配置器,例如
DefaultJoranConfigurator
(见下文)。自定义的
Configurator
是 ch.qos.logback.classic.spi.Configurator 接口的实现。通过查找位于 META-INF/services/ch.qos.logback.classic.spi.Configurator 下的文件资源来搜索自定义配置器。该文件的内容应指定所需Configurator
实现的完全限定类名。 -
==自 1.3.9/1.4.9 版本起== 如果在上一步中没有找到用户提供的自定义
Configurator
,logback 将实例化一个 SerializedModelConfigurator。-
如果系统属性
"logback.serializedModelFile"
已设置,则SerializedModelConfigurator
将尝试定位指定的文件。如果可以找到指定的文件,将读取并解释其配置。 -
如果未设置上述系统属性或无法找到指定的文件,则
SerializedModelConfigurator
将在类路径中搜索序列化配置模型文件 logback-test.scmo。如果可以找到此文件,将读取并解释其配置。 -
如果找不到上述文件,则
SerializedModelConfigurator
将在类路径中搜索序列化配置模型文件 logback.scmo。 -
如果找不到序列化配置模型文件,则
SerializedModelConfigurator
将返回执行状态,并要求调用下一个可用的配置器,即DefaultJoranConfigurator
。
从序列化模型文件进行的配置执行速度更快,不需要任何 XML 库。与 GraalVM 一起使用,这可能会产生启动更快、可执行文件更小的效果。
-
-
==正常步骤== 如果前面的配置器无法找到所需的资源,则将创建并调用 DefaultJoranConfigurator 的实例。
-
如果系统属性
"logback.configurationFile"
已设置,则DefaultJoranConfigurator
将尝试定位指定的文件。如果可以找到该文件,将读取并解释其配置。 -
如果上一步失败,
DefaultJoranConfigurator
将尝试在类路径中查找配置文件 "logback-test.xml"(参见 类路径上) 。如果可以找到该文件,将读取并解释其配置。 -
如果找不到此文件,它将尝试在类路径中查找配置文件 "logback.xml"(参见 类路径上)。如果可以找到该文件,将读取并解释其配置。请注意,这是 正常 的配置步骤。
-
如果找不到配置文件,则
DefaultJoranConfigurator
将返回执行状态,并要求调用下一个可用的配置器,即BasicConfigurator
。
-
-
如果上述步骤都失败,logback-classic 将使用 BasicConfigurator 进行自我配置,将日志输出定向到控制台。
最后一步是最后的努力,在没有配置文件的情况下提供默认(但非常基本的)日志记录功能。
==Groovy== 鉴于 Groovy 是一种完整的语言,我们已经放弃支持 logback.groovy,以保护无辜者。然而,Tucker Pelletier 在 virtualdogbert/logback-groovy-config 上提供了对 groovy 的支持。
如果您正在使用符合 Maven 文件夹结构的构建工具,那么如果您将 logback-test.xml 放在 src/test/resources 文件夹下,Maven 将确保它不会包含在生成的构件中。因此,在测试期间,您可以使用不同的配置文件,即 logback-test.xml,而在生产环境中使用另一个文件,即 logback.xml。
==快速启动== Joran 解析给定的 logback 配置文件大约需要 100 毫秒。为了在应用程序启动时减少这些毫秒数,您可以使用服务提供程序加载功能(上述项目 1),通过加载自己的自定义 Configurator
类,并以 BasicConfigurator 作为良好的起点。
将 XML 文件转换为 serialized model 格式是改进配置时间的一种快速便捷方法。
自动配置 logback
配置 logback 的最简单方法是让 logback 回退到其默认配置。让我们来看一下在一个名为 MyApp1
的虚构应用程序中如何实现这一点。
示例:BasicConfigurator
用法的简单示例 (logback-examples/src/main/java/chapters/configuration/MyApp1.java)
package chapters.configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyApp1 {
final static Logger logger = LoggerFactory.getLogger(MyApp1.class);
public static void main(String[] args) {
logger.info("Entering application.");
Foo foo = new Foo();
foo.doIt();
logger.info("Exiting application.");
}
}
这个类定义了一个静态的 logger 变量。然后它实例化了一个 Foo
对象。Foo
类如下:
示例:进行日志记录的小型类 (logback-examples/src/main/java/chapters/configuration/Foo.java)
package chapters.configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Foo {
static final Logger logger = LoggerFactory.getLogger(Foo.class);
public void doIt() {
logger.debug("Did it again!");
}
}
为了运行本章中的示例,您需要确保某些 jar 文件存在于类路径上。请参考 设置页 获取更多详细信息。
假设配置文件 logback-test.xml 或 logback.xml 不存在,logback 将默认调用 BasicConfigurator,它将设置一个最小配置。这个最小的配置包括一个连接到根日志记录器的 ConsoleAppender
。输出使用设置为模式 %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n
的 PatternLayoutEncoder
进行格式化。此外,默认情况下,根日志记录器被分配了 DEBUG
级别。
因此,命令 java chapters.configuration.MyApp1 的输出应类似于:
16:06:09.031 [main] INFO chapters.configuration.MyApp1 -- Entering application.
16:06:09.046 [main] DEBUG chapters.configuration.Foo -- Did it again!
16:06:09.046 [main] INFO chapters.configuration.MyApp1 -- Exiting application.
除了配置 logback 的代码(如果存在)之外,客户端代码不需要依赖 logback。使用 logback 作为其日志记录框架的应用程序将在编译时依赖于 SLF4J,而不是 logback。
MyApp1
应用程序通过调用 org.slf4j.LoggerFactory
和 org.slf4j.Logger
类与 logback 建立链接,检索它想要使用的记录器,然后继续执行。请注意,Foo
类对 logback 的唯一依赖是通过 org.slf4j.LoggerFactory
和 org.slf4j.Logger
导入。除了配置 logback 的代码(如果存在)之外,客户端代码不需要依赖 logback。由于 SLF4J 允许在其抽象层下使用任何日志记录框架,因此可以很容易地将大量代码从一个日志记录框架迁移到另一个日志记录框架。
使用 logback-test.xml 或 logback.xml 进行配置
如前所述,如果在类路径上找到文件 logback-test.xml 或 logback.xml,logback 将尝试使用它们进行配置。下面是一个等效于我们刚刚看到的 BasicConfigurator
建立的配置文件。
示例:基本配置文件(logback-examples/src/main/resources/chapters/configuration/sample0.xml)
传统格式
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
规范格式 (1.3)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.ConsoleAppender"/>
<appender name="STDOUT" class="ConsoleAppender">
<encoder class="PatternLayoutEncoder">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
将 sample0.xml 重命名为 logback.xml(或 logback-test.xml)后,将其放置在可从类路径访问的目录中。运行 MyApp1 应用程序应该会得到与之前运行相同的结果。
在警告或错误情况下自动打印状态消息
如果在解析配置文件时发生警告或错误,logback 将自动在控制台上打印其内部状态消息。
如果在解析配置文件时发生警告或错误,则 logback 将自动在控制台上打印其内部状态数据。请注意,为避免重复,如果用户显式注册了状态监听器(下面将讨论),则会禁用自动状态打印。
如果没有警告或错误,但仍希望检查 logback 的内部状态,则可以通过调用 StatusPrinter
类的 print()
来指示 logback 打印状态数据。下面的 MyApp2 应用程序与 MyApp1 相同,只是增加了两行代码来打印内部状态数据。
示例:打印 logback 的内部状态信息 (logback-examples/src/main/java/chapters/configuration/MyApp2.java)
public static void main(String[] args) {
// 假设 SLF4J 已在当前环境中绑定到 logback
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
// 打印 logback 的内部状态
StatusPrinter.print(lc);
...
}
如果一切顺利,您应该在控制台上看到以下输出
17:44:58,578 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback-test.xml]
17:44:58,671 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
17:44:58,671 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
17:44:58,687 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
17:44:58,812 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Popping appender named [STDOUT] from the object stack
17:44:58,812 |-INFO in ch.qos.logback.classic.joran.action.LevelAction - root level set to DEBUG
17:44:58,812 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[root]
17:44:58.828 [main] INFO chapters.configuration.MyApp2 -- Entering application.
17:44:58.828 [main] DEBUG chapters.configuration.Foo -- Did it again!
17:44:58.828 [main] INFO chapters.configuration.MyApp2 -- Exiting application.
在这个输出的末尾,您可以识别出在先前示例中打印的行。您还应该注意到 logback 的内部消息,也就是“Status”对象,它们允许方便地访问 logback 的内部状态。
状态数据
启用状态数据的输出通常可以在诊断 logback 问题时大有帮助。
启用状态数据的输出通常可以在诊断 logback 问题时大有帮助。请注意,错误也可能发生在配置后,例如当磁盘已满或由于权限错误无法归档日志文件时。因此,强烈建议您注册如下所述的 StatusListener
。
下面的示例说明了安装 OnConsoleStatusListener
的方法。
示例:注册状态侦听器(logback-examples/src/main/resources/chapters/configuration/onConsoleStatusListener.xml)
传统格式
<configuration>
<!-- 推荐将状态监听器放置在配置文件的顶部 -->
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
<!-- ... 配置文件的其余部分 -->
</configuration>
规范格式 (1.3)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.core.status.OnConsoleStatusListener"/>
<statusListener class="OnConsoleStatusListener"/>
</configuration>
可以使用配置文件安装 StatusListener
,假设:
- 找到了配置文件
- 配置文件是格式良好的 XML。
如果这两个条件中的任何一个不满足,Joran 无法解释配置文件,特别是元素。如果找到的配置文件格式不正确,则 logback 将检测到错误条件并自动在控制台上打印其内部状态。但是,如果找不到配置文件,则 logback 不会自动打印其状态数据,因为这不一定是错误条件。通过编程方式调用 StatusPrinter.print()
,如上面的 MyApp2 应用程序所示,可以确保在所有情况下都打印状态信息。
==强制状态输出== 在没有状态消息的情况下,跟踪流氓的 logback.xml 配置文件可能很困难,特别是在生产中,应用程序源不能很容易地修改。为了帮助识别流氓配置文件的位置,您可以通过设置“logback.statusListenerClass
”系统属性(下面讨论)来设置 StatusListener
,以强制输出状态消息。在发生错误时自动生成并自动输出的输出也可以使用“logback.statusListenerClass
”系统属性来静音。
简写
作为简写,可以在元素内将 debug 属性设置为 true
,以注册 OnConsoleStatusListener
,如下所示。
示例:使用调试模式的基本配置文件(logback-examples/src/main/resources/chapters/configuration/sample1.xml)
传统格式
<configuration debug="true">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are by default assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
规范格式 (1.3)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration debug="true">
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.ConsoleAppender"/>
<appender name="STDOUT" class="ConsoleAppender">
<encoder class="PatternLayoutEncoder">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
顺便说一下,设置 debug="true"
与先前显示的安装 OnConsoleStatusListener
是严格等价的。
"logback.statusListenerClass"
系统属性
可以通过将 Java 系统属性 "logback.statusListenerClass"
设置为要注册的监听器类的名称来注册状态监听器。例如,
java -Dlogback.statusListenerClass=ch.qos.logback.core.status.OnConsoleStatusListener...
作为简写,字符串 "ch.qos.logback.core.status.OnConsoleStatusListener"
可以替换为不区分大小写的字符串 "STDOUT"
或 "SYSOUT"
。例如:
java -Dlogback.statusListenerClass=stdout...
或等效地:
java -Dlogback.statusListenerClass=sysout...
其他 StatusListener
实现
Logback 附带了几个状态监听器实现。OnConsoleStatusListener 在控制台上(即 System.out)打印传入的状态消息。OnErrorConsoleStatusListener 在 System.err 上打印传入的状态消息。NopStatusListener 会丢弃传入的状态消息。
请注意,如果在配置期间注册任何状态侦听器,尤其是如果用户通过 "logback.statusListenerClass"
系统指定状态侦听器,则会禁用 自动状态打印(在出现错误的情况下)。因此,通过将 NopStatusListener
设置为状态侦听器,可以完全将内部状态打印静音。
java -Dlogback.statusListenerClass=ch.qos.logback.core.status.NopStatusListener...
查看状态消息
Logback 将其内部状态数据收集在一个 StatusManager 对象中,可通过 LoggerContext
访问。
给定 StatusManager
,可以访问与 logback 上下文相关联的所有状态数据。为了保持内存使用在合理水平,缺省的 StatusManager
实现将状态消息存储在两个独立的部分中:头部和尾部。头部存储前 个状态消息,而尾部存储最后 个消息。目前,,尽管这些值可能在未来版本中更改。
Logback-classic 附带了一个名为 ViewStatusMessagesServlet
的 servlet。此 servlet 将当前 LoggerContext
关联的 StatusManager
的内容打印为 HTML 表格。这是样本输出。
要将此 servlet 添加到您的 Web 应用程序中,请在其 WEB-INF/web.xml 文件中添加以下行。
<servlet>
<servlet-name>ViewStatusMessages</servlet-name>
<servlet-class>ch.qos.logback.classic.ViewStatusMessagesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ViewStatusMessages</servlet-name>
<url-pattern>/lbClassicStatus</url-pattern>
</servlet-mapping>
ViewStatusMessages
servlet 可在 URL http://host/yourWebapp/lbClassicStatus
中查看。
通过代码侦听状态消息
您还可以通过 Java 代码注册 StatusListener
。以下是 示例代码。
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
StatusManager statusManager = lc.getStatusManager();
OnConsoleStatusListener onConsoleListener = new OnConsoleStatusListener();
statusManager.add(onConsoleListener);
请注意,注册的状态侦听器仅接收其注册后的状态事件。它不会收到先前的消息。因此,通常建议在其他指令之前在配置文件的顶部放置状态侦听器注册指令。
通过系统属性设置配置文件的位置
您可以使用名为 "logback.configurationFile"
的系统属性来指定默认配置文件的位置。该属性的值可以是 URL、类路径上的资源或应用程序外部文件的路径。
java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1
注意,文件扩展名必须是 ".xml" 或 ".groovy"。其他扩展名将被忽略。明确注册状态监听器 可能有助于调试定位配置文件问题。
由于 "logback.configurationFile"
是一个 Java 系统属性,您也可以在应用程序中设置它。但是,系统属性必须在创建任何日志记录器实例之前设置。
import ch.qos.logback.classic.util.ContextInitializer;
public class ServerMain {
public static void main(String args[]) throws IOException, InterruptedException {
// 必须在第一次调用 LoggerFactory.getLogger() 之前设置
// ContextInitializer.CONFIG_FILE_PROPERTY 设置为"logback.configurationFile"
System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, "/path/to/config.xml");
...
}
}
文件修改后自动重新加载配置文件
Logback-classic 能够监视其配置文件的更改,并在配置文件更改时自动重新配置自身。
如果有指示,logback-classic 可以监视其配置文件的更改,并在配置文件更改时自动重新配置自身。为了指示 logback-classic 监视其配置文件的更改并在配置文件更改时自动重新配置自身,请将 <configuration>
元素的 scan
属性设置为 true
,如下所示。
示例:监视配置文件更改并自动重新配置(logback-examples/src/main/resources/chapters/configuration/scan1.xml)
<configuration scan="true">
...
</configuration>
默认情况下,配置文件将每隔一分钟扫描一次以进行更改。您可以通过设置 <configuration>
元素的 scanPeriod
属性来指定不同的扫描周期。值可以用毫秒、秒、分钟或小时为单位指定。以下是一个示例:
示例:指定不同的扫描周期(logback-examples/src/main/resources/chapters/configuration/scan2.xml)
<configuration scan="true" scanPeriod="30 seconds" >
...
</configuration>
==注意== 如果未指定时间单位,则假定时间单位为毫秒,这通常是不合适的。如果更改默认扫描周期,请不要忘记指定时间单位。
在幕后,当您将 scan
属性设置为 true
时,将安装一个 ReconfigureOnChangeTask。此任务将在单独的线程中运行,并检查您的配置文件是否已更改。ReconfigureOnChangeTask
还将自动监视任何 包含的 文件。
由于在编辑配置文件时很容易出错,如果配置文件的最新版本存在 XML 语法错误,它将退回到之前不包含 XML 语法错误的配置文件。
启用堆栈跟踪中的打包数据
虽然有用,但在异常频繁抛出的应用程序中计算打包数据是昂贵的。
==注意== 从 1.1.4 版本开始,默认情况下禁用打包数据。
如果被指示这么做,logback 可以在输出的每一行堆栈跟踪中包含打包数据。打包数据包括堆栈跟踪行的类的 jar 文件的名称和版本。打包数据在识别软件版本问题方面非常有用。然而,它相当昂贵,在异常频繁抛出的应用程序中特别如此。以下是一个示例输出:
14:28:48.835 [btpool0-7] INFO c.q.l.demo.prime.PrimeAction - 99 is not a valid value
java.lang.Exception: 99 is invalid
at ch.qos.logback.demo.prime.PrimeAction.execute(PrimeAction.java:28) [classes/:na]
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431) **[struts-1.2.9.jar:1.2.9]**
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236) [struts-1.2.9.jar:1.2.9]
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432) [struts-1.2.9.jar:1.2.9]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) **[servlet-api-2.5-6.1.12.jar:6.1.12]**
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:502) [jetty-6.1.12.jar:6.1.12]
at ch.qos.logback.demo.UserServletFilter.doFilter(UserServletFilter.java:44) [classes/:na]
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1115) **[jetty-6.1.12.jar:6.1.12]**
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:361) [jetty-6.1.12.jar:6.1.12]
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417) [jetty-6.1.12.jar:6.1.12]
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230) [jetty-6.1.12.jar:6.1.12]
默认情况下禁用打包数据,但可以通过配置启用:
<configuration packagingData="true">
...
</configuration>
或者,可以通过在 LoggerContext
中调用 setPackagingDataEnabled(boolean)方法来编程方式启用/禁用打包数据,如下所示:
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
lc.setPackagingDataEnabled(true);
直接调用 JoranConfigurator
Logback 依赖于一个称为 Joran 的配置库,它是 logback-core 的一部分。Logback 的默认配置机制会在类路径上找到的默认配置文件上调用 JoranConfigurator
。如果出于任何原因想覆盖 logback 的默认配置机制,则可以直接调用 JoranConfigurator
。下一个应用程序 MyApp3 在传递的参数上调用了 JoranConfigurator
的配置文件。
示例:直接调用 JoranConfigurator
(logback-examples/src/main/java/chapters/configuration/MyApp3.java)
package chapters.configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;
public class MyApp3 {
final static Logger logger = LoggerFactory.getLogger(MyApp3.class);
public static void main(String[] args) {
// assume SLF4J is bound to logback in the current environment
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
try {
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(context);
// Call context.reset() to clear any previous configuration, e.g. default
// configuration. For multi-step configuration, omit calling context.reset().
context.reset();
configurator.doConfigure(args[0]);
} catch (JoranException je) {
// StatusPrinter will handle this
}
StatusPrinter.printInCaseOfErrorsOrWarnings(context);
logger.info("Entering application.");
Foo foo = new Foo();
foo.doIt();
logger.info("Exiting application.");
}
}
该应用程序获取当前生效的 LoggerContext
,创建一个新的 JoranConfigurator
,设置它要操作的上下文,重置日志记录器上下文,最后要求配置器使用传递给应用程序的配置文件配置上下文。在发出警告或错误时打印内部状态数据。请注意,在多步配置中,应省略 context.reset()
调用。
停止 logback-classic
为了释放 logback-classic 使用的资源,停止 logback 上下文是一个好的做法。停止上下文将关闭由上下文定义的所有附加器 (appender),并以有序的方式停止任何活动线程。请还阅读下面关于 "shutdown hooks" 的部分。
import org.sflf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
...
// assume SLF4J is bound to logback-classic in the current environment
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
loggerContext.stop();
为了释放 logback-classic 使用的资源,停止 logback 上下文始终是一个好主意。停止上下文将关闭由上下文定义的日志记录器附加的所有附加器,并以有序的方式停止任何活动线程。请还阅读下面的“关闭挂钩”部分。
在 Web 应用程序中,上述代码可以在 ServletContextListener
的 contextDestroyed方法中调用,以停止 logback-classic 并释放资源。从版本 1.1.10 开始,适当的 ServletContextListener
会自动为您安装(请参见下文)。
通过关闭挂钩停止 logback-classic
安装 JVM 关闭挂钩是关闭 logback 并释放关联资源的便捷方式。
传统格式
<configuration debug="true">
<!-- in the absence of the class attribute, assume
ch.qos.logback.core.hook.DefaultShutdownHook -->
<shutdownHook/>
<!-- rest of the config file.. -->
</configuration>
规范格式 (1.3)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration debug="true">
<import class="ch.qos.logback.core.hook.DefaultShutdownHook"/>
<shutdownHook class="DefaultShutdownHook"/>
</configuration>
请注意,您可以通过将类属性设置为与您的关闭挂钩类名称相对应来安装自己制作的关闭挂钩。
默认的关闭挂钩,即 DefaultShutdownHook,将在指定延迟(默认为 0)后 停止 logback 上下文。停止上下文将允许任何在后台运行的日志文件压缩任务有最多 30 秒的时间完成。在独立的 Java 应用程序中,向配置文件添加 <shutdownHook/>
指令是确保任何正在进行的压缩任务在 JVM 退出之前有机会完成的简单方法。在 Web 服务器中的应用程序中,webShutdownHook 将自动安装,使 <shutdownHook/>
指令变得非常冗余和不必要。
WebShutdownHook 或在 Web 应用程序中停止 logback-classic
==自 1.1.10 起== Logback-classic 将 自动 要求 Web 服务器安装实现 ServletContainerInitializer
接口(servlet-api 3.x 及更高版本)的 LogbackServletContainerInitializer。此初始化程序将安装并实例化 LogbackServletContextListener。此侦听器将在停止或重新加载 Web 应用程序时停止当前的 logback-classic 上下文。
您可以通过在 Web 应用程序的 web.xml 文件中设置名为 logbackDisableServletContainerInitializer
的 <context-param>
来禁用自动安装 LogbackServletContextListener
。以下是相关片段。
<web-app>
<context-param>
<param-name>logbackDisableServletContainerInitializer</param-name>
<param-value>true</param-value>
</context-param>
....
</web-app>
请注意,logbackDisableServletContainerInitializer
变量也可以设置为 Java 系统属性或操作系统环境变量。就地设置具有优先级,即首先是 Web 应用程序,其次是系统属性,最后是操作系统环境。
配置文件语法
正如您迄今在手册中看到的大量示例仍在跟进,logback 允许您重新定义日志记录行为,而无需重新编译您的代码。事实上,您可以轻松配置 logback 以便禁用应用程序的某些部分的日志记录,将输出定向到 UNIX Syslog 守护程序、数据库、日志可视化程序,或将日志事件转发到远程 logback 服务器,该服务器将根据本地服务器策略进行记录,例如将日志事件转发到第二个 logback 服务器。
本节的其余部分介绍了配置文件的语法。
正如将一遍又一遍地演示的那样,logback 配置文件的语法非常灵活。因此,无法使用 DTD 文件或 XML 模式指定允许的语法。然而,配置文件的非常基本的结构可以描述为,包含零个或多个 <appender>
元素的 <configuration>
元素,后跟零个或多个 <logger>
元素,最多一个 <root>
元素。下图说明了这种基本结构。
如果您不确定要使用哪种情况来给定标记名称,只需遵循几乎总是正确的 驼峰命名约定。
标记名称的大小写敏感性
自 logback 版本 0.9.17 以来,涉及显式规则的标记名称是大小写不敏感的。例如,<logger>
、<Logger>
和 <LOGGER>
都是有效的配置元素,并且将以相同的方式解释。请注意,XML 格式的规则仍然适用,如果您将标记打开为 <xyz>
,您必须将其关闭为 </xyz>
,</XyZ>
将不起作用。至于 隐式规则,标记名称区分大小写,除了第一个字母。因此,<xyz>
和 <Xyz>
是等效的,但 <xYz>
不是。隐式规则通常遵循 驼峰命名约定,在 Java 世界中很常见。由于很难判断标记何时与显式操作相关联,何时与隐式操作相关联,因此很难说 XML 标记是相对于首字母是区分大小写还是不区分大小写。如果您不确定要使用给定标记名称的哪种情况,只需遵循几乎总是正确的驼峰命名约定。
配置记录器,或 <logger>
元素
目前,您应该至少对 级别继承 和 基本选择规则 有一定了解。否则,除非您是埃及学家,否则 logback 配置对您来说将毫无意义,就像象形文字一样。
可以使用 <logger>
元素配置记录器。<logger>
元素具有一个必填的名称属性,一个可选的级别属性和一个可选的 additivity
属性,接受值 true
或 false
。级别属性的值可以是不区分大小写的字符串值 TRACE
、DEBUG
、INFO
、WARN
、ERROR
、ALL
或 OFF
。特殊的不区分大小写的值 INHERITED
或其同义词 NULL
将强制记录器的级别从层次结构的更高位置继承。如果设置了记录器的级别,稍后决定它应该继承其级别,这将非常方便。
请注意,与 log4j 不同,logback-classic 在配置给定记录器时 不 关闭也不删除任何先前引用的附加器。
<logger>
元素可以包含零个或多个 <appender-ref>
元素;每个被引用的附加器都将添加到指定的记录器。请注意,与 log4j 不同,logback-classic 在配置给定记录器时 不 关闭也不删除任何先前引用的附加器。
配置根记录器,或 <root>
元素
<root>
元素配置根记录器。它支持一个名为级别的属性。它不允许任何其他属性,因为 additivity
标志不适用于根记录器。此外,由于根记录器已命名为 "ROOT"
,因此它也不允许名称属性。级别属性的值可以是不区分大小写的字符串 TRACE
、DEBUG
、INFO
、WARN
、ERROR
、ALL
或 OFF
。请注意,根记录器的级别不能设置为 INHERITED
或 NULL
。
请注意,与 log4j 不同,logback-classic 在配置根记录器时 不 关闭也不删除任何先前引用的附加器。
与 <logger>
元素类似,<root>
元素可以包含零个或多个 <appender-ref>
元素;每个被引用的附加器都将添加到根记录器。请注意,与 log4j 不同,logback-classic 在配置根记录器时 不 关闭也不删除任何先前引用的附加器。
示例
设置记录器或根记录器的级别就像声明它并设置其级别一样简单,如下一个示例所示。假设我们不再希望看到属于 "chapters.configuration"
包的任何组件生成的任何 DEBUG 消息。以下配置文件显示了如何实现该目标。
示例:设置记录器的级别(logback-examples/src/main/resources/chapters/configuration/sample2.xml)
传统格式
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n</pattern>
</encoder>
</appender>
<logger name="chapters.configuration" level="INFO"/>
<!-- 严格来说,级别属性是不必要的,因为根级别的级别默认为 DEBUG。-->
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>
规范格式 (1.3)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.ConsoleAppender"/>
<appender name="STDOUT" class="ConsoleAppender">
<encoder class="PatternLayoutEncoder">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n</pattern>
</encoder>
</appender>
<logger name="chapters.configuration" level="INFO"/>
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
将上述配置文件用作 MyApp3 应用程序的参数时,将产生以下输出:
17:34:07.578 [main] INFO chapters.configuration.MyApp3 -- Entering application.
17:34:07.578 [main] INFO chapters.configuration.MyApp3 -- Exiting application.
请注意,由 "chapters.configuration.Foo" 记录器生成的级别为 DEBUG 的消息已被抑制。另请参阅 Foo
类。
您可以配置尽可能多的记录器的级别。在下一个配置文件中,我们将 chapters.configuration 记录器的级别设置为 INFO
,同时将 chapters.configuration.Foo 记录器的级别设置为 DEBUG
。
示例:设置多个记录器的级别(logback-examples/src/main/resources/chapters/configuration/sample3.xml)
传统格式
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n
</pattern>
</encoder>
</appender>
<logger name="chapters.configuration" level="INFO" />
<logger name="chapters.configuration.Foo" level="DEBUG" />
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>