您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關SpringBoot2集成日志以及復雜業務下的自定義實現是怎樣的,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
在系統的開發中,最關鍵的一個組件工具就是日志,日志打印方便問題排查,或者生產事故回溯,日志記錄用來監控并分析系統性能點,并以此為依據,不斷對系統進行優化;同時基于用戶的操作日志,對用戶行為進行分析,開發智能推薦的功能,或者進行營銷投放,這在系統中都是常見且關鍵的業務流程。
在大型系統架構中,ELK的日志管理系統是系統必備功能,ELK-Stack是Elasticsearch、Logstash、Kiban三個開源軟件的組合,通常用來做日志分析,實時數據檢索。基于Logstash做數據流動通道,使日志數據不斷的流入搜索組件,基于Elasticsearch做數據實時查詢,基于Kiban的ES可視化界面,以此實現日志數據的搜集、存儲、分析等核心功能,且該體系方便擴展。
基于ELK體系的核心操作,有關于ElasticSearch其他文章可以自行查閱之前的內容,這里不在陳列,好像很多東西都是這樣一點點積累出來的。
defined-log-api:測試工程;
defined-log-config:日志核心模塊,依賴之后使用該模塊下注解即可;
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 = '日志記錄表';
這里完全基于業務需求自定義即可。
@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:是否異步處理,在一些并發高的接口中,避免日志記錄成為性能問題的一個因素;
其他相關參數都是十分常見,例如接口類型增刪改查,入參出參報文存儲,方法模塊的描述等等,這些都可以基于業務的需求自定義,然后做相關業務處理開發,思路開闊即可。
基于切面編程是方式,做相關日志處理,獲取相應參數,構建日志模型即可。
@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 ; } }
DefinedLog注解在接口方法上即可。
@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" ; } }
這樣自定義日志流程就完成了。
上述就是小編為大家分享的SpringBoot2集成日志以及復雜業務下的自定義實現是怎樣的了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。