logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- <pattern> %d{yyyy-MM-dd HH:mm:ss} [%level] - %msg%n Logger: %logger Class: %class File: %file Caller: %caller Line: %line Message: %m Method: %M Relative: %relative Thread: %thread Exception: %ex xException: %xEx nopException: %nopex rException: %rEx Marker: %marker newline:%n </pattern> --> <property name="CUSTOM_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread]%logger -%msg%n"/> <include resource="org/springframework/boot/logging/logback/base.xml"/> <appender name="ROLLING-FILE-INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/todo.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- daily rollover --> <fileNamePattern>logs/todo.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- keep 30 days' worth of history capped at 1GB total size --> <maxHistory>30</maxHistory> <totalSizeCap>1GB</totalSizeCap> </rollingPolicy> <encoder> <pattern>${CUSTOM_LOG_PATTERN}</pattern> </encoder> </appender> <appender name="ROLLING-FILE-WARN" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/todo-warn.log</file> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>WARN</level> </filter> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- daily rollover --> <fileNamePattern>logs/todo-warn.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- keep 30 days' worth of history capped at 5GB total size --> <maxHistory>30</maxHistory> <totalSizeCap>5GB</totalSizeCap> </rollingPolicy> <encoder> <pattern>${CUSTOM_LOG_PATTERN}</pattern> </encoder> </appender> <logger name="com.tangcheng" level="INFO"> <appender-ref ref="ROLLING-FILE-WARN"/> </logger> <logger name="org" level="INFO"> <appender-ref ref="ROLLING-FILE-WARN"/> </logger> <root level="INFO"> <appender-ref ref="ROLLING-FILE-INFO"/> </root> </configuration>
In the remainder of this document, we will write "logback" to refer to the logback-classic module.
Logger, Appenders and Layouts
Logback is built upon three main classes: Logger, Appender and Layout.
These three types of components work together to enable developers to log messages according to message type and level, and to control at runtime how these messages are formatted and where they are reported.
The Logger class is part of the logback-classic module.
On the other hand, the Appender and Layout interfaces are part of logback-core.
As a general-purpose module, logback-core has no notion of loggers.
Example: Additivity flag (logback-examples/src/main/resources/chapters/configuration/additivityFlag.xml)
<configuration> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>foo.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.Foo" additivity="false"> <appender-ref ref="FILE" /> </logger> <root level="debug"> <appender-ref ref="STDOUT" /> </root> </configuration>
This example, the appender named FILE is attached to the chapters.configuration.Foo logger. Moreover, the chapters.configuration.Foo logger has its additivity flag set to false such that its logging output will be sent to the appender named FILE but not to any appender attached higher in the hierarchy. Other loggers remain oblivious to the additivity setting of the chapters.configuration.Foo logger.
Running the MyApp3 application with the additivityFlag.xml configuration file will output results on the console from the chapters.configuration.MyApp3 logger.
However, output from the chapters.configuration.Foo logger will appear in the foo.log file and only in that file.
https://logback.qos.ch/manual/configuration.html
File inclusion
Joran supports including parts of a configuration file from another file. This is done by declaring a <include>
element, as shown below:
Example: File include (logback-examples/src/main/resources/chapters/configuration/containingConfig.xml)
<configuration> <include file="src/main/java/chapters/configuration/includedConfig.xml"/> <root level="DEBUG"> <appender-ref ref="includedConsole" /> </root> </configuration>
The target file MUST have its elements nested inside an <included>
element. For example, a ConsoleAppender
could be declared as:
Example: File include (logback-examples/src/main/resources/chapters/configuration/includedConfig.xml)
<included> <appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>"%d - %m%n"</pattern> </encoder> </appender> </included>
Again, please note the mandatory <included>
element.
The contents to include can be referenced as a file, as a resource, or as a URL.
- As a file:
To include a file use the file attribute. You can use relative paths but note that the current directory is defined by the application and is not necessarily related to the path of the configuration file. -
As a resource:
To include a resource, i.e a file found on the class path, use the resource attribute.
<include resource="includedConfig.xml"/>
As a URL:
To include the contents of a URL use the url attribute.
<include url="http://some.host.com/includedConfig.xml"/>
If it cannot find the file to be included, logback will complain by printing a status message. In case the included file is optional, you can suppress the warning message by setting optional attribute to true
in the <include>
element.
<include optional="true" ..../>
Appender Additivity
The output of a log statement of logger L will go to all the appenders in L and its ancestors. This is the meaning of the term "appender additivity".
However, if an ancestor of logger L, say P, has the additivity flag set to false, then L's output will be directed to all the appenders in L and its ancestors up to and including P but not the appenders in any of the ancestors of P.
Loggers have their additivity flag set to true by default.
The table below shows an example:
Logger Name | Attached Appenders | Additivity Flag | Output Targets | Comment |
---|---|---|---|---|
root | A1 | not applicable | A1 | Since the root logger stands at the top of the logger hierarchy, the additivity flag does not apply to it. |
x | A-x1, A-x2 | true | A1, A-x1, A-x2 | Appenders of "x" and of root. |
x.y | none | true | A1, A-x1, A-x2 | Appenders of "x" and of root. |
x.y.z | A-xyz1 | true | A1, A-x1, A-x2, A-xyz1 | Appenders of "x.y.z", "x" and of root. |
security | A-sec | false | A-sec | No appender accumulation since the additivity flag is set to false . Only appender A-sec will be used. |
security.access | none | true | A-sec | Only appenders of "security" because the additivity flag in "security" is set to false . |
More often than not, users wish to customize not only the output destination but also the output format. This is accomplished by associating a layout with an appender. The layout is responsible for formatting the logging request according to the user's wishes, whereas an appender takes care of sending the formatted output to its destination. ThePatternLayout
, part of the standard logback distribution, lets the user specify the output format according to conversion patterns similar to the C language printf
function.
The following two lines will yield the exact same output. However, in case of a disabled logging statement, the second variant will outperform the first variant by a factor of at least 30.
logger.debug("The new entry is "+entry+"."); logger.debug("The new entry is {}.", entry);
https://logback.qos.ch/manual/architecture.html
Conversion Word | Effect | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
c{length} lo{length} logger{length} |
Outputs the name of the logger at the origin of the logging event.
This conversion word takes an integer as its first and only option. The converter's abbreviation algorithm will shorten the logger name, usually without significant loss of meaning. Setting the value of length option to zero constitutes an exception. It will cause the conversion word to return the sub-string right to the rightmost dot character in the logger name. The next table provides examples of the abbreviation algorithm in action.
Please note that the rightmost segment in a logger name is never abbreviated, even if its length is longer than the length option. Other segments may be shortened to at most a single character but are never removed. |
Below are various format modifier examples for the logger conversion specifier.
Format modifier | Left justify | Minimum width | Maximum width | Comment |
---|---|---|---|---|
%20logger | false | 20 | none | Left pad with spaces if the logger name is less than 20 characters long. |
%-20logger | true | 20 | none | Right pad with spaces if the logger name is less than 20 characters long. |
%.30logger | NA | none | 30 | Truncate from the beginning if the logger name is longer than 30 characters. |
%20.30logger | false | 20 | 30 | Left pad with spaces if the logger name is shorter than 20 characters. However, if logger name is longer than 30 characters, then truncate from the beginning. |
%-20.30logger | true | 20 | 30 | Right pad with spaces if the logger name is shorter than 20 characters. However, if logger name is longer than 30 characters, then truncate from the beginning. |
%.-30logger | NA | none | 30 | Truncate from the end if the logger name is longer than 30 characters. |
The table below list examples for format modifier truncation. Please note that the square brackets, i.e the pair of "[]" characters, are not part of the output. They are used to delimit the width of output.
Format modifier | Logger name | Result |
---|---|---|
[%20.20logger] | main.Name |
[ main.Name] |
[%-20.20logger] | main.Name |
[main.Name ] |
[%10.10logger] | main.foo.foo.bar.Name |
[o.bar.Name] |
[%10.-10logger] | main.foo.foo.bar.Name |
[main.foo.f]
|
https://logback.qos.ch/manual/layouts.html
spring boot中使用logback时一个一个配置文件示例:
简单的:
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml" /> <logger name="sample.logback" level="DEBUG" /> <springProfile name="staging"> <logger name="sample.logback" level="TRACE" /> </springProfile> </configuration>
include语句利用了spring boot中默认的logback中的一些配置。有些引用,可以不用定义名字为STDOUT和File的appender,不用定义Root节点
在spring boot中使用logback,可以使用profile的设定。在不同的环境,使用不同的logger定义。
如果使用maven的Filter插件,也可以在logback-spring.xml中引用相关变量,package后也会替换,因为maven Filter插件会替换classpath下相关文件中与之匹配的 标识位
小结:就上面的需求,不建议使用spring-logback.xml配置文件,直接在application.yml(或application.properties)文件中定义即可
示例:
logging: level: org.springframework.web: ERROR com.demo: DEBUG pattern: console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n" file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" file: logs/application.log
如果要将error日志和info日志分开输出,就需要自定义appender
<?xml version="1.0" encoding="UTF-8"?> <configuration> <property name="CUSTOM_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread]%logger -%msg%n"/> <include resource="org/springframework/boot/logging/logback/base.xml"/> <appender name="ROLLING-FILE-INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/whatif.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- daily rollover --> <fileNamePattern>logs/whatif.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 保留30天的历史日志 --> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>${CUSTOM_LOG_PATTERN}</pattern> </encoder> </appender> <appender name="ROLLING-FILE-WARN" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/whatif-warn.log</file> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>WARN</level> </filter> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- daily rollover --> <fileNamePattern>logs/whatif-warn.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 保留30天的历史日志 --> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>${CUSTOM_LOG_PATTERN}</pattern> </encoder> </appender> <logger name="com.tang" level="WARN"> <appender-ref ref="ROLLING-FILE-WARN"/> </logger> <logger name="com.tang" level="INFO"> <appender-ref ref="ROLLING-FILE-INFO"/> </logger> <root level="INFO"> <appender-ref ref="ROLLING-FILE-INFO"/> </root> </configuration>
上面的定义方法,会导致com.tang这个package的info及以上级别的log会在 ROLLING-FILE-INFO appender中打印两遍。即红色加粗的logger配置是不需要的,删除即可
选定义root,再定义某个package下的log打印,是一种 “先禁止所有,再允许个别”的配置方法,即“除了xxx,其它的都要xxx做
生成的日志文件:
一:根节点<configuration>包含的属性: scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。 scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 例如: <configuration scan="true" scanPeriod="60 seconds" debug="false"> <!-- 其他配置省略--> </configuration> 2.1设置上下文名称:<contextName> 每个logger都关联到logger上下文,默认上下文名称为“default”。但可以使用<contextName>设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改。 <configuration scan="true" scanPeriod="60 seconds" debug="false"> <contextName>myAppName</contextName> <!-- 其他配置省略--> </configuration> 2.2设置变量: <property> 用来定义变量值的标签,<property> 有两个属性,name和value;其中name的值是变量的名称,value的值时变量定义的值。通过<property>定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 例如使用<property>定义上下文名称,然后在<contentName>设置logger上下文时使用。 <configuration scan="true" scanPeriod="60 seconds" debug="false"> <property name="APP_Name" value="myAppName" /> <contextName>${APP_Name}</contextName> <!-- 其他配置省略--> </configuration> 2.3设置loger: <loger> 用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。<loger>仅有一个name属性,一个可选的level和一个可选的addtivity属性。 name: 用来指定受此loger约束的某一个包或者具体的某一个类。 level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。 如果未设置此属性,那么当前loger将会继承上级的级别。 addtivity: 是否向上级loger传递打印信息。默认是true。会在Root中打印。如果root也引用了自定义logger中引用过的appender,则Root就会打印两份信息到appender <loger>可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个loger。 <root> 也是<loger>元素,但是它是根loger。只有一个level属性,应为已经被命名为"root". level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能设置为INHERITED或者同义词NULL。 默认是DEBUG。 <root>可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个loger。
spring boot默认配置的logback中的信息:
default.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- Default logback configuration provided for import, equivalent to the programmatic initialization performed by Boot --> <included> <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" /> <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" /> <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /> <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <appender name="DEBUG_LEVEL_REMAPPER" class="org.springframework.boot.logging.logback.LevelRemappingAppender"> <destinationLogger>org.springframework.boot</destinationLogger> </appender> <logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR"/> <logger name="org.apache.catalina.util.LifecycleBase" level="ERROR"/> <logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN"/> <logger name="org.apache.sshd.common.util.SecurityUtils" level="WARN"/> <logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN"/> <logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="ERROR"/> <logger name="org.hibernate.validator.internal.util.Version" level="WARN"/> <logger name="org.springframework.boot.actuate.endpoint.jmx" additivity="false"> <appender-ref ref="DEBUG_LEVEL_REMAPPER"/> </logger> </included>
console-appender.xml 会引用default.xmk中定义的属性
<?xml version="1.0" encoding="UTF-8"?> <!-- Console appender logback configuration provided for import, equivalent to the programmatic initialization performed by Boot --> <included> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${CONSOLE_LOG_PATTERN}</pattern> <charset>utf8</charset> </encoder> </appender> </included>
file-appender.xml会引用default.xmk中定义的属性
<?xml version="1.0" encoding="UTF-8"?> <!-- File appender logback configuration provided for import, equivalent to the programmatic initialization performed by Boot --> <included> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <encoder> <pattern>${FILE_LOG_PATTERN}</pattern> </encoder> <file>${LOG_FILE}</file> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <fileNamePattern>${LOG_FILE}.%i</fileNamePattern> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <MaxFileSize>10MB</MaxFileSize> </triggeringPolicy> </appender> </included>
base.xml属于集上面于大成者,引用上面的default.xml,file-appender.xml,console-appender.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- Base logback configuration provided for compatibility with Spring Boot 1.1 --> <included> <include resource="org/springframework/boot/logging/logback/defaults.xml" /> <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/> <include resource="org/springframework/boot/logging/logback/console-appender.xml" /> <include resource="org/springframework/boot/logging/logback/file-appender.xml" /> <root level="INFO"> <appender-ref ref="CONSOLE" /> <appender-ref ref="FILE" /> </root> </included>
因为spring boot 中已经定义,所以在logback-spring.xml中可以不用定义
=====================================================finish=====================================================
报错:
java.lang.IllegalStateException: Logback configuration error detected: ERROR in c.q.l.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy - Filename pattern [logs/log.%d{yyyy-MM-dd}_%i.log] contains an integer token converter, i.e. %i, INCOMPATIBLE with this configuration. Remove it. ERROR in c.q.l.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy - Filename pattern [logs/log-warn.%d{yyyy-MM-dd}_%i.log] contains an integer token converter, i.e. %i, INCOMPATIBLE with this configuration. Remove it. at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:152) at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:72) at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:50) at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:106)
解决办法:
将日志文件格式中的"%i"去掉。因为TimeBasedRollingPolicy是按日期分隔文件的,不需要这个%i,这个按文件大小分隔文件时才会使用。
如果使用ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"策略时,就需要这个%i了
eg:
<configuration> <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>mylog.txt</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern> <!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB --> <maxFileSize>100MB</maxFileSize> <maxHistory>60</maxHistory> <totalSizeCap>20GB</totalSizeCap> </rollingPolicy> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="ROLLING" /> </root> </configuration>
Note the "%i" conversion token in addition to "%d". Both the %i and %d tokens are mandatory.
Each time the current log file reaches maxFileSize before the current time period ends, it will be archived with an increasing index, starting at 0.
Size and time based archiving supports deletion of old archive files.
You need to specify the number of periods to preserve with the maxHistory property.
When your application is stopped and restarted, logging will continue at the correct location, i.e. at the largest index number for the current period.
http://mcs.une.edu.au/doc/logback/manual/appenders.html
Declaring project dependencies for logging
Given Maven's transitive dependency rules, for "regular" projects (not libraries or frameworks) declaring logging dependencies can be accomplished with a single dependency declaration.
LOGBACK-CLASSIC(需要slf4j-api和logback-classic)
If you wish to use logback-classic as the underlying logging framework, all you need to do is to declare "ch.qos.logback:logback-classic" as a dependency in your pom.xml file as shown below. In addition to logback-classic-1.0.13.jar, this will pull slf4j-api-1.7.25.jar as well as logback-core-1.0.13.jar into your project. Note that explicitly declaring a dependency on logback-core-1.0.13 or slf4j-api-1.7.25.jar is not wrong and may be necessary to impose the correct version of said artifacts by virtue of Maven's "nearest definition" dependency mediation rule.
<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.13</version> </dependency>
LOG4J(需要slf4j-log4j12这个jar)
If you wish to use log4j as the underlying logging framework, all you need to do is to declare "org.slf4j:slf4j-log4j12" as a dependency in your pom.xml file as shown below. In addition to slf4j-log4j12-1.7.25.jar, this will pull slf4j-api-1.7.25.jar as well as log4j-1.2.17.jar into your project. Note that explicitly declaring a dependency on log4j-1.2.17.jar or slf4j-api-1.7.25.jar is not wrong and may be necessary to impose the correct version of said artifacts by virtue of Maven's "nearest definition" dependency mediation rule.
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> </dependency>
JAVA.UTIL.LOGGING(需要slf4j-jdk14这个jar)
If you wish to use java.util.logging as the underlying logging framework, all you need to do is to declare "org.slf4j:slf4j-jdk14" as a dependency in your pom.xml file as shown below. In addition to slf4j-jdk14-1.7.25.jar, this will pull slf4j-api-1.7.25.jar into your project. Note that explicitly declaring a dependency on slf4j-api-1.7.25.jar is not wrong and may be necessary to impose the correct version of said artifact by virtue of Maven's "nearest definition" dependency mediation rule.
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <version>1.7.25</version> </dependency>
Binary com
https://www.slf4j.org/manual.html
例如:%-4relative 表示,将输出从程序启动到创建日志记录的时间 进行左对齐 且最小宽度为4
格式修饰符,与转换符共同使用:
可选的格式修饰符位于“%”和转换符之间。
第一个可选修饰符是左对齐 标志,符号是减号“-”;
接着是可选的最小宽度 修饰符,用十进制数表示。如果字符小于最小宽度,则左填充或右填充,默认是左填充(即右对齐),填充符为空格。如果字符大于最小宽度,字符永远不会被截断。最大宽度 修饰符,符号是点号"."后面加十进制数。如果字符大于最大宽度,则从前面截断。点符号“.”后面加减号“-”在加数字,表示从尾部截断。
2016-07-04 07:37:29.801 [restartedMain] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'configurationPropertiesRebinderAutoConfiguration' of type [class org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$97204b4c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2016-07-04 07:37:30.482 [restartedMain] ERROR org.springframework.boot.SpringApplication - Application startup failed java.lang.IllegalStateException: Logback configuration error detected: ERROR in ch.qos.logback.core.rolling.RollingFileAppender[FILE] - Appender [FILE] failed to append. java.lang.NullPointerException ERROR in c.q.l.c.recovery.ResilientFileOutputStream@403418161 - IO failure while writing to file [demo.log] java.io.IOException: Stream Closed at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:151) at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:71) at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:49) at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:106) at org.springframework.boot.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:301) at org.springframework.boot.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:253) at org.springframework.boot.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:225) at org.springframework.boot.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:201) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:163) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:136) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:119) at org.springframework.boot.context.event.EventPublishingRunListener.publishEvent(EventPublishingRunListener.java:111) at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:65) at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:54) at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:330) at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) at com.DemoApplication.main(DemoApplication.java:17) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) 2016-07-04 07:37:30.486 [restartedMain] INFO o.s.b.logging.ClasspathLoggingApplicationListener - Application failed to start with classpath: [file:/D:/workspace/demo/target/classes/, file:/D:/workspace/common/target/classes/] 2016-07-04 07:51:03.820 [restartedMain] INFO o.s.c.a.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1237898e: startup date [Mon Jul 04 07:51:03 CST 2016]; root of context hierarchy 2016-07-04 07:51:04.568 [restartedMain] INFO o.s.b.f.a.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring 2016-07-04 07:51:04.623 [restartedMain] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'configurationPropertiesRebinderAutoConfiguration' of type [class org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$67d72258] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2016-07-04 07:51:05.312 [restartedMain] INFO com.DemoApplication - No active profile set, falling back to default profiles: default
出现上面报错时,很有可能是因为maxFileSize设置有不合理(一般是太小),文件rename太快,导致异常发生。
如果想了解详解信息,可以查看logback的日志打印,可以把logback的debug打开:(1)
<configuration debug="true"> (2)
<configuration> <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" /> ... the rest of the configuration file </configuration>http://logback.qos.ch/manual/configuration.html
http://jira.qos.ch/browse/LOGBACK-1054
http://logback.qos.ch/dist/
https://codeload.github.com/qos-ch/logback/zip/v_1.1.5
logback-sizeAndTime.xml(按照如下配置,经测试是可用的。idea中可能出现问题,但重启idea应用程序(是exit,不是close project)即可恢复正常)
<configuration> <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener"/> <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>mylog.txt</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!-- or whenever the file size reaches 100MB --> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="ROLLING"/> </root> </configuration>
logback.xml
<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <Pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread]%logger -%msg%n</Pattern> </encoder> </appender> <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>mylog.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!-- or whenever the file size reaches 100MB --> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder> <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread]%logger -%msg%n</pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="ROLLING"/> <appender-ref ref="STDOUT"/> </root> </configuration>
Appenders accumulate
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.
Example: Duplicate appender (logback-examples/src/main/resources/chapters/configuration/duplicate.xml)
View as .groovy
<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> <logger name="chapters.configuration"> <appender-ref ref="STDOUT" /> </logger> <root level="debug"> <appender-ref ref="STDOUT" /> </root></configuration>
Running MyApp3
with duplicate.xml will yield the following output:
14:25:36.343 [main] INFO chapters.configuration.MyApp3 - Entering application. 14:25:36.343 [main] INFO chapters.configuration.MyApp3 - Entering application. 14:25:36.359 [main] DEBUG chapters.configuration.Foo - Did it again! 14:25:36.359 [main] DEBUG chapters.configuration.Foo - Did it again! 14:25:36.359 [main] INFO chapters.configuration.MyApp3 - Exiting application. 14:25:36.359 [main] INFO chapters.configuration.MyApp3 - Exiting application.
Notice the duplicated output. The appender named STDOUT is attached to two loggers, to root and tochapters.configuration. Since the root logger is the ancestor of all loggers and chapters.configuration is the parent of both chapters.configuration.MyApp3 and chapters.configuration.Foo, each logging request made with these two loggers will be output twice, once because STDOUT is attached to chapters.configuration and once because it is attached to root.
Appender additivity is not intended as a trap for new users. It is quite a convenient logback feature. 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.
Example: Multiple appender (logback-examples/src/main/resources/chapters/configuration/restricted.xml)
View as .groovy
<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.logfile.
http://logback.qos.ch/manual/configuration.html
or the shorter equivalent (DEPRECATED)
<appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>testFile.log</file> ... <!-- layout are assigned the type ch.qos.logback.classic.PatternLayout by default --> <layout> <pattern>%msg%n</pattern> </layout></appender>
to (GOOD)
<appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>testFile.log</file> ... <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%msg%n</pattern> </encoder></appender>
or the shorter equivalent (GOOD)
<appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>testFile.log</file> ... <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> <encoder> <pattern>%msg%n</pattern> </encoder></appender>
http://logback.qos.ch/codes.html
效果图:
<?xml version="1.0" encoding="UTF-8"?> <!-- debug:打印logback内部日志信息,实时查看logback的运行状态,默认为false --> <!-- scan:配置文件如果发生改变,是否被重新加载,默认为true。 --> <!-- scanPeriod:设置检测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒,默认的时间间隔为1分钟,默认为true。 --> <configuration debug="true" scan="true" scanPeriod="30 seconds"> <contextName>SpringBoot Demo</contextName> <!-- 时间戳定义,timeReference:使用日志产生日期为时间基准 --> <timestamp key="byDay" datePattern="yyyy-MM-dd" timeReference="contextBirth"/> <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径,可以使用系统变量 --> <!-- <property name="LOG_HOME" value="${app.home}/log" /> --> <property name="LOG_HOME" value="log"/> <!-- appender很重要,一个配置文件会有多个appender --> <!-- ConsoleApperder意思是从console中打印出来 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- On Windows machines setting withJansi to true enables ANSI color code interpretation by the Jansi library. This requires org.fusesource.jansi:jansi:1.8 on the class path. Note that Unix-based operating systems such as Linux and Mac OS X support ANSI color codes by default. http://blog.csdn.net/u013613428/article/details/51499552 -->
<withJansi>true</withJansi> <!-- 过滤器,一个appender可以有多个 --> <!-- 阈值过滤,就是log行为级别过滤,debug及debug以上的信息会被打印出来 --> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>debug</level> </filter> <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> <!-- encoder编码规则 --> <encoder> <!--<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>--> <!--<pattern>%d %contextName %msg%n</pattern>--> <!-- pattern模式 %d时间 %thread 线程名 %level行为级别 %logger logger名称 %method 方法名称 %message 调用方法的入参消息 --> <pattern>%-4d [%green(%thread)] %highlight(%-5level) %cyan(%logger).%-10method - %message%n</pattern> </encoder>
<!-- 常用的Pattern变量,大家可打开该pattern进行输出观察 --> <!-- <pattern> %d{yyyy-MM-dd HH:mm:ss} [%level] - %msg%n Logger: %logger Class: %class File: %file Caller: %caller Line: %line Message: %m Method: %M Relative: %relative Thread: %thread Exception: %ex xException: %xEx nopException: %nopex rException: %rEx Marker: %marker %n </pattern> -->
</appender> <!-- 按照每天生成日志文件 --> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 日志输出文件 --> <file>${LOG_HOME}/LoggingBack.log</file> <!-- 追加日志到原文件结尾 --> <append>true</append> <!-- timebasedrollingpolicy:演示时间和大小为基础的日志文件归档 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定。 --> <!--可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。 --> <!--而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 --> <!-- 文件滚动日期格式:每天:.YYYY-MM-dd(默认);每星期:.YYYY-ww;每月:.YYYY-MM --> <!-- 每隔半天:.YYYY-MM-dd-a;每小时:.YYYY-MM-dd-HH;每分钟:.YYYY-MM-dd-HH-mm --> <fileNamePattern>${LOG_HOME}/log-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!-- 控制归档文件的最大数量的保存,删除旧的文件,默认单位天数 --> <maxHistory>7</maxHistory> <!-- 设置当前日志的文件的大小,决定日志翻滚 --> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!-- 除按日志记录之外,还配置了日志文件不能超过10M(默认),若超过10M,日志文件会以索引0开始, --> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy>
<!-- encoders 作用是将logger事件转换成字节数组,并将字节数组写入到输出流-->
<encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n </pattern> </encoder> </appender> <appender name="FILE-INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 这里添加一个过滤器 --> <file>${LOG_HOME}/LoggingBack-info.log</file> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_HOME}/LOG-INFO-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <maxHistory>7</maxHistory> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n </pattern> </encoder> </appender> <appender name="FILE-ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 这里添加一个过滤器 --> <file>${LOG_HOME}/LoggingBack-error.log</file> <!--<filter>标签。 过滤器,执行一个过滤器会有返回个枚举值,即DENY,NEUTRAL,ACCEPT其中之一。 返回DENY,日志将立即被抛弃不再经过其他过滤器; 返回NEUTRAL,有序列表里的下个过滤器过接着处理日志; 返回ACCEPT,日志会被立即处理,不再经过剩余过滤器。 过滤器被添加到<Appender> 中,为<Appender> 添加一个或多个过滤器后,可以用任意条件对日志进行过滤。<Appender> 有多个过滤器时,按照配置顺序执行。 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_HOME}/LOG-ERROR-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <maxHistory>7</maxHistory> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n </pattern> </encoder> </appender> <!-- 可以写多个日志文件appender,然后区分多个模块的日志 --> <appender name="BACKUP" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_HOME}/LoggingBack2.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_HOME}/LOG-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <maxHistory>7</maxHistory> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n </pattern> </encoder> </appender> <!-- 为单独的包配置日志级别,若root的级别大于此级别, 此处级别也会输出 应用场景:生产环境一般不会将日志级别设置为trace或debug,但是为详细的记录SQL语句的情况, 可将hibernate的级别设置为debug,如此一来,日志文件中就会出现hibernate的debug级别日志, 而其它包则会按root的级别输出日志 --> <logger name="org.hibernate.SQL" level="DEBUG"/> <logger name="org.hibernate.jdbc" level="DEBUG"/> <logger name="org.springframework" level="DEBUG"/> <!-- 指定一个包,name必填,additivity选填:控制是否继承父类appender,默认true --> <!-- level选填,如果木有指定从最近的父类继承,顶级为root的级别 --> <logger name="com.wisely.ch7_7" additivity="true"> <appender-ref ref="FILE"/> <appender-ref ref="FILE-INFO"/> <appender-ref ref="FILE-ERROR"/> <appender-ref ref="BACKUP"/> </logger> <!-- root, 只有在level及以上级别的日志会被输出 --> <!-- 例如: 当root level设置为INFO时, appender DEBUG中无法获取到DEBUG级别的日志事件, 则DEBUG日志信息也不会写入debug.log中. --> <root level="DEBUG"> <appender-ref ref="STDOUT"/> </root> </configuration>
RollingFileAppender 继承 FileAppender,能够滚动记录文件。例如,RollingFileAppender能先记录到文件"log.txt",然后当符合某个条件时,变成记录到其他文件。 RollingFileAppender 有两个与之互动的重要子组件。第一个是RollingPolicy,负责滚动。第二个是 TriggeringPolicy,决定是否以及何时进行滚动。所以,RollingPolicy 负责"什么", TriggeringPolicy 负责"何时"。
要想 RollingFileAppender 起作用,必须同时设置 RollingPolicy 和 TriggeringPolicy。不过,如果 RollingPolicy 也实现了 TriggeringPolicy 接口,那么只需要设置 RollingPolicy。
FixedWindowRollingPolicy当发生滚动时,FixedWindowRollingPolicy 根据如下固定窗口(window)算法重命名文件。 选项"fileNamePattern"代表归档(滚动)记录文件的文件名模式。该选项是必需的,且必需在模式的某处包含标志"%i"。如示例3中的MyApp3-RollingFixedWindow.xml 。
TimeBasedRollingPolicy 或许是最受流行的滚动策略。它根据时间来制定滚动策略,例如根据日或月。TimeBasedRollingPolicy 既负责滚动也负责触发滚动。实际上,TimeBasedRollingPolicy 同时实现了 RollingPolicy 接口和 TriggeringPolicy 接口。和 FixedWindowRollingPolicy一样,TimeBasedRollingPolicy 也支持自动压缩文件。如果"fileNamePattern"选项以".gz"或".zip"结尾,就表示需要压缩。如示例3中的MyApp3-RollingTimeBased.xml 。
SizeAndTimeBasedFNATP按照日期进行归档的同时限制每个记录文件的大小,特别是当后处理工具对记录文件大小有限制时。Logback 为此提供了 SizeAndTimeBasedFNATP,它是TimeBasedRollingPolicy 的子组件,FNATP 代表"FNATP stands for File Naming And Triggering Policy"。 下面的例子MyApp3-sizeAndTime.xml演示了基于大小和时间的记录文件归档。
如给定的一个格式:%-5p [%t]: %m%n中,并没有明确的分隔转换字符和普通文本的字符存在。PatternLayout能自己区分普通文本和转换字符。其中%-5p是日志的调用级别。事件是左对齐的,5个字符宽度。
格式修饰符,放在%和转换符之间。 第一个可选的格式修饰符是左对齐(-);第二个可选的格式修饰符是字段最小宽度。一个整数。表示输出的最小字符数。如果数据未达到指定最小大小,那么它将以左填充(默认)或者右填充方式(左对齐情况下只能使用右填充了)。用空格填充,直到达到最小宽度。如果大于指定最小宽度,不会被截断 。当然可以指定最大字符数,使用.符号加数字表示最大字符数。如果大于指定长度,多余的字符会被删除。它是从前面删除,而不是从后面删除的。如最大字符是8个,数据有10个字符,那么前面两个字符会被删除。
%20.30c 右对齐,最少20字符,最多30字符,填充或截取规则略
%-20.30c 左对齐,最少20字符,最多30字符,填充或截取规则略
Appender累积
默认情况下,appender 是可累积的:logger 会把记录输出到它自身的 appender 和它所有祖先的 appender。因此,把同一 appender 关联到多个 logger 会导致重复输出,如下面的配置文件会导致重复的输出:
<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>
<logger name="chapters.configuration">
<appender-ref ref="STDOUT" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" /> <!—这会导致重复输出-->
</root>
</configuration>
输出结果如下:
20:53:29.328 [main] INFO c.t.chapters.configuration.MyApp2 - Entering application.
20:53:29.328 [main] INFO c.t.chapters.configuration.MyApp2 - Entering application.
20:53:29.328 [main] DEBUG com.ttpod.chapters.configuration.Foo - Did it again!
20:53:29.328 [main] DEBUG com.ttpod.chapters.configuration.Foo - Did it again!
20:53:29.328 [main] INFO c.t.chapters.configuration.MyApp2 - Exiting application.
20:53:29.328 [main] INFO c.t.chapters.configuration.MyApp2 - Exiting application.
覆盖默认的累积行为
如果你觉得默认的累积行为不合适,可以设置叠加性标识为 false 以关闭它。 这样的话,logger 树里的某个分支可以输出到与其他 logger 不同的 appender。
示例:叠加性标识
<configuration>
…………
<logger name="com.ttpod.chapters.configuration.Foo" additivity="false">
<appender-ref ref="FILE" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
输出结果:
Entering application.
Exiting application.
此例中,logger"chapters.configuration.Foo"关联 appender"FILE",它的叠加性标记为false,这样它的记录输出仅会被发送到 appender"FILE",不会被发送到更高logger 等级关联的 appender。其他 logger 不受此影响。 用 additivityFlag.xml 配置 MyApp3 , 运 行 后 , 控 制 台 上 由 输 出由"chapters.configuration.MyApp3"产生的记录。而 logger" chapters.configuration.Foo"将且仅仅将输出到文件 foo.log。
http://www.cnblogs.com/luowei010101/archive/2012/01/04/2312438.html
When you specify the MaxFileSize to be used by the SizeBasedRollingPolicy, logback expects a rather precise format:
- The number has to be an integer
- You can add 'KB', 'MB' or 'GB' after the number.
Here are some correct values: 500KB, 15MB, 2GB.
No TriggeringPolicy
was set for the RollingFileAppender
.
The RollingFileAppender
must be set up with a TriggeringPolicy
. It permits the Appender to know when the rollover must be activated.
To find more information about TriggeringPolicy
objects, please read the following javadocs:
Please note that the TimeBasedRollingPolicy
is a TriggeringPolicy and and RollingPolicy
at the same time.
Missing integer token, that is %i, in FileNamePattern [...].
The %i conversion token is mandatory for size and time based archiving. In case the %i token is missing,SizeAndTimeBasedFNATP
attached to RollingFileAppender
will detect the omission and will not start.
http://logback.qos.ch/codes.html
SizeBasedTriggeringPolicy
SizeBasedTriggeringPolicy
looks at the size of the currently active file. If it grows larger than the specified size, it will signal the owning RollingFileAppender
to trigger the rollover of the existing active file.
SizeBasedTriggeringPolicy
accepts only one parameter, namely maxFileSize, with a default value of 10 MB.
The maxFileSize option can be specified in bytes, kilobytes, megabytes or gigabytes by suffixing a numeric value with KB, MB and respectively GB. For example, 5000000, 5000KB, 5MB and 2GB are all valid values, with the first three being equivalent.
Here is a sample configuration with a RollingFileAppender
in conjunction with SizeBasedTriggeringPolicy
triggering rollover when the log file reaches 5MB in size.
Example: Sample configuration of a RollingFileAppender
using a SizeBasedTriggeringPolicy
(logback-examples/src/main/resources/chapters/appenders/conf/logback-RollingSizeBased.xml)
<configuration> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>test.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <fileNamePattern>test.%i.log.zip</fileNamePattern> <minIndex>1</minIndex> <maxIndex>3</maxIndex> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <maxFileSize>5MB</maxFileSize> </triggeringPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="FILE" /> </root> </configuration>
file:///D:/jar/logback-1.1.7/docs/manual/appenders.html#TimeBasedRollingPolicy
https://yq.aliyun.com/articles/25530
26.2 Console output
The default log configuration will echo messages to the console as they are written. By default ERROR
, WARN
and INFO
level messages are logged. You can also enable a “debug” mode by starting your application with a --debug
flag.
$ java -jar myapp.jar --debug
you can also specify |
When the debug mode is enabled, a selection of core loggers (embedded container, Hibernate and Spring) are configured to output more information. Enabling the debug mode does not configure your application log all messages with DEBUG
level.
If your terminal supports ANSI, color output will be used to aid readability. You can set spring.output.ansi.enabled
to a supported value to override the auto detection.
Color coding is configured using the %clr
conversion word. In its simplest form the converter will color the output according to the log level, for example:
%clr(%5p)
The mapping of log level to a color is as follows:
Level | Color |
---|---|
|
Red |
|
Red |
|
Yellow |
|
Green |
|
Green |
|
Green |
Alternatively, you can specify the color or style that should be used by providing it as an option to the conversion. For example, to make the text yellow:
%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}
The following colors and styles are supported:
blue
cyan
faint
green
magenta
red
yellow
26.5 Custom log configuration
The various logging systems can be activated by including the appropriate libraries on the classpath, and further customized by providing a suitable configuration file in the root of the classpath, or in a location specified by the Spring Environment
property logging.config
.
Since logging is initialized before the |
Depending on your logging system, the following files will be loaded:
Logging System | Customization |
---|---|
Logback |
|
Log4j |
|
Log4j2 |
|
JDK (Java Util Logging) |
|
When possible we recommend that you use the |
There are known classloading issues with Java Util Logging that cause problems when running from an ‘executable jar’. We recommend that you avoid it if at all possible. |
To help with the customization some other properties are transferred from the Spring Environment
to System properties:
Spring Environment | System Property | Comments |
---|---|---|
|
|
The conversion word that’s used when logging exceptions. |
|
|
Used in default log configuration if defined. |
|
|
Used in default log configuration if defined. |
|
|
The log pattern to use on the console (stdout). (Not supported with JDK logger.) |
|
|
The log pattern to use in a file (if LOG_FILE enabled). (Not supported with JDK logger.) |
|
|
The format to use to render the log level (default |
|
|
The current process ID (discovered if possible and when not already defined as an OS environment variable). |
All the logging systems supported can consult System properties when parsing their configuration files. See the default configurations in spring-boot.jar
for examples.
If you want to use a placeholder in a logging property, you should use Spring Boot’s syntax and not the syntax of the underlying framework. Notably, if you’re using Logback, you should use
|
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-logging.html
默认情况下,Spring Boot的日志是输出到控制台的,不写入任何日志文件。
要让Spring Boot输出日志文件,最简单的方式是在application.properties配置文件中配置logging.path键值,如下:(日志文件为spring.log)
logging.path=/var/log
第二种方法是在application.properties配置文件中配置logging.file键值,如下:
logging.file=/var/log/myapp.log
这两种配置方法适用于开发阶段,对于部署则存在一定的问题。比如部署到不同的环境,可能就存在需要修改application.properties文件的情况,这就意味着需要重新打包,再次部署,显得不便捷。
有鉴于此,Spring Boot提供了一种覆写application.properties配置文件中键值的方法,在命令行通过指定参数来实现覆写——在运行时把命令行参数当作标准的系统属性,如下:
java -jar -Dlogging.path=/tmp myapp.jar
最后,还可以在命令行调用Spring Boot的Maven插件时覆写这个值。但是,直接使用系统属性对于插件方式是无效的。需要使用run.jvmArguments参数来指定系统属性,设置想要的值:
mvn spring-boot:run -Drun.jvmArguments="-Dlogging.path=/tmp"
一切都变得很完美了!
http://m.blog.csdn.net/article/details?id=50737925
<appender>:
<appender>是<configuration>的子节点,是负责写日志的组件。
<appender>有两个必要属性name和class。name指定appender名称,class指定appender的全限定名。
1.ConsoleAppender:
把日志添加到控制台,有以下子节点:
<encoder>:对日志进行格式化。(具体参数稍后讲解 )
<target>:字符串 System.out 或者 System.err ,默认 System.out ;
rollingPolicy:
TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。有以下子节点:
<fileNamePattern>:
必要节点,包含文件名及“%d”转换符, “%d”可以包含一个java.text.SimpleDateFormat指定的时间格式,如:%d{yyyy-MM}。如果直接使用 %d,默认格式是 yyyy-MM-dd。
RollingFileAppender 的file字节点可有可无,通过设置file,可以为活动文件和归档文件指定不同位置,当前日志总是记录到file指定的文件(活动文件),活动文件的名字不会改变;如果没设置file,活动文件的名字会根据fileNamePattern 的值,每隔一段时间改变一次。“/”或者“\”会被当做目录分隔符。
http://blog.csdn.net/haidage/article/details/6794529 good
logback-spring.xml
Logback的核心对象:Logger、Appender、Layout
Logback主要建立于Logger、Appender 和 Layout 这三个类之上。
Logger:日志的记录器,把它关联到应用的对应的context上后,主要用于存放日志对象,也可以定义日志类型、级别。Logger对象一般多定义为静态常量
Appender:用于指定日志输出的目的地,目的地可以是控制台、文件、远程套接字服务器、 MySQL、 PostreSQL、Oracle和其他数据库、 JMS和远程UNIX Syslog守护进程等。
Layout:负责把事件转换成字符串,格式化的日志信息的输出。具体的Layout通配符,可以直接查看帮助文档。
3、Level 有效级别
Logger可以被分配级别。级别包括:TRACE、DEBUG、INFO、WARN和ERROR,定义于ch.qos.logback.classic.Level类。程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少。如果设置级别为INFO,则优先级高于等于INFO级别(如:INFO、 WARN、ERROR)的日志信息将可以被输出,小于该级别的如DEBUG将不会被输出。为确保所有logger都能够最终继承一个级别,根logger总是有级别,默认情况下,这个级别是DEBUG
4、 三值逻辑
Logback的过滤器基于三值逻辑(ternary logic),允许把它们组装或成链,从而组成任意的复合过滤策略。过滤器很大程度上受到Linux的iptables启发。这里的所谓三值逻辑是说,过滤器的返回值只能是ACCEPT、DENY和NEUTRAL的其中一个。
如果返回DENY,那么记录事件立即被抛弃,不再经过剩余过滤器;
如果返回NEUTRAL,那么有序列表里的下一个过滤器会接着处理记录事件;
如果返回ACCEPT,那么记录事件被立即处理,不再经过剩余过滤器。
5、Filter 过滤器
Logback-classic提供两种类型的过滤器:常规过滤器和TuroboFilter过滤器。Logback整体流程:Logger 产生日志信息;Layout修饰这条msg的显示格式;Filter过滤显示的内容;Appender具体的显示,即保存这日志信息的地方。
Java项目中一般都会应用比如struts、spring、hibernate等开源框架,而这些框架很多是应用log4j记录日志的,所以我们考虑用log4j + slf4j + logback 。这样我们需要导入log4j-over-slf4j-1.6.4.jar 、logback-classic-1.0.1.jar 、logback-core-1.0.1.jar 、slf4j-api-1.6.4.jar ,如果你要用到EvaluatorFilter过滤器来过滤日志Msg中的特殊字符需要导入其依赖包 janino-2.3.2.jar
http://www.cnblogs.com/yongze103/archive/2012/05/05/2484753.html
Coloring
Grouping by parentheses as explained above allows coloring of sub-patterns. As of version 1.0.5, PatternLayout recognizes "%black", "%red", "%green","%yellow","%blue", "%magenta","%cyan", "%white", "%gray", "%boldRed","%boldGreen", "%boldYellow", "%boldBlue", "%boldMagenta""%boldCyan", "%boldWhite" and "%highlight" as conversion words. These conversion words are intended to contain a sub-pattern. Any sub-pattern enclosed by a coloring word will be output in the specified color.
Below is a configuration file illustrating coloring. Note the %cyan conversion specifier enclosing "%logger{15}". This will output the logger name abbreviated to 15 characters in cyan. The %highlight conversion specifier prints its sub-pattern in bold-red for events of level ERROR, in red for WARN, in BLUE for INFO, and in the default color for other levels.
Example: Highlighting levels (logback-examples/src/main/resources/chapters/layouts/highlighted.xml) View as .groovy
<configuration debug="true">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- On Windows machines setting withJansi to true enables ANSI
color code interpretation by the Jansi library. This requires
org.fusesource.jansi:jansi:1.8 on the class path. Note that
Unix-based operating systems such as Linux and Mac OS X
support ANSI color codes by default. -->
<withJansi>true</withJansi>
<encoder>
<pattern>[%thread] %highlight(%-5level) %cyan(%logger{15}) - %msg %n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Here is the corresponding output:
It takes very few lines of code to create a coloring conversion word. The section entitled creating a custom conversion specifier discusses the steps necessary for registering a conversion word in your configuration file.
http://logback.qos.ch/manual/layouts.html
SizeBasedTriggeringPolicy
<configuration> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>test.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <fileNamePattern>test.%i.log.zip</fileNamePattern> <minIndex>1</minIndex> <maxIndex>3</maxIndex> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <maxFileSize>5MB</maxFileSize> </triggeringPolicy> <encoder> <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="FILE" /> </root> </configuration>
http://blog.csdn.net/huozhonbin/article/details/12560617
下载对于的JAR 包:
http://logback.qos.ch/
logback-access-1.1.2.jar
logback-classic-1.1.2.jar
logback-core-1.1.2.jar
http://www.slf4j.org/
slf4j-api-1.7.10.jar
mvaven , 配置如下:
<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.3</version> </dependency><dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-access</artifactId> <version>1.1.3</version> </dependency><dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.3</version> </dependency><dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency>
将logback.xml 放置到web工程的classes目路下,运行项目
http://www.cnblogs.com/dragonflyyi/p/4245250.html
- LogBack在类路径下尝试查找logback.groovy的文件。
- 如果logback.groovy没有找到,就在类路径下查找logback-test.xml文件。
- 若logback-test.xml文件没有找到,就会在类路径下查找logback.xml文件(自己使用的就是这种方式,将logback.xml配置文件放到类路径下)。
- 如果都找不到,LogBack就会使用BasicConfigurator启动默认配置,该配置会将日志输出到控制上。
http://blog.csdn.net/wangdongsong1229/article/details/17463113
Code:
package com.wisely.ch7_7; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @SpringBootApplication public class Ch77Application { private static final Logger LOGGER = LoggerFactory.getLogger(Ch77Application.class); @RequestMapping(value = "/search", produces = {MediaType.APPLICATION_JSON_VALUE}) public Person search(String personName) { LOGGER.info("info level"); LOGGER.error("error level"); LOGGER.warn("warn level"); LOGGER.debug("debug level"); LOGGER.info("info level"); return new Person(personName, 32, "shanghai"); } public static void main(String[] args) { SpringApplication.run(Ch77Application.class, args); } }
package com.wisely.ch7_7; public class Person { private String name; private Integer age; private String address; public Person() { super(); } public Person(String name, Integer age, String address) { super(); this.name = name; this.age = age; this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.wisely</groupId> <artifactId>ch7_7</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>ch7_7</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.0.M1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> <pluginRepository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> </project>
一、logback的介绍
Logback是由log4j创始人设计的又一个开源日志组件。logback当前分成三个模块:logback-core,logback- classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个 改良版本。此外logback-classic完整实现SLF4J API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging。logback-access访问模块与Servlet容器集成提供通过Http来访问日志的功能。 Logback是要与SLF4J结合起来用两个组件的官方网站如下:
logback的官方网站: http://logback.qos.ch
SLF4J的官方网站:http://www.slf4j.org
本文章用到的组件如下:请自行到官方网站下载!
logback-access-1.0.0.jar
logback-classic-1.0.0.jar
logback-core-1.0.0.jar
slf4j-api-1.6.0.jar
maven配置
<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.11</version> </dependency>
这样依赖包全部自动下载了!
二、logback取代 log4j的理由:
Logback和log4j是非常相似的,如果你对log4j很熟悉,那对logback很快就会得心应手。下面列了logback相对于log4j的一些优点:
1、更快的实现 Logback的内核重写了,在一些关键执行路径上性能提升10倍以上。而且logback不仅性能提升了,初始化内存加载也更小了。
2、非常充分的测试 Logback经过了几年,数不清小时的测试。Logback的测试完全不同级别的。在作者的观点,这是简单重要的原因选择logback而不是log4j。
3、Logback-classic非常自然实现了SLF4j Logback-classic实现了 SLF4j。在使用SLF4j中,你都感觉不到logback-classic。而且因为logback-classic非常自然地实现了SLF4J, 所 以切换到log4j或者其他,非常容易,只需要提供成另一个jar包就OK,根本不需要去动那些通过SLF4JAPI实现的代码。
4、非常充分的文档 官方网站有两百多页的文档。
5、自动重新加载配置文件 当配置文件修改了,Logback-classic能自动重新加载配置文件。扫描过程快且安全,它并不需要另外创建一个扫描线程。这个技术充分保证了应用程序能跑得很欢在JEE环境里面。
6、Lilith Lilith是log事件的观察者,和log4j的chainsaw类似。而lilith还能处理大数量的log数据 。
7、谨慎的模式和非常友好的恢复 在谨慎模式下,多个FileAppender实例跑在多个JVM下,能 够安全地写道同一个日志文件。RollingFileAppender会有些限制。Logback的FileAppender和它的子类包括 RollingFileAppender能够非常友好地从I/O异常中恢复。
8、配置文件可以处理不同的情况 开发人员经常需要判断不同的Logback配置文件在不同的环境下(开发,测试,生产)。而这些配置文件仅仅只有一些很小的不同,可以通过,和来实现,这样一个配置文件就可以适应多个环境。
9、Filters(过滤器) 有些时候,需要诊断一个问题,需要打出日志。在log4j,只有降低日志级别,不过这样会打出大量的日志,会影响应用性能。在Logback,你可以继续 保持那个日志级别而除掉某种特殊情况,如alice这个用户登录,她的日志将打在DEBUG级别而其他用户可以继续打在WARN级别。要实现这个功能只需 加4行XML配置。可以参考MDCFIlter 。
10、SiftingAppender(一个非常多功能的Appender) 它可以用来分割日志文件根据任何一个给定的运行参数。如,SiftingAppender能够区别日志事件跟进用户的Session,然后每个用户会有一个日志文件。
11、自动压缩已经打出来的log RollingFileAppender在产生新文件的时候,会自动压缩已经打出来的日志文件。压缩是个异步过程,所以甚至对于大的日志文件,在压缩过程中应用不会受任何影响。
12、堆栈树带有包版本 Logback在打出堆栈树日志时,会带上包的数据。
13、自动去除旧的日志文件 通过设置TimeBasedRollingPolicy或者SizeAndTimeBasedFNATP的maxHistory属性,你可以控制已经产生日志文件的最大数量。如果设置maxHistory 12,那那些log文件超过12个月的都会被自动移除。
总之,logback比log4j太优秀了,让我们的应用全部建立logback上吧 !
三、Logback的配置介绍
1、Logger、appender及layout
Logger作为日志的记录器,把它关联到应用的对应的context上后,主要用于存放日志对象,也可以定义日志类型、级别。
Appender主要用于指定日志输出的目的地,目的地可以是控制台、文件、远程套接字服务器、 MySQL、 PostreSQL、 Oracle和其他数据库、 JMS和远程UNIX Syslog守护进程等。
Layout 负责把事件转换成字符串,格式化的日志信息的输出。
2、logger context
各个logger 都被关联到一个 LoggerContext,LoggerContext负责制造logger,也负责以树结构排列各 logger。其他所有logger也通过org.slf4j.LoggerFactory 类的静态方法getLogger取得。 getLogger方法以 logger 名称为参数。用同一名字调用LoggerFactory.getLogger 方法所得到的永远都是同一个logger对象的引用。
3、有效级别及级别的继承
Logger 可以被分配级别。级别包括:TRACE、DEBUG、INFO、WARN 和 ERROR,定义于 ch.qos.logback.classic.Level类。如果 logger没有被分配级别,那么它将从有被分配级别的最近的祖先那里继承级别。root logger 默认级别是 DEBUG。
4、打印方法与基本的选择规则
打印方法决定记录请求的级别。例如,如果 L 是一个 logger 实例,那么,语句 L.info("..")是一条级别为 INFO 的记录语句。记录请求的级别在高于或等于其 logger 的有效级别时被称为被启用,否则,称为被禁用。记录请求级别为 p,其 logger的有效级别为 q,只有则当 p>=q时,该请求才会被执行。
该规则是 logback 的核心。级别排序为: TRACE < DEBUG < INFO < WARN < ERROR。
http://www.cnblogs.com/yuanermen/archive/2012/02/13/2348942.html
LogBack入门实践
一、简介
LogBack是一个日志框架,它是Log4j作者Ceki的又一个日志组件。
LogBack,Slf4j,Log4j之间的关系
slf4j是The Simple Logging Facade for Java的简称,是一个简单日志门面抽象框架,它本身只提供了日志Facade API和一个简单的日志类实现,一般常配合Log4j,LogBack,java.util.logging使用。Slf4j作为应用层的Log接入时,程序可以根据实际应用场景动态调整底层的日志实现框架(Log4j/LogBack/JdkLog...);
LogBack和Log4j都是开源日记工具库,LogBack是Log4j的改良版本,比Log4j拥有更多的特性,同时也带来很大性能提升。
LogBack官方建议配合Slf4j使用,这样可以灵活地替换底层日志框架。
LogBack的结构
LogBack分为3个组件,logback-core, logback-classic 和 logback-access。
其中logback-core提供了LogBack的核心功能,是另外两个组件的基础。
logback-classic则实现了Slf4j的API,所以当想配合Slf4j使用时,则需要引入这个包。
logback-access是为了集成Servlet环境而准备的,可提供HTTP-access的日志接口。
Log的行为级别
OFF、
FATAL、
ERROR、
WARN、
INFO、
DEBUG、
ALL
从下向上,当选择了其中一个级别,则该级别向下的行为是不会被打印出来。
举个例子,当选择了INFO级别,则INFO以下的行为则不会被打印出来。
二、slf4j与logback结合使用原理
我们从java代码最简单的获取logger开始
Logger logger = LoggerFactory.getLogger(xxx.class.getName());
LoggerFactory是slf4j的日志工厂,获取logger方法就来自这里。
public static Logger getLogger(String name) { ILoggerFactory iLoggerFactory = getILoggerFactory(); return iLoggerFactory.getLogger(name); }
这个方法里面有分为两个过程。
第一个过程是获取ILoggerFactory,就是真正的日志工厂。
第二个过程就是从真正的日志工厂中获取logger。
第一个过程又分为三个部分。
第一个部分加载org/slf4j/impl/StaticLoggerBinder.class文件
paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);//STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class"
第二部分随机选取一个StaticLoggerBinder.class来创建一个单例
当项目中存在多个StaticLoggerBinder.class文件时,运行项目会出现以下日志:
SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/C:/Users/zhangheng5/.m2/repository/ch/qos/logback/logback-classic/1.1.3/logback-classic-1.1.3.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/C:/Users/zhangheng5/.m2/repository/org/slf4j/slf4j-log4j12/1.7.12/slf4j-log4j12-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
最后会随机选择一个StaticLoggerBinder.class来创建一个单例
StaticLoggerBinder.getSingleton()
第三部分返回一个ILoggerFactory实例
StaticLoggerBinder.getSingleton().getLoggerFactory();
所以slf4j与其他实际的日志框架的集成jar包中,都会含有这样的一个org/slf4j/impl/StaticLoggerBinder.class类文件,并且提供一个ILoggerFactory的实现。
第二个过程就是每一个和slf4j集成的日志框架中实现ILoggerFactory方法getLogger()的实例所做的事了。
三、slf4j与logback结合使用实践
第一步引入jar包
slf4j-api
logback-core
logback-classic(含有对slf4j的集成包)
<!-- slf4j-api --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency> <!-- logback --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.3</version> </dependency>
第二步编写简单的logback配置文件
<?xml version="1.0" encoding="UTF-8"?> <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>
文件位置位于src/main/resources下,名字默认为logback.xml。
当然,logback也支持groovy格式的配置文件,如果你会用那更好。
接下来,自己随便写一个类调用一下logger
package log.test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author jiangmitiao * @date 2016/3/24 * @description TODO */ public class Foo { public static void doIt(){ Logger logger = LoggerFactory.getLogger(Foo.class.getName()); logger.debug("let`s do it"); } } package log.test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyApp1 { public static void main(String[] args) { Logger logger = LoggerFactory.getLogger(MyApp1.class.getName()); logger.info("before"); Foo.doIt(); logger.info("after"); try { int i = 10 / 0; } catch (Exception e) { logger.error("errorTest",e); } } }
最后的结果是:
16:22:13.459 [main] INFO log.test.MyApp1 - before 16:22:13.463 [main] DEBUG log.test.Foo - let`s do it 16:22:13.463 [main] INFO log.test.MyApp1 - after 16:22:13.466 [main] ERROR log.test.MyApp1 - errorTest java.lang.ArithmeticException: / by zero at log.test.MyApp1.main(MyApp1.java:19) ~[classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_25] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.6.0_25] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_25] at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_25] at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) [idea_rt.jar:na]
配置规则简述
上边这么简单的配置当然是没有用的,下面这个就能够说明logback配置文件的编写规则了。
<!-- scan的意思是是否扫描 seconds是说多长时间扫描一次 --> <configuration scan="true" scanPeriod="30 seconds" debug="false" packagingData="true"> <!-- 项目名称 --> <contextName>myApp1 contextName</contextName> <!-- 属性 --> <property name="USER_HOME" value="./log"/> <!-- Insert the current time formatted as "yyyyMMdd'T'HHmmss" under the key "bySecond" into the logger context. This value will be available to all subsequent configuration elements. --> <timestamp key="bySecond" datePattern="yyyyMMdd" timeReference="contextBirth"/> <!-- appender很重要,一个配置文件会有多个appender --> <!-- ConsoleApperder意思是从console中打印出来 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- 过滤器,一个appender可以有多个 --> <!-- 阈值过滤,就是log行为级别过滤,debug及debug以上的信息会被打印出来 --> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>debug</level> </filter> <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> <!-- encoder编码规则 --> <encoder> <!--<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>--> <!--<pattern>%d %contextName %msg%n</pattern>--> <!-- pattern模式 %d时间 %thread 线程名 %level行为级别 %logger logger名称 %method 方法名称 %message 调用方法的入参消息 --> <pattern>%-4d [%thread] %highlight%-5level %cyan%logger.%-10method - %message%n</pattern> </encoder> </appender> <!-- FileAppender 输出到文件 --> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <!-- 文件存放位置 %{xxx} 就是之前定义的属性xxx --> <file>${USER_HOME}/myApp1log-${bySecond}.log</file> <encoder> <!-- %date和%d是一个意思 %file是所在文件 %line是所在行 --> <pattern>%date %level [%thread] %logger{30} [%file:%line] %msg%n</pattern> </encoder> </appender> <!-- 输出到HTML格式的文件 --> <appender name="HTMLFILE" class="ch.qos.logback.core.FileAppender"> <!-- 过滤器,这个过滤器是行为过滤器,直接过滤掉了除debug外所有的行为信息 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>debug</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <!-- HTML输出格式 可以和上边差不多 --> <layout class="ch.qos.logback.classic.html.HTMLLayout"> <pattern>%relative%thread%mdc%level%logger%msg</pattern> </layout> </encoder> <file>${USER_HOME}/test.html</file> </appender> <!-- 滚动日志文件,这个比较常用 --> <appender name="ROLLINGFILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 当project等于true的时候file就不会起效果--> <prudent>true</prudent> <!--<file>${USER_HOME}/logFile.log</file>--> <!-- 按天新建log日志 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- daily rollover --> <fileNamePattern>${USER_HOME}/logFile.%d{yyyy-MM-dd}_%i.log</fileNamePattern> <!-- 保留30天的历史日志 --> <maxHistory>30</maxHistory> <!-- 基于大小和时间,这个可以有,可以没有 --> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!-- or whenever the file size reaches 100MB --> <!-- 当一个日志大小大于10KB,则换一个新的日志。日志名的%i从0开始,自动递增 --> <maxFileSize>10KB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder> <!-- %ex就是指抛出的异常,full是显示全部,如果在{}中写入数字,则表示展示多少行 --> <pattern>%-4date [%thread] %-5level %logger{35} - %msg%n%ex{full, DISPLAY_EX_EVAL}</pattern> </encoder> </appender> <!-- 重点来了,上边都是appender输出源。这里开始就是looger了 --> <!-- name意思是这个logger管的哪一片,像下面这个管的就是log/test包下的所有文件 level是只展示什么行为信息级别以上的,类似阈值过滤器 additivity表示是否再抛出事件,就是说如果有一个logger的name是log,如果这个属性是true,另一个logger就会在这个logger处理完后接着继续处理 --> <logger name="log.test" level="INFO" additivity="false"> <!-- 连接输出源,也就是上边那几个输出源,你可以随便选几个appender --> <appender-ref ref="STDOUT"/> <appender-ref ref="ROLLINGFILE"/> <appender-ref ref="HTMLFILE"/> </logger> <!-- 这个logger详细到了类 --> <logger name="log.test.Foo" level="debug" additivity="false"> <appender-ref ref="STDOUT"/> <appender-ref ref="ROLLINGFILE"/> <appender-ref ref="HTMLFILE"/> </logger> <!-- Strictly speaking, the level attribute is not necessary since --> <!-- the level of the root level is set to DEBUG by default. --> <!-- 这就是上边logger没有管到的情况下 root默认接管所有logger --> <root level="debug"> <appender-ref ref="STDOUT"/> </root> </configuration>
四、过滤器的一些疑问
Logback的过滤器基于三值逻辑(ternary logic),允许把它们组装或成链,从而组成任意的复合过滤策略。过滤器很大程度上受到Linux的iptables启发。这里的所谓三值逻辑是说,过滤器的返回值只能是ACCEPT、DENY和NEUTRAL的其中一个。
如果返回DENY,那么记录事件立即被抛弃,不再经过剩余过滤器;
如果返回NEUTRAL,那么有序列表里的下一个过滤器会接着处理记录事件;
如果返回ACCEPT,那么记录事件被立即处理,不再经过剩余过滤器。
写一个简单的过滤器大家就明白了。
package log.test; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.filter.Filter; import ch.qos.logback.core.spi.FilterReply; public class SampleFilter extends Filter<ILoggingEvent> { @Override public FilterReply decide(ILoggingEvent event) { if (event.getMessage().contains("let")) { return FilterReply.ACCEPT; } else { return FilterReply.DENY; } } }
可以选择任意几个输出源加入这个filter
<filter class="log.test.SampleFilter" />
最后的结果是,加入该filter的输出源只能输出Foo.doIt()中的日志了。
五、总结
logback配置比较简单,官网手册也是比较容易看懂的。除上边几种输出源之外,logback还支持输出到远程套接字服务器、 MySQL、 PostreSQL、Oracle和其他数据库、 JMS和远程UNIX Syslog守护进程等等。
第一次学习log方面的知识,如有错误,请不吝赐教。
相关资源:
http://logback.qos.ch/manual/index.html
http://www.cnblogs.com/mailingfeng/p/3499436.html
http://yuri-liuyu.iteye.com/blog/954038
http://www.cnblogs.com/yongze103/archive/2012/05/05/2484753.html
http://blog.csdn.net/haidage/article/details/6794509
http://my.oschina.net/jiangmitiao/blog/647902
SLF4J与Logback简介
SLF4J——Simple Logging Facade For Java,它是一个针对于各类Java日志框架的统一Facade抽象。Java日志框架众多——常用的有java.util.logging
, log4j
, logback
,commons-logging
, Spring框架使用的是Jakarta Commons Logging API (JCL)。而SLF4J定义了统一的日志抽象接口,而真正的日志实现则是在运行时决定的——它提供了各类日志框架的binding。
Logback是log4j框架的作者开发的新一代日志框架,它效率更高、能够适应诸多的运行环境,同时天然支持SLF4J。
Spring Boot Logging
Spring Boot实现了一套日志系统——它能够根据类路径上的内容来决定使用哪一种日志框架,logback
是最优先的选择。配置了logback.xml
可以利用Spring Boot提供的默认日志配置:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml"/> <logger name="org.springframework.web" level="DEBUG"/> </configuration>
这样就定义了一个<logger>
捕获org.springframework.web
的日志,日志级别是DEBUG
,base.xml
内容如下:
<included> <include resource="org/springframework/boot/logging/logback/defaults.xml" /> <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/> <include resource="org/springframework/boot/logging/logback/console-appender.xml" /> <include resource="org/springframework/boot/logging/logback/file-appender.xml" /> <root level="INFO"> <appender-ref ref="CONSOLE" /> <appender-ref ref="FILE" /> </root> </included>
Spring Boot的日志系统预先定义了一些系统变量:
${PID}
,当前进程ID${LOG_FILE}
,Spring Boot配置文件中logging.file
的值${LOG_PATH}
, Spring Boot配置文件中logging.path
的值
同时默认情况下包含另个appender
——一个是控制台,一个是文件,分别定义在console-appender.xml
和file-appender.xml
中。同时对于应用的日志级别也可以通过application.properties
进行定义:
logging.level.org.springframework.web=DEBUG logging.level.org.hibernate=ERROR
这等价于在logback.xml
配置appender
的日志级别。
ConsoleAppender
Logback使用appender
来定义日志输出,在开发过程中最常用的是将日志输出到控制台:
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <Pattern>.%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %n</Pattern> </encoder> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>TRACE</level> </filter> </appender>
<encoder>
表示对日志进行编码:
%d{HH:mm:ss.SSS}
——日志输出时间%thread
——输出日志的进程名字,这在Web应用以及异步任务处理中很有用%-5level
——日志级别,并且使用5个字符靠左对齐%logger{36}
——日志输出者的名字%msg
——日志消息%n
——平台的换行符
在这种格式下一条日志的输出结果如下:
0:12:51.012 [qtp231719230-45] DEBUG o.c.d.r.util.LoggingResponseFilter
RollingFileAppender
另一种常见的日志输出到文件,随着应用的运行时间越来越长,日志也会增长的越来越多,将他们输出到同一个文件并非一个好办法。RollingFileAppender
用于切分文件日志:
<appender name="dailyRollingFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>/data/log/app.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- daily rollover --> <FileNamePattern>rest-demo.%d{yyyy-MM-dd}.log</FileNamePattern> <!-- keep 30 days' worth of history --> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg %n</Pattern> </encoder> </appender>
其中重要的是rollingPolicy
的定义,上例中<FileNamePattern>rest-demo.%d{yyyy-MM-dd}.log</FileNamePattern>
定义了日志的切分方式——把每一天的日志归档到一个文件中,<maxHistory>30</maxHistory>
表示只保留最近30天的日志,以防止日志填满整个磁盘空间。同理,可以使用%d{yyyy-MM-dd_HH-mm}
来定义精确到分的日志切分方式。
Sentry
Sentry是一个统一的日志跟踪平台,在传统的日志管理中,都是在服务器上通过tail
, vim
等工具查看日志,并且不同的日志位置也个不相同,而Sentry则是将这些日志(主要是错误日志)通过统一的接口收集起来,并且提供跟踪、管理的功能,使得应用程序的错误、Bug能够即时被解决。
Sentry提供了Java库——Raven Java,Java应用程序能够在捕获异常后将其发送到Sentry服务器中,另一方面它包含了各类日志框架的支持,以Logbakc为例:
<dependency> <groupId>net.kencochrane.raven</groupId> <artifactId>raven-logback</artifactId> <version>6.0.0</version> </dependency>
在logback.xml
中定义appender
:
<configuration> <appender name="Sentry" class="net.kencochrane.raven.logback.SentryAppender"> <dsn>https://publicKey:secretKey@host:port/1?options</dsn> <tags>tag1:value1,tag2:value2</tags> <!-- Optional, allows to select the ravenFactory --> <!--<ravenFactory>net.kencochrane.raven.DefaultRavenFactory</ravenFactory>--> </appender> <root level="warn"> <appender-ref ref="Sentry"/> </root> </configuration>
我们推荐在这个<appender>
中加入<filter>
用于过滤ERROR
级别的日志。
http://blog.csdn.net/xiaoyu411502/article/details/48295973
72. Logging
Spring Boot has no mandatory logging dependency, except for the commons-logging
API, of which there are many implementations to choose from. To use Logback you need to include it, and some bindings for commons-logging
on the classpath. The simplest way to do that is through the starter poms which all depend onspring-boot-starter-logging
. For a web application you only need spring-boot-starter-web
since it depends transitively on the logging starter. For example, using Maven:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
Spring Boot has a LoggingSystem
abstraction that attempts to configure logging based on the content of the classpath. If Logback is available it is the first choice.
If the only change you need to make to logging is to set the levels of various loggers then you can do that in application.properties
using the "logging.level" prefix, e.g.
logging.level.org.springframework.web=DEBUG logging.level.org.hibernate=ERROR
You can also set the location of a file to log to (in addition to the console) using "logging.file".
To configure the more fine-grained settings of a logging system you need to use the native configuration format supported by the LoggingSystem
in question. By default Spring Boot picks up the native configuration from its default location for the system (e.g. classpath:logback.xml
for Logback), but you can set the location of the config file using the "logging.config" property.
If you put a logback.xml
in the root of your classpath it will be picked up from there (or logback-spring.xml
to take advantage of the templating features provided by Boot). Spring Boot provides a default base configuration that you can include if you just want to set levels, e.g.
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml"/> <logger name="org.springframework.web" level="DEBUG"/> </configuration>
If you look at that base.xml
in the spring-boot jar, you will see that it uses some useful System properties which the LoggingSystem
takes care of creating for you. These are:
${PID}
the current process ID.${LOG_FILE}
iflogging.file
was set in Boot’s external configuration.${LOG_PATH}
iflogging.path
was set (representing a directory for log files to live in).${LOG_EXCEPTION_CONVERSION_WORD}
iflogging.exception-conversion-word
was set in Boot’s external configuration.
Spring Boot also provides some nice ANSI colour terminal output on a console (but not in a log file) using a custom Logback converter. See the default base.xml
configuration for details.
If Groovy is on the classpath you should be able to configure Logback with logback.groovy
as well (it will be given preference if present).
If you want to disable console logging and write output only to a file you need a custom logback-spring.xml
that imports file-appender.xml
but notconsole-appender.xml
:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/defaults.xml" /> <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/> <include resource="org/springframework/boot/logging/logback/file-appender.xml" /> <root level="INFO"> <appender-ref ref="FILE" /> </root> </configuration>
You also need to add logging.file
to your application.properties
:
logging.file=myapplication.log
http://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html
下面是几个常用的过滤器: 1,LevelFilter: 级别过滤器,根据日志级别进行过滤。如果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。有以下子节点:<level>:设置过滤级别<onMatch>:用于配置符合过滤条件的操作<onMismatch>:用于配置不符合过滤条件的操作例如:将过滤器的日志级别配置为INFO,所有INFO级别的日志交给appender处理,非INFO级别的日志,被过滤掉。前面我已经举过例子了,这里就不做赘述了。2,ThresholdFilter: 临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝。
3,EvaluatorFilter: 求值过滤器,评估、鉴别日志是否符合指定条件。有一下子节点:
<evaluator>:鉴别器,常用的鉴别器是JaninoEventEvaluato,也是默认的鉴别器,它以任意的java布尔值表达式作为求值条件,求值条件在配置文件解释过成功被动态编译,布尔值表达式返回true就表示符合过滤条件。
evaluator有个子标签<expression>,用于配置求值条件
<onMatch>,用于配置符合过滤条件的操作
<onMismatch>,用于配置不符合过滤条件的操作
http://blog.csdn.net/u011794238/article/details/50770557
来源:https://www.cnblogs.com/softidea/p/5642174.html