Spring boot2.0 实现日志集成的方法(3)

 更新时间:2022年04月21日 10:16:42   作者:剑圣无痕   
这篇文章主要介绍了Spring boot2.0 实现日志集成的方法,基于上一篇将日志信息根据类别输出到不同的文件中,这篇文章将通过日志来监控用户的操作行为、请求的耗时情况,针对耗时久的请求进行性能分析,提升系统性能,需要的小伙伴可以参考一下

前言

上一章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来实现。

到此这篇关于Spring boot2.0 实现日志集成的方法(3)的文章就介绍到这了,更多相关Spring boot 日志集成内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java实现网络文件下载以及下载到指定目录

    Java实现网络文件下载以及下载到指定目录

    在Spring框架中,StreamUtils和FileCopyUtils两个工具类提供了方便的文件下载功能,它们都属于org.springframework.util包,可以通过简单的方法调用实现文件流的复制和下载,这些工具类支持多种参数传递,涵盖了文件下载的多种场景
    2024-09-09
  • Java基础之extends用法详解及简单实例

    Java基础之extends用法详解及简单实例

    这篇文章主要介绍了 Java基础之extends用法详解及简单实例的相关资料,需要的朋友可以参考下
    2017-02-02
  • Java中临时文件目录的使用

    Java中临时文件目录的使用

    :Java提供了系统属性java.io.tmpdir来获取默认临时文件目录,适用于不同操作系统,使用Files.createTempFile方法创建临时文件,并在不需要时应及时删除,下面就来介绍一下
    2024-10-10
  • 解决子线程无法访问父线程中通过ThreadLocal设置的变量问题

    解决子线程无法访问父线程中通过ThreadLocal设置的变量问题

    这篇文章主要介绍了解决子线程无法访问父线程中通过ThreadLocal设置的变量问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • JAVA定义变量与输出详解

    JAVA定义变量与输出详解

    这篇文章主要介绍了JAVA定义变量与输出详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • Java特性 Lambda 表达式和函数式接口

    Java特性 Lambda 表达式和函数式接口

    这篇文章主要介绍了Java特性 Lambda 表达式和函数式接口,Lambda表达式基于函数式编程思想,也可以称为闭包,是Java 8引入的重要新特性, Lambda允许把函数作为一个方法的参数
    2022-06-06
  • SpringBoot遇到的坑@Qualifier报红的解决

    SpringBoot遇到的坑@Qualifier报红的解决

    这篇文章主要介绍了SpringBoot遇到的坑@Qualifier报红的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • SpringBoot监听Nacos动态修改日志级别的操作方法

    SpringBoot监听Nacos动态修改日志级别的操作方法

    线上系统的日志级别一般都是 INFO 级别,有时候需要查看 WARN 级别的日志,所以需要动态修改日志级别,微服务项目中使用 Nacos 作为注册中心,我们可以监听 Nacos 配置,修改日志级别,这篇文章主要介绍了SpringBoot监听Nacos动态修改日志级别的操作方法,需要的朋友可以参考下
    2023-12-12
  • SpringBoot实现阿里云快递物流查询的示例代码

    SpringBoot实现阿里云快递物流查询的示例代码

    本文将基于springboot实现快递物流查询,物流信息的获取通过阿里云第三方实现,具有一定的参考价值,感兴趣的可以了解一下
    2021-10-10
  • Java线程池队列PriorityBlockingQueue原理分析

    Java线程池队列PriorityBlockingQueue原理分析

    这篇文章主要介绍了Java线程池队列PriorityBlockingQueue原理分析,PriorityBlockingQueue队列是 JDK1.5 的时候出来的一个阻塞队列,但是该队列入队的时候是不会阻塞的,永远会加到队尾,需要的朋友可以参考下
    2023-12-12

最新评论