本文源码: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网关核心,落地实现计划