SpringBoot第8讲:SpringBoot添加Logback日志
本文是SpringBoot第8讲,对SpringBoot添加Logback日志。SpringBoot开发中如何选用日志框架呢? 出于性能等原因,Logback 目前是springboot应用日志的标配; 当然有时候在生产环境中也会考虑和三方中间件采用统一处理方式。
文章目录
- SpringBoot第8讲:SpringBoot添加Logback日志
- 1、日志框架的基础
- 1.1、关于日志框架(日志门面)
- 1.2、配置时考虑点
- 2、实现范例
- 2.1、综合范例
- 2.2、在配置前可以参考如下文章
- 2.3、商品中心配置示例
- 2.4、白龙马配置示例
- 3、参考文档
1、日志框架的基础
在学习这块时需要一些日志框架的发展和基础,同时了解日志配置时考虑的因素。
1.1、关于日志框架(日志门面)
Java日志库是最能体现Java库在进化中的渊源关系的,在理解时重点理解日志框架本身和日志门面,以及比较好的实践等。要关注其历史渊源和设计(比如桥接),而具体在使用时查询接口即可,否则会陷入JUL(Java Util Log), JCL(Commons Logging), Log4j, SLF4J, Logback,Log4j2 傻傻分不清楚的境地。
关于日志框架(日志门面)这篇文章有过详细的介绍。
开发工具篇第十四讲:日志类库详解
1.2、配置时考虑点
在配置日志时需要考虑哪些因素?
- 支持日志路径,日志level等配置
<appender-ref ref="${log.appender.application}"/>
- 日志控制配置通过application.yml下发
- 按天生成日志,当天的日志>50MB回滚
- 最多保存15天日志
- 生成的日志中Pattern自定义
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] [%traceId] %logger{5} - %msg%n</pattern>
- Pattern中添加用户自定义的MDC字段,比如用户信息(当前日志是由哪个用户的请求产生),request信息。此种方式可以通过AOP切面控制,在MDC中添加requestID,在spring-logback.xml中配置Pattern。
- 根据不同的运行环境设置Profile - dev,test,product
- 例如:huxun.gateway.profile=dev
- 对控制台,Err和全量日志分别配置
- 对第三方包路径日志控制
2、实现范例
如下两个例子基本包含了上述的考虑点:
2.1、综合范例
- application.yml
logging:
level:
root: debug
path: C:/data/logs/springboot-logback-demo
server:
port: 8080
spring:
application:
name: springboot-logback-demo
debug: false
- Spring-logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 日志根目录-->
<springProperty scope="context" name="LOG_HOME" source="logging.path" defaultValue="/data/logs/springboot-logback-demo"/>
<!-- 日志级别 -->
<springProperty scope="context" name="LOG_ROOT_LEVEL" source="logging.level.root" defaultValue="DEBUG"/>
<!-- 标识这个"STDOUT" 将会添加到这个logger -->
<springProperty scope="context" name="STDOUT" source="log.stdout" defaultValue="STDOUT"/>
<!-- 日志文件名称-->
<property name="LOG_PREFIX" value="spring-boot-logback" />
<!-- 日志文件编码-->
<property name="LOG_CHARSET" value="UTF-8" />
<!-- 日志文件路径+日期-->
<property name="LOG_DIR" value="${LOG_HOME}/%d{yyyyMMdd}" />
<!--对日志进行格式化-->
<property name="LOG_MSG" value="- | [%X{requestUUID}] | [%d{yyyyMMdd HH:mm:ss.SSS}] | [%level] | [${HOSTNAME}] | [%thread] | [%logger{36}] | --> %msg|%n "/>
<!--文件大小,默认10MB-->
<property name="MAX_FILE_SIZE" value="50MB" />
<!-- 配置日志的滚动时间 ,表示只保留最近 10 天的日志-->
<property name="MAX_HISTORY" value="10"/>
<!--输出到控制台-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- 输出的日志内容格式化-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${LOG_MSG}</pattern>
</layout>
</appender>
<!--输出到文件-->
<appender name="0" class="ch.qos.logback.core.rolling.RollingFileAppender">
</appender>
<!-- 定义 ALL 日志的输出方式:-->
<appender name="FILE_ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件路径,日志文件名称-->
<File>${LOG_HOME}/all_${LOG_PREFIX}.log</File>
<!-- 设置滚动策略,当天的日志大小超过 ${MAX_FILE_SIZE} 文件大小时候,新的内容写入新的文件, 默认10MB -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件路径,新的 ALL 日志文件名称,“ i ” 是个变量 -->
<FileNamePattern>${LOG_DIR}/all_${LOG_PREFIX}%i.log</FileNamePattern>
<!-- 配置日志的滚动时间 ,表示只保留最近 10 天的日志-->
<MaxHistory>${MAX_HISTORY}</MaxHistory>
<!--当天的日志大小超过 ${MAX_FILE_SIZE} 文件大小时候,新的内容写入新的文件, 默认10MB-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 输出的日志内容格式化-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${LOG_MSG}</pattern>
</layout>
</appender>
<!-- 定义 ERROR 日志的输出方式:-->
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 下面为配置只输出error级别的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<OnMismatch>DENY</OnMismatch>
<OnMatch>ACCEPT</OnMatch>
</filter>
<!--日志文件路径,日志文件名称-->
<File>${LOG_HOME}/err_${LOG_PREFIX}.log</File>
<!-- 设置滚动策略,当天的日志大小超过 ${MAX_FILE_SIZE} 文件大小时候,新的内容写入新的文件, 默认10MB -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件路径,新的 ERR 日志文件名称,“ i ” 是个变量 -->
<FileNamePattern>${LOG_DIR}/err_${LOG_PREFIX}%i.log</FileNamePattern>
<!-- 配置日志的滚动时间 ,表示只保留最近 10 天的日志-->
<MaxHistory>${MAX_HISTORY}</MaxHistory>
<!--当天的日志大小超过 ${MAX_FILE_SIZE} 文件大小时候,新的内容写入新的文件, 默认10MB-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 输出的日志内容格式化-->
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>${LOG_MSG}</Pattern>
</layout>
</appender>
<!-- additivity 设为false, 则logger内容不附加至root,配置以配置包下的所有类的日志的打印,级别是 ERROR-->
<logger name="org.springframework" level="ERROR" />
<logger name="org.apache.commons" level="ERROR" />
<logger name="org.apache.zookeeper" level="ERROR" />
<logger name="com.alibaba.dubbo.monitor" level="ERROR"/>
<logger name="com.alibaba.dubbo.remoting" level="ERROR" />
<!-- ${LOG_ROOT_LEVEL} 日志级别 -->
<root level="${LOG_ROOT_LEVEL}">
<!-- 标识这个"${STDOUT}"将会添加到这个logger -->
<appender-ref ref="${STDOUT}"/>
<!-- FILE_ALL 日志输出添加到 logger -->
<appender-ref ref="FILE_ALL"/>
<!-- FILE_ERROR 日志输出添加到 logger -->
<appender-ref ref="FILE_ERROR"/>
</root>
</configuration>
Profile 相关的配置可以参考:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<!-- roll by day -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/springboot-logback-demo.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<!-- dev -->
<logger name="org.springframework.web" level="INFO"/>
<root level="INFO">
<appender-ref ref="FILE" />
</root>
<!-- test or production -->
<springProfile name="test,prod">
<logger name="org.springframework.web" level="INFO"/>
<logger name="com.pdai.springboot" level="INFO"/>
<root level="INFO">
<appender-ref ref="FILE" />
</root>
</springProfile>
</configuration>
商品中心的做法:
<!--将日志输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date %5level %6relative --- [%15thread] [%-40logger{40}] [%C:%L] : [%X{traceId:-0}||%X{PtxId:-0}]
%msg%n
</pattern>
</encoder>
</appender>
%date 2006-10-20 14:06:49,812
%5level 转换说明符 %5level 表示日志记录事件的级别应该左对齐到五个字符的宽度
%6relative 输出从应用程序启动到创建日志事件所经过的毫秒数。
[%15thread] 输出生成日志事件的线程的名称。
%-40logger{40} 日志记录
[%X{traceId:-0}||%X{PtxId:-0}]
日志的使用
// case 1
@Slf4j
@Component
public class XxxProcessor {
log.info("Xxx.getByIds response={}", JsonUtils.toJson(response));
}
// case 2
public class XxxUtils {
private static final Logger logger = LoggerFactory.getLogger(XxxUtils.class);
logger.error("", e);
}
2.2、在配置前可以参考如下文章
logback的使用和logback.xml详解
2.3、商品中心配置示例
- application.yml
apollo:
bootstrap:
enabled: true
namespaces: application,dev.common,dev.drds-common
spring:
application:
name: item-platform-center
application:
name: item-platform-center
dubbo:
name: item-platform-center
provider:
filter: dubboMonitor
management:
health:
elasticsearch:
enabled: false
# mybatis-plus配置 多数据源不生效,全部移到BaseSourceConfig和OtherSourceConfig
mybatis-plus:
# Mapper 所对应的 XML 文件位置
#mapper-locations: classpath*:/mapper/**/*Mapper.xml
# 实体类根路径
#type-aliases-package: cn.gov.zcy.service.domain.dto
# 配置超类,如果配置了该属性,则仅仅会扫描路径下以该类作为父类的域对象
#type-aliases-super-type: cn.gov.zcy.service.domain.BaseEntity
configuration:
# 日志打印,需要集成扩展虚竹插件
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 开启驼峰功能
# map-underscore-to-camel-case: true
# 二级缓存
cache-enabled: false
# 关闭一级缓存
local-cache-scope: statement
global-config:
# banner 取消
banner: false
# db 配置
db-config:
# id 生成策略
id-type: auto
# 加入自己的typehandler
#type-handlers-package: cn.gov.zcy.item.infra.db.type.handlers
elasticjobs: []
-
logback-spring.xml
-
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <property name="APP_NAME" value="item-platform-center"/> <property name="level" value="${logLevel:-info}"/> <property name="mapperLevel" value="${mapperLogLevel:-info}"/> <property name="tag" value="${tags:-default}"/> <property name="rLogIp" value="${rLogIp:-127.0.0.1}"/> <property name="rLogPort" value="${rLogPort:-00}"/> <logger name="org.springframework.web" level="INFO"/> <logger name="org.reflections.Reflections" level="ERROR"/> <logger name="org.apache.dubbo" level="ERROR"/> <logger name="cn.gov.zcy.dubbo.filter" level="ERROR"/> <logger name="cn.gov.zcy.spi.framework.aop.SpiExecutionAspect" level="WARN"/> <logger name="cn.gov.zcy.spi.framework.SpiProviderManager" level="WARN"/> <logger name="cn.gov.zcy.zmq.core.ons" level="WARN"/> <logger name="cn.gov.zcy.zmq.util.DefaultZMQTemplate" level="WARN"/> <logger name="MySQL" level="WARN"/> <logger name="com.zaxxer.hikari.HikariDataSource" level="WARN"/> <logger name="cn.gov.zcy.itemplatform.infra.db.mapper" level="${mapperLevel}"/> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%date %5level %6relative --- [%15thread] [%-40logger{40}] [%C:%L] : [%X{traceId:-0}||%X{PtxId:-0}] %X{biz} %msg%n</pattern> </encoder> </appender> <root level="${level}"> <appender-ref ref="CONSOLE"/> </root> <logger name="io.terminus.license" level="OFF"/> <logger name="io.terminus.pampas.webc.controller" level="OFF"/> </configuration>
2.4、白龙马配置示例
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<conversionRule conversionWord="traceId" converterClass="com.huxun.agent.finance.util.TraceIdConverter"/>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="BASE_DIR" value="${log.dir}"/>
<property name="LOG_PATH" value="${BASE_DIR}/server/logs"/>
<!-- 控制台输出 -->
<appender name="CONSOLE" 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} %-5level [%thread] [%traceId] %logger{5} - %msg%n</pattern>
</encoder>
</appender>
<appender name="APPLICATION" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/application.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_PATH}/application.log.%d{yyyy-MM-dd}.%i</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>7</MaxHistory>
<!--日志文件最大的大小-->
<maxFileSize>1GB</maxFileSize>
<totalSizeCap>40GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] [%traceId] %logger{5} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="${log.appender.application}"/>
</root>
</configuration>
3、参考文档
-
Logback官网
-
Logback官网 文档
-
Logback中 Encoder Pattern
<encoder>
<pattern>%d{HH:mm:ss} [%thread][%X{traceId}] %-5level %logger{36} - %msg%n</pattern>
</encoder>