From a22c110d080fe4387cd7b29a9bd36a727eb5944a Mon Sep 17 00:00:00 2001
From: manailin <261030956@qq.com>
Date: 星期三, 08 十二月 2021 09:49:36 +0800
Subject: [PATCH] [新增]打印业务慢日志
---
springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/resources/logback-spring.xml | 29 ++++
springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/config/ParamOutAspect.java | 143 +++++++++++++++++++++++
springcloud_k8s_panzhihuazhihuishequ/service_user/src/main/resources/logback-spring.xml | 27 ++++
springcloud_k8s_panzhihuazhihuishequ/service_user/src/main/java/com/panzhihua/service_user/config/ParamOutAspect.java | 128 +++++++++++++++++++++
springcloud_k8s_panzhihuazhihuishequ/zuul/src/main/resources/logback-spring.xml | 2
5 files changed, 327 insertions(+), 2 deletions(-)
diff --git a/springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/config/ParamOutAspect.java b/springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/config/ParamOutAspect.java
new file mode 100644
index 0000000..7d1df28
--- /dev/null
+++ b/springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/java/com/panzhihua/service_community/config/ParamOutAspect.java
@@ -0,0 +1,143 @@
+package com.panzhihua.service_community.config;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
+
+import com.alibaba.fastjson.JSONObject;
+import com.panzhihua.common.model.vos.R;
+import com.panzhihua.common.utlis.DateUtils;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 应用模块名称
+ * <p>
+ * 代码描述
+ * <p>
+ * 拦截controller,输出入参、响应内容和响应时间 Copyright: Copyright (C) 2021 XXX, Inc. All rights reserved.
+ * <p>
+ * Company: 成都呐喊信息技术有限公司
+ * <p>
+ *
+ * @author manailin
+ * @since 2021/8/24 15:30
+ */
+@Slf4j
+@Aspect
+@Component
+public class ParamOutAspect {
+
+ /**
+ * 记录特定日志的声明
+ */
+ private final Logger slowClassAndMethodLog = LoggerFactory.getLogger("slowClassAndMethodLog");
+ /**
+ * 设定方法的执行时间限制毫秒数
+ */
+ private long maxReduceTime = 100;
+
+ @Pointcut("execution(* com.panzhihua.service_community.api..*.*(..)) || execution (public * com.panzhihua.service_community.service..* (..))")
+ public void aspect() {}
+
+ /**
+ * [方法描述] 环绕通知,拦截controller,输出请求参数、响应内容和响应时间
+ *
+ * @param joinPoint
+ * @return java.lang.Object
+ * @author manailin
+ * @date 2021/8/24 17:04
+ */
+ @Around("aspect()")
+ public Object processLog(ProceedingJoinPoint joinPoint) {
+ log.info("进入方法性能检查方法");
+ Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();
+ String className = method.getDeclaringClass().getName();
+ // 获取方法名称
+ String methodName = method.getName();
+ // 获取参数名称
+ LocalVariableTableParameterNameDiscoverer paramNames = new LocalVariableTableParameterNameDiscoverer();
+ String[] params = paramNames.getParameterNames(method);
+ // 获取参数
+ Object[] args = joinPoint.getArgs();
+ // 过滤掉request和response,不能序列化
+ List<Object> filteredArgs = Arrays.stream(args)
+ .filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse)))
+ .collect(Collectors.toList());
+ JSONObject rqsJson = new JSONObject();
+ rqsJson.put("rqsMethod", methodName);
+ rqsJson.put("rqsTime", DateUtils.getCurrentDateStr_MS());
+ if (ObjectUtils.isEmpty(filteredArgs)) {
+ rqsJson.put("rqsParams", null);
+ } else {
+ // 拼接请求参数
+ Map<String, Object> rqsParams = IntStream.range(0, filteredArgs.size()).boxed()
+ .collect(Collectors.toMap(j -> params[j], j -> filteredArgs.get(j)));
+ rqsJson.put("rqsParams", rqsParams);
+ }
+ log.info(className + ":" + methodName + "请求信息为:" + rqsJson.toJSONString());
+ Object resObj = null;
+ long startTime = System.currentTimeMillis();
+ try {
+ // 执行原方法
+ resObj = joinPoint.proceed(args);
+ } catch (Throwable e) {
+ log.error(className + ":" + methodName + "方法执行异常!", e);
+ // throw new ServiceException(methodName + "方法执行异常!");
+ }
+ long endTime = System.currentTimeMillis();
+ if (resObj != null) {
+ if (resObj instanceof R) {
+ // 输出响应信息
+ R resJson = (R)resObj;
+ // 打印耗时的信息
+ this.printExecTime(className , methodName,rqsJson,resJson, startTime, endTime);
+ return resJson;
+ } else {
+ return resObj;
+ }
+ } else {
+ return R.ok();
+ }
+ }
+
+ /**
+ * [方法描述] 打印方法执行耗时的信息,如果超过了一定的时间,才打印
+ *
+ * @param methodName
+ * 执行方法名
+ * @param startTime
+ * 执行开始时间
+ * @param endTime
+ * 执行结束时间
+ * @author manailin
+ * @date 2021/8/24 17:05
+ */
+ private void printExecTime(String className,String methodName, JSONObject rqsJson,R resJson, long startTime, long endTime) {
+ long diffTime = endTime - startTime;
+ if (diffTime > maxReduceTime) {
+ slowClassAndMethodLog.info(className+":"+methodName + " 方法执行耗时:" + diffTime + " ms");
+ slowClassAndMethodLog.info(methodName + " 请求参数:" +rqsJson.toJSONString());
+ slowClassAndMethodLog.info(className + " 响应信息:" + JSONObject.toJSONString(resJson));
+ }
+ // TODO 可以集成redis,将每个controller的执行时间追加到redis中,再用定时每周一次同步到库中
+ }
+
+}
diff --git a/springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/resources/logback-spring.xml b/springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/resources/logback-spring.xml
index 57c5249..a9d9b88 100644
--- a/springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/resources/logback-spring.xml
+++ b/springcloud_k8s_panzhihuazhihuishequ/service_community/src/main/resources/logback-spring.xml
@@ -2,7 +2,7 @@
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<springProfile name="dev">
- <property name="LOG_HOME" value="F:/log" />
+ <property name="LOG_HOME" value="F:\log"/>
</springProfile>
<springProfile name="test">
<property name="LOG_HOME" value="/mnt/data/gocd/log" />
@@ -48,4 +48,31 @@
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
+
+ <!--慢接口和方法日志记录到不同的文件-->
+ <appender name="slowClassAndMethodAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <File>${LOG_HOME}/slow_service_community.log</File>
+ <append>true</append>
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${LOG_HOME}/slow_service_community.%d.%i.log</fileNamePattern>
+ <maxHistory>10</maxHistory>
+ <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+ <maxFileSize>10MB</maxFileSize>
+ </timeBasedFileNamingAndTriggeringPolicy>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%d{yyyy/MM/dd HH:mm:ss.SSS} %-5level [%thread] [%c{0}:%L] : %msg%n</pattern>
+ <charset>UTF-8</charset>
+ </encoder>
+ </appender>
+
+ <!--这是我们定义的慢接口和方法日志传入的名称-->
+ <logger name="slowClassAndMethodLog" additivity="false" level="INFO">
+ <appender-ref ref="slowClassAndMethodAppender"/>
+ </logger>
</configuration>
\ No newline at end of file
diff --git a/springcloud_k8s_panzhihuazhihuishequ/service_user/src/main/java/com/panzhihua/service_user/config/ParamOutAspect.java b/springcloud_k8s_panzhihuazhihuishequ/service_user/src/main/java/com/panzhihua/service_user/config/ParamOutAspect.java
new file mode 100644
index 0000000..9eacc10
--- /dev/null
+++ b/springcloud_k8s_panzhihuazhihuishequ/service_user/src/main/java/com/panzhihua/service_user/config/ParamOutAspect.java
@@ -0,0 +1,128 @@
+package com.panzhihua.service_user.config;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
+import org.springframework.util.ObjectUtils;
+
+import com.alibaba.fastjson.JSONObject;
+import com.panzhihua.common.model.vos.R;
+import com.panzhihua.common.utlis.DateUtils;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 应用模块名称
+ * <p>
+ * 代码描述
+ * <p>
+ * 拦截controller,输出入参、响应内容和响应时间 Copyright: Copyright (C) 2021 XXX, Inc. All rights reserved.
+ * <p>
+ * Company: 成都呐喊信息技术有限公司
+ * <p>
+ *
+ * @author manailin
+ * @since 2021/8/24 15:30
+ */
+@Slf4j
+// @Aspect
+// @Component
+public class ParamOutAspect {
+
+ /**
+ * 设定方法的执行时间限制毫秒数
+ */
+ private long maxReduceTime = 2000;
+
+ @Pointcut("execution (public * com.panzhihua.service_user.api..* (..))||execution (public * com.panzhihua.service_user.service..* (..))")
+ public void aspect() {}
+
+ /**
+ * [方法描述] 环绕通知,拦截controller,输出请求参数、响应内容和响应时间
+ *
+ * @param joinPoint aspect()
+ * @return java.lang.Object
+ * @author manailin
+ * @date 2021/8/24 17:04
+ */
+ @Around("aspect()")
+ public Object processLog(ProceedingJoinPoint joinPoint) {
+ log.info("进入方法性能检查方法");
+ Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();
+ String className = joinPoint.getSignature().getDeclaringTypeName();
+ // 获取方法名称
+ String methodName = method.getName();
+ // 获取参数名称
+ LocalVariableTableParameterNameDiscoverer paramNames = new LocalVariableTableParameterNameDiscoverer();
+ String[] params = paramNames.getParameterNames(method);
+ // 获取参数
+ Object[] args = joinPoint.getArgs();
+ // 过滤掉request和response,不能序列化
+ List<Object> filteredArgs = Arrays.stream(args)
+ .filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse)))
+ .collect(Collectors.toList());
+ JSONObject rqsJson = new JSONObject();
+ rqsJson.put("rqsMethod", methodName);
+ rqsJson.put("rqsTime", DateUtils.getCurrentDateStr_MS());
+ if (ObjectUtils.isEmpty(filteredArgs)) {
+ rqsJson.put("rqsParams", null);
+ } else {
+ // 拼接请求参数
+ Map<String, Object> rqsParams = IntStream.range(0, filteredArgs.size()).boxed()
+ .collect(Collectors.toMap(j -> params[j], j -> filteredArgs.get(j)));
+ rqsJson.put("rqsParams", rqsParams);
+ }
+ log.info(className + ":" + methodName + "请求信息为:" + rqsJson.toJSONString());
+ Object resObj = null;
+ long startTime = System.currentTimeMillis();
+ try {
+ // 执行原方法
+ resObj = joinPoint.proceed();
+ } catch (Throwable e) {
+ log.error(className + ":" + methodName + "方法执行异常!", e);
+ }
+ long endTime = System.currentTimeMillis();
+ // 打印耗时的信息
+ this.printExecTime(className + ":" + methodName, startTime, endTime);
+ if (resObj != null) {
+ // 打印返回消息
+ log.info(className + ":" + methodName + "响应信息为:" + JSONObject.toJSON(resObj));
+ return resObj;
+ } else {
+ return R.ok();
+ }
+ }
+
+ /**
+ * [方法描述] 打印方法执行耗时的信息,如果超过了一定的时间,才打印
+ *
+ * @param classAndMethodName
+ * 执行方法名
+ * @param startTime
+ * 执行开始时间
+ * @param endTime
+ * 执行结束时间
+ * @author manailin
+ * @date 2021/8/24 17:05
+ */
+ private void printExecTime(String classAndMethodName, long startTime, long endTime) {
+ long diffTime = endTime - startTime;
+ if (diffTime > maxReduceTime) {
+ log.info(classAndMethodName + " 方法执行耗时:" + diffTime + " ms");
+ }
+ // TODO 可以集成redis,将每个controller的执行时间追加到redis中,再用定时每周一次同步到库中
+ }
+
+}
diff --git a/springcloud_k8s_panzhihuazhihuishequ/service_user/src/main/resources/logback-spring.xml b/springcloud_k8s_panzhihuazhihuishequ/service_user/src/main/resources/logback-spring.xml
index c883696..12cb9aa 100644
--- a/springcloud_k8s_panzhihuazhihuishequ/service_user/src/main/resources/logback-spring.xml
+++ b/springcloud_k8s_panzhihuazhihuishequ/service_user/src/main/resources/logback-spring.xml
@@ -48,4 +48,31 @@
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
+
+ <!--慢接口和方法日志记录到不同的文件-->
+ <appender name="slowClassAndMethodAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <File>${LOG_HOME}/slow_service_user.log</File>
+ <append>true</append>
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>INFO</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <fileNamePattern>${LOG_HOME}/slow_service_user.%d.%i.log</fileNamePattern>
+ <maxHistory>10</maxHistory>
+ <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+ <maxFileSize>10MB</maxFileSize>
+ </timeBasedFileNamingAndTriggeringPolicy>
+ </rollingPolicy>
+ <encoder>
+ <pattern>%d{yyyy/MM/dd HH:mm:ss.SSS} %-5level [%thread] [%c{0}:%L] : %msg%n</pattern>
+ <charset>UTF-8</charset>
+ </encoder>
+ </appender>
+
+ <!--这是我们定义的慢接口和方法日志传入的名称-->
+ <logger name="slowClassAndMethodLog" additivity="false" level="INFO">
+ <appender-ref ref="slowClassAndMethodAppender"/>
+ </logger>
</configuration>
\ No newline at end of file
diff --git a/springcloud_k8s_panzhihuazhihuishequ/zuul/src/main/resources/logback-spring.xml b/springcloud_k8s_panzhihuazhihuishequ/zuul/src/main/resources/logback-spring.xml
index b89e4fb..21f452a 100644
--- a/springcloud_k8s_panzhihuazhihuishequ/zuul/src/main/resources/logback-spring.xml
+++ b/springcloud_k8s_panzhihuazhihuishequ/zuul/src/main/resources/logback-spring.xml
@@ -2,7 +2,7 @@
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<springProfile name="dev">
- <property name="LOG_HOME" value="F:/log" />
+ <property name="LOG_HOME" value="F:\log"/>
</springProfile>
<springProfile name="test">
<property name="LOG_HOME" value="/mnt/data/gocd/log" />
--
Gitblit v1.7.1