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(); + } + +}