参考文献:
总述
日志接口有:commons-logging、slf4j 等
实现日志的框架有:log4j、logging(JDK 自带)、logback、log4j2 等
日志级别
log4j
定义了8个级别的log(除去 OFF 和 ALL,可以说分为6个级别),
优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL
ALL
最低等级的,用于打开所有日志记录。
TRACE
很低的日志级别,一般不会使用。
DEBUG
指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。
INFO
消息在粗粒度级别上突出强调应用程序的运行过程,这个可以用于生产环境中输出程序运行的一些重要信息。
WARN
表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给开发者的一些提示。
ERROR
指出发生错误的信息,可能会导致系统出错或是宕机等,必须要避免
FATAL
指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。
OFF
最高等级,用于关闭所有日志记录。
commons-logging
Apache Commons Logging
官方地址: https://commons.apache.org/proper/commons-logging/
commons-logging 能够选择使用 log4j 还是 JDK logging。如果项目的 classpath 中包含了 log4j 的类库,就会使用 log4j,否则就使用 JDK logging。使用 commons-logging 能够灵活的选择使用那些日志方式,而且不需要修改源代码。不过现在 Apache Commons Logging 也不更新了
依赖
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
使用方法
public class Test {
public static Log LOG= LogFactory.getLog(Test.class);
public static void main(String[] args) {
LOG.debug("debug()...");
LOG.info("info()...");
LOG.error("error()...");
}
}
slf4j
SLF4J(Simple Logging Facade for Java)用作各种日志框架(java.util.logging,logback,log4j)的抽象,允许最终用户在部署时插入所需的日志框架。
依赖
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
<scope>test</scope>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
Springboot 项目不需要引入任何依赖都可以使用
使用方法:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Test{
private static final Logger logger = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) {
logger.info("Current Time: " + System.currentTimeMillis());
logger.info("Current Time: {}", System.currentTimeMillis());
logger.trace("trace log");
logger.warn("warn log");
logger.debug("debug log");
logger.error("error log");
}
}
通常输出日志开销非常大,SLF4J
通过 {}
作为占位符的方式输出字符串,相比字符串拼接的方式,效率有显著的提升。
打印信息:
INFO pers.rainsheep.Test - Current Time: 1531731149036
INFO pers.rainsheep.Test - Current Time: 1531731149040
WARN pers.rainsheep.Test - warn log
DEBUG pers.rainsheep.Test - debug log
ERROR pers.rainsheep.Test - error log
log4j
已过时,不深究
官网地址:https://logging.apache.org/log4j/1.2/
依赖
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
log4j2
官网地址:https://logging.apache.org/log4j/2.x/
Log4j 的升级版,重构 log4j 做了很多优化,提供了 logback 中可用的许多改进,同时修复了 logback 架构中的一些固有问题。
依赖
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.12.1</version>
</dependency>
Spring boot 中自带 log4j2 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>
logback
logback 和 log4j 是同一个作者创作,它是 log4j 的升级版
依赖
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>1.2.3</version>
</dependency>
springboot 不需要引入,引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
配置简介
如果没有配置文件,那么 logback 默认地会调用 BasicConfigurator ,创建一个最小化配置。最小化配置由一个关联到根 logger 的 ConsoleAppender 组成。输出用模式为 %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
的 PatternLayoutEncoder 进行格式化。
官方推荐使用的 xml 名字的格式为:logback-spring.xml
而不是 logback.xml
,因为带 spring
后缀的可以使用 <springProfile>
这个标签。
选择使用
logback 是 Spring Boot 默认的日志系统,假如对日志没有特殊要求,可以完全零配置(当然也可以自定义 logback-spring.xml 使用 SLF4J 的 logback 来输出日志)。
本人使用slf4j + log4j2
使用 slf4j2
maven 坐标
<properties>
<slf4j.version>1.7.30</slf4j.version>
<log4j.version>2.12.1</log4j.version>
</properties>
<!-- slf4j 依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log4j2 和 slf4j 桥接依赖 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- log4j2 依赖 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
测试类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Test {
private static final Logger logger = LoggerFactory.getLogger(Test.class);
public void fun(){
logger.info("{} level", "info");
}
}
配置文件命名
系统选择配置文件的优先级(从先到后)如下:
classpath
下的名为log4j2-test.json
或者log4j2-test.jsn
的文件.classpath
下的名为log4j2-test.xml
的文件.classpath
下名为log4j2.json
或者log4j2.jsn
的文件.classpath
下名为log4j2.xml
的文件.
我们一般默认使用 log4j2.xml
进行命名。如果本地要测试,可以把 log4j2-test.xml
放到 classpath
,而正式环境使用 log4j2.xml
,则在打包部署的时候不要打包 log4j2-test.xml
即可。
配置文件结点解析
-
根节点 Configuration
属性:
- status:用来指定 log4j 本身的打印日志的级别。
- monitorinterval:用于指定 log4j 自动重新配置的监测间隔时间,单位是 s,最小是 5s
子节点:
- Appenders
- Loggers (可以定义多个 Appender 和 Logger)
-
Appenders 节点
子节点:
- Console :用来定义输出到控制台的 Appender
(1)name:指定 Appender 的名字
(2)target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT
(3)PatternLayout:输出格式,不设置默认为%m%n
- File:用来定义输出到指定位置的文件的 Appender
(1)name:指定 Appender 的名字
(2)fileName:指定输出日志的目的文件,带全路径的文件名
(3)PatternLayout:输出格式,不设置默认为%m%n
- RollingFile:用来定义超过指定大小自动删除旧的并创建新的的 Appender
(1)name:指定 Appender 的名字
(2)fileName:指定输出日志的目的文件带全路径的文件名
(3)PatternLayout:输出格式,不设置默认为%m%n
(4)filePattern:指定新建日志文件的名称格式
(5)Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志
(6)TimeBasedTriggeringPolicy:Policies 子节点,基于时间的滚动策略,interval 属性用来指定多久滚动一次,默认是 1 hour。modulate=true 用来调整时间:比如现在是早上3am, interval 是4,那么第一次滚动是在 4am,接着是8am,12am...而不是 7am
(7)SizeBasedTriggeringPolicy:Policies 子节点,基于指定文件大小的滚动策略,size 属性用来定义每个日志文件的大小.
(8)DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过 max 属性)。
- Console :用来定义输出到控制台的 Appender
-
Loggers 节点
子节点:
- Root :用来指定项目的根日志,如果没有单独指定 Logger,那么就会默认使用该 Root 日志输出
(1)level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF
(2)AppenderRef:Root的子节点,用来指定该日志输出到哪个 Appender - Logger:用来单独指定日志的形式,比如要为指定包下的 class 指定不同的日志级别等。
(1)level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF
(2)name:用来指定该 Logger 所适用的类或者类所在的包全路径,继承自 Root 节点.
(3)AppenderRef:Logger 的子节点,用来指定该日志输出到哪个 Appender,如果没有指定,就会默认继承自 Root。如果指定了,那么会在指定的这个 Appender 和 Root 的 Appender 中都会输出,此时我们可以设置 Logger 的additivity="false"
只在自定义的 Appender 中进行输出。
- Root :用来指定项目的根日志,如果没有单独指定 Logger,那么就会默认使用该 Root 日志输出
-
关于日志 level
- 共有8个级别,按照从低到高为:
All < Trace < Debug < Info < Warn < Error < Fatal < OFF
:
- All:最低等级的,用于打开所有日志记录.
- Trace:是追踪,就是程序推进以下,你就可以写个 trace 输出,所以 trace 应该会特别多,不过没关系,我们可以设置最低日志级别不让他输出.
- Debug:指出细粒度信息事件对调试应用程序是非常有帮助的.
- Info:消息在粗粒度级别上突出强调应用程序的运行过程.
- Warn:输出警告及warn以下级别的日志.
- Error:输出错误信息日志.
- Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志.
- OFF:最高等级的,用于关闭所有日志记录.
- 程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少。
PatternLayout
参数:
charset #指定字符集
pattern #指定格式
alwaysWriteExceptions #默认为true,输出异常
header #可选项。包含在每个日志文件的顶部
footer #可选项。包含在每个日志文件的尾部。
格式:
######### 常见参数 #########
%c{参数} 或 %logger{参数} ##输出日志名称
%C{参数} 或 %class{参数} ##输出类型
%d{参数} ##输出时间
%F|%file ##输出文件名
highlight{pattern}{style}##高亮显示
%l ##输出错误的完整位置
%L ##输出错误行号
%m 或 %msg 或 %message ##输出错误信息
%M 或 %method ##输出方法名
%n ##输出换行符
%level{参数1}{参数2}{参数3} ##输出日志的级别
%t 或 %thread ##创建logging事件的线程名
%p # 显示该日志的等级
*/
######### 特殊符号 ############
#有些特殊符号不能直接打印,需要使用实体名称或者编号
//
& —— & 或者 &
< —— < 或者 <
> —— > 或者 >
“ —— " 或者 "
‘ —— ' 或者 '
*/
######## pattern对齐修饰 ##########
// 对齐修饰,可以指定信息的输出格式,如是否左对齐,是否留空格等。
## 编写格式为在任何pattern和%之间加入一个小数,可以是正数,也可以是负数。
## 整数表示右对齐,负数表示左对齐;
## 整数位表示输出信息的最小n个字符,如果输出信息不够n个字符,将用空格补齐;
## 小数位表示输出信息的最大字符数,如果超过n个字符,则只保留最后n个字符的信息
## (注意:保留的是后20个字符,而不是前20个字符)
*/
#示例如下
//
+ —— 右对齐,不足20个字符则在信息前面用空格补足,超过20个字符则保留原信息
%-20 —— 左对齐,不足20个字符则在信息后面用空格补足,超过20个字符则保留原信息
%.30 —— 如果信息超过30个字符,则只保留最后30个字符
+.30 —— 右对齐,不足20个字符则在信息前面用空格补足,超过30个字符则只保留最后30个字符
%-20.30 —— 左对齐,不足20个字符则在信息后面用空格补足,超过30个字符则只保留最后30个字符
模板
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="WARN" monitorInterval="30">
<!--先定义所有的appender-->
<appenders>
<!--这个输出控制台的配置-->
<console name="Console" target="SYSTEM_OUT">
<!--输出日志的格式-->
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
</console>
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用-->
<File name="log" fileName="log/test.log" append="false">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</File>
<!-- 这个会打印出所有的info及以上级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileInfo" fileName="${sys:user.home}/logs/info.log"
filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
<RollingFile name="RollingFileWarn" fileName="${sys:user.home}/logs/warn.log"
filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
<DefaultRolloverStrategy max="20"/>
</RollingFile>
<RollingFile name="RollingFileError" fileName="${sys:user.home}/logs/error.log"
filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
</appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
<logger name="org.springframework" level="INFO"></logger>
<logger name="org.mybatis" level="INFO"></logger>
<root level="all">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</configuration>