设计思路
针对以往在Spring Boot应用中实现简单的审计日志的逻辑,基本是使用注解加上AOP(面向切面)将一些业务日志进行入库存储,应或者是记录到自建的ELK之类的日志分析系统或者是传输到一些云服务提供的日志收集系统,以方便进行二次加工日志。或者是提供日志工具类,直接侵入业务代码,将业务日志进行详细记录。上述提到的2种方法,在比较小的单一系统里是常用方式。但是对于我司这种业务系统较多的场景,如果需要每个业务系统都去对接注解之类的,容易给业务系统增加性能损耗以及侵入代码去做修改。而且我司的业务系统较多,所以最好是要设计出无侵入业务系统的审计日志。
先看下下面的简单的系统结构图,随着Spring Cloud在2018年后开始在国内流行起来,我司的不少系统已经是采用了这种微服务框架,审计系统由于其又需要给接口去查询,所以也把它当作一个微服务去使用。为了减少侵入业务系统,但是日志详情又需要记录具体的对象,好在我司各个业务系统的表都入了数仓StarRocks。所以审计日志系统就只往数仓上进行操作。
如上图所示,引入的一个MQ组件Kafka,这里解释下为什么。首先,网关的请求日志量是十分巨大的,如果不使用MQ进行缓存,把网关收集到的日志直接通过http或者grpc等其他协议直接上送日志,那有可能带来一是可能阻塞了网关,二来审计系统的资源可能处理不及时,导致日志丢失,或者引发审计系统宕机。然后,引入Kafka后,审计系统就可以去配置并发处理请求日志的流量大小,防止写入过大将SR写崩溃了。其实公司已经有MQ组件了,Pulsar,但是它已经用在业务和canal数据同步以及xxl-job,还有流程camunda里了。日志审计毕竟不能和业务系统竞争过多资源,也不能影响到业务系统的正常使用,所以用Kafka,而且国内Kafka也基本上用在日志和大数据方面比较多。下图是审计日志的具体逻辑:
如上图所示,基本上只需要将完整的Http请求转换成MQ消息,审计系统就可以基于配置项进行解析日志,从而达到处理成业务人员能够看得懂的日志明细。在解析处理http日志的逻辑中,坚持一个原则,能从请求和响应的参数中拿到事件明细里需要的数据就不去查库!
前端改造
上述的方案是满足了产品规划的需求,记录的事件明细基本上就只是一句话概括的,比如 ”在碧桂山城项目中,修改业主【小王】“,这句话根本就没体现修改了什么东西,是修改了业主的手机号?身份证?等等都没记录起来,所以我们要和前端同学做个约定,就是在修改接口中,将修改前的数据也传入到请求参数中。我们的业务系统(至少基础数据下是)绝大部分接口都是POST,而且是json格式,参数都用data包装,我们可以加多一个before-data字段,将修改前的数据也记录起来。简单展示可以参考下面:
这种形式的展示日志,其实对于开发人员是十分友好的,但对于业务人员就像看天书了。所以呢,需要针对参数json数据的key进行翻译一下!怎么翻译?三种方案!
第一种:前端同学抓取表单,比如表单有个字段 ,”证件号码:[一个input框]“ ,对于json字段是certNo ,然后前端解析成 {“certNo”:”证件号码”} 然后又用多一个和参数data同级的,比如 keyNameMapping 将解析出的映射关系一并在接口参数中上传,审计日志系统就可以二次加工 前后 json数据,转换成业务人员看的懂的样子。
第二种:后端定时通过swagger文档进行抓取url的参数,对应的中文名,这个方案比较可行。
第三种:人工维护配置,费时费力,就这么一说。
对接流程
1.参考基础平台的对接流程,首先,需要产品给出需要记录日志的业务范围,包括需要记录的 业务对象,业务动作,日志表达格式,例如 针对角色管理, 的表达格式是 :“新增【子系统管理员】角色”,对象则是 这一条角色,针对这条角色的ID,需要在请求参数,或者响应参数中存在,而角色的名字,有些禁用/启用接口,共用一个,而且入参只有一个ID,返回参数data里一般没数据,只根据当次的http请求,根本无法判断是禁用还是启用,以及名字是哪个,所以这种接口需要统一改造,使用封装的返回格式例如下面的接口:
我们就需要在返回数据中多返回一些数据