首頁 > 軟體

Spring boot2.0 實現紀錄檔整合的方法(3)

2022-04-21 13:01:22

前言

上一章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 紀錄檔整合內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com