本文源码:GitHub·点这里 || GitEE·点这里

一、日志体系集成

1、日志管理

在系统的开发中,最关键的一个组件工具就是日志,日志打印方便问题排查,或者生产事故回溯,日志记录用来监控并分析系统性能点,并以此为依据,不断对系统进行优化;同时基于用户的操作日志,对用户行为进行分析,开发智能推荐的功能,或者进行营销投放,这在系统中都是常见且关键的业务流程。

2、ELK日志体系

在大型系统架构中,ELK的日志管理系统是系统必备功能,ELK-Stack是Elasticsearch、Logstash、Kiban三个开源软件的组合,通常用来做日志分析,实时数据检索。基于Logstash做数据流动通道,使日志数据不断的流入搜索组件,基于Elasticsearch做数据实时查询,基于Kiban的ES可视化界面,以此实现日志数据的搜集、存储、分析等核心功能,且该体系方便扩展。

ELK相关文章:

基于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)
@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、切面拦截

基于切面编程是方式,做相关日志处理,获取相应参数,构建日志模型即可。

@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注解在接口方法上即可。

@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、记录参数

这样自定义日志流程就完成了。

四、源代码地址

GitHub·地址
https://github.com/cicadasmile/middle-ware-parent
GitEE·地址
https://gitee.com/cicadasmile/middle-ware-parent

推荐阅读:微服务架构系列

标题
微服务架构:项目技术选型简介,架构图解说明
微服务架构:业务架构设计,系统分层管理
微服务架构:数据库选型简介,业务数据规划设计
微服务架构:中间件集成,公共服务封装
微服务架构:SpringCloud 基础组件应用设计
微服务架构:通过业务、应用、技术、存储,聊聊架构
微服务技术栈:常见注册中心组件,对比分析
微服务技术栈:流量整形算法,服务熔断与降级
微服务技术栈:API网关中心,落地实现方案

SpringBoot2 集成日志,复杂业务下的自定义实现的更多相关文章

  1. Activiti(二) springBoot2集成activiti,集成activiti在线设计器

    摘要 本篇随笔主要记录springBoot2集成activiti流程引擎,并且嵌入activiti的在线设计器,可以通过浏览器直接编辑出我们需要的流程,不需要通过eclipse或者IDEA的actiB ...

  2. go-zero docker-compose 搭建课件服务(九):http统一返回和集成日志服务

    0.索引 go-zero docker-compose 搭建课件服务(九):http统一返回和集成日志服务 0.1源码地址 https://github.com/liuyuede123/go-zero ...

  3. 权限管理系统之项目框架搭建并集成日志、mybatis和分页

    前一篇博客中使用LayUI实现了列表页面和编辑页面的显示交互,但列表页面table渲染的数据是固定数据,本篇博客主要是将固定数据变成数据库数据. 一.项目框架 首先要解决的是项目框架问题,搭建什么样的 ...

  4. 小D课堂 - 零基础入门SpringBoot2.X到实战_第11节 Logback日志框架介绍和SpringBoot整合实战_45、SpringBoot2.x日志讲解和Logback配置实战

    笔记 2.SpringBoot2.x日志讲解和自定义Logback配置实战     简介:讲解SpringBoot2.x整合Logback配置实战 1.官网介绍:https://docs.spring ...

  5. ASP.NET全局错误处理和异常日志记录以及IIS配置自定义错误页面

    应用场景和使用目的 很多时候,我们在访问页面的时候,由于程序异常.系统崩溃会导致出现黄页.在通常的情况下,黄页对于我们来说,帮助是极大的,因为它可以帮助我们知道问题根源,甚至是哪一行代码出现了错误.但 ...

  6. Spring Boot 揭秘与实战(三) 日志框架篇 - 如何快速集成日志系统

    文章目录 1. 默认的日志框架 logback2. 常用的日志框架 log4j 1.1. 日志级别 1.2. 日志文件 3. 源代码 Java 有很多日志系统,例如,Java Util Logging ...

  7. UidGenerator springboot2集成篇

    uid-generator 官网集成文档: https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md 由于并没有提供spri ...

  8. Android Camera开发系列(下)——自定义Camera实现拍照查看图片等功能

    Android Camera开发系列(下)--自定义Camera实现拍照查看图片等功能 Android Camera开发系列(上)--Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片 上 ...

  9. QLViewController在iOS7下的自定义

    原文来自:QLViewController在iOS7下的自定义 原先的项目使用了quicklook framework,用于在iPhone上浏览各类文件,除了txt文本会有乱码的问题,其他文件的显示都 ...

随机推荐

  1. Cenos系统防火墙开放指定端口

    1.查看已经开放的端口 firewall-cmd --list-ports 2.开启指定端口 firewall-cmd --zone=public --add-port=2181/tcp --perm ...

  2. C++socket编程write()、read()简介及与send()、recv()的区别

    1. write 函数原型:ssize_t write(int fd, const void*buf,size_t nbytes)write函数将buf中的nbytes字节内容写入文件描述符fd.成功 ...

  3. C#LeetCode刷题之#160-相交链表(Intersection of Two Linked Lists)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3824 访问. 编写一个程序,找到两个单链表相交的起始节点. 例如 ...

  4. 二、JAVA 的了解与安装

    1.java了解 1.1.java三大版本 javaSE:标准版(桌面程序,控制台开发...) javaME:嵌入式开发(手机.小家电...)[可以忽略] javaEE:企业版开发(web端,服务器开 ...

  5. SpringMVC的简介和工作流程

    一.简介 Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面.Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块.Spri ...

  6. 一句话木马变形(截止2020年8月16日通杀D盾、安全狗,微步,webshellKiller)

    首先一句话木马: <?php assert($_POST['a']); ?> D盾扫描,5级 分开写: <?php $a = "assert"; $b = $_P ...

  7. Socket、ServerSocket

    1.服务器端程序 package demo12.net; import java.io.IOException; import java.io.InputStream; import java.io. ...

  8. 动态数组java实现

    数组是一种顺序存储的线性表,所有元素的内存地址是连续的. 动态数组相对于一般数组的优势是可以灵活地添加或删除元素.而一般数组则受限于固定的内存空间.只能有限的添加元素 动态数组(Dynamic Arr ...

  9. 二叉搜索树及java实现

    二叉搜索树(Binary Search Tree) 二叉搜索树是二叉树的一种,是应用非常广泛的一种二叉树,英文简称为 BST 又被称为:二叉查找树.二叉排序树 任意一个节点的值都大于其左子树所有节 ...

  10. MongoDB联表查询

    表A: id name --------------------------- 1 Tom 2 Roger 3 Mars 4 Brent 表B: id result ----------------- ...