简记
- logback 是 springboot 到目前5.0 版本默认的日志框架, 是log4j的升级
- 异步性能效果不是很明显,性能不如 log4j2
配置说明
LogBack配置文件可以分为几个节点,其中 Configuration 是根节点,Appender、Logger、Root是Configuration的子节点。
configuration
ch.qos.logback.core.ConsoleAppender 控制台输出
ch.qos.logback.core.FileAppender 文件输出
ch.qos.logback.core.RollingFileAppender 文件滚动输出
consoleAppender
把日志添加到控制台,有如下节点:
- <encoder> : 对日志进行格式化。- <target> : 字符串System.out 或者 System.err, 默认 System.out;
FileAppender
把日志添加到文件,有如下节点:
- <file>:被写入的文件名,可以是相对目录 , 也可以是绝对目录 , 如果目录不存在则会自动创建。
- <append>:如果是true , 日志被追加到文件结尾 , 如果是false,清空现存文件 , 默认是true。
- <encoder>:对日志进行格式化
rollingFileAppender
滚动纪录文件,先将日志记录到指定文件,当符合某种条件时,将日志记录到其他文件,有如下节点:
- <file>:被写入的文件名,可以是相对目录,也可以解决目录,如果目录不存在则自动创建。
- <append>:如果是true,日志被追加到文件结尾,如果是false,清空现存文件,默认是true。
- <encoder>:对日志进行格式化。<br />
- <rollingPolicy>:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。<br />
- ch.qos.logback.core.rolling.TimeBasedRollingPolicy
- 最常用的滚动策略,根据时间来制定滚动策略,**即负责滚动也负责触发滚动**。有如下节点;<br />
- ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy
- 基于时间+大小进行滚动。是对于第一种的补充。避免单个日志文件过大,不便于阅读
- ch.qos.logback.core.rolling.FixedWindowRollingPolic
- 基于窗口滚动, 可以理解成自定义滚动规则,避免使用出现单个文件过大或者日志文件过多的情况。**需要同时配置triggeringPolicy用于指定滚动触发规则**
- <triggeringPolicy> 配合基于窗口滚动策略使用 , 用于通知何时触发滚动
- 官方只有一个策略实现类 ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy
- 观察当前活动文件的大小,如果已经大于了指定的值,它会给 RollingFileAppender 发一个信号触发对当前活动文件的轮转。
- 只接收 maxFileSize 这一个参数,它的默认值是 10 MB。
- maxFileSize 可以为字节,千字节,兆字节,千兆字节,通过在数值后面指定一个后缀 KB,MB 或者 GB。例如,5000000,5000KB,5MB 以及 2GB 都是有效的,前三个是一样的。
fileNamePattern的介绍
/wombat/foo.%d :
每天轮转(晚上零点)。由于省略了指定 %d 的日期格式,所以默认为 yyyy-MM-dd。
/wombat/%d{yyyy/MM}/foo.txt:
每个月开始的时候轮转。
/wombat/foo.%d{yyyy-ww}.log:
每周的第一天(取决于时区)轮转。
/wombat/foo%d{yyyy-MM-dd_HH}.log:
每小时轮转。
/wombat/foo%d{yyyy-MM-dd_HH-mm}.log:
每分钟轮转。
/wombat/foo%d{yyyy-MM-dd_HH-mm, UTC}.log:
每分钟轮转,时间格式为UTC。
/foo/%d{yyyy-MM, aux}/%d.log:
每天轮转。归档文件在包含年月的文件夹下。
任何斜杆或者反斜杠够会被当作文件夹分隔符。任何必要的文件夹都会在有需要的时候创建。可以将日志文件放在单独的文件夹中。
TimeBasedRollingPolicy支持文件自动压缩。如果 fileNamePattern以 .gz 或者 .zip结尾,将会启动这个特性。
例如:/wombat/foo.%d.gz:每天轮转(晚上零点),自动将归档文件压缩成 GZIP 格式
三种滚动策略
<!-- 三种滚动策略-->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logFile.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- keep 30 days' worth of history capped at 3GB total size -->
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<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>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>test.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>tests.%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>
常用的Pattern变量
<!-- 常用的Pattern变量-->
</encoder>
<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>
</encoder>
filter
1. **级别过滤器(LevelFilter)**
1. ch.qos.logback.classic.filter.LevelFilter
1. LevelFilter 根据记录级别对记录事件进行过滤。如果事件的级别等于配置的级别,过滤 器会根据 onMatch 和 onMismatch 属性接受或拒绝事件。<br />
2. **临界值过滤器(ThresholdFilter)**
1. ch.qos.logback.classic.filter.ThresholdFilter
1. 过滤掉低于指定临界值的事件
3. **求值过滤器(EvaluatorFilter)**
1. ch.qos.logback.classic.filter.EvaluatorFilter
1. 评估是否符合指定的条件
1. 子节点 evaluator 和 matcher 设置条件, 不常用
logger
设置某一个包或者具体的某一个类的日志打印级别,以及指定。logger仅有一个name属性,两个可选属性 level/addtivity。
可以包含零个或多个appender-ref,表示这个appender将会添加到logger。
- name:用来指定受此loger约束的某一个包或者具体的某一个类。
- level:用来设置打印级别,大小写无关。可选值有TRACE、DEBUG、INFO、WARN、ERROR、ALL和OFF。还有一个特俗值INHERITED 或者 同义词NULL,代表强制执行上级的级别。如果未设置此属性,那么当前logger将会继承上级的级别。
- addtivity:是否向上级logger传递打印信息,默认为true;设置为false 时,name指定的包和类的日志将不被 root配置的appender打印,当自身也不配置appender时,将没有日志输出
root
元素配置根logger。该元素有一个level属性,没有name属性,因为已经被命名 为root。Level属性的值大小写无关,其值为下面其中一个字符串:TRACE、 DEBUG, INFO、 WARN、ERROR、ALL 和 OFF。如果 root 元素没 有引用任何 appender,就会失去所有 appender。
附 完整配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<springProperty scope="context" name="logPath" source="web.upload-path"/>
<property name="LOG_HOME" value="logback-logs"/>
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%line - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!--控制台的输出级别,生产环境使用INFO只打印少量日志和异常信息 ,debug 日志在 data/logs/dev.log, 没有异常信息-->
<level>DEBUG</level>
</filter>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/error/error.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%line - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印错误日志 -->
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/warn/warn.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%line - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印错误日志 -->
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/info/info.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%line - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印INFO日志 -->
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/debug/debug.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%line - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印DEBUG日志 -->
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/trace/trace.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%line - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>TRACE</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="DEV" class="ch.qos.logback.core.FileAppender">
<file>${LOG_HOME}/dev.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%line - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!--标准日志文件只记录debug以上级别日志-->
<level>DEBUG</level>
</filter>
</appender>
<!--日志文件采用异步输出-->
<appender name="ASYNC-INFO" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>256</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="INFO"/>
</appender>
<appender name="ASYNC-DEBUG" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>256</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="DEBUG"/>
</appender>
<appender name="ASYNC-ERROR" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>256</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="ERROR"/>
</appender>
<appender name="ASYNC-WARN" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>256</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="WARN"/>
</appender>
<appender name="ASYNC-TRACE" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>256</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="TRACE"/>
</appender>
<appender name="ASYNC-DEV" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>256</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="DEV"/>
</appender>
<!--降低部分有大量日志的依赖的日志级别-->
<logger additivity="false" name="org.activiti" level="TRACE">
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
</logger>
<logger additivity="false" name="druid.sql" level="TRACE">
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
</logger>
<logger additivity="false" name="org.hibernate" level="TRACE">
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
</logger>
<logger additivity="false" name="org.freeswitch" level="TRACE">
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
</logger>
<logger additivity="false" name="com.alibaba" level="TRACE">
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
</logger>
<logger additivity="false" name="org.apache" level="TRACE">
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
</logger>
<logger additivity="false" name="org.snaker" level="TRACE">
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
</logger>
<logger additivity="false" name="springfox" level="TRACE">
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
</logger>
<logger additivity="false" name="org.springframework" level="TRACE">
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
</logger>
<logger additivity="false" name="org.elasticsearch" level="TRACE">
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
</logger>
<logger additivity="false" name="freemarker" level="TRACE">
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
</logger>
<logger additivity="false" name="io.netty" level="TRACE">
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
</logger>
<logger additivity="false" name="ws.schild" level="TRACE">
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
</logger>
<!-- 日志输出级别 -->
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC-ERROR"/>
<appender-ref ref="ASYNC-WARN"/>
<appender-ref ref="ASYNC-INFO"/>
<appender-ref ref="ASYNC-DEBUG"/>
<appender-ref ref="ASYNC-DEV"/>
</root>
</configuration>
