前言
本文为Chapter 3: Logback configuration的笔记,由于“Chapter 3: Logback configuration”内容较长,本篇为其笔记的第二篇。
本文的小标题英文直接从官方文档复制,可以直接在官方文档中通过搜索立刻定位到对应的官方文档中对应的小节。
正文
配置文件(xml)的基本结构
> As will be demonstrated over and over, the syntax of logback configuration files is extremely flexible. As such, it is not possible to specify the allowed syntax with a DTD file or an XML schema. Nevertheless, the very basic structure of the configuration file can be described as, <configuration> element, containing zero or more <appender> elements, followed by zero or more <logger> elements, followed by at most one <root> element. The following diagram illustrates this basic structure.>> 基本结构为
在官方文档本章的读取配置文件顺序/优先级时,谈及默认配置,并给了一个默认配置等效的xml配置图,不妨取来结合着看。
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<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>
从这里我们可以看到,这个xml元素以<configuration></configuration>
为总览,其内部直接子元素有<appender></appender>
和<root></root>
,没有<logger></logger>
。这与appender
与logger
可有0到无穷多个的下标相符合,也与root
没有任何下标表示有且必须只有一个相符。
配置文件(xml)的注意事项:大小写
> Since logback version 0.9.17, tag names pertaining to explicit rules are case insensitive. For example, <logger>, <logger> and <logger> are valid configuration elements and will be interpreted in the same way. Note that XML well-formedness rules still apply, if you open a tag as <xyz> you must close it as </xyz>, will not work. As for implicit rules, tag names are case sensitive except for the first letter. Thus, <xyz> and <xyz> are equivalent but not <xyz>. Implicit rules usually follow the camelCase convention, common in the Java world. Since it is not easy to tell when a tag is associated with an explicit action and when it is associated with an implicit action, it is not trivial to say whether an XML tag is case-sensitive or insensitive with respect to the first letter. If you are unsure which case to use for a given tag name, just follow the camelCase convention which is almost always the correct convention.
简单来说,就是像logger,appender,layout,encoder,filter这样的明确的被logback内置和实现的组件,它们的标签名不区分大小写。对于搞不清楚什么成分的,保险起见,使用驼峰命名法准没错。
配置文件(xml)的logger元素的配置语法
Configuring loggers, or the<logger>
element
> A logger is configured using the <logger> element. A <logger> element takes exactly one mandatory name attribute, an optional level attribute, and an optional additivity attribute, admitting the values true or false. The value of the level attribute admitting one of the case-insensitive string values TRACE, DEBUG, INFO, WARN, ERROR, ALL or OFF. The special case-insensitive value INHERITED, or its synonym NULL, will force the level of the logger to be inherited from higher up in the hierarchy. This comes in handy if you set the level of a logger and later decide that it should inherit its level.
配置logger的appender
> The <logger> element may contain zero or more <appender-ref> elements; each appender thus referenced is added to the named logger. Note that unlike log4j, logback-classic does not close nor remove any previously referenced appenders when configuring a given logger.
<appender-ref>怎么写其实没说明白。通过在文档中以'appender-ref'为关键词搜索,就得到的例子,可以推测其使用方式如图:
再过几节有几段文字再度谈及了logger引用appender。
Configuring the root logger, or the<root>
element
> It supports a single attribute, namely the level attribute. It does not allow any other attributes because the additivity flag does not apply to the root logger. Moreover, since the root logger is already named as "ROOT", it does not allow a name attribute either. The value of the level attribute can be one of the case-insensitive strings TRACE, DEBUG, INFO, WARN, ERROR, ALL or OFF. Note that the level of the root logger cannot be set to INHERITED or NULL.
消息记录请求是否被允许只考虑被直接调用的Logger
> Let us note that the basic-selection rule depends on the effective level of the logger being invoked, not the level of the logger where appenders are attached.
这一段和我们之前的笔记(三)的“输出器的可加性(additivity)”一节有呼应关系,何为“the logger being invoked”?何为“the logger where appenders are attached”?注意这里都是logger,两个logger有何不同?我认为前者是记录消息的请求直接发出的日志记录器,后者指因为可加性而被调用的日志记录器。并且在那一小节我们所作的实验也和这段描述相符:被可加性传递的父级日志记录器没有再审查要求被记录的消息。
> Logback will first determine whether a logging statement is enabled or not, and if enabled, it will invoke the appenders found in the logger hierarchy, regardless of their level.
这段话则是说输出器并不能审查要被它输出(记录)的消息是否有资格,它只能老老实实记录。这么说是因为,'regardless of their level',这里的这个their中的它,指的最合句子结构和语境的,其实是Appender。同时这说明Appender可能也有级别问题。
appender元素必需属性
> An appender is configured with the <appender> element, which takes two mandatory attributes name and class. The name attribute specifies the name of the appender whereas the class attribute specifies the fully qualified name of the appender class to instantiate.
<appender>元素标签必需(mandatory)的两个属性为name和class。即要用appender标签,至少也会有这样的代码:<appender class="..." name="...">...</appender>
。
appender标签内部元素(标签)
> The <appender>
element may contain zero or one <layout>
elements, zero or more <encoder>
elements and zero or more <filter>
elements. Apart from these three common elements, <appender>
elements may contain any number of elements corresponding to JavaBean properties of the appender class. Seamlessly supporting any property of a given logback component is one of the major strengths of Joran as discussed in a later chapter.
appender的appender标签内部元素(标签)有layout,encoder,filter以及对应于它的JavaBean属性的配置标签。
这个所谓的JavaBean属性的配置标签,我推测和Spring的xml配置应该差不多。比如一个<bean></bean>
元素标签,内部可以通过<property name="..."></property>
这样来指定这个bean的内部成员变量。
> The <layout>
element takes a mandatory class attribute specifying the fully qualified name of the layout class to instantiate. As with the <appender>
element, <layout>
may contain other elements corresponding to properties of the layout instance. Since it's such a common case, if the layout class is PatternLayout
, then the class attribute can be omitted as specified by default class mapping rules.
<layout></layout>
元素有一个必需的class
属性 ==> layout
元素的标签至少为<layout class="fully qualified name of the layout class"></layout>
<layout></layout>
元素和<appender></appender>
元素一样可以配置javabean属性。
不过因为这个组件用的实在是太普遍了,所以class
属性省略也行,省略的话会自动根据default class mapping中的规则指定。
default class mapping中的规则是这样弄的:首先根据所在的appender
元素标签的class
属性,从'parent class'类中选出对应的,然后自己是'layout',就从剩下的里面选出property name
为layout
的,那么用什么类也就确定了。
> The <encoder>
element takes a mandatory class attribute specifying the fully qualified name of the encoder class to instantiate. Since it's such a common case, if the encoder class is PatternLayoutEncoder
, then the class attribute can be omitted as specified by default class mapping rules.
大体上和上一段对<layout></layout>
元素没有两样。
> Note that each appender has its own encoder. Encoders are usually not designed to be shared by multiple appenders. The same is true for layouts. As such, logback configuration files do not provide any syntactical means for sharing encoders or layouts.
这段文字在官方文档中并不是直接接着的,而是又跳开讲了一些关于logger引用appender的知识后才出现,这内容布置我也是服了。
主要内容就是Encoder和Layout在设计时都没有把它们在多个Appender中复用的想法,因此不要想着一个encoder组件或layout组件被多个appender组件使用,能不能提出来一个和appender平级,不存在的。
logger绑定自己的appender:appender-ref
> Logging to multiple appenders is as easy as defining the various appenders and referencing them in a logger, as the next configuration file illustrates:>> > <configuration> > > <appender name="FILE" class="ch.qos.logback.core.FileAppender"> > <file>myApp.log</file> > > <encoder> > <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern> > </encoder> > </appender> > > <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> > <encoder> > <pattern>%msg%n</pattern> > </encoder> > </appender> > > <root level="debug"> > <appender-ref ref="FILE" /> > <appender-ref ref="STDOUT" /> > </root> > </configuration> >
>> The appenders are attached to the root logger by referencing them by name within an appender-ref element.
logger在appender上的累进
> By default, appenders are cumulative: a logger will log to the appenders attached to itself (if any) as well as all the appenders attached to its ancestors. Thus, attaching the same appender to multiple loggers will cause logging output to be duplicated.
logger会调用所有它能调用的appender,包括其自己引用的,其在开启addivity下所有上级logger的,都会被调用。在此基础上,若一个appender被多个logger引用,可能导致重复日志记录的问题。
善用logger的additivity实现全软件控制台输出信息,特定类型的信息输出到文件。
> For instance, you can configure logging such that log messages appear on the console (for all loggers in the system) while messages only from some specific set of loggers flow into a specific appender.
> > <configuration> > > <appender name="FILE" class="ch.qos.logback.core.FileAppender"> > <file>myApp.log</file> > <encoder> > <pattern>%date %level [%thread] %logger{10} [%file:%line] %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"> > <appender-ref ref="FILE" /> > </logger> > > <root level="debug"> > <appender-ref ref="STDOUT" /> > </root> > </configuration> >
>> In this example, the console appender will log all the messages (for all loggers in the system) whereas only logging requests originating from the chapters.configuration logger and its children will go into the myApp.log file.</encoder></layout></appender></layout></appender></filter></encoder></layout></appender></appender></appender></root></appender-ref></appender-ref></logger></logger></logger></logger></xyz></xyz></xyz></logger></logger></logger></root></logger></appender></configuration>