一、背景
在咱们开发的过程中,可能存在如下状况:
1、有些时候咱们须要调用第三方的接口
,个别状况下,调用接口,咱们都会记录申请的入参和响应的。如果咱们本人零碎的日志和第三方的日志混合到一个日志文件中,那么可能查找日志就比拟麻烦了。 那么咱们是否能够将第三方零碎的日志独自放到另外的文件中呢?
2、或者有些时候咱们零碎须要进行数据迁徙,如果某条数据迁徙失败了,是否独自放到一个日志文件中比拟清晰呢?
二、需要
从上图中能够看到咱们的需要比较简单
1、系统启动日志和 login
模块日志记录到 springboot-spring.log
文件中。
2、第三方业务 (QQ
) 模块的日志记录到 springboot-qq.log
文件中。
3、第三方业务 (QQ
) 模块提供了一个 login(loginName)
办法,办法的入参 loginName
须要记录到 springboot-qqLoginName.log
文件中,模仿 一、背景
中提到的数据迁徙失败,记录失败的数据到独自的日志文件中。
三、技术实现
1、采纳的日志框架
此处应用 logback
来实现日志的记录,因为 SpringBoot
应用程序默认的就是采纳的 logback 来记录日志。
2、如果实现分模块、分文件记录日志
1、编写appender
,这个能够简略的了解日志须要输入到哪里。
比方:
<!-- 此处定义的日志输入到控制台 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:-}] [%thread] %-5level %logger{50}#%method:%L -%msg%n</pattern>
</encoder>
</appender>
<!-- 此处定义日志输入到 springboot-qq- 日期. 第几个.log 文件中 -->
<appender name="qqAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/springboot-qq-%d{yyyy-MM-dd}-.%i.log</fileNamePattern>
</rollingPolicy>
</appender>
2、如何实现模块输入日志
此处就须要咱们来配置 logger
了。logger 的 name
属性指定到具体的全包名,而后援用咱们下面定义的 appender
即可。
<!-- 在 QQ 这个包下的日志独自应用 qqAppender 来输入 -->
<logger name="com.huan.springboot.qq" level="info" additivity="false">
<appender-ref ref="qqAppender"/>
<appender-ref ref="stdout"/>
</logger>
配置 logger,logger 的 name 为须要独自生成文件的那个包的全包名,而后在外面援用下面定义的 appender
3、如果实现将 loginName 输入到指定的文件
其实还是应用 logger
来实现,logger 的 name
须要和 LoggerFactory.getLogger("此处写具体 logger 的 name 的值")
留神:
此处可能有一个坑,就是可能会失落类名,那么咱们如何进行解决呢?能够通过 MDC
来解决。
.... %X{CLASSNAME}#%method:%L -%msg%n
MDC.put("CLASSNAME", QQService.class.getName());
qqLoginName.info("登录用户:[{}]", loginName);
即 xml
中应用 %X{CLASSNAME}
,在java
代码中应用 MDC
存入 CLASSNAME
的值。
四、代码实现
1、编写 xml 日志文件
1、编写 appender
1、输入日志到控制台
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:-}] [%thread] %-5level %logger{50}#%method:%L -%msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
2、编写 login
模板的日志
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/springboot-spring-%d{yyyy-MM-dd}-.%i.log</fileNamePattern>
<maxHistory>7</maxHistory>
<maxFileSize>1MB</maxFileSize>
<totalSizeCap>2GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:-}] [%thread] %-5level %logger{50}#%method:%L -%msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
3、编写 qq
模板的日志
<appender name="qqAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/springboot-qq-%d{yyyy-MM-dd}-.%i.log</fileNamePattern>
<maxHistory>7</maxHistory>
<maxFileSize>1MB</maxFileSize>
<totalSizeCap>2GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:-}] [%thread] %-5level %logger{50}#%method:%L -%msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
4、编写 qq 模块 loginName 独自输入到文件的日志
<appender name="qqLoginNameAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/springboot-qqLoginName-%d{yyyy-MM-dd}-.%i.log</fileNamePattern>
<maxHistory>7</maxHistory>
<maxFileSize>1MB</maxFileSize>
<totalSizeCap>2GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:-}] [%thread] %-5level %X{CLASSNAME}#%method:%L -%msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
2、配置日志输入到具体位置
1、配置 login 模块
<root level="INFO">
<appender-ref ref="stdout"/>
<appender-ref ref="file"/>
</root>
login
模块属于咱们本人的零碎模块,此处应用 root
标签来配置。
2、配置 qq 模块
<!-- 在 QQ 这个包下的日志独自应用 qqAppender 来输入 -->
<logger name="com.huan.springboot.qq" level="info" additivity="false">
<appender-ref ref="qqAppender"/>
<appender-ref ref="stdout"/>
</logger>
此处 name
的值间接指定到了 qq
的全包名门路。
3、配置 loginName 独自输入到文件
<!-- 将所有的 QQ 登录名避免在另外的文件中 -->
<logger name="qqLoginName" level="info" additivity="false">
<appender-ref ref="qqLoginNameAppender"/>
<appender-ref ref="stdout"/>
</logger>
2、编写 QQ 模块的代码
@Component
public class QQService {private static final Logger log = LoggerFactory.getLogger(QQService.class);
// getLogger("qqLoginName") 里的 qqLoginName 须要和 logback-spring.xml 中 logger 的 name 统一,才会利用
private static final Logger qqLoginName = LoggerFactory.getLogger("qqLoginName");
public void login(String loginName) {log.info("QQ 业务: 用户:[{}]开始应用 QQ 来登录零碎", loginName);
MDC.put("CLASSNAME", QQService.class.getName());
qqLoginName.info("登录用户:[{}]", loginName);
}
}
3、编写 login 模块的代码
@RestController
public class LoginController {private static final Logger log = LoggerFactory.getLogger(LoginController.class);
@Resource
private QQService qqService;
@GetMapping("login/{loginName}")
public String login(@PathVariable("loginName") String loginName) {log.info("本人业务:用户:[{}]进行登录", loginName);
qqService.login(loginName);
return "ok";
}
}
五、运行后果
能够看到失去了咱们冀望的后果。
六、残缺代码
https://gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/springboot-logger-split-file
七、一个小知识点
在 SpringBoot 中,如果咱们要笼罩默认的 logback 配置,举荐应用 logback-spring.xml
来配置。