概念
appender
负责日志写入策略, 如写入到console、文件,日志格式,文件分隔等
layout
负责日志最终输出的格式
encoder
负责将代码中要打印的内容转换成最终将要打印的内容。
encoder 完成转换工作主要是通过 layout 来完成的。
Logger
用户打印日志的入口,一个logger只有关联上 appender 才能输出日志.
每个 Logger 都有一个父 Logger.
所有 Logger 都有一个默认的父Logger: ROOT.
ROOT Logger 没有父 Logger。
module 简介
logback-core
核心模块, appender 和 layout 在这里实现
logback-classic
提供 Logger,
logback-access
主要提供和容器的集成, 如 tomcat, jetty等
logback与log4j比较
- 内核重写、测试充分、初始化内存加载更小,这一切让logback性能和log4j相比有诸多倍的提升
- logback非常自然地直接实现了slf4j,这个严格来说算不上优点,只是这样,再理解slf4j的前提下会很容易理解logback,也同时很容易用其他日志框架替换logback
- logback有比较齐全的200多页的文档
- logback当配置文件修改了,支持自动重新加载配置文件,扫描过程快且安全,它并不需要另外创建一个扫描线程
- 支持自动去除旧的日志文件,可以控制已经产生日志文件的最大数量
(取自: www.cnblogs.com/xrq730/p/86…)
配置
下面以xml配置为例
一般在 resource下配置 logback.xml 即可.
注意: spring-boot 项目最好使用 logback-spring.xml, 因为 logback.xml 的加载会早于 application.properties, 那么在 application.properties 里定义的变量, logback 是取不到的, 而且 spring-boot 提供的一些额外功能也无法使用
<configuration>
<property name="LOG_HOME" value="${catalina.base}/logs"/>
<springProperty scope="context" name="springAppName" source="spring.application.name"/>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<property name="CONSOLE_LOG_PATTERN"
value="%clr(%green(%d{yyyy-MM-dd HH:mm:ss.SSS})){faint} %highlight(%p) %cyan(%clr([${springAppName:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}])){yellow} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<include resource="com/atour/web/logback/base.xml"/>
<turboFilter class="com.atour.concurrency.profile.ProfileTurboFilter" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoder 默认配置为PatternLayoutEncoder -->
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/sys.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/sys.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
<maxFileSize>2GB</maxFileSize>
<totalSizeCap>80GB</totalSizeCap>
<!-- 除按日志记录之外,还配置了日志文件不能超过自定大小,若超过,日志文件会以索引0开始,命名日志文件,例如sys.2018-03-25.0.log -->
<!--<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">-->
<!--<maxFileSize>2MB</maxFileSize>-->
<!--</timeBasedFileNamingAndTriggeringPolicy>-->
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!--async-->
<appender name="FILEAsync" class="ch.qos.logback.classic.AsyncAppender">
<!-- 丢弃日志的阈值, 如配置20,表示队列还剩 20% 时,丢弃 trace, debug, info 日志 -->
<discardingThreshold>20</discardingThreshold>
<!-- 队列大小 -->
<queueSize>1024</queueSize>
<!-- 真正的日志输出 -->
<appender-ref ref="FILE"/>
<!-- 是否永不阻塞 -->
<neverBlock>true</neverBlock>
<!--提取调用者数据,默认为false, 否则无法打印类信息和行号-->
<includeCallerData>true</includeCallerData>
</appender>
<appender name="SLOW_SQL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/slow.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/slow.%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>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!--async-->
<appender name="SLOWSQLAsync" class="ch.qos.logback.classic.AsyncAppender">
<!-- 丢弃日志的阈值, 如配置20,表示队列还剩 20% 时,丢弃 trace, debug, info 日志 -->
<discardingThreshold>20</discardingThreshold>
<!-- 队列大小 -->
<queueSize>1024</queueSize>
<!-- 真正的日志输出 -->
<appender-ref ref="SLOW_SQL_FILE"/>
<!-- 是否永不阻塞 -->
<neverBlock>true</neverBlock>
<!--提取调用者数据,默认为false, 否则无法打印类信息和行号-->
<includeCallerData>true</includeCallerData>
</appender>
<logger name="slow_log" level="warn" additivity="false">
<appender-ref ref="SLOWSQLAsync"/>
</logger>
<root level="INFO">
<appender-ref ref="FILEAsync"/>
</root>
</configuration>
| 属性 | 类型 | 含义 |
|---|---|---|
| debug | boolean | 是否开启 debug |
| packagingData | boolean | 是否打印每个类所在的 jar 包 |
| scan | boolean | 是否开始自动扫描 |
| scanPeriod | string | 扫描周期, 默认是毫秒, 可以指定时间单位, 如 30 seconds |
定义具体的日志输出方式
| 属性 | 含义 |
|---|---|
| name | appender 的名称 |
| class | appender 具体的处理类 |
常用的 appender 如下:
ch.qos.logback.core.ConsoleAppenderch.qos.logback.core.rolling.RollingFileAppenderch.qos.logback.classic.AsyncAppender
文件的切割侧率, 常用的有
ch.qos.logback.core.rolling.TimeBasedRollingPolicy按照日期进行分割ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy按日期进行分割, 如果单文件的大小超过限制, 会在进行分割
下面以 SizeAndTimeBasedRollingPolicy 为例
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/sys.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
<!--单个文件的大小-->
<maxFileSize>2GB</maxFileSize>
<!--所有文件的大小-->
<totalSizeCap>80GB</totalSizeCap>
</rollingPolicy>
异步输出
对于想要异步输出, 可以用如下的配置
<appender name="FILEAsync" class="ch.qos.logback.classic.AsyncAppender">
<!-- 丢弃日志的阈值, 如配置20,表示队列还剩 20% 时,丢弃 trace, debug, info 日志 -->
<discardingThreshold>20</discardingThreshold>
<!-- 队列大小 -->
<queueSize>1024</queueSize>
<!-- 真正的日志输出 -->
<appender-ref ref="FILE"/>
<!-- 是否永不阻塞 -->
<neverBlock>true</neverBlock>
<!--提取调用者数据,默认为false, 否则无法打印类信息和行号-->
<includeCallerData>true</includeCallerData>
</appender>
注意:
- 如果未配置
<file>标签, 默认的文件名为<FileNamePattern>指定的文件名, 例如: sys.2020-07-07.0.log - 如果不希望这样, 可以通过指定
<file>${LOG_HOME}/sys.log</file>来让默认的文件为 sys.log, 这样当过了一天或者文件超过大小才会分割出一个sys.2020-07-07.0.log文件
将内容装换为最终日志要输出的内容
一般使用 pattern 的形式, 如下:
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
当然也可以自定义自己的 layout
public class MySampleLayout extends LayoutBase<ILoggingEvent> {
public String doLayout(ILoggingEvent event) {
StringBuffer sbuf = new StringBuffer(128);
sbuf.append(event.getTimeStamp() - event.getLoggingContextVO.getBirthTime());
sbuf.append(" ");
sbuf.append(event.getLevel());
sbuf.append(" [");
sbuf.append(event.getThreadName());
sbuf.append("] ");
sbuf.append(event.getLoggerName();
sbuf.append(" - ");
sbuf.append(event.getFormattedMessage());
sbuf.append(CoreConstants.LINE_SEP);
return sbuf.toString();
}
}
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="chapters.layouts.MySampleLayout" />
</encoder>
定义logger
- 属性如下
| 属性 | 含义 |
|---|---|
| name | 代码里指定的日志名称或者类的全路径 |
| level | 日志输出级别 |
| additivity | 是否在父 logger 里输出, 一般设置 false, 否则会打印两份 |
- 指定 appender
用 <appender-ref ref="FILEAsync"/> 指定appender
- root 是根 logger
- 任何没有在配置中指定的logger, 都将按
<root>里的配置输出日志
其他标签
定义属性, 可以通过 ${} 引用
用于引用其他的配置
动态控制日志的级别
其他
statusListener
shutdownHook