时间:2023-03-21 09:47:21 | 栏目:JAVA代码 | 点击:次
上一章Spring boot2.0 实现日志集成的方法(2)主要讲解了将日志信息根据类别输出到不同的文件中,实际开发中我们需要通过日志来监控用户的操作行为、请求的耗时情况,针对耗时久的请求进行性能分析,提升系统性能。
采用的Spring Aop切面技术来实现控用户的操作行为、请求的耗时情况。
@Target({ ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface LogAnnotation { // 模块 String model() default ""; // 功能 String func() default ""; //描述 String desc() default ""; }
@Aspect @Component public class LogAspect { //请求监控日志,输出到不同日志文件 public static Log logger = LogManager.getLogger("request-access"); /** * 定义切面 */ @Pointcut("@annotation(com.test.aspect.LogAnnotation)") private void logPoinCut() { } /** * * @param joinPoint */ @Before(value = "logPoinCut()") public void doBefore(JoinPoint joinPoint) { String requestId =TraceIdUtil.getTraceId(); logger.info("Start invoke requestID:[{}]",requestId); } @Around(value = "logPoinCut()") public Object doAround(ProceedingJoinPoint jp) throws Throwable { String requestId =TraceIdUtil.getTraceId(); logger.info("Enter request start requestId :[{}]",requestId); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder .getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); MethodSignature signature = (MethodSignature) jp.getSignature(); Method method = signature.getMethod(); long startTime= System.currentTimeMillis(); OperationLog operationLog = new OperationLog(); LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class); if (logAnnotation != null) { String model = logAnnotation.model(); String func = logAnnotation.func(); String desc = logAnnotation.desc(); operationLog.setModel(model); operationLog.setFunc(func); operationLog.setDesc(desc); } String className = jp.getTarget().getClass().getName(); String methodName = jp.getSignature().getName(); String uri = request.getRequestURI(); String ip = IpUtil.getIpAddr(request); operationLog.setClassName(className); operationLog.setMethodName(methodName); operationLog.setIp(ip); operationLog.setUri(uri); StringBuilder param = new StringBuilder(); Object[] args = jp.getArgs(); Object arg = null; for (int i = 0, j = args.length; i < j; i++) { arg = args[i]; param.append(" ") .append(arg == null ? null : args[i].toString()); if (i != (j - 1)) { param.append(",").append("\n"); } } operationLog.setParam(param.toString()); operationLog.setCreateDate(new Date()); long endTime=System.currentTimeMillis()-startTime; //可以通过配置设置异常调用请求时间 long costTime=3; operationLog.setCostTime(endTime); String logStr = JSON.toJSONString(operationLog); //将异常请求数据插入数据库 if(endTime>costTime){ //saveOpetionLog(operationLog); } logger.info("invoke finish message:{}",logStr); Object obj = jp.proceed(); return obj; } /** * 方法之后调用 * @param joinPoint * @param returnValue 方法返回值 */ @AfterReturning(pointcut = "logPoinCut()") public void doAfterReturning(JoinPoint joinPoint) { String requestId=TraceIdUtil.getTraceId(); logger.info("End invoke request ID [{}]",requestId); } }
@LogAnnotation(model="用户管理",func="查询用户信息",desc="根据用户名称") @GetMapping("getUserByName") public Result getUserByName(@RequestParam String name) { logger.info("getUserByName paramter name:[{}]",name); return Result.success(userService.getUserByName(name)); }
{ "className": "com.test.controller.UserController", "costTime": 19, "createDate": "2022/03/11 15:20:30", "createUser": "xx", "ip": "172.18.188.111", "methodName": "getUserByName", "param": " zhangsan", "uri": "/user/getUserByName", "model":"用户管理", "func":"查询用户信息", "desc":"根据用户名称", "version": 0 }
对于一些敏感的信息需要进行加密处理。针对异常的请求进行分析和性能优化。
上述日志信息虽然记录的比较详细,但是缺少了请求的来源,尤其是跨服务之间的调用,则无法进行追踪。链路追踪可以采用Spring Boot +logbck+MDC来实现。