利用注解式切面单独打印接口调用日志

背景: 我们可能希望对项目中的接口性能进行监控,例如:接口调用时间,开始时间,结束时间,传入的参数等等,通常的做法是在接口代码开始处记录startTime,结尾处记录endTime,然后计算startTime和endTime之差,这种做法无法把这部分日志单独拆分成文件,而且冗余代码会比较多。可以考虑使用spring切面和环绕通知来打印这部分日志,并使用log4j2将这部分日志单独拆分出来。
ps:拆分的出来的日志可以考虑使用shell脚本和awk命令来进行日志分析,将一些关键的数据存库,然后使用echarts来分析来展示图表,就可以成为一个小型的接口监控系统,使用linux的crontab来定时执行脚本,每天刷新数据。

技术点:spring 注解式切面和环绕通知

使用的项目:工作流、规则引擎

具体实现(以规则引擎为例):
1.在rpc-impl层新增PerformenceMonitor类(名字可以随便起)
  1. package com.yixin.ndss.common.aop;

  2. import java.text.SimpleDateFormat;
  3. import java.util.Date;
  4. import org.apache.logging.log4j.Level;
  5. import org.apache.logging.log4j.LogManager;
  6. import org.apache.logging.log4j.Logger;
  7. import org.aspectj.lang.ProceedingJoinPoint;
  8. import org.aspectj.lang.annotation.Around;
  9. import org.aspectj.lang.annotation.Aspect;
  10. import org.aspectj.lang.annotation.Pointcut;
  11. import org.springframework.stereotype.Component;
  12. import com.yixin.common.utils.JsonObjectUtils;

  13. /**
  14. * 监控方法的执行时间

  15. * <p>

  16. * Package : com.yixin.common.system.ioc

  17. * @author YixinCapital -- shaoml
  18. *                   2016年10月20日 下午6:55:45
  19. *
  20. */
  21. @Aspect  
  22. @Component
  23. public class PerformenceMonitor {
  24.         
  25.         private static final Logger LOGGER = LogManager.getLogger(PerformenceMonitor.class);
  26.         
  27.         /**
  28.          * 切点监控com.yixin.wfpt.api.process.impl包的所有public方法  
  29.          *  
  30.          * @author YixinCapital -- shaoml
  31.          *               2017年4月26日 上午9:55:31
  32.          */
  33.     @Pointcut("execution(* com.yixin.ndss.application.api.impl..*(..))")    
  34.     private void pointCutMethod() {
  35.             
  36.     }    
  37.   
  38.     /**
  39.      * 声明环绕通知
  40.      * 
  41.      * @param pjp 代理对象
  42.      * @return Object 方法调用出参
  43.      * @throws Throwable 
  44.      * @author YixinCapital -- shaoml
  45.      *               2017年4月26日 上午9:55:16
  46.      */
  47.     @Around("pointCutMethod()")    
  48.     public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
  49.             
  50.             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  51.             
  52.         // 执行方法开始时间
  53.             long begin = System.currentTimeMillis();
  54.         String beginStr = sdf.format(new Date(begin));
  55.         
  56.         Object obj = pjp.proceed();
  57.         
  58.         // 入参拦截
  59.         Object[] args = pjp.getArgs();
  60.         
  61.         // 执行方法结束时间
  62.         long end = System.currentTimeMillis();
  63.         String endStr = sdf.format(new Date(end));
  64.         
  65.         LOGGER.log(Level.forName("CAP", 460),
  66.                         "======调用" + pjp.getTarget().getClass().getSimpleName()
  67.                         + "类中方法: " + pjp.getSignature().getName()
  68.                         + "(), 开始时间: " + beginStr + ", 结束时间: " + endStr + ", 总耗时: " + (end - begin) + "ms,"
  69.                         + "入参=【" + JsonObjectUtils.objectToJson(args) + "】, 出参=【" + JsonObjectUtils.objectToJson(obj) + "】");
  70.         
  71.         return obj;    
  72.     }
  73.     
  74. }
复制代码

2.spring-context xml文件中新增aspectJ自动代理和aop的引用
  1.   
复制代码
 

3.配置异步日志:
在log4j2.xml文件中进行如下配置:
 
 

2.png (30.13 KB, 下载次数: 0)

下载附件

2017-7-25 16:25 上传


 


4.本地启动项目,postman调用哪个接口测试:
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用 @Slf4j 注解和 AOP 统一处理打印日志,具体实现可参考以下代码: 1. 引入依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency> ``` 2. 在应用主类上添加 @EnableAspectJAutoProxy 注解启用 AOP: ```java @SpringBootApplication @EnableAspectJAutoProxy(proxyTargetClass = true) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 3. 定义切面类: ```java @Aspect @Component @Slf4j public class LogAspect { @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)" + "||@annotation(org.springframework.web.bind.annotation.GetMapping)" + "||@annotation(org.springframework.web.bind.annotation.PostMapping)" + "||@annotation(org.springframework.web.bind.annotation.PutMapping)" + "||@annotation(org.springframework.web.bind.annotation.DeleteMapping)") public void webLog() { } @Before("webLog()") public void doBefore(JoinPoint joinPoint) { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 记录请求内容 log.info("URL : " + request.getRequestURL().toString()); log.info("HTTP_METHOD : " + request.getMethod()); log.info("IP : " + request.getRemoteAddr()); // 记录调用方法 log.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); // 记录请求参数 log.info("ARGS : " + Arrays.toString(joinPoint.getArgs())); } @AfterReturning(returning = "ret", pointcut = "webLog()") public void doAfterReturning(Object ret) { // 记录响应内容 log.info("RESPONSE : " + ret); } } ``` 4. 在需要打印日志接口方法上添加 @RequestMapping 等注解即可。 压缩文件的操作请参考以下代码: ```java public static void zip(Path sourcePath, Path zipPath) throws IOException { try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(zipPath)); Stream<Path> paths = Files.walk(sourcePath)) { paths.filter(p -> !Files.isDirectory(p)) .forEach(p -> { ZipEntry entry = new ZipEntry(sourcePath.relativize(p).toString()); try { zos.putNextEntry(entry); zos.write(Files.readAllBytes(p)); zos.closeEntry(); } catch (IOException e) { e.printStackTrace(); } }); } } ``` 对于中文加密的问题,我不是很确定您要表达的意思,请再提供更详细的问题描述。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值