1. 程式人生 > >SpringBoot2 整合日誌,複雜業務下的自定義實現

SpringBoot2 整合日誌,複雜業務下的自定義實現

本文原始碼:[GitHub·點這裡](https://github.com/cicadasmile/middle-ware-parent) || [GitEE·點這裡](https://gitee.com/cicadasmile/middle-ware-parent) # 一、日誌體系整合 ## 1、日誌管理 在系統的開發中,最關鍵的一個元件工具就是日誌,日誌列印方便問題排查,或者生產事故回溯,日誌記錄用來監控並分析系統性能點,並以此為依據,不斷對系統進行優化;同時基於使用者的操作日誌,對使用者行為進行分析,開發智慧推薦的功能,或者進行營銷投放,這在系統中都是常見且關鍵的業務流程。 ## 2、ELK日誌體系 在大型系統架構中,ELK的日誌管理系統是系統必備功能,ELK-Stack是Elasticsearch、Logstash、Kiban三個開源軟體的組合,通常用來做日誌分析,實時資料檢索。基於Logstash做資料流動通道,使日誌資料不斷的流入搜尋元件,基於Elasticsearch做資料實時查詢,基於Kiban的ES視覺化介面,以此實現日誌資料的蒐集、儲存、分析等核心功能,且該體系方便擴充套件。 ELK相關文章: - **[SpringBoot2整合ElasticSearch框架](https://mp.weixin.qq.com/s/ZUj4qy7qHgmfYPTdimO-Hw)** - **[搜尋引擎框架,ElasticSearch叢集模式](https://mp.weixin.qq.com/s/Qgear9nCwXn8W98SHkXJZw)** - **[基於Logstash全量或增量同步資料到ES中介軟體](https://mp.weixin.qq.com/s/SVS9O5WF38AYbsxQilNO4g)** 基於ELK體系的核心操作,有關於ElasticSearch其他文章可以自行查閱之前的內容,這裡不在陳列,好像很多東西都是這樣一點點積累出來的。 # 二、整合環境 ## 1、專案結構 ![](https://img2020.cnblogs.com/blog/1691717/202009/1691717-20200910163916685-1233271385.png) **defined-log-api**:測試工程; **defined-log-config**:日誌核心模組,依賴之後使用該模組下註解即可; ## 2、資料表結構 ```sql CREATE TABLE dt_defined_log ( id INT ( 11 ) NOT NULL AUTO_INCREMENT COMMENT '主鍵', class_name VARCHAR ( 200 ) DEFAULT NULL COMMENT '請求類名', method_name VARCHAR ( 100 ) DEFAULT NULL COMMENT '請求方法名', method_desc VARCHAR ( 100 ) DEFAULT NULL COMMENT '請求方法描述', api_type INT ( 1 ) DEFAULT 0 COMMENT 'API型別', biz_nature INT ( 1 ) DEFAULT 0 COMMENT '業務性質型別', data_flow_type INT ( 1 ) DEFAULT 0 COMMENT '日誌資料流向', req_param VARCHAR ( 200 ) DEFAULT NULL COMMENT '請求報文', res_param VARCHAR ( 200 ) DEFAULT NULL COMMENT '響應報文', PRIMARY KEY ( `id` ) ) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '日誌記錄表'; ``` 這裡完全基於業務需求自定義即可。 # 三、核心程式碼說明 ## 1、註解引數 ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public @interface DefinedLog { /** * 操作型別 */ ApiTypeEnum apiType () ; /** * 方法描述 */ String methodDesc(); /** * 業務性質 */ BizNatureEnum bizNature() ; /** * 資料流向,與業務性質關聯 */ DataFlowEnum dataFlow() ; /** * 儲存入參 */ boolean isSaveReqParam () default true ; /** * 儲存出參 */ boolean isSaveResParam() default true ; /** * 是否需要非同步處理 */ boolean isAsync () default false ; } ``` 這裡描述一下如下幾個引數的意思: **bizNature**:業務性質,即該日誌是否有分析,或者營銷推廣操作,例如在在電商業務中,瀏覽系列商品後是否推送廣告; **dataFlow**:資料流向,即資料儲存後是否向其他資料來源推送,常見可能推送到MQ或者Redis或者分析引擎中,推薦類系統中對關鍵日誌實時性要求極高,可以基於此做使用者行為實時分析; **isAsync**:是否非同步處理,在一些併發高的介面中,避免日誌記錄成為效能問題的一個因素; 其他相關引數都是十分常見,例如介面型別增刪改查,入參出參報文儲存,方法模組的描述等等,這些都可以基於業務的需求自定義,然後做相關業務處理開發,思路開闊即可。 ## 2、切面攔截 基於切面程式設計是方式,做相關日誌處理,獲取相應引數,構建日誌模型即可。 ```java @Component @Aspect public class LogAop { private static final Logger LOGGER = LoggerFactory.getLogger(LogAop.class); @Value("${spring.application.app-id}") private String appId ; @Resource private DefineLogService defineLogService ; /** * 日誌切入點 */ @Pointcut("@annotation(com.defined.log.annotation.DefinedLog)") public void logPointCut() { } /** * 環繞切入 */ @Around("logPointCut()") public Object around (ProceedingJoinPoint proceedingJoinPoint) throws Throwable { Object result = null ; StopWatch stopWatch = new StopWatch(); stopWatch.start(); try{ // 執行方法 result = proceedingJoinPoint.proceed(); stopWatch.stop(); } catch (Exception e){ stopWatch.stop(); } finally { // 儲存日誌 LOGGER.info(" execute time: {} ms ", stopWatch.getTotalTimeMillis()); DefineLogModel defineLogModel = buildLogParam (proceedingJoinPoint); defineLogModel.setResParam(JSONObject.toJSONString(result)); defineLogService.saveLog(defineLogModel) ; } return result ; } private DefineLogModel buildLogParam (ProceedingJoinPoint point){ DefineLogModel defineLogModel = new DefineLogModel() ; MethodSignature signature = (MethodSignature) point.getSignature(); Method reqMethod = signature.getMethod(); String className = point.getTarget().getClass().getName(); Object[] reqParam = point.getArgs(); LOGGER.info("請求方法:"+reqMethod.getName()); LOGGER.info("請求類名:"+className); LOGGER.info("請求引數:"+ JSONObject.toJSONString(reqParam)); // 獲取方法上註解 reqMethod.getAnnotation(DefinedLog.class).getClass(); DefinedLog definedLog = reqMethod.getAnnotation(DefinedLog.class); // 構建引數 String methodName = reqMethod.getName() ; Integer apiType = definedLog.apiType().getApiType(); String apiTypeDesc = definedLog.apiType().getApiTypeDesc(); String methodDesc = definedLog.methodDesc() ; Integer bizNature = definedLog.bizNature().getBizNature() ; Integer dataFlowType = definedLog.dataFlow().getDataFlowType(); boolean isSaveReqParam = definedLog.isSaveReqParam(); boolean isSaveResParam = definedLog.isSaveResParam(); boolean isAsync = definedLog.isAsync() ; defineLogModel.setAppId(appId); defineLogModel.setClassName(className); defineLogModel.setMethodName(methodName); defineLogModel.setMethodDesc(methodDesc); defineLogModel.setApiType(apiType); defineLogModel.setApiTypeDesc(apiTypeDesc); defineLogModel.setBizNature(bizNature); defineLogModel.setDataFlowType(dataFlowType); defineLogModel.setSaveReqParam(isSaveReqParam); defineLogModel.setSaveResParam(isSaveResParam); defineLogModel.setAsync(isAsync); defineLogModel.setReqParam(JSONObject.toJSONString(reqParam)); return defineLogModel ; } } ``` ## 3、使用方式 DefinedLog註解在介面方法上即可。 ```java @RestController public class LogController { @GetMapping("/logApi") @DefinedLog(apiType=ApiTypeEnum.COMPOSITE, methodDesc="測試日誌", bizNature= BizNatureEnum.DEFAULT, dataFlow= DataFlowEnum.DEFAULT) public String logApi (@RequestParam("param") String param){ return "success-re" ; } } ``` ## 4、記錄引數 ![](https://img2020.cnblogs.com/blog/1691717/202009/1691717-20200910163851685-2056204354.png) 這樣自定義日誌流程就完成了。 # 四、原始碼地址 ``` GitHub·地址 https://github.com/cicadasmile/middle-ware-parent GitEE·地址 https://gitee.com/cicadasmile/middle-ware-parent ``` **推薦閱讀:微服務架構系列** | 標題| |:---| | [微服務架構:專案技術選型簡介,架構圖解說明](https://mp.weixin.qq.com/s/kxbNXupDxcuISm-vW9nhyA)| | [微服務架構:業務架構設計,系統分層管理](https://mp.weixin.qq.com/s/sx_BSfA5zMJ9FaPAApS3Aw)| | [微服務架構:資料庫選型簡介,業務資料規劃設計](https://mp.weixin.qq.com/s/hdS2IB0kx-ehBsEWed75xg)| | [微服務架構:中介軟體整合,公共服務封裝](https://mp.weixin.qq.com/s/5yR5czRHu4EARw5MvnyxcQ)| | [微服務架構:SpringCloud 基礎元件應用設計](https://mp.weixin.qq.com/s/ddyXWTtN2zMnWJZ-T8H8_w)| | [微服務架構:通過業務、應用、技術、儲存,聊聊架構](https://mp.weixin.qq.com/s/mzOK_JOb_i_G1cqy0YAvYw)| | [微服務技術棧:常見註冊中心元件,對比分析](https://mp.weixin.qq.com/s/yBrIZFXe6q7tfRrJC_FUQA)| | [微服務技術棧:流量整形演算法,服務熔斷與降級](https://mp.weixin.qq.com/s/ocYnPQl-KQ-QPRHnTki7zg)| | [微服務技術棧:API閘道器中心,落地實現方案](https://mp.weixin.qq.com/s/flNZVxrV5bmz1Qas