Spring如何按業(yè)務(wù)模塊輸出日志到不同的文件詳解
一、背景
在我們開發(fā)的過程中,可能存在如下情況:
1、有些時(shí)候我們需要調(diào)用第三方的接口,一般情況下,調(diào)用接口,我們都會(huì)記錄請(qǐng)求的入?yún)⒑晚憫?yīng)的。如果我們自己系統(tǒng)的日志和第三方的日志混合到一個(gè)日志文件中,那么可能查找日志就比較麻煩了。那么我們是否可以將第三方系統(tǒng)的日志單獨(dú)放到另外的文件中呢?
2、或者有些時(shí)候我們系統(tǒng)需要進(jìn)行數(shù)據(jù)遷移,如果某條數(shù)據(jù)遷移失敗了,是否單獨(dú)放到一個(gè)日志文件中比較清晰呢?
二、需求
從上圖中可以看到我們的需求比較簡(jiǎn)單
1、系統(tǒng)啟動(dòng)日志和 login 模塊日志記錄到 springboot-spring.log 文件中。
2、第三方業(yè)務(wù)(QQ)模塊的日志記錄到 springboot-qq.log文件中。
3、第三方業(yè)務(wù)(QQ)模塊提供了一個(gè)login(loginName)方法,方法的入?yún)oginName需要記錄到springboot-qqLoginName.log文件中,模擬一、背景中提到的數(shù)據(jù)遷移失敗,記錄失敗的數(shù)據(jù)到單獨(dú)的日志文件中。
三、技術(shù)實(shí)現(xiàn)
1、采用的日志框架
此處使用logback來完成日志的記錄,因?yàn)镾pringBoot應(yīng)用程序默認(rèn)的就是采用的logback來記錄日志。
2、如果實(shí)現(xiàn)分模塊、分文件記錄日志1、 編寫appender,這個(gè)可以簡(jiǎn)單的理解日志需要輸出到哪里。
比如:
<!-- 此處定義的日志輸出到控制臺(tái) --> <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-日期.第幾個(gè).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、如何實(shí)現(xiàn)模塊輸出日志
此處就需要我們來配置 logger了。logger的name屬性指定到具體的全包名,然后引用我們上面定義的appender即可。
<!-- 在QQ這個(gè)包下的日志單獨(dú)使用 qqAppender 來輸出 --> <logger name="com.huan.springboot.qq" level="info" additivity="false"> <appender-ref ref="qqAppender"/> <appender-ref ref="stdout"/> </logger>
配置logger,logger的name為需要單獨(dú)生成文件的那個(gè)包的全包名,然后在里面引用上面定義的appender
3、如果實(shí)現(xiàn)將loginName輸出到指定的文件
其實(shí)還是使用 logger 來實(shí)現(xiàn),logger的name需要和 LoggerFactory.getLogger("此處寫具體logger的name的值")
注意:
此處可能有一個(gè)坑,就是可能會(huì)丟失類名,那么我們?nèi)绾芜M(jìn)行解決呢?可以通過MDC來解決。
.... %X{CLASSNAME}#%method:%L -%msg%n
MDC.put("CLASSNAME", QQService.class.getName()); qqLoginName.info("登錄用戶:[{}]", loginName);
即xml中使用%X{CLASSNAME},在java代碼中使用MDC存入CLASSNAME的值。
四、代碼實(shí)現(xiàn)
1、編寫xml日志文件
1、編寫appender
1、輸出日志到控制臺(tái)
<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單獨(dú)輸出到文件的日志
<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模塊屬于我們自己的系統(tǒng)模塊,此處使用 root標(biāo)簽來配置。
2、配置qq模塊
<!-- 在QQ這個(gè)包下的日志單獨(dú)使用 qqAppender 來輸出 --> <logger name="com.huan.springboot.qq" level="info" additivity="false"> <appender-ref ref="qqAppender"/> <appender-ref ref="stdout"/> </logger>
此處name的值直接指定到了qq的全包名路徑。
3、配置loginName單獨(dú)輸出到文
<!-- 將所有的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一致,才會(huì)應(yīng)用 private static final Logger qqLoginName = LoggerFactory.getLogger("qqLoginName"); public void login(String loginName) { log.info("QQ業(yè)務(wù): 用戶:[{}]開始使用QQ來登錄系統(tǒng)", 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("自己業(yè)務(wù):用戶:[{}]進(jìn)行登錄", loginName); qqService.login(loginName); return "ok"; } }
五、運(yùn)行結(jié)果
可以看到得到了我們期望的結(jié)果。
六、完整代碼
https://gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/springboot-logger-split-file
七、一個(gè)小知識(shí)點(diǎn)
在SpringBoot中,如果我們要覆蓋默認(rèn)的logback配置,推薦使用logback-spring.xml來配置。
總結(jié)
到此這篇關(guān)于Spring如何按業(yè)務(wù)模塊輸出日志到不同文件的文章就介紹到這了,更多相關(guān)Spring輸出日志內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot基于IDEA環(huán)境熱加載與熱部署教程
這篇文章主要為大家介紹了springboot在IDEA環(huán)境下的熱加載與熱部署教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03java并發(fā)編程專題(一)----線程基礎(chǔ)知識(shí)
這篇文章主要介紹了java并發(fā)編程線程的基礎(chǔ)知識(shí),文中講解非常詳細(xì),幫助大家更好的學(xué)習(xí)JAVA并發(fā)編程,感興趣想學(xué)習(xí)JAVA的可以了解下2020-06-06解決springboot文件配置端口不起作用(默認(rèn)8080)
這篇文章主要介紹了解決springboot文件配置端口不起作用(默認(rèn)8080),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Java?Maven構(gòu)建工具中mvnd和Gradle誰更快
這篇文章主要介紹了Java?Maven構(gòu)建工具中mvnd和Gradle誰更快,mvnd?是?Maven?Daemon?的縮寫?,翻譯成中文就是?Maven?守護(hù)進(jìn)程,下文更多相關(guān)資料,需要的小伙伴可以參考一下2022-05-05SpringBoot實(shí)現(xiàn)在webapp下直接訪問html,jsp
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)在webapp下直接訪問html,jsp問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10spring-data-redis連接操作redis的實(shí)現(xiàn)
spring-data-redis則是對(duì)Jedis進(jìn)行了高度封裝,使用起來非常方便。本文主要介紹了spring-data-redis連接操作redis的實(shí)現(xiàn),感興趣的可以了解一下2021-07-07