日志框架背景
-
log4j(作者Ceki Gülcü)出来时就等到了广泛的应用(注意这里是直接使用),是Java日志事实上的标准,并成为了Apache的项目
-
Apache要求把log4j并入到JDK,SUN拒绝,并在jdk1.4版本后增加了JUL(java.util.logging)
-
毕竟是JDK自带的,JUL也有很多人用。同时还有其他日志组件,如SimpleLog等。这时如果有人想换成其他日志组件,如log4j换成JUL,因为api完全不同,就需要改动代码。
-
Apache见此,开发了JCL(Jakarta Commons Logging),即commons-logging-xx.jar。它只提供一套通用的日志接口api,并不提供日志的实现。很好的设计原则嘛,依赖抽象而非实现。这样应用程序可以在运行时选择自己想要的日志实现组件。
-
这样看上去也挺美好的,但是log4j的作者觉得JCL不好用,自己开发出slf4j,它跟JCL类似,本身不替供日志具体实现,只对外提供接口或门面。目的就是为了替代JCL。同时,还开发出logback,一个比log4j拥有更高性能的组件,目的是为了替代log4j。
-
Apache参考了logback,并做了一系列优化,推出了log4j2。
-
各个日志框架必要的配置
// 使用log4j,需要log4j.jar import org.apache.log4j.Logger; Logger logger_log4j = Logger.getLogger(Test.class); logger_log4j.info("Hello World!"); // 使用log4j2,需要log4j-api.jar、log4j-core.jar import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; Logger logger_log4j2 = LogManager.getLogger(Test.class); logger_log4j2.info("Hello World!"); // logback,需要logback-classic.jar、logback-core.jar import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.LoggerContext; Logger logger_logback = new LoggerContext().getLogger(Test.class); logger_logback.info("Hello World!"); // java.until.logging,简称jul import java.util.logging.Logger; Logger logger_jul = Logger.getLogger("java.Test");
SLF4J getLogger源码简单解析
-
部分源码
private static final Logger logger = LoggerFactory.getLogger(MDCMain.class); public static Logger getLogger(Class<?> clazz) { Logger logger = getLogger(clazz.getName()); //... return logger; } public static Logger getLogger(String name) { ILoggerFactory iLoggerFactory = getILoggerFactory(); return iLoggerFactory.getLogger(name); } public static ILoggerFactory getILoggerFactory() { if (INITIALIZATION_STATE == 0) { Class var0 = LoggerFactory.class; synchronized(LoggerFactory.class) { if (INITIALIZATION_STATE == 0) { INITIALIZATION_STATE = 1; performInitialization(); } } } switch(INITIALIZATION_STATE) { case 1: return SUBST_FACTORY; case 2: throw new IllegalStateException("org.slf4j.LoggerFactory in failed state. Original exception was thrown EARLIER. See also http://www.slf4j.org/codes.html#unsuccessfulInit"); case 3: //事实上,StaticLoggerBinder.getSingleton() //这里能直接加载到具体的实现类,log4j或logback,默认是logback,但不知道怎么找到的 //具体实现类的路径/org/slf4j/impl/StaticLoggerBinder.class return StaticLoggerBinder.getSingleton().getLoggerFactory(); case 4: return NOP_FALLBACK_FACTORY; default: throw new IllegalStateException("Unreachable code"); } } private static final void performInitialization() { bind(); if (INITIALIZATION_STATE == 3) { versionSanityCheck(); } } private static final void bind() { try { String msg; try { Set<URL> staticLoggerBinderPathSet = null; if (!isAndroid()) { //这里判断是否绑定多个路径的工厂,如果是打印日志提示,并取默认的logback //判断的路径是/org/slf4j/impl/StaticLoggerBinder.class staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet(); reportMultipleBindingAmbiguity(staticLoggerBinderPathSet); } StaticLoggerBinder.getSingleton(); INITIALIZATION_STATE = 3; reportActualBinding(staticLoggerBinderPathSet); } //... } //... } /**存在logback和log4j2冲突时打印提示,并取logback绑定 SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/D:/maven-repository/ch/qos/logback/logback-classic/1.2.11/logback-classic-1.2.11.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/D:/maven-repository/org/apache/logging/log4j/log4j-slf4j-impl/2.17.2/log4j-slf4j-impl-2.17.2.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] */
log4j2.xml详解
log4j2.x版本不再支持像1.x中的.properties后缀的文件配置方式,2.x版本配置文件后缀名只能为".xml",“.json"或者”.jsn"。
系统选择配置文件的优先级(从先到后)如下:
(1).classpath下的名为log4j2-test.json 或者log4j2-test.jsn的文件.
(2).classpath下的名为log4j2-test.xml的文件.
(3).classpath下名为log4j2.json 或者log4j2.jsn的文件.
(4).classpath下名为log4j2.xml的文件.
我们一般默认使用log4j2.xml进行命名。
-
根节点Configuration
- status:用来指定log4j本身的打印日志的级别
- monitorinterval:用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s
两个子节点: - Appenders
- Loggers(表明可以定义多个Appender和Logger).
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <!-- status="OFF" 关闭log4j2自身日志,设置为trace会有各种log4j2的日志信息。--> <Configuration status="OFF" monitorInterval="60"> </Configuration>
-
Appenders节点
常见的有三种子节点:Console、RollingFile、File
-
Console节点用来定义输出到控制台的Appender
- name:指定Appender的名字.
- target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT.
- PatternLayout:输出格式,不设置默认为:%m%n.
- File节点用来定义输出到指定位置的文件的Appender.
-
File节点用来定义输出到指定位置的文件的Appender
- name:指定Appender的名字.
- fileName:指定输出日志的目的文件带全路径的文件名.
- PatternLayout:输出格式,不设置默认为:%m%n.
- RollingFile节点用来定义超过指定条件自动删除旧的创建新的Appender.
-
RollingFile节点用来定义超过指定条件自动删除旧的创建新的Appender
- name:指定Appender的名字.
- fileName:指定输出日志的目的文件带全路径的文件名.
- PatternLayout:输出格式,不设置默认为:%m%n.
- filePattern : 指定当发生Rolling时,文件的转移和重命名规则.
- Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志.
- TimeBasedTriggeringPolicy:Policies子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am…而不是7am.
- SizeBasedTriggeringPolicy:Policies子节点,基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小.
- DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)。
-
Loggers节点,常见的有两种:Root和Logger
Root节点用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出
- level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < - AppenderRef:Root的子节点,用来指定该日志输出到哪个Appender.
- Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。
- level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
- name:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点.
- AppenderRef:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root.如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity="false"只在自定义的Appender中进行输出
-
log4j2.xml例子
<?xml version="1.0" encoding="UTF-8"?> <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <!-- 根节点Configuration:有 Appenders 和 Loggers 两个子节点。--> <!-- status="OFF" 关闭log4j2自身日志,设置为trace会有各种log4j2的日志信息。 monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数--> <configuration status="OFF" monitorInterval="60"> <!-- <property name="name">xxx</property> name是自己定义的内容,在当前内容中使用${name}:xxx的值获取,相当于设置变量 --> <properties> <!-- 服务器生产环境日志目录 --> <property name="SERVER_HOME_PATH">/home/java/logs/</property> <!-- 日志目录 --> <property name="LOG_HOME">${SERVER_HOME_PATH}</property> <!-- 日志备份目录 --> <property name="BACKUP_HOME">{LOG_HOME}/backup</property> <!-- 系统/服务名称 用于生成路径名称--> <property name="SERVER_NAME">bfs-web</property> <!-- 定义输出格式 --> <property name="PATTERN_MY">${LOG_HOME}/%date{yyyy-MM-dd}/${SERVER_NAME}/monitor-%d{yyyyMMdd-HH}.log"> <PatternLayout pattern="[%TraceId] %T %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %.36c %-4L - %msg%xEx%n"</property> </properties> <appenders> <!-- 定义控制台输出 生产环境可以去掉--> <!-- SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT --> <Console name="Console" target="SYSTEM_OUT" follow="true"> <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/> <!--设置日志格式及颜色,具体格式解释在下面引用处--> <PatternLayout pattern="[%T] [%style{%d{HH:mm:ss.SSS}}{bright,green}][%highlight{%-5level}][%style{%.36c %-4L}{bright,yellow}]: %msg%n%style{%throwable}{red}" disableAnsi="false" noConsoleNoAnsi="false"/> </Console> <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用--> <File name="FileLog" fileName="${BACKUP_HOME}/webTest.log" append="false"> <PatternLayout pattern="${PATTERN_MY}"/> </File> <!-- 生产环境文件日志 --> <!-- immediateFlush: --> <RollingRandomAccessFile name="ProductEnvLog" fileName="${LOG_HOME}/current/${SERVER_NAME}.log" immediateFlush="true" filePattern="${LOG_HOME}/%date{yyyy-MM-dd}/${SERVER_NAME}/monitor-%d{yyyyMMdd-HH}.log"> <PatternLayout pattern="[%TraceId] %T %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %.36c %-4L - %msg%xEx%n"/> <!-- 指定滚动日志的策略 --> <Policies> <!-- TimeBasedTriggeringPolicy:Policies 子节点,基于时间的滚动策略。interval 属性根据日期模式中最具体的时间单位进行翻转的频率,默认为1。 --> <TimeBasedTriggeringPolicy interval="1" modulate="true"/> <!-- SizeBasedTriggeringPolicy:Policies 子节点,基于文件大小的滚动策略。size属性用来定义每个日志文件的大小。大小可以以字节为单位指定,后缀为KB,MB或GB,例如20MB。 --> <SizeBasedTriggeringPolicy size="50MB" /> <!-- 以上两种策略2选1 --> </Policies> </RollingRandomAccessFile> </appenders> <loggers> <!-- Root:指定项目的根日志,如果没有单独指定 Logger,那么默认使用该 Root 日志输出。--> <root level="info"> <appender-ref ref="Console"/> <appender-ref ref="ProductEnvLog"/> </root> <!-- Logger:用来单独指定日志的形式。 --> <logger level="debug" name="com.bfs"/> <logger level="warn" name="org.apache.zookeeper.ZooKeeper"/> <!-- 等等自由配置 --> </loggers> </configuration>
logback
-
基本使用
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.5</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.0.11</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.11</version> </dependency>
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Demo { //只需要slf4j-api和logback-classic即可基本使用,springboot默认依赖包已存在 //这里并没有引用任何一个跟 Logback 相关的类,而是引用了 SLF4J 相关的类,这样在需要将日志框架切换为其它日志框架时,无需改动代码。 private static final Logger logger = LoggerFactory.getLogger(Demo.class); public static void main(String[] args) { logger.info("Hello world"); } }
-
分层命名规则
例如, 命名为 com.wsl 的 logger,是命名为 com.wsl.test 的 logger 的父亲,是命名为 com.wsl.test.logback 的 logger 的祖先。
在 logger 上下文中,有一个 root logger,作为所有 logger 的祖先,这是 logback 内部维护的一个 logger,并非开发者自定义的 logger。
可通过以下方式获得这个 logger :
Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
-
三个重要的类
Logger 类位于 logback-classic 模块中, 而 Appender 和 Layout 位于 logback-core 中,这意味着, Appender 和 Layout 并不关心 Logger 的存在,不依赖于 Logger,同时也能看出, Logger 会依赖于 Appender 和 Layout 的协助,日志信息才能被正常打印出来。
Appender 是绑定在 logger 上的,而 logger 又有继承关系,因此一个 logger 打印信息时的目的地 Appender 需要参考它的父亲和祖先。在 logback 中,默认情况下,如果一个 logger 打印一条信息,那么这条信息首先会打印至它自己的 Appender,然后打印至它的父亲和父亲以上的祖先的 Appender,但如果它的父亲设置了 additivity = false,那么这个 logger 除了打印至它自己的 Appender 外,只会打印至其父亲的 Appender,因为它的父亲的 additivity 属性置为了 false,开始变得忘祖忘宗了,所以这个 logger 只认它父亲的 Appender;此外,对于这个 logger 的父亲来说,如果父亲的 logger 打印一条信息,那么它只会打印至自己的 Appender中(如果有的话),因为父亲已经忘记了爷爷及爷爷以上的那些父辈了。
-
打印的方式
//这种打印日志的方式有个缺点,就是无论日志级别是什么,程序总要先拼接字符串,再内部判断一次级别 logger.debug("the message is " + msg + " from " + somebody); //这样的方式确实能避免字符串拼接的不必要损耗,但这也不是最好的方法,因为会有两次判断日志级别 if(logger.isDebugEnabled()) { logger.debug("the message is " + msg + " from " + somebody); } //有一种更好的方法,那就是提供占位符的方式,以参数化的方式打印日志 logger.debug("the message {} is from {}", msg, somebody);
-
启动时读取文件
在 classpath 中寻找 logback-test.xml文件
如果找不到 logback-test.xml,则在 classpath 中寻找 logback.groovy 文件
如果找不到 logback.groovy,则在 classpath 中寻找 logback.xml文件
如果上述的文件都找不到,则 logback 会使用 JDK 的 SPI 机制查找 META-INF/services/ch.qos.logback.classic.spi.Configurator 中的 logback 配置实现类,这个实现类必须实现 Configuration 接口,使用它的实现来进行配置
如果上述操作都不成功,logback 就会使用它自带的 BasicConfigurator 来配置,并将日志输出到 console -
基本的logback.xml
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <!-- 配置集中管理的属性 直接使用该属性的value value格式":${name} --> <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %c [%thread] %-5level %msg%n"/> <!-- 日志文件存放目录 --> <property name="log_dir" value="D:/logback_test"/> <!-- 日志输出格式: %-5level 级别从左显示5个字符宽度 %d{yyyy-MM-dd HH:mm:ss.SSS}日期 %c类的完整名称 %M为method %L为行号 %thread线程名称 %m或者%msg为信息 %n换行 --> <!-- Appender: 设置日志信息的去向,常用的有以下几个 ch.qos.logback.core.ConsoleAppender (控制台) ch.qos.logback.core.rolling.RollingFileAppender (文件大小到达指定尺 寸的时候产生一个新文件) ch.qos.logback.core.FileAppender (文件) --> <!--控制日志输出位置的Appender--> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <!--控制台输出的对象 默认System.out 改为System.err 就变为了红色字体--> <target>System.out</target> <!--日志消息格式的配置--> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${pattern}</pattern> </encoder> </appender> <!--日志文件输出appender对象--> <appender name="file" class="ch.qos.logback.core.FileAppender"> <!--日志格式配置--> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${pattern}</pattern> </encoder> <!--日志输出路径--> <file>${log_dir}/logback.log</file> </appender> <!-- 如果未设置level,那么当前logger将会继承上级的级别。 additivity: 是否向上级loger传递打印信息。默认是true。 --> <root level="INFO"> <appender-ref ref="console"/> <appender-ref ref="file"/> </root> </configuration>
-
日志拆分和归档Appender
<!--日志拆分和归档Appender--> <appender name="rolling" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--日志格式配置--> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${pattern}</pattern> </encoder> <!--日志输出路径--> <file>${log_dir}/roll_logback.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!--指定具体实现规则--> <!--按照时间和压缩格式声明拆分的文件名--> <!-- <fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd-HH-mm-ss}.log%i.gz</fileNamePattern>--> <fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd-HH}.log%i.gz</fileNamePattern> <!--日志文件的保存期限--> <maxHistory>15</maxHistory> <!--按照文件大小拆分--> <maxFileSize>10KB</maxFileSize> </rollingPolicy> </appender> <root level="INFO"> <appender-ref ref="console"/> <appender-ref ref="rolling"/> </root>
-
日志级别过滤
<appender name="rolling" class="ch.qos.logback.core.rolling.RollingFileAppender"> ... <filter class="ch.qos.logback.classic.filter.LevelFilter"> <!--日志过滤规则--> <level>INFO</level> <!--超过当前级别放行--> <onMath>ACCEPT</onMath> <!--小于当前级别拦截--> <onMismatch>DENY</onMismatch> </filter> </appender>
-
异步日志实现(root标签要放最后)
<appender name="async" class="ch.qos.logback.classic.AsyncAppender"> <!--指定某个具体的Appender实现--> <appender-ref ref="rolling"/> </appender> <root level="ALL"> <appender-ref ref="async"></appender-ref> </root>
-
自定义logger设置additivity为false,避免重复打印日志浪费空间
<!--【强制】避免重复打印日志,浪费磁盘空间,务必在日志配置文件中设置 additivity=false。--> <!--自定义logger additivity自定义logger对象是否继承rootLogger--> <logger name="com.linp.mypro1.task" level="warn" additivity="false"> <appender-ref ref="console"></appender-ref> </logger>
-
logback默认配置
<!--base.xml--> <?xml version="1.0" encoding="UTF-8"?> <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> <!--console-appender.xml--> <included> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${CONSOLE_LOG_PATTERN}</pattern> <charset>${CONSOLE_LOG_CHARSET}</charset> </encoder> </appender> </included> <!--file-appender.xml--> <included> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <encoder> <pattern>${FILE_LOG_PATTERN}</pattern> <charset>${FILE_LOG_CHARSET}</charset> </encoder> <file>${LOG_FILE}</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern> <cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart> <maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize> <totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap> <maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-7}</maxHistory> </rollingPolicy> </appender> </included> <!--defaults.xml--> <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{${LOG_DATEFORMAT_PATTERN:-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="CONSOLE_LOG_CHARSET" value="${CONSOLE_LOG_CHARSET:-${file.encoding:-UTF-8}}"/> <property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <property name="FILE_LOG_CHARSET" value="${FILE_LOG_CHARSET:-${file.encoding:-UTF-8}}"/> <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" level="WARN"/> </included>
Pattern
LOG4J PatternLayout
-
log4j占位符含义
c 使用它为输出的日志事件分类,比如对于分类 "a.b.c",模式 %c{2} 会输出 "b.c" 。 C 使用它输出发起记录日志请求的类的全名。比如对于类 "org.apache.xyz.SomeClass",模式 %C{1} 会输出 "SomeClass"。 d 使用它输出记录日志的日期,比如 %d{HH:mm:ss,SSS} 或 %d{dd MMM yyyy HH:mm:ss,SSS}。 F 在记录日志时,使用它输出文件名。 l 用它输出生成日志的调用者的地域信息。 L 使用它输出发起日志请求的行号。 m 使用它输出和日志事件关联的,由应用提供的信息。 M 使用它输出发起日志请求的方法名。 n 输出平台相关的换行符。 p 输出日志事件的优先级。 r 使用它输出从构建布局到生成日志事件所花费的时间,以毫秒为单位。 t 输出生成日志事件的线程名。 x 输出和生成日志事件线程相关的 MDC (嵌套诊断上下文)。 X 该字符后跟 MDC 键,比如 X{clientIP} 会输出保存在 MDC 中键 clientIP 对应的值。 % 百分号, %% 会输出一个 %。
Logback Pattern
-
logback占位符含义
<!-- 输出日志的logger名,可有一个整形参数,功能是缩短logger名,设置为0表示只输入logger最右边点符号之后的字符串。--> <!-- %logger mainPackage.sub.sample.Bar mainPackage.sub.sample.Bar--> <!-- %logger{5} mainPackage.sub.sample.Bar m.s.s.Bar--> %c {length } %lo {length } %logger {length } <!-- 输出执行记录请求的调用者的全限定名。参数与上面的一样。尽量避免使用,除非执行速度不造成任何问题。--> %C {length } %class {length } <!--输出上下文名称。--> %contextName %cn <!-- 输出日志的打印日志,模式语法与java.text.SimpleDateFormat 兼容。--> <!-- %d 2006-10-20 14:06:49,812 --> <!-- %date 2006-10-20 14:06:49,812 --> <!-- %d{yyyy-MM-dd HH:mm:ss.SSS} 2006-10-20 14:06:49,812 --> %d {pattern } %date {pattern } <!--输出执行记录请求的java源文件名。尽量避免使用,除非执行速度不造成任何问题。--> %F / %file <!--输出生成日志的调用者的位置信息,整数选项表示输出信息深度。--> %caller{depth} %caller{depth, evaluator-1, ... evaluator-n} <!--输出执行日志请求的行号。尽量避免使用,除非执行速度不造成任何问题。--> %L / %line <!--输出应用程序提供的信息。--> %m / %msg / %message <!--输出执行日志请求的方法名。尽量避免使用,除非执行速度不造成任何问题。--> %M / %method <!--输出平台先关的分行符“\n”或者“\r\n”。--> %n <!--输出日志级别。--> %p / %le / %level <!--输出从程序启动到创建日志记录的时间,单位是毫秒--> %r / %relative <!--输出产生日志的线程名。--> %t / %thread <!--p 为日志内容,r 是正则表达式,将p 中符合r 的内容替换为t 。--> <!--例如, "%replace(%msg){'\s', ''}"--> %replace(p ){r, t} <!--%X用于输出和当前线程相关联的NDC(嵌套诊断环境),在代码中给org.slf4j.MDC添加key/value即可增加新值--> <!--%X{testKey:-aaa} 输出testKey所对应的value,默认为aaa--> %X