来源: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](#serialized model "#serializeModel") 格式是改进配置时间的一种快速便捷方法。
自动配置 logback
配置 logback 的最简单方法是让 logback 回退到其默认配置。让我们来看一下在一个名为 MyApp1
的虚构应用程序中如何实现这一点。
示例:BasicConfigurator
用法的简单示例 (logback-examples/src/main/java/chapters/configuration/MyApp1.java)
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)
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 的输出应类似于:
accesslog
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)
传统格式
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
<?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)
java
public static void main(String[] args) {
// 假设 SLF4J 已在当前环境中绑定到 logback
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
// 打印 logback 的内部状态
StatusPrinter.print(lc);
...
}
如果一切顺利,您应该在控制台上看到以下输出
accesslog
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)
传统格式
xml
<configuration>
<!-- 推荐将状态监听器放置在配置文件的顶部 -->
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
<!-- ... 配置文件的其余部分 -->
</configuration>
规范格式 (1.3)
xml
<?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)
传统格式
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
<?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"
设置为要注册的监听器类的名称来注册状态监听器。例如,
bash
java -Dlogback.statusListenerClass=ch.qos.logback.core.status.OnConsoleStatusListener...
作为简写,字符串 "ch.qos.logback.core.status.OnConsoleStatusListener"
可以替换为不区分大小写的字符串 "STDOUT"
或 "SYSOUT"
。例如:
bash
java -Dlogback.statusListenerClass=stdout...
或等效地:
bash
java -Dlogback.statusListenerClass=sysout...
其他 StatusListener
实现
Logback 附带了几个状态监听器实现。OnConsoleStatusListener 在控制台上(即 System.out)打印传入的状态消息。OnErrorConsoleStatusListener 在 System.err 上打印传入的状态消息。NopStatusListener 会丢弃传入的状态消息。
请注意,如果在配置期间注册任何状态侦听器,尤其是如果用户通过 "logback.statusListenerClass"
系统指定状态侦听器,则会禁用 自动状态打印(在出现错误的情况下)。因此,通过将 NopStatusListener
设置为状态侦听器,可以完全将内部状态打印静音。
bash
java -Dlogback.statusListenerClass=ch.qos.logback.core.status.NopStatusListener...
查看状态消息
Logback 将其内部状态数据收集在一个 StatusManager
对象中,可通过 LoggerContext
访问。
给定 StatusManager
,可以访问与 logback 上下文相关联的所有状态数据。为了保持内存使用在合理水平,缺省的 StatusManager
实现将状态消息存储在两个独立的部分中:头部和尾部。头部存储前 <math xmlns="http://www.w3.org/1998/Math/MathML"> H H </math>H 个状态消息,而尾部存储最后 <math xmlns="http://www.w3.org/1998/Math/MathML"> T T </math>T 个消息。目前, <math xmlns="http://www.w3.org/1998/Math/MathML"> H = T = 150 H=T=150 </math>H=T=150,尽管这些值可能在未来版本中更改。
Logback-classic 附带了一个名为 ViewStatusMessagesServlet
的 servlet。此 servlet 将当前 LoggerContext
关联的 StatusManager
的内容打印为 HTML 表格。这是样本输出。
要将此 servlet 添加到您的 Web 应用程序中,请在其 WEB-INF/web.xml 文件中添加以下行。
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
。以下是 示例代码。
java
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
StatusManager statusManager = lc.getStatusManager();
OnConsoleStatusListener onConsoleListener = new OnConsoleStatusListener();
statusManager.add(onConsoleListener);
请注意,注册的状态侦听器仅接收其注册后的状态事件。它不会收到先前的消息。因此,通常建议在其他指令之前在配置文件的顶部放置状态侦听器注册指令。
通过系统属性设置配置文件的位置
您可以使用名为 "logback.configurationFile"
的系统属性来指定默认配置文件的位置。该属性的值可以是 URL、类路径上的资源或应用程序外部文件的路径。
bash
java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1
注意,文件扩展名必须是 ".xml" 或 ".groovy"。其他扩展名将被忽略。明确注册状态监听器 可能有助于调试定位配置文件问题。
由于 "logback.configurationFile"
是一个 Java 系统属性,您也可以在应用程序中设置它。但是,系统属性必须在创建任何日志记录器实例之前设置。
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)
xml
<configuration scan="true">
...
</configuration>
默认情况下,配置文件将每隔一分钟扫描一次以进行更改。您可以通过设置 <configuration>
元素的 scanPeriod
属性来指定不同的扫描周期。值可以用毫秒、秒、分钟或小时为单位指定。以下是一个示例:
示例:指定不同的扫描周期(logback-examples/src/main/resources/chapters/configuration/scan2.xml)
xml
<configuration scan="true" scanPeriod="30 seconds" >
...
</configuration>
==注意== 如果未指定时间单位,则假定时间单位为毫秒,这通常是不合适的。如果更改默认扫描周期,请不要忘记指定时间单位。
在幕后,当您将 scan
属性设置为 true
时,将安装一个 ReconfigureOnChangeTask
。此任务将在单独的线程中运行,并检查您的配置文件是否已更改。ReconfigureOnChangeTask
还将自动监视任何 包含的 文件。
由于在编辑配置文件时很容易出错,如果配置文件的最新版本存在 XML 语法错误,它将退回到之前不包含 XML 语法错误的配置文件。
启用堆栈跟踪中的打包数据
虽然有用,但在异常频繁抛出的应用程序中计算打包数据是昂贵的。
==注意== 从 1.1.4 版本开始,默认情况下禁用打包数据。
如果被指示这么做,logback 可以在输出的每一行堆栈跟踪中包含打包数据。打包数据包括堆栈跟踪行的类的 jar 文件的名称和版本。打包数据在识别软件版本问题方面非常有用。然而,它相当昂贵,在异常频繁抛出的应用程序中特别如此。以下是一个示例输出:
java
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]
默认情况下禁用打包数据,但可以通过配置启用:
xml
<configuration packagingData="true">
...
</configuration>
或者,可以通过在 LoggerContext
中调用 setPackagingDataEnabled(boolean)
方法来编程方式启用/禁用打包数据,如下所示:
java
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)
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" 的部分。
java
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 并释放关联资源的便捷方式。
传统格式
xml
<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
<?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
。以下是相关片段。
xml
<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)
传统格式
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
<?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 应用程序的参数时,将产生以下输出:
accesslog
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)
传统格式
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>
规范格式 (1.3)
xml
<?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"/>
<logger name="chapters.configuration.Foo" level="DEBUG"/>
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
使用此配置文件运行 MyApp3
将在控制台上产生以下输出:
accesslog
17:39:27.593 [main] INFO chapters.configuration.MyApp3 -- Entering application.
17:39:27.593 [main] DEBUG chapters.configuration.Foo -- Did it again!
17:39:27.593 [main] INFO chapters.configuration.MyApp3 -- Exiting application.
在使用 JoranConfigurator
通过 sample3.xml 配置文件配置 logback 后,下表列出了日志记录器及其级别。
日志记录器名称 | 分配的级别 | 生效的级别 |
---|---|---|
root | DEBUG |
DEBUG |
chapters.configuration | INFO |
INFO |
chapters.configuration.MyApp3 | null |
INFO |
chapters.configuration.Foo | DEBUG |
DEBUG |
由此可见,MyApp3
类中两个级别为 INFO
的日志语句以及 Foo.doIt()
中的 DEBUG
消息都是启用的。需要注意的是,根日志记录器的级别始终设置为非空值,默认为 DEBUG
。
请注意,基本选择规则 取决于调用的日志记录器的生效级别,而不是附加器所附加的日志记录器的级别。Logback 首先确定日志语句是否启用,如果启用,则调用日志记录器层次结构中找到的附加器,而不考虑它们的级别。sample4.xml 配置文件是一个典型例子:
传统格式
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" />
<!-- 关闭所有日志记录(子记录器可以覆盖) -->
<root level="OFF">
<appender-ref ref="STDOUT" />
</root>
</configuration>
规范格式 (1.3)
xml
<?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="OFF">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
下表列出了应用 sample4.xml 配置文件后的日志记录器及其级别。
日志记录器名称 | 分配的级别 | 生效的级别 |
---|---|---|
root | OFF |
OFF |
chapters.configuration | INFO |
INFO |
chapters.configuration.MyApp3 | null |
INFO |
chapters.configuration.Foo | null |
INFO |
STDOUT 是 sample4.xml 中唯一配置的附加器,它附加在级别为 OFF
的根日志记录器上。然而,使用配置脚本 sample4.xml 运行 MyApp3 将产生以下结果:
accesslog
17:52:23.609 [main] INFO chapters.configuration.MyApp3 - Entering application.
17:52:23.609 [main] INFO chapters.configuration.MyApp3 - Exiting application.
因此,根日志记录器的级别似乎没有影响,因为 chapters.configuration.MyApp3
和 chapters.configuration.Foo
类中的日志记录器都启用了 INFO
级别。值得一提的是,chapters.configuration 日志记录器存在是由于配置文件中的声明,即使 Java 源代码没有直接引用它。
配置附加器
使用 <appender>
元素配置附加器,它包含两个必需的属性:name
和 class
。name
属性指定附加器的名称,而 class
属性指定要实例化的附加器类的完全限定名称。<appender>
元素可以包含零个或一个 <layout>
元素,零个或多个 <encoder>
元素和零个或多个 <filter>
元素。除了这三个常见元素之外,<appender>
元素还可以包含与附加器类的 JavaBean 属性对应的任意数量的元素。无缝支持给定 logback 组件的任何属性是 Joran 的主要优势之一,后面的章节将详细讨论。下图说明了常见结构,注意图中未显示属性的支持。
<layout>
元素使用一个必需的 class
属性,指定要实例化的布局类的完全限定名称。与 <appender>
元素一样,<layout>
可以包含其他元素,对应于布局实例的属性。由于这是一个常见情况,如果布局类是 PatternLayout
,则可以省略 class
属性,根据 默认类映射 规则指定。
<encoder>
元素使用一个必需的 class
属性,指定要实例化的编码器类的完全限定名称。由于这是一个常见情况,如果编码器类是 PatternLayoutEncoder
,则可以省略 class
属性,根据 默认类映射 规则指定。
配置多个附加器非常简单,只需定义各种附加器并在日志记录器中引用它们,如下一个配置文件所示:
示例:多个日志记录器 (logback-examples/src/main/resources/chapters/configuration/multiple.xml)
传统格式
xml
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>myApp.log</file>
<encoder>
<pattern>%date %level [%thread] %logger{10} [%file:%line] -%kvp- %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
规范格式 (1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.FileAppender"/>
<import class="ch.qos.logback.core.ConsoleAppender"/>
<appender name="FILE" class="FileAppender">
<file>myApp.log</file>
<encoder class="PatternLayoutEncoder">
<pattern>%date %level [%thread] %logger{10} [%file:%line] -%kvp- %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ConsoleAppender">
<encoder class="PatternLayoutEncoder">
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE"/>
<appender-ref ref="STDOUT"/>
</root>
</configuration>
这些配置脚本定义了两个名为 FILE 和 STDOUT 的附加器。FILE 附加器将日志记录到名为 myApp.log 的文件中。该附加器的编码器是一个 PatternLayoutEncoder
,它输出日志请求所在的日期、级别、线程名称、记录器名称、文件名和行号,以及消息和换行符字符。第二个名为 STDOUT
的附加器将日志输出到控制台。该附加器的编码器只输出消息字符串,后面跟着一个换行符。
这些附加器通过在 appender-ref 元素内引用它们的名称来附加到根记录器上。注意每个附加器都有自己的编码器。编码器通常不设计为被多个附加器共享。布局也是如此。因此,logback 配置文件不提供任何语法手段来共享编码器或布局。
附加器默认是累积的:一个记录器会将日志记录到附加到自身的附加器(如果有的话),以及附加到其祖先的所有附加器中。因此,将相同的附加器附加到多个记录器上将导致日志输出重复。
示例:重复的附加器(logback-examples/src/main/resources/chapters/configuration/duplicate.xml)
传统格式
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">
<appender-ref ref="STDOUT" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
规范格式 (1.3)
xml
<?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">
<appender-ref ref="STDOUT"/>
</logger>
<root level="debug">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
使用 duplicate.xml 运行 MyApp3
将产生以下输出:
accesslog
14:25:36.343 [main] INFO chapters.configuration.MyApp3 -- 进入应用程序。
14:25:36.343 [main] INFO chapters.configuration.MyApp3 -- 进入应用程序。
14:25:36.359 [main] DEBUG chapters.configuration.Foo -- 又来了一次!
14:25:36.359 [main] DEBUG chapters.configuration.Foo -- 又来了一次!
14:25:36.359 [main] INFO chapters.configuration.MyApp3 -- 退出应用程序。
14:25:36.359 [main] INFO chapters.configuration.MyApp3 -- 退出应用程序。
请注意重复的输出。名为 STDOUT 的附加器附加到两个记录器,根记录器和 chapters.configuration 。由于根记录器是所有记录器的祖先,而 chapters.configuration 是 chapters.configuration.MyApp3 和 chapters.configuration.Foo 的父级,使用这两个记录器进行的每个日志请求将输出两次,一次是因为 STDOUT 附加到 chapters.configuration ,一次是因为它附加到 root。
附加器的可累积性并不意味着对新用户有难度。它是 logback 的一个非常方便的功能。例如,您可以配置日志,使日志消息显示在控制台上(对于系统中的所有记录器),而仅将来自某个特定记录器集合的消息流入特定的附加器中。
示例:多个附加器(logback-examples/src/main/resources/chapters/configuration/restricted.xml)
传统格式
xml
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>myApp.log</file>
<encoder>
<pattern>%date %level [%thread] %logger{10} [%file:%line] -%kvp- %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<logger name="chapters.configuration">
<appender-ref ref="FILE" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
规范格式 (1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.FileAppender"/>
<import class="ch.qos.logback.core.ConsoleAppender"/>
<appender name="FILE" class="FileAppender">
<file>myApp.log</file>
<encoder class="PatternLayoutEncoder">
<pattern>%date %level [%thread] %logger{10} [%file:%line] -%kvp- %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ConsoleAppender">
<encoder class="PatternLayoutEncoder">
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<logger name="chapters.configuration">
<appender-ref ref="FILE"/>
</logger>
<root level="debug">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
在这个例子中,控制台附加器将记录所有消息(对于系统中的所有记录器),而仅有来自 chapters.configuration 记录器及其子记录器的日志请求将流入 myApp.log 文件中。
覆盖默认的累积行为
如果默认的累积行为不适合您的需求,您可以通过将 additivity
标志设置为 false
来覆盖它。因此,您的记录器树中的一个分支可以将输出定向到与其余部分的附加器不同的一组附加器中。
示例:additivity
标志(logback-examples/src/main/resources/chapters/configuration/additivityFlag.xml)
传统格式
xml
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>foo.log</file>
<encoder>
<pattern>%date %level [%thread] %logger{10} [%file : %line] -%kvp- %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<logger name="chapters.configuration.Foo" additivity="false">
<appender-ref ref="FILE" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
规范格式 (1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.FileAppender"/>
<import class="ch.qos.logback.core.ConsoleAppender"/>
<appender name="FILE" class="FileAppender">
<file>foo.log</file>
<encoder class="PatternLayoutEncoder">
<pattern>%date %level [%thread] %logger{10} [%file : %line] -%kvp- %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ConsoleAppender">
<encoder class="PatternLayoutEncoder">
<pattern>%msg%n</pattern>
</encoder>
</appender>
<logger name="chapters.configuration.Foo" additivity="false">
<appender-ref ref="FILE"/>
</logger>
<root level="debug">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
该示例中,名为 "FILE"
的附加程序被附加到名为 "chapters.configuration.Foo"
的记录器。此外,"chapters.configuration.Foo"
记录器的 additivity
标志设置为 false
,因此其日志输出将被发送到名为 "FILE"
的附加程序,而不会发送到更高层次的任何附加程序。其他记录器对于 "chapters.configuration.Foo"
记录器的 additivity
设置毫不知情。使用 "additivityFlag.xml"
配置文件运行 "MyApp3" 应用程序将在控制台上输出来自 "chapters.configuration.MyApp3"
记录器的结果。然而,"chapters.configuration.Foo"
记录器的输出将只出现在 "foo.log"
文件中,而且只有在该文件中。
设置上下文名称
如前文所述,在每个记录器都附加了一个记录器上下文。默认情况下,记录器上下文称为 "default"
。但是,您可以使用 <contextName>
配置指令设置不同的名称。请注意,一旦设置,记录器上下文名称 不能更改。设置上下文名称是一种简单直接的方法,用于区分多个记录到相同目标的应用程序。
示例:设置上下文名称并显示它(logback-examples/src/main/resources/chapters/configuration/contextName.xml)
传统格式
xml
<configuration>
<contextName>myAppName</contextName>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %contextName [%t] %level %logger{36} -%kvp- %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
规范格式 (1.3)
xml
<?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"/>
<contextName>myAppName</contextName>
<appender name="STDOUT" class="ConsoleAppender">
<encoder class="PatternLayoutEncoder">
<pattern>%d %contextName [%t] %level %logger{36} -%kvp- %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
最后一个示例说明了记录器上下文的命名。在布局的模式中添加 contextName 转换词 将输出该名称。
变量替换
注意 本文档的早期版本使用术语 "property substitution" 来代替 "variable" 一词。请将这两个术语视为可互换的,尽管后者传达了更清晰的含义。
与许多脚本语言一样,logback 配置文件支持定义和替换变量。变量具有 作用域(见下文)。此外,变量可以在配置文件本身中定义,也可以从外部文件、外部资源中加载,甚至可以计算并且 动态定义。
变量替换可以发生在配置文件中可以指定值的任何位置。
变量替换可以发生在配置文件中可以指定值的任何位置。变量替换的语法类似于 Unix shell 的语法。在开头的 ${
和结尾的 }
之间的字符串被解释为对属性的 value
的引用。对于属性 aName
,字符串 "${aName}"
将被替换为 aName
属性持有的值。
由于它们经常非常有用,HOSTNAME
和 CONTEXT_NAME
变量以及上下文范围是自动定义的。鉴于在某些环境中计算主机名可能需要一些时间,其值是懒惰计算的(仅在需要时) 。此外,HOSTNAME
可以从 配置直接 设置。
定义变量
变量可以逐个在配置文件本身中定义,也可以批量从外部属性文件或外部资源加载。出于历史原因,用于定义变量的 XML 元素是 <property>
,尽管在 logback 1.0.7 及更高版本中也可以使用元素 <variable>
互换使用。
下一个示例显示了在配置文件开头声明的一个变量。然后在文件的后面使用它来指定输出文件的位置。
示例:简单的变量替换(logback-examples/src/main/resources/chapters/configuration/variableSubstitution1.xml)
传统格式
xml
<configuration>
<variable name="USER_HOME" value="/home/sebastien" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder>
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
规范格式 (1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.FileAppender"/>
<variable name="USER_HOME" value="/home/sebastien"/>
<appender name="FILE" class="FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder class="PatternLayoutEncoder">
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE"/>
</root>
</configuration>
下面的示例展示了使用系统属性来实现相同结果的方法。该属性未在配置文件中声明,因此 logback 将在系统属性中查找它。Java 系统属性可以通过以下命令行设置:
bash
java -DUSER_HOME="/home/sebastien" MyApp2
示例:使用系统变量替换(logback-examples/src/main/resources/chapters/configuration/variableSubstitution2.xml)
传统格式
xml
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder>
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
规范格式(1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.FileAppender"/>
<appender name="FILE" class="FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder class="PatternLayoutEncoder">
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE"/>
</root>
</configuration>
当需要多个变量时,创建一个包含所有变量的单独文件可能更方便。下面是如何进行此类设置的方法。
示例:使用单独文件进行变量替换(logback-examples/src/main/resources/chapters/configuration/variableSubstitution3.xml)
传统格式
xml
<configuration>
<variable file="src/main/java/chapters/configuration/variables1.properties" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder>
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
规范格式(1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.FileAppender"/>
<variable file="src/main/java/chapters/configuration/variables1.properties"/>
<appender name="FILE" class="FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder class="PatternLayoutEncoder">
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE"/>
</root>
</configuration>
该配置文件包含对名为 variables1.properties 的文件的引用。该文件中包含的变量将被读取,然后在本地范围内进行定义。下面是 variable.properties 文件的示例。
示例:变量文件(logback-examples/src/main/resources/chapters/configuration/variables1.properties)
properties
USER_HOME=/home/sebastien
您还可以引用类路径上的资源,而不是文件。
传统格式
xml
<configuration>
<variable resource="resource1.properties" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder>
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
规范格式(1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.FileAppender"/>
<variable resource="resource1.properties"/>
<appender name="FILE" class="FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder class="PatternLayoutEncoder">
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE"/>
</root>
</configuration>
作用域
一个属性可以被定义为插入到 局部作用域 、上下文作用域 或 系统作用域。局部作用域是默认的。尽管可以从操作系统环境中读取变量,但无法写入操作系统环境。
==局部作用域== 局部作用域中的属性存在于配置文件中定义的时候直到解析和执行该配置文件结束。由此推论,每次解析和执行配置文件时,局部作用域中的变量都会重新定义。
==上下文作用域== 具有上下文作用域的属性被插入到上下文中,并在上下文中持续存在,直到上下文被清除或属性被清除为止。一旦定义,上下文作用域中的属性就成为上下文的一部分。因此,它在所有日志事件中都可用,包括通过序列化发送到远程主机的事件。
==系统作用域== 具有系统作用域的属性被插入到 JVM 系统属性中,并在 JVM 中持续存在,直到 JVM 或属性被清除。
首先在局部作用域中查找属性,其次在上下文作用域中查找属性,第三在系统属性作用域中查找属性,在 OS 环境中最后查找。
在替换期间,首先在局部作用域中查找属性,其次在上下文作用域中查找属性,第三在系统属性作用域中查找属性,在 OS 环境中最后查找。
<property>
元素、<define>
元素或 <insertFromJNDI>
元素的 scope
属性可用于设置属性的作用域。scope
属性接受 "local"、"context" 和 "system" 字符串作为可能的值。如果没有指定,作用域始终被假定为 "local"。
例子:在 "context" 作用域中定义的变量(logback-examples/src/main/resources/chapters/configuration/contextScopedVariable.xml)
传统格式
xml
<configuration>
<variable scope="context" name="nodeId" value="firstNode" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/opt/${nodeId}/myApp.log</file>
<encoder>
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
规范格式 (1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.FileAppender"/>
<variable name="nodeId" value="firstNode" scope="context"/>
<appender name="FILE" class="FileAppender">
<file>/opt/${nodeId}/myApp.log</file>
<encoder class="PatternLayoutEncoder">
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE"/>
</root>
</configuration>
在上面的例子中,由于 nodeId
属性在上下文范围内定义,它将在每个日志事件中可用,即使是通过序列化发送到远程主机的事件也是如此。
变量的默认值
在某些情况下,如果变量未被声明或其值为空,变量具有默认值可能是有益的。与 Bash shell 类似,可以使用 ":-
" 运算符指定默认值。例如,假设名为 aName
的变量未定义,则 "${aName:-golden}"
将被解释为 "golden"。
嵌套变量
变量嵌套是完全支持的。变量的名称、默认值和值定义都可以引用其他变量。
值的嵌套
变量的值定义可以包含对其他变量的引用。假设您希望使用变量来指定目标目录以及文件名,并将这两个变量组合在名为 "destination"
的第三个变量中。下面的属性文件给出了一个例子。
例子:嵌套变量引用(logback-examples/src/main/resources/chapters/configuration/variables2.properties)
properties
USER_HOME=/home/sebastien
fileName=myApp.log
destination=${USER_HOME}/${fileName}
请注意,在上面的属性文件中,"destination
" 由另外两个变量 "USER_HOME
" 和 "fileName
" 组成。
例子:使用单独的文件进行变量替换(logback-examples/src/main/resources/chapters/configuration/variableSubstitution4.xml)
传统格式
xml
<configuration>
<variable file="variables2.properties" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${destination}</file>
<encoder>
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
规范格式 (1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
<import class="ch.qos.logback.core.FileAppender"/>
<variable file="variables2.properties"/>
<appender name="FILE" class="FileAppender">
<file>${destination}</file>
<encoder class="PatternLayoutEncoder">
<pattern>%kvp %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE"/>
</root>
</configuration>
嵌套名称
在引用变量时,变量名可以包含对另一个变量的引用。例如,如果名为 "userid"
的变量被赋值为 "alice"
,那么 "${${userid}.password}"
就引用了名为 "alice.password"
的变量。
默认值嵌套
变量的默认值可以引用另一个变量。例如,假设变量 'id'
未赋值,而变量 'userid'
被赋值为 "alice"
,那么表达式 "${id:-${userid}}"
将返回 "alice"
。
HOSTNAME 属性
由于经常有用,HOSTNAME
属性在配置期间会自动定义,并具有上下文范围。
CONTEXT_NAME 属性
正如其名称所示,CONTEXT_NAME
属性对应于当前日志上下文的名称。
设置时间戳
timestamp 元素可以根据当前日期和时间定义属性。timestamp 元素将在后续章节中进行解释。
动态定义变量,即属性
您可以使用 <define>
元素动态地定义属性。define
元素需要两个必填属性:name
和 class
。name
属性指定要设置的属性的名称,而 class
属性指定实现 PropertyDefiner
接口的任何类。PropertyDefiner
实例的 getPropertyValue
() 方法返回的值将是命名属性的值。您还可以通过指定 scope
属性为命名属性指定 作用域。
以下是一个示例。
传统格式
xml
<configuration>
<define name="rootLevel" class="a.class.implementing.PropertyDefiner">
<shape>round</shape>
<color>brown</color>
<size>24</size>
</define>
<root level="${rootLevel}"/>
</configuration>
规范格式 (1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="a.class.implementing.PropertyDefiner"/>
<define name="rootLevel" class="PropertyDefiner">
<shape>round</shape>
<color>brown</color>
<size>24</size>
</define>
<root level="${rootLevel}"/>
</configuration>
在上面的示例中,shape
、color
和 size
是 "a.class.implementing.PropertyDefiner"
的属性。只要在 PropertyDefiner
实现中为给定属性设置了 setter,logback 就会根据配置文件中指定的适当值注入相应的值。
目前,logback 附带了一些相当简单的 PropertyDefiner
实现。
实现名称 | 描述 |
---|---|
CanonicalHostNamePropertyDefiner |
将命名变量设置为本地主机的规范主机名。请注意,获取规范主机名可能需要几秒钟的时间。 |
FileExistsPropertyDefiner |
如果路径属性指定的文件存在,则将命名变量设置为 "true" ,否则设置为 "false" 。 |
ResourceExistsPropertyDefiner |
如果用户指定的资源在类路径上可用,则将命名变量设置为 "true" ,否则设置为 "false" 。 |
条件处理配置文件
开发人员经常需要在针对不同环境(如开发、测试和生产)的多个 logback 配置文件之间进行切换。这些配置文件在很大程度上相似,只有一些地方有所不同。为了避免重复,logback 支持使用 <if>
、<then>
和 <else>
元素对配置文件进行条件处理,以便单个配置文件可以适当地针对多个环境。请注意,条件处理需要 Janino 库。
条件语句的一般格式如下所示。
xml
<!-- if-then形式 -->
<if condition="某个条件表达式">
<then>
...
</then>
</if>
<!-- if-then-else形式 -->
<if condition="某个条件表达式">
<then>
...
</then>
<else>
...
</else>
</if>
条件是一个 Java 表达式,在其中只能访问上下文属性或系统属性。对于作为参数传递的键,property()
或其更短的等效形式 p()
方法返回属性的字符串值。例如,要访问具有键 "k"
的属性的值,可以编写 property("k")
或等效的 p("k")
。如果键 "k"
的属性未定义,property
方法将返回空字符串而不是 null
。这样可以避免检查 null
值的需要。
isDefined()
方法可用于检查属性是否已定义。例如,要检查属性 "k"
是否已定义,可以编写 isDefined("k")
。同样,如果需要检查属性是否为空,可以使用 isNull()
方法。示例:isNull("k")
。
传统格式
xml
<configuration debug="true">
<if condition='property("HOSTNAME").contains("torino")'>
<then>
<appender name="CON" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %-5level %logger{35} -%kvp- %msg %n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="CON" />
</root>
</then>
</if>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${randomOutputDir}/conditional.log</file>
<encoder>
<pattern>%d %-5level %logger{35} -%kvp- %msg %n</pattern>
</encoder>
</appender>
<root level="ERROR">
<appender-ref ref="FILE" />
</root>
</configuration>
规范格式 (1.3)
xml
<?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.FileAppender"/>
<import class="ch.qos.logback.core.ConsoleAppender"/>
<appender name="FILE" class="FileAppender">
<file>${randomOutputDir}/conditional.log</file>
<encoder class="PatternLayoutEncoder">
<pattern>%d %-5level %logger{35} -%kvp- %msg %n</pattern>
</encoder>
</appender>
<root level="ERROR">
<appender-ref ref="FILE"/>
</root>
</configuration>
条件处理可以在 <configuration>
元素的 任何位置 进行支持。还支持嵌套的 if-then-else 语句。然而,XML 语法非常繁琐,并不适合作为通用编程语言的基础。因此,太多的条件语句会使您的配置文件对于后续读者(包括您自己)难以理解。
从 JNDI 获取变量
在某些情况下,您可能想使用存储在 JNDI 中的 env-entry
。 <insertFromJNDI>
配置指令提取存储在 JNDI 中的 env-entry
,并使用由 as
属性指定的键将属性插入本地范围中。与所有属性一样,可以使用 scope
属性将新属性插入 不同的作用域 中。
示例:通过 JNDI 插入作为属性的 env-entry
(logback-examples/src/main/resources/chapters/configuration/insertFromJNDI.xml)
传统格式
xml
<configuration>
<insertFromJNDI env-entry-name="java:comp/env/appName" as="appName" />
<contextName>${appName}</contextName>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d ${CONTEXT_NAME} %level -%kvp- %msg %logger{50}%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
规范格式 (1.3)
xml
<?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"/>
<insertFromJNDI as="appName" envEntryName="java:comp/env/appName"/>
<contextName>${appName}</contextName>
<appender name="CONSOLE" class="ConsoleAppender">
<encoder class="PatternLayoutEncoder">
<pattern>%d ${CONTEXT_NAME} %level -%kvp- %msg %logger{50}%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>
在这个例子中,"java:comp/env/appName"
env-entry 被插入为 appName
属性。请注意, <contextName>
指令基于由前面的 <insertFromJNDI>
指令插入的 appName
属性值设置上下文名称。
序列化模型
从 1.3.9/1.4.9 开始,logback-classic 可以创建与 XML 配置文件匹配的配置模型的序列化版本。
这是通过添加 <serializeModel>
元素并指定序列化模型文件路径来完成的。
xml
<configuration debug="false">
<serializeModel file="path/to/logback.scmo"/>
...
</configuration>
请注意,在 logback-classic 初始化期间会创建 SerializedModelConfigurator
的实例并调用它。SerializedModelConfigurator
实例可以从序列化配置模型 (.scmo) 文件读取和配置 logback-classic。请参阅早期关于 初始化配置 的部分。
文件包含
Joran 支持从另一个文件中包含配置文件的一部分。这是通过声明 <include>
元素来完成的,如下所示:
示例:文件包含(logback-examples/src/main/resources/chapters/configuration/containingConfig.xml)
传统格式
xml
<configuration>
<include file="src/main/java/chapters/configuration/includedConfig.xml"/>
<root level="DEBUG">
<appender-ref ref="includedConsole" />
</root>
</configuration>
规范格式 (1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<include file="src/main/java/chapters/configuration/includedConfig.xml"/>
<root level="DEBUG">
<appender-ref ref="includedConsole"/>
</root>
</configuration>
目标文件必须将其元素嵌套在 <included>
元素内。例如,可以声明 ConsoleAppender
:
Example: File include (logback-examples/src/main/resources/chapters/configuration/includedConfig.xml)
xml
<included>
<appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>"%d -%kvp- %m%n"</pattern>
</encoder>
</appender>
</included>
请再次注意必须加入 <included>
元素。
要包含的内容可以引用为文件、资源或 URL。
-
作为文件: 要包含文件,请使用
file
属性。您可以使用相对路径,但请注意,当前目录由应用程序定义,不一定与配置文件的路径相关。 -
作为资源: 要包含资源,即在类路径上找到的文件,请使用
resource
属性。xml<include resource="includedConfig.xml"/>
-
作为 URL: 要包含 URL 的内容,请使用
url
属性。xml<include url="http://some.host.com/includedConfig.xml"/>
如果找不到要包含的文件,logback 将通过打印状态消息来抱怨。如果包含的文件是可选的,您可以在 <include>
元素中将 optional
属性设置为 true
,以抑制警告消息。
xml
<include optional="true" ..../>
添加一个上下文监听器
LoggerContextListener
接口的实例侦听与日志记录器上下文的生命周期相关的事件。
JMXConfigurator
是 LoggerContextListener
接口的一种实现。它在 后续章节 中进行了描述。
LevelChangePropagator
从版本 0.9.25 开始,logback-classic 随附有 LevelChangePropagator
,它是 LoggerContextListener
的实现,它将对任何 logback-classic 日志记录器级别的更改传播到 java.util.logging
框架。这种传播消除了禁用的日志语句的性能影响。 LogRecord
的实例将仅为启用的日志语句发送到 logback(通过 SLF4J)。这使得真实世界的应用程序使用 jul-to-slf4j 桥接变得合理。
可以使用 contextListener
元素来安装 LevelChangePropagator
,如下所示。
传统格式
xml
<configuration debug="true">
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"/>
<!-- rest of the configuration file .... -->
</configuration>
规范格式 (1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration debug="true">
<import class="ch.qos.logback.classic.jul.LevelChangePropagator"/>
<contextListener class="LevelChangePropagator"/>
</configuration>
LevelChangePropagator
的 resetJUL
属性设置将重置所有之前的 j.u.l.
记录器的级别配置。但是,以前安装的处理程序将保持不变。
传统格式
xml
<configuration debug="true">
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<!-- rest of the configuration file .... -->
</configuration>
规范格式 (1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration debug="true">
<import class="ch.qos.logback.classic.jul.LevelChangePropagator"/>
<contextListener class="LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
</configuration>
SequenceNumberGenerator
从 1.3.0 版本开始,Logback 支持一个自动填充事件创建时序列号字段。此字段由附加到日志记录上下文的序列号生成器填充。
以下方式设置序列号生成器:
传统格式
xml
<configuration>
<sequenceNumberGenerator class="ch.qos.logback.core.spi.BasicSequenceNumberGenerator"/>
<!-- rest of the configuration file .... -->
</configuration>
规范格式 (1.3)
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
<import class="ch.qos.logback.core.spi.BasicSequenceNumberGenerator"/>
<sequenceNumberGenerator class="BasicSequenceNumberGenerator"/>
</configuration>
版权声明:本文为博主「佳佳」的原创文章,遵循 CC 4.0 BY-NC-SA 版权协议,转载请附上原文出处链接及本声明。