先介绍一下springboot如何集成日志
常用处理java日志的组件有:slf4j、log4j、logback、common-logging等,LogBack是基于Log4j基础上大量改良的一种日志框架,但是它不能单独使用,推荐配合日志框架SLF4J来使用。
springboot继承了许多日志框架,但默认配置为logBack,日志级别为info,所以我们就不用引日志的依赖了,可以通过如下路径找到继承的有哪些日志框架:
在pom文件中找到spring-boot-starter-parent依赖,点击去,再依次点进:spring-boot-dependencies,spring-boot-starter,spring-boot-starter-logging,到此就可以看到原有的日志包了(logback,log4j,slf4j):
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.11.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.25</version>
<scope>compile</scope>
</dependency>
日志格式
springboot默认输入的日志格式为:
2019-03-05 10:57:51.112 INFO 45469 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/7.0.52
2019-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1358 ms
2019-03-05 10:57:51.698 INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2019-03-05 10:57:51.702 INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
下面从左边开始依次做说明:
- 日志产生的时间,精确到毫秒
- 日志级别
- PID:进程ID
- 输出日志的线程名
- 输出日志的完成类名
- 详细信息
自定义日志格式
SpringBoot默认使用的是LogBack框架,官方建议日志配置文件取名为xml名字的格式的 logback-spring.xml,而不是logback.xml,至于为什么,因为带spring后缀的可以使用<springProfile>
这个标签。
在resource下创建logback-spring.xml文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!--输出格式-->
<appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>
%d{yyyy/MM/dd-HH:mm:ss} %level [%thread] %caller{1} - %msg%n
</pattern>
</layout>
</appender>
<appender name="p6spyConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>
%msg%n
</pattern>
</layout>
</appender>
<!--输出sql文件->
<appender name="p6spyFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>
%msg%n
</pattern>
</encoder>
<!--滚动策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径-->
<fileNamePattern>logs/kernel-p6spy.%d.log</fileNamePattern>
</rollingPolicy>
</appender>
<!--输出error文件->
<appender name="fileErrorLog" 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} %level [%thread] %caller{1} - %msg%n
</pattern>
</encoder>
<!--日志记录器的滚动策略,TimeBasedRoolingPolicy 基于时间滚动策略;https://blog.youkuaiyun.com/qq_33121481/article/details/93485180-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件路径及文件名-->
<fileNamePattern>logs/kernel-provider-error.%d.log</fileNamePattern>
</rollingPolicy>
</appender>
<!--输出info文件-->
<appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!--过滤error日志-->
<level>ERROR</level>
<onMatch>DENY</onMatch>
<onMismatch>ACCEPT</onMismatch>
</filter>
<encoder>
<pattern>
%d{yyyy/MM/dd-HH:mm:ss} %level [%thread] %caller{1} - %msg%n
</pattern>
</encoder>
<!--滚动策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径-->
<fileNamePattern>logs/kernel-provider-info.%d.log</fileNamePattern>
</rollingPolicy>
</appender>
<appender name="addIntegralLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>
%d{yyyy/MM/dd-HH:mm:ss} %level [%thread] %caller{1} - %msg%n
</pattern>
</encoder>
<!--滚动策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径-->
<fileNamePattern>logs/add-integral.%d.log</fileNamePattern>
</rollingPolicy>
</appender>
<logger name="p6spy" level="INFO" additivity="false">
<appender-ref ref="p6spyConsoleAppender"/>
<appender-ref ref="p6spyFileAppender"/>
</logger>
<!--<logger>用来设置某一个包或者具体的某一个类的日志打印级别、-->
<logger name="com.dmsdbj.integral.kernel.provider.service.impl.AddIntegralServiceImpl" level="INFO" additivity="false">
<appender-ref ref="addIntegralLogAppender"/>
<appender-ref ref="consoleLog"/>
</logger>
<!--全局应用该日志配置-->
<root level="info">
<appender-ref ref="consoleLog"/>
<appender-ref ref="fileErrorLog"/>
<appender-ref ref="fileInfoLog"/>
</root>
</configuration>
ZuulFilter过滤器
我们项目用Spring Cloud 的Zuul记录接口响应数据,因为springboot中如果不认为的打印参数,日志里是没有参数信息的,排查错误时也不好排查,我们利用ZuulFilter的Post方式记录请求信息和返回数据,具体应用参见:https://blog.youkuaiyun.com/weixin_34112181/article/details/87306901
共有4个方法:
- filterType():该函数需要返回一个字符串代表过滤器的类型,而这个类型就是在http请求过程中定义的各个阶段。在zuul中默认定义了4个不同的生命周期过程类型
- pre:可以在请求被路由之前调用
- routing: 路由请求时被调用
- post:在routing和error过滤器之后被调用
- 处理请求时发生错误时被调用
- filterOrder():通过int值来定义过滤器的执行顺序,值越小越先执行
- shouldFilter():返回一个boolean类型来判断该过滤器是否要执行,所以通过此函数可实现过滤器的开关
- run():过滤器的具体逻辑