好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

前言

上一章 Spring boot2.0 实现日志集成的方法(2) 主要讲解了将日志信息根据类别输出到不同的文件中,实际开发中我们需要通过日志来监控用户的操作行为、请求的耗时情况,针对耗时久的请求进行性能分析,提升系统性能。

具体实现

采用的Spring Aop切面技术来实现控用户的操作行为、请求的耗时情况。

定义日志注解

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

@Target ({ ElementType.METHOD })

@Retention (RetentionPolicy.RUNTIME)

@Documented

public @interface LogAnnotation

{

     // 模块

     String model() default "" ;

 

     // 功能

     String func() default "" ;

 

     //描述

     String desc() default "" ;

}

定义日志切面

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

@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);

     }

}

基本使用

?

1

2

3

4

5

6

7

@LogAnnotation (model= "用户管理" ,func= "查询用户信息" ,desc= "根据用户名称" )

@GetMapping ( "getUserByName" )

public Result getUserByName( @RequestParam String name)

{

     logger.info( "getUserByName paramter name:[{}]" ,name);

     return Result.success(userService.getUserByName(name));

}

输出信息

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

{

      "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 日志集成内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

原文链接:https://juejin.cn/post/7073750042921680926

查看更多关于Spring boot2.0 实现日志集成的方法(3)的详细内容...

  阅读:16次