diff --git a/README.md b/README.md
index c9105606..fad886f4 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,7 @@ RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 `分布式集群` 场景升级(不兼
| 分布式限流 | Redisson | [Redisson文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | 全局、请求IP、集群ID 多种限流 |
| 分布式锁 | Lock4j | [Lock4j官网](https://gitee.com/baomidou/lock4j) | 注解锁、工具锁 多种多样 |
| 分布式幂等 | Lock4j | [Lock4j文档](https://gitee.com/baomidou/lock4j) | 基于分布式锁实现 |
+| 分布式日志 | TLog | [TLog文档](https://yomahub.com/tlog/docs) | 支持跟踪链路日志记录、性能分析、链路排查 |
| 文件存储 | Minio | [Minio文档](https://docs.min.io/) | 本地存储 |
| 文件存储 | 七牛、阿里、腾讯 | [OSS使用文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4359146&doc_id=1469725) | 云存储 |
| 监控框架 | SpringBoot-Admin | [SpringBoot-Admin文档](https://codecentric.github.io/spring-boot-admin/current/) | 全方位服务监控 |
diff --git a/pom.xml b/pom.xml
index 6fa31db6..c35d1312 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,6 +36,7 @@
3.16.3
2.2.1
3.4.1
+ 1.3.2
3.0.1
@@ -204,6 +205,35 @@
lock4j-redisson-spring-boot-starter
${lock4j.version}
+
+
+ com.yomahub
+ tlog-spring-boot-configuration
+ ${tlog.version}
+
+
+
+ com.yomahub
+ tlog-webroot
+ ${tlog.version}
+
+
+ javassist
+ org.javassist
+
+
+ guava
+ com.google.guava
+
+
+
+
+
+ com.yomahub
+ tlog-feign
+ ${tlog.version}
+
+
com.ruoyi
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 145469d3..dd1c6bab 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -59,6 +59,10 @@ logging:
org.springframework: warn
config: classpath:logback.xml
+# tlog 全局访问性能拦截
+tlog:
+ enable-invoke-time-print: true
+
# Spring配置
spring:
application:
diff --git a/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml
index c939785e..33a16972 100644
--- a/ruoyi-admin/src/main/resources/logback.xml
+++ b/ruoyi-admin/src/main/resources/logback.xml
@@ -7,7 +7,7 @@
-
+
${console.log.pattern}
utf-8
@@ -22,7 +22,7 @@
1
-
+
${log.pattern}
utf-8
@@ -42,7 +42,7 @@
60
-
+
${log.pattern}
@@ -64,7 +64,7 @@
60
-
+
${log.pattern}
@@ -86,7 +86,7 @@
60
-
+
${log.pattern}
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index f4f7ab93..dd9c1820 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -156,6 +156,21 @@
com.baomidou
lock4j-redisson-spring-boot-starter
+
+
+ com.yomahub
+ tlog-spring-boot-configuration
+
+
+
+ com.yomahub
+ tlog-webroot
+
+
+
+ com.yomahub
+ tlog-feign
+
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/Interceptor/PlusWebInvokeTimeInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/Interceptor/PlusWebInvokeTimeInterceptor.java
new file mode 100644
index 00000000..e2120bf0
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/Interceptor/PlusWebInvokeTimeInterceptor.java
@@ -0,0 +1,85 @@
+package com.ruoyi.framework.Interceptor;
+
+import cn.hutool.core.map.MapUtil;
+import com.alibaba.ttl.TransmittableThreadLocal;
+import com.ruoyi.common.utils.JsonUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.yomahub.tlog.context.TLogContext;
+import com.yomahub.tlog.web.interceptor.AbsTLogWebHandlerMethodInterceptor;
+import com.yomahub.tlog.web.wrapper.RequestWrapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.time.StopWatch;
+import org.springframework.http.MediaType;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+/**
+ * 重写Tlog web的调用时间统计拦截器
+ *
+ * @author Lion Li
+ * @since 3.3.0
+ */
+@Slf4j
+public class PlusWebInvokeTimeInterceptor extends AbsTLogWebHandlerMethodInterceptor {
+
+ private final TransmittableThreadLocal invokeTimeTL = new TransmittableThreadLocal<>();
+
+ @Override
+ public boolean preHandleByHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ if (TLogContext.enableInvokeTimePrint()) {
+ String url = request.getMethod() + " " + request.getRequestURI();
+
+ // 打印请求参数
+ if (isJsonRequest(request)) {
+ String jsonParam = new RequestWrapper(request).getBodyString();
+ log.info("[PLUS]开始请求 => URL[{}],参数类型[json],参数:[{}]", url, jsonParam);
+ } else {
+ Map parameterMap = request.getParameterMap();
+ if (MapUtil.isNotEmpty(parameterMap)) {
+ String parameters = JsonUtils.toJsonString(parameterMap);
+ log.info("[PLUS]开始请求 => URL[{}],参数类型[param],参数:[{}]", url, parameters);
+ } else {
+ log.info("[PLUS]开始请求 => URL[{}],无参数", url);
+ }
+ }
+
+ StopWatch stopWatch = new StopWatch();
+ invokeTimeTL.set(stopWatch);
+ stopWatch.start();
+ }
+ return true;
+ }
+
+ @Override
+ public void postHandleByHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
+
+ }
+
+ @Override
+ public void afterCompletionByHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+ if (TLogContext.enableInvokeTimePrint()) {
+ StopWatch stopWatch = invokeTimeTL.get();
+ stopWatch.stop();
+ log.info("[PLUS]结束请求 => URL[{}],耗时:[{}]毫秒", request.getMethod() + " " + request.getRequestURI(), stopWatch.getTime());
+ invokeTimeTL.remove();
+ }
+ }
+
+ /**
+ * 判断本次请求的数据类型是否为json
+ *
+ * @param request request
+ * @return boolean
+ */
+ private boolean isJsonRequest(HttpServletRequest request) {
+ String contentType = request.getContentType();
+ if (contentType != null) {
+ return StringUtils.startsWithIgnoreCase(contentType, MediaType.APPLICATION_JSON_VALUE);
+ }
+ return false;
+ }
+
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
index b1ecf81f..f4e2b5fa 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
@@ -1,10 +1,13 @@
package com.ruoyi.framework.config;
+import com.ruoyi.framework.Interceptor.PlusWebInvokeTimeInterceptor;
+import com.yomahub.tlog.web.interceptor.TLogWebInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@@ -20,6 +23,14 @@ public class ResourcesConfig implements WebMvcConfigurer {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
}
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 全局链路跟踪拦截器
+ registry.addInterceptor(new TLogWebInterceptor());
+ // 全局访问性能拦截
+ registry.addInterceptor(new PlusWebInvokeTimeInterceptor());
+ }
+
/**
* 跨域配置
*/
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java
new file mode 100644
index 00000000..68bc425d
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java
@@ -0,0 +1,49 @@
+package com.ruoyi.framework.config;
+
+import com.yomahub.tlog.core.aop.AspectLogAop;
+import com.yomahub.tlog.feign.filter.TLogFeignFilter;
+import com.yomahub.tlog.spring.TLogPropertyInit;
+import com.yomahub.tlog.spring.TLogSpringAware;
+import com.yomahub.tlog.springboot.property.TLogProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.core.annotation.Order;
+
+/**
+ * 整合 TLog 框架配置
+ *
+ * @author Lion Li
+ * @since 3.3.0
+ */
+@Order(-999)
+@Configuration
+@Import(TLogProperty.class)
+public class TLogConfig {
+
+ @Bean
+ public TLogPropertyInit tLogPropertyInit(TLogProperty tLogProperty) {
+ TLogPropertyInit tLogPropertyInit = new TLogPropertyInit();
+ tLogPropertyInit.setPattern(tLogProperty.getPattern());
+ tLogPropertyInit.setEnableInvokeTimePrint(tLogProperty.enableInvokeTimePrint());
+ tLogPropertyInit.setIdGenerator(tLogProperty.getIdGenerator());
+ tLogPropertyInit.setMdcEnable(tLogProperty.getMdcEnable());
+ return tLogPropertyInit;
+ }
+
+ @Bean
+ public TLogSpringAware tLogSpringAware(){
+ return new TLogSpringAware();
+ }
+
+ @Bean
+ public AspectLogAop aspectLogAop() {
+ return new AspectLogAop();
+ }
+
+ @Bean
+ public TLogFeignFilter tLogFeignFilter() {
+ return new TLogFeignFilter();
+ }
+
+}