当前位置: 首页 > 科技观察

基于IDEA插件开发和字节码插桩技术,实现研发交付质量自动分析

时间:2023-03-18 20:34:49 科技观察

转载请联系bugstack公众号。目录1.前言2.技术实现准备3.字节码插入1.方法入门2.资料收集4.IDEA插件开发5.效果演示6.总结7.系列推荐1.前言如何保证代码质量?Business提出需求,制定产品计划,实施研发,测试测试流程。四个角色的配合是保证一个需求上线的必要条件。在整个需求交付质量的分类中,研发和测试是非常重要的环节。如果研发和测试的代码质量不高,就会存在不同程度的bug修复、返工甚至重做的风险。那么,如何提高代码质量呢?一般我们在开发代码的过程中都会要求R&D写单元测试来验证他们的代码逻辑。如果最终的单元测试覆盖率不足,则可以拒绝该测试进行开发和测试。但是整个需求的实现代码是在所有开发完成后进行测试的,也就是临近上线的最后一个环节,让大家知道某个研发的某个功能域的实现是否满足条件供测试用。如果此时代码质量不高,那么下一步就是项目有风险的时候。压测时间,调整上线时间,总之,病拖拖拉,最后变成大病!当然,你可以在项目开发期间定期检查代码,或者通过日常会议等方式反馈进度。但这种一一开发、调研的方式需要大量的时间,难以满足较大型、流程复杂的项目开发,对于项目风险控制也难以预测。因此,我们希望收集研发在开发过程中的执行动作,从而提前进行风险判断。实际操作的一个例子是,当你开发一个接口,开始试运行时,我们的插件可以收集这个接口的所有信息,包括:接口名称,输入参数类型和内容,输出参数类型和内容,异常信息,调用关系链等。然后将这些信息提交给服务器生成这个需求代码分支下的所有接口动作,以及各个系统之间的关系链接,随时生成最新的接口文档,一键生成测试验证功能。当后期测试人员介入时,他们可以参考编码过程中开发的所有测试用例,也可以检查整个功能的覆盖率。此外,测试人员在测试过程中的数据也会被保留。有了这些数据和信息,我们就可以完全生成一套研发测试质量交付概览图,让整个项目开发交付的质量评估变得透明。接下来,我们将根据以上描述内容进行实践和开发案例体验。我们走吧!2.技术实现准备字节码检测,因为我们需要收集接口执行信息,所以需要使用字节码检测组件来增强接口方法。这种实现有点类似于谷歌的Dapper,大规模分布式架构的非侵入式监控。只是我们需要收集更多的描述性信息。关于bytecodeinstrumentation,你可以学习ASM、Javassist、Byte-Buddy,它们都可以做这件事。IDEA插件开发,因为我们需要在研发人员的开发过程中收集,不要破坏研发的操作习惯。那么最好的办法就是嵌入到启动运行中。只要在开发过程中有运行代码的动作,就会收集相应的界面信息。最后是数据的传输和处理。传输可以直接使用MQ或者Netty。处理数据的过程会比较复杂。在这个过程中,需要对有价值的数据、相似的数据进行分析,合并某个执行环节的数据,生成相关的接口文档和工程服务地图。3.插入字节码我们在这里使用的字节码检测组件是Byte-buddy,它是一个代码生成和操作库,用于在Java应用程序在没有编译器帮助的情况下运行时创建和修改Java类。除了Java类库中包含的代码生成实用程序之外,ByteBuddy还允许创建任意类,并且不限于实现用于创建运行时代理的接口。此外,ByteBuddy提供了一个方便的API来使用Java代理或在构建过程中手动更改类。无需理解字节码指令,一个简单的API就可以轻松操作字节码、控制类和方法。已经支持Java11,库是轻量级的,只依赖Java字节码解析库ASM的visitorAPI,本身不需要任何其他依赖。与JDK动态代理、cglib、Javassist相比,字节好友在性能上有一定的优势。1.方法入口publicstaticvoidpremain(StringagentArgs,Instrumentationinst){AgentBuilder.Transformertransformer=(builder,typeDescription,classLoader,javaModule)->{returnbuilder.method(ElementMatchers.any())//拦截任何method.intercept(MethodDelegation.to(MonitorMethod.class));};newAgentBuilder.Default().type(ElementMatchers.nameStartsWith(agentArgs)).transform(transformer).installOn(inst);}如果你接触过Javaagent开发,你会比较熟悉与预维护。如果不清楚,可以理解为程序启动时的方法入口。你可以从这个入口中截取你需要的方法,然后对其进行字节码增强。其实就是动态的写代码,把你的代码加到方法中去收集方法信息。2.收集信息@RuntimeTypepublicstaticObjectintercept(@OriginMethodmethod,@SuperCallCallablecallable,@AllArgumentsObject[]args)throwsException{longstart=System.currentTimeMillis();ObjectresObj=null;try{resObj=callable.call();returnresObj;}finally{System.out.println("方法名:"+method.getName());System.out.println("输入参数个数:"+method.getParameterCount());for(inti=0;i