声明:本博客内容,均根据网络上的博客内容汇总而成,其中大部分内容以及在项目中进行验证和测试。主要参考文章,在文末以及注明。
1、常用的日志框架
在日常的Java开发中,常见的日志框架有如下这些:
- Log4j
最早的日志组件是Apache 提供的Log4j。Log4j 能够通过配置文件轻松的实现日志系统的管理和多样化配置,是我们接触比较早的日志组件,几乎成了java 日志的标准,如它定义的Looger、Appender、Level等概念一直沿用至今。 - JUL(Java Util Logging)
SUN 公司搞了个属于自己的日志组件,即日志框架JUL(Java Util Logging)。SUN 公司在java1.4版本中,增加了日志库(Java Util Logging),其实现基本模仿了Log4j的实现 ,因为对开发者不友好,使用成本太高和日志级别分类不清晰等问题,所有很少有开发者用。 - Logback
Logback是Log4j的作者的另一个开源日志组件,与Log4j相比,Logback重新了内核,使它的性能提升了很多,大约是Log4j的10倍,同时占用更小的内存,并且完整的实现了SLF4J API是你可以很方便的切换日志框架。 - Log4j2
Log4j2有着和Logback相同的功能,但又有自己单用的功能,比如:插件式结构、配置文件优化、异步日志等。Log4j2是Log4j的升级,它比其前身Log4j 1.x提供了重大改进,并提供了Logback中可用的许多改进,同时修复了Logback架构中的一些固有问题。 - JCL(Jakarta Commons-Logging)
Apache 推出了一个Apache Commons Logging组件,JCL只是定义了一套日志接口,支持运行时动态加载日志组件的实现,也就是说,在应用代码里,只需调用Commons Logging 的接口,底层实现可以是Log4j,也可以是Java Util Logging,由于它很出色的完成了主流日志的兼容,所以基本上在后面很长一段时间是无敌的存在。连Spring 也都是依赖JCL 进行日志管理。 - slf4j
SLF4J(Simple Logging Facade For Java)简单日志门面,和JCL功能类似,但JCL有一个致命的缺点就是算法复杂,出现问题难以排除,而SLF4J的诞生就是为了解决JCL的缺点。值得一提的是SLF4J的作者就是Log4j的作者。
2、SpringBoot默认的日志框架 Logback
在SpringBoot中,底层是Spring框架,Spring框架默认使用JCL,而SpringBoot默认集成的日志框架使用的是SLF4j+Logback组合。
因为spring-boot-starter-logging是Logback的日志实现,而Spring Boot启动项spring-boot-starter又依赖了spring-boot-starter-logging,所以Spring Boot就默认集成了Logback。
SpringBoot默认集成了Logback,可以开箱即用,非常方便。在基于SpringBoot实现的系统中,使用SLF4j方法如下:
日志记录方法的调用,不应该来直接调用日志的实现类,而是应该调用日志抽象层的方法,即直接使用SLF4j日志门面。
在代码中使用的方式如下:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogDemo{
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(LogDemo.class);
logger.info("Hello World");
}
}
默认情况下,SpringBoot内部使用logback作为系统日志实现的框架,将日志输出到控制台,不会写到日志文件。如果在application.properties或application.yml配置,这样只能配置简单的场景,保存路径、日志格式等。复杂的场景(区分 info 和 error 的日志、每天产生一个日志文件等)满足不了,只能自定义配置文件logback-spring.xml。
3、logback.xml配置文件
3.1、logback.xml配置路径
在resources文件夹下创建logback.xml,logback会自动在该目录下加载该配置文件,在该文件中对打印日志的级别、形式、保存路径等进行配置。
3.2、logback配置文件标签说明
logback配置文件如下所示,我们分别介绍每个节点和属性的意义和用法。
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!--彩色日志输出格式-->
<property name="CONSOLE_LOG_PATTERN" value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%level){blue} %clr(${PID}){magenta} %clr([%thread]){orange} %clr(%logger){cyan} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!--非彩色日志输出格式-->
<property name="PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
<!--dev文件路径:src同级目录logs,如果上级目录不存在会自动创建-->
<property name="DEV_FILE_PATH" value="./logs" />
<!-- pro文件路径 -->
<property name="PRO_FILE_PATH" value="/opt/prod/logs" />
<!-- 控制台输出 -->
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 按照每天生成输出日志文件 -->
<appender name="fileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<!--格式化输出:%d表示日期,%thread表示线程,%-5level:级别从左显示五个字符宽度,%logger{36}:logger是class的全名,后面的数字代表限制最长的字符,%msg:日志消息,%n换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
<!--滚动策略按照时间滚动-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- rollover daily 文件名称 -->
<fileNamePattern>${DEV_FILE_PATH}/output-%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- each file should be at most 10MB, keep 60 days worth of history, but at most 2GB -->
<!--单个文件大小-->
<maxFileSize>10MB</maxFileSize>
<!--日志文件保留天数-->
<maxHistory>60</maxHistory>
<!--用来指定日志文件的上限大小,到了这个值就会删除旧日志-->a
<totalSizeCap>2GB</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 按照每天生成错误日志文件 -->
<appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
<!--输出日志到src同级目录logs中的error.log文件中-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--基于大小和时间的轮转策略,当日志内容超出文件大小限制后,会自动生成一个文件来继续记录和重命名-->
<fileNamePattern>${DEV_FILE_PATH}/error-%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- each file should be at most 10MB, keep 60 days worth of history, but at most 2GB -->
<maxFileSize>10MB</maxFileSize>
<maxHistory>60</maxHistory>
<totalSizeCap>2GB</totalSizeCap>
</rollingPolicy>
</appender>
<!--开发环境:打印控制台-->
<springProfile name="dev">
<root level="INFO">
<appender-ref ref="consoleAppender" />
<appender-ref ref="fileAppender" />
<appender-ref ref="errorAppender" />
</root>
</springProfile>
<!--生产环境:输出到文件-->
<springProfile name="pro">
<!-- root日志以INFO级别输出,指定日志信息输出到哪个地方-->
<root level="INFO">
<appender-ref ref="consoleAppender" />
<appender-ref ref="fileAppender" />
<appender-ref ref="errorAppender" />
</root>
</springProfile>
</configuration>
configuration 根节点
<configuration scan="true" scanPeriod="60 seconds" debug="false">
configuration 根节点包含的属性:
- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
<configuration>的子节点有contextName、property、appender、logger、root等,其中contextName和property是属性节点,appender、root、logger是
contextName 节点
contextName:日志名,可以使用%contextName来引用。
<contextName>logback-spring-demo-dev</contextName>
如果同时存在logback.xml和logback-spring.xml,或者同时存在logback.xml和自定义的配置文件,则会先加载logback.xml,再根据application配置加载指定配置文件,或加载logback-spring,xml。如果这两个配置文件的contextName不同,就会报错:
ERROR in ch.qos.logback.classic.joran.action.ContextNameAction - Failed to rename context [logback-demo] as [logback-spring-demo-dev] java.lang.IllegalStateException: Context has been already given a name
property节点
property标签可用于自定义属性,比如定义一个,然后使用${LOG_HOME}去引用它。
<property name="log.level" value="debug"/>
<property name="log.maxHistory" value="30"/>
<property name="log.filePath" value="${catalina.base}/logs/webapps"/>
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{50} >> %msg%n"/>
appender节点
是负责写日志的组件,在这里可以理解为一个日志的渲染器,比如console日志选择器、文件渲染器。有两个必要属性name和class:
- name指定的名称,表示该渲染器的名字。
- class指定的全限定名,表示使用的输出策略,常见的有控制台输出策略和文件输出策略。
appender日志输出方式实现类:ConsoleAppender、FileAppender、RollingFileAppender、SocketAppender、SMTPAppender、DBAppender、SyslogAppender、SiftingAppender等.
平时主要使用的是ConsoleAppender和RollingFileAppender,其中ConsoleAppender是往控制台打印日志,RollingFileAppender是往磁盘文件追加日志,而且可以按照一定的设置方式动态分割日志。
控制台输出–ConsoleAppender
<property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg %n"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>
ThresholdFilter为系统定义的拦截器,例如我们用ThresholdFilter来过滤掉ERROR级别以下的日志不输出到文件中。如果不用记得注释掉,不然你控制台会发现没日志。
encoder表示输出格式,具体说明如下:
%d表示时间
%thread表示线程名
%-5level 表示日志级别,允许以五个字符长度输出
%logger{50}表示具体的日志输出者,比如类名,括号内表示长度
%msg表示具体的日志消息,就是logger.info("xxx")中的xxx
%n表示换行
%color(xxx)来指定对应列的输出颜色,可以实现控制台输出的颜色高亮
<property name="pattern-color" value="%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%thread] %highlight(%-5level) %green(%logger{50}) - %highlight(%msg) %n"/>
<appender name="CONSOLE-WITH-COLOR" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern-color}</pattern>
</encoder>
</appender>
文件输入RollingFileAppender
文件输出主要包括配置:以指定格式将日志输出到指定文件夹下的文件中,可以配置该文件的名称、最大大小、保存时间等。
<property name="LOG_HOME" value="logs"/>
<property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg %n"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/all.%d.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${pattern}</pattern>
</encoder>
</appender>
上述配置的主要内容是:以指定的格式向logs文件下的文件输出日志,文件名称格式被指定为logs/all.日期.索引号.log,日志文件最大大小为10MB,超出则创建新文件,日志文件保留三十天。索引从0开始递增,rollingPolicy指滚动粗略,具体配置如上。关于日志文件大小限制也可以使用1GB配置。
- <rollingPolicy>:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名(重命名文件)。<rollingPolicy>的作用是当发生滚动时,定义RollingFileAppender的行为,其中上面的TimeBasedRollingPolicy是最常用的滚动策略,它根据时间指定滚动策略,既负责滚动也负责触发滚动,有以下节点:
- <fileNamePattern>,必要节点,包含文件名及"%d"转换符,"%d"可以包含一个Java.text.SimpleDateFormat指定的时间格式,如%d{yyyy-MM},如果直接使用%d那么格式为yyyy-MM-dd。RollingFileAppender的file子节点可有可无,通过设置file可以为活动文件和归档文件指定不同的位置。
- <maxHistory>,可选节点,控制保留的归档文件的最大数量,如果超出数量就删除旧文件,假设设置每个月滚动且<maxHistory>是6,则只保存最近6个月的文件。
- <triggeringPolicy>:告知 RollingFileAppender 何时激活滚动。
- <encoder>是0.9.19版本之后引进的,以前的版本使用<layout>,logback极力推荐的是使用<encoder>而不是<layout>。最常用的FileAppender和它的子类的期望是使用<encoder>而不再使用<layout>
root节点
root节点实际上是配置启用哪种appender,可以添加多个appender。<root>也是<logger>元素,但是它是根logger,只有一个level属性,因为它的name就是ROOT。 如果没有指定logger,则那么所有的logger都会继承根logger的level。
<root level="INFO">
<appender-ref ref="CONSOLE-WITH-COLOR"/>
<appender-ref ref="FILE"/>
</root>
按照这样配置,表示level为info级别,启用渲染器CONSOLE-WITH-COLOR和FILE,输出日志时,控制台会按照CONSOLE定义的格式输出,而日志文件会按照CONSOLE-WITH-COLOR的配置去输出。
logger节点
<logger>用来设置某一个包或者具体某一个类的日志打印级别、以及指定<appender>。<logger>可以包含零个或者多个<appender-ref>元素,标识这个appender将会添加到这个logger。<logger>仅有一个name属性、一个可选的level属性和一个可选的additivity属性:
- name:用来指定受此logger约束的某一个包或者具体的某一个类
- level:用来设置打印级别,五个常用打印级别从低至高依次为TRACE、DEBUG、INFO、WARN、ERROR,如果未设置此级别,那么当前logger会继承上级的级别
- additivity:是否向上级logger传递打印信息,默认为true。
<!-- logger节点可以指定具体包或类的日志配置 -->
<!-- name属性为必选,指定要配置的包或类,level和additivity为可选,有缺省值 -->
<!-- level表示日志级别,这里配置info级别,表示info及以上级别的日志被输出 -->
<!-- additivity表示日志是否传递到上一级,默认为true -->
<logger name="com.apple.controller.TestController2" level="info" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
<springProfile>多环境输出日志文件
SpringBoot官方建议使用logback-spring.xml作为logback框架的自定义日志配置文件,使用logback-spring.xml而不是logback.xml,因为带-spring后缀的配置文件可以使用使用Spring扩展profile支持,提供profile多环境日志输出得功能。
Logback 配置文件中的 节点指令允许您根据配置文件激活参数(active) 选择性的包含和排查部分配置信息。根据不同环境来定义不同的日志输出,在 logback-spring.xml中使用 节点来定义,方法如下:
<!--开发环境:打印控制台-->
<springProfile name="dev">
<!--用来设置某一个包或者具体的某一个类的日志打印级别,可以让控制台输出debug-->
<logger name="com.hs" level="debug" />
<!--
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性,可以包含零个或多个appender元素。
-->
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</springProfile>
<!--生产环境:输出到文件-->
<springProfile name="pro">
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="ERROR_FILE" />
<appender-ref ref="WARN_FILE" />
</root>
</springProfile>
4、参考:
https://blog.csdn.net/u013978512/article/details/117898022
https://blog.csdn.net/belongtocode/article/details/108451092