前言
logback 官方文档
本文关于官方文档第三章:Logback configuration。
因第三章篇幅较长,会分为几份笔记。本章第二份笔记:
正文
logback 的配置文件
Let us begin by discussing the initialization steps that logback follows to try to configure itself:
- Logback tries to find a file called_logback-test.xml in the classpath.
- If no such file is found, logback tries to find a file called_logback.groovy in the classpath.
- If no such file is found, it checks for the file_logback.xml in the classpath..
- If no such file is found,service-provider loading facility (introduced in JDK 1.6) is used to resolve the implementation of
com.qos.logback.classic.spi.Configurator
interface by looking up the file_META-INF\services\ch.qos.logback.classic.spi.Configurator_in the class path. Its contents should specify the fully qualified class name of the desiredConfigurator
implementation.- If none of the above succeeds, logback configures itself automatically using the
BasicConfigurator
which will cause logging output to be directed to the console.The last step is meant as last-ditch effort to provide a default (but very basic) logging functionality in the absence of a configuration file.
If you are using Maven and if you place the_logback-test.xml_under the src/test/resources folder, Maven will ensure that it won’t be included in the artifact produced. Thus, you can use a different configuration file, namely logback-test.xml during testing, and another file, namely, logback.xml , in production.
FAST START-UP t takes about 100 miliseconds for Joran to parse a given logback configuration file. To shave off those miliseconds at aplication start up, you can use the service-provider loading facility (item 4 above) to load your own custom
Configurator
class with BasicConfigrator serving as a good starting point.
这一段主要讲了 logback 如何定位它的配置文件,在有多个可用的配置文件下不同配置文件的优先级。
最后讲了如何加快带有 logback 的软件的启动速度。但涉及的知识点在于 service-provider loading facility,本文不多做讨论。
默认配置的情况
Assuming the configuration files logback-test.xml or logback.xml are not present, logback will default to invoking BasicConfigurator which will set up a minimal configuration. This minimal configuration consists of a ConsoleAppender attached to the root logger. The output is formatted using a PatternLayoutEncoder set to the pattern
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
. Moreover, by default the root logger is assigned the DEBUG level.
logback 的解耦
Except code that configures logback (if such code exists) client code does not need to depend on logback. Since SLF4J permits the use of any logging framework under its abstraction layer, it is easy to migrate large bodies of code from one logging framework to another.
除了配置 logback 的代码外,客户端代码不需要依赖于 logback。这是因为 SLF4J 作为抽象层横置在客户代码与日志系统实现之间,客户代码只需要对 SLF4J 负责,只要是遵循 SLF4J 而实现的日志系统,相互之间都能更换。
默认配置的 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} - %msg%n</pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="STDOUT" /> </root> </configuration>
输出 logback 内部准备信息
If warnings or errors occur during the parsing of the configuration file, logback will automatically print its internal status data on the console. Note that to avoid duplication, automatic status printing is disabled if the user explicitly registers a status listener (defined below).
In the absence of warnings or errors, if you still wish to inspect logback’s internal status, then you can instruct logback to print status data by invoking the
print()
of theStatusPrinter
class. The MyApp2 application shown below is identical to MyApp1 except for the addition of two lines of code for printing internal status data.public static void main(String[] args) { // assume SLF4J is bound to logback in the current environment LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); // print logback's internal status StatusPrinter.print(lc); ... }
Instead of invoking StatusPrinter programmatically from your code, you can instruct the configuration file to dump status data, even in the absence of errors. To achieve this, you need to set the debug attribute of the configuration element, i.e. the top-most element in the configuration file, as shown below. Please note that this debug attribute relates only to the status data. It does not affect logback’s configuration otherwise, in particular with respect to logger levels. (If you are asking, no, the root logger will not be set to DEBUG.)
Setting debug=”true” within the <configuration> element will output status information, assuming that:
the configuration file is found
the configuration file is well-formed XML.
If any of these two conditions is not fulfilled, Joran cannot interpret the debug attribute since the configuration file cannot be read. If the configuration file is found but is malformed, then logback will detect the error condition and automatically print its internal status on the console. However, if the configuration file cannot be found, logback will not automatically print its status data, since this is not necessarily an error condition. Programmatically invoking StatusPrinter.print() as shown in the MyApp2 application above ensures that status information is printed in every case.之后还有几段文字与此有关,但我认为意义不大,不再复制。
四件事
第一,默认的,如果 logback 在启动配置准备阶段(这一阶段在于解析配置文件)出现了错误或警告,才会有输出相关信息。
第二,如果设置了专门的内部信息监听者,则第一的默认输出不会有。
第三,可以通过第二段所示方法要求输出全部的或者也输出说低于错误和警告级别的信息。
第四,通过修改配置文件中根元素 <configure>,为其添加 debug=”true”,也可以实现第三件事的效用。
之后一些原文没有在复制粘贴过来,它们又讲了在 logback 的配置文件糟糕的情况下,该如何做以能继续输出信息。感觉这一块在实践中的使用并不多,因此本文并不继续深究。
Specifying the location of the default configuration file as a system property
通过设置 logback.configurationFile
的系统变量,可以修改 logback 定位(在此属性被赋值的情况下,其是最高优先级)的配置文件的路径。
但其必需在 logback 的任何 Logger 被加载出来前修改。
Automatically reloading configuration file upon modification
<configuration scan="true"> ... </configuration>
By default, the configuration file will be scanned for changes once every minute. You can specify a different scanning period by setting the scanPeriod attribute of the <configuration> element. Values can be specified in units of milliseconds, seconds, minutes or hours. Here is an example:
<configuration scan="true" scanPeriod="30 seconds" > ... </configuration>
If no unit of time is specified, then the unit of time is assumed to be milliseconds, which is usually inappropriate. If you change the default scanning period, do not forget to specify a time unit.
As it is easy to make errors while editing a configuration file, in case the latest version of the configuration file has XML syntax errors, it will fall back to a previous configuration file free of XML syntax errors.
我之前一直认为是一旦修改配置文件则重载配置,这导致我几次调整配置文件而不重启应用,试图看看自己设置后的配置文件带给 logback 什么变化。
但细读这段话,其实 logback 不能立刻知道配置文件是否被修改了(也是,它归根结底一个 jar 包,凭什么能知道),它只是每隔一段时间去扫描比对,比对出有没有被修改。
最后它说开启扫描后自动,如果发现修改后的配置文件有问题,则会回退到最近的无问题的配置文件。
Enabling packaging data in stack traces
<configuration packagingData="true">
...
</configuration>
或者
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
lc.setPackagingDataEnabled(true);
开启输出 packaging data 数据。
何为 packaging data?
Packaging data consists of the name and version of the jar file whence the class of the stack trace line originated.
Viewing status messages
Logback collects its internal status data in a
[StatusManager](http://logback.qos.ch/xref/ch/qos/logback/core/status/StatusManager.html)
object, accessible via theLoggerContext
.Given a
StatusManager
you can access all the status data associated with a logback context.
老生常谈如何查看 logback 内部配置过程中的信息。
不过接下来开始整活了。
Logback-classic ships with a servlet called ViewStatusMessagesServlet. This servlet prints the contents of the StatusManager associated with the current LoggerContext as an HTML table.
To add this servlet to your web-application, add the following lines to its WEB-INF/web.xml file.
<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>
The ViewStatusMessages servlet will be viewable at the URL http://host/yourWebapp/lbClas…
通过将 ViewStatusMessagesServlet
注册,可以直接访问该组件从而以 HTML 的形式查看 logback 内部状态信息。
Listening to status messages
说来说去,还是一个将 logback 的内部状态信息对外输出的功能。
Stopping logback-classic
Stopping the context will close all appenders attached to loggers defined by the context and stop any active threads in an orderly way.
stop 操作的效果。
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); loggerContext.stop();
<configuration debug="true"> <!-- in the absence of the class attribute, assume ch.qos.logback.core.hook.DefaultShutdownHook --> <shutdownHook/> .... </configuration>
Note that you may install a shutdown hook of your own making by setting the class attribute to correspond to your shutdown hook’s class name.
非 web 应用的 java 程序 stop 的两种方法。
The default shutdown hook, namely DefaultShutdownHook, will stop the logback context after a specified delay (0 by default). Stopping the context will allow up to 30 seconds for any log file compression tasks running in the background to finish. In standalone Java applications, adding a <shutdownHook/> directive to your configuration file is an easy way to ensure that any ongoing compression tasks are allowed to finish before JVM exit.
In applications within a Web server, webShutdownHook will be installed automatically making <shutdownHook/> directive quite redundant and unnecessary.
Logback-classic will automatically ask the web-server to install a LogbackServletContainerInitializer implementing the ServletContainerInitializer interface (available in servlet-api 3.x and later). This initializer will in turn install and instance of LogbackServletContextListener. This listener will stop the current logback-classic context when the web-app is stopped or reloaded.
web 应用的 java 程序的 stop 方法
You may disable the automatic the installation of LogbackServletContextListener by setting a <context-param> named logbackDisableServletContainerInitializer in your web-application’s web.xml file. Here is the relevant snippet.
<web-app> <context-param> <param-name>logbackDisableServletContainerInitializer</param-name> <param-value>true</param-value> </context-param> .... </web-app>
Note that logbackDisableServletContainerInitializer variable can also be set as a Java system property an OS environment variable. The most local setting has priority, i.e. web-app first, system property second and OS environment last.
对 web 程序的自动 stop 可以关闭。虽然不知道为什么要关闭。