在我们开发的过程中,可能存在如下情况:
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
来配置。
热门文章
- Glance基础服务运维_在线工具Live2D
- 12月7日 | Clash Verge每天更新19.4M/S免费节点订阅链接
- hadoop运行jar包处理文件一直处于Running job状态的解决方法
- 1月16日 | Clash Verge每天更新18.6M/S免费节点订阅链接地址
- 11月30日 | Clash Verge每天更新22.7M/S免费节点订阅链接
- 动物医院有限公司是国企吗还是私企 动物医院有限公司是国企吗还是私企啊
- 分布式一致性算法 2PC与3PC
- 动物医院主管部门是哪里 动物医院主管部门是哪里的
- 动物医院技术院长(动物医院技术院长招聘)
- 1月25日 | Clash Verge每天更新19.6M/S免费节点订阅链接地址