本文源码:GitHub·点这里 || GitEE·点这里
一、日志体系集成
1、日志治理
在零碎的开发中,最要害的一个组件工具就是日志,日志打印不便问题排查,或者生产事变回溯,日志记录用来监控并剖析零碎性能点,并以此为根据,一直对系统进行优化;同时基于用户的操作日志,对用户行为进行剖析,开发智能举荐的性能,或者进行营销投放,这在零碎中都是常见且要害的业务流程。
2、ELK日志体系
在大型零碎架构中,ELK的日志管理系统是零碎必备性能,ELK-Stack是Elasticsearch、Logstash、Kiban三个开源软件的组合,通常用来做日志剖析,实时数据检索。基于Logstash做数据流动通道,使日志数据一直的流入搜寻组件,基于Elasticsearch做数据实时查问,基于Kiban的ES可视化界面,以此实现日志数据的收集、存储、剖析等外围性能,且该体系不便扩大。
ELK相干文章:
- SpringBoot2整合ElasticSearch框架
- 搜索引擎框架,ElasticSearch集群模式
- 基于Logstash全量或增量同步数据到ES中间件
基于ELK体系的外围操作,有对于ElasticSearch其余文章能够自行查阅之前的内容,这里不在排列,如同很多货色都是这样一点点积攒进去的。
二、集成环境
1、我的项目构造
defined-log-api:测试工程;
defined-log-config:日志外围模块,依赖之后应用该模块下注解即可;
2、数据表构造
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、注解参数
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Documentedpublic @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、切面拦挡
基于切面编程是形式,做相干日志解决,获取相应参数,构建日志模型即可。
@Component@Aspectpublic 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注解在接口办法上即可。
@RestControllerpublic 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、记录参数
这样自定义日志流程就实现了。
四、源代码地址
GitHub·地址https://github.com/cicadasmile/middle-ware-parentGitEE·地址https://gitee.com/cicadasmile/middle-ware-parent
举荐浏览:微服务架构系列
题目 |
---|
微服务架构:我的项目技术选型简介,架构图解阐明 |
微服务架构:业务架构设计,零碎分层治理 |
微服务架构:数据库选型简介,业务数据规划设计 |
微服务架构:中间件集成,公共服务封装 |
微服务架构:SpringCloud 根底组件利用设计 |
微服务架构:通过业务、利用、技术、存储,聊聊架构 |
微服务技术栈:常见注册核心组件,比照剖析 |
微服务技术栈:流量整形算法,服务熔断与降级 |
微服务技术栈:API网关核心,落地实现计划 |