refactor(trace): Refactoring the tracking module and migrating to a new location

- Migrated the RequestIdProvider interface from the forgeboot-common-result module to the forgeboot-trace-api module
- Refactored the TraceAutoConfiguration class to use a new package structure
- Create the forgeboot-trace-api, forgeboot-trace-autoconfigure, and forgeboot-trace-impl modules
- Update the location of the relevant classes and files to accommodate the new module structure
This commit is contained in:
gewuyou 2025-05-28 21:56:57 +08:00
parent 88f016dad2
commit 48228574be
27 changed files with 136 additions and 139 deletions

View File

@ -1,14 +1,6 @@
dependencies {
implementation(project(Modules.Core.EXTENSION))
implementation(project(Modules.Common.RESULT_API))
// Spring Cloud OpenFeign (Compile Only)
// https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign
compileOnly(libs.springCloudStarter.openfeign)
// Reactor Core (Compile Only)
// https://mvnrepository.com/artifact/io.projectreactor/reactor-core
compileOnly(libs.reactor.core)
compileOnly(libs.springBootStarter.web)
compileOnly(libs.springBootStarter.webflux)
extra{
setProperty(ProjectFlags.IS_ROOT_MODULE,true)
}
dependencies {
}

View File

@ -0,0 +1 @@
spring.application.name=api

View File

@ -0,0 +1,15 @@
dependencies {
compileOnly(platform(libs.springBootDependencies.bom))
compileOnly(platform(libs.springCloudDependencies.bom))
compileOnly(libs.springBootStarter.web)
compileOnly(libs.springBootStarter.webflux)
compileOnly(project(Modules.TRACE.API))
compileOnly(project(Modules.TRACE.IMPL))
// Spring Cloud OpenFeign (Compile Only)
// https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign
compileOnly(libs.springCloudStarter.openfeign)
// Reactor Core (Compile Only)
// https://mvnrepository.com/artifact/io.projectreactor/reactor-core
compileOnly(libs.reactor.core)
}

View File

@ -1,13 +1,14 @@
package com.gewuyou.forgeboot.trace.config
package com.gewuyou.forgeboot.trace.autoconfig
import com.gewuyou.forgeboot.common.result.api.RequestIdProvider
import com.gewuyou.forgeboot.trace.config.entities.TraceProperties
import com.gewuyou.forgeboot.trace.decorator.RequestIdTaskDecorator
import com.gewuyou.forgeboot.trace.filter.ReactiveRequestIdFilter
import com.gewuyou.forgeboot.trace.filter.RequestIdFilter
import com.gewuyou.forgeboot.trace.filter.WebClientRequestIdFilter
import com.gewuyou.forgeboot.trace.interceptor.FeignRequestIdInterceptor
import com.gewuyou.forgeboot.trace.provider.TraceRequestIdProvider
import com.gewuyou.forgeboot.trace.api.RequestIdProvider
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties
import com.gewuyou.forgeboot.trace.impl.decorator.RequestIdTaskDecorator
import com.gewuyou.forgeboot.trace.impl.filter.ReactiveRequestIdFilter
import com.gewuyou.forgeboot.trace.impl.filter.RequestIdFilter
import com.gewuyou.forgeboot.trace.impl.filter.WebClientRequestIdFilter
import com.gewuyou.forgeboot.trace.impl.interceptor.FeignRequestIdInterceptor
import com.gewuyou.forgeboot.trace.impl.provider.TraceRequestIdProvider
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean

View File

@ -0,0 +1 @@
com.gewuyou.forgeboot.trace.autoconfig.TraceAutoConfiguration

View File

@ -0,0 +1,12 @@
dependencies {
implementation(project(Modules.Core.EXTENSION))
compileOnly(project(Modules.TRACE.API))
compileOnly(platform(libs.springBootDependencies.bom))
compileOnly(platform(libs.springCloudDependencies.bom))
compileOnly(libs.springBootStarter.webflux)
compileOnly(libs.springBootStarter.web)
// Spring Cloud OpenFeign (Compile Only)
// https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign
compileOnly(libs.springCloudStarter.openfeign)
kapt(libs.springBoot.configuration.processor)
}

View File

@ -0,0 +1,30 @@
package com.gewuyou.forgeboot.trace.impl.config
import org.springframework.boot.context.properties.ConfigurationProperties
/**
* 跟踪属性
* 该类用于配置和管理请求跟踪相关的属性通过这些属性可以对请求进行唯一的标识和跟踪
* 主要功能包括定义请求ID的HTTP头名称请求ID在MDC中的键名称以及忽略跟踪的URL模式
*
* @author gewuyou
* @since 2025-05-02 20:58:45
*/
@ConfigurationProperties(prefix = "forgeboot.trace")
class TraceProperties {
/**
* HTTP请求头中用于传递请求ID的字段名称默认为"X-Request-Id"
*/
var requestIdHeaderName: String = "X-Request-Id"
/**
* MDCMapped Diagnostic Context中用于存储请求ID的键名默认为"requestId"
*/
var requestIdMdcKey: String = "requestId"
/**
* 配置忽略日志记录的路径模式通常用于静态资源文件
* 默认忽略以.css.js.png等结尾的静态资源请求
*/
var ignorePatten = arrayOf(".*\\.(css|js|png|jpg|jpeg|gif|svg)")
}

View File

@ -1,6 +1,6 @@
package com.gewuyou.forgeboot.trace.decorator
package com.gewuyou.forgeboot.trace.impl.decorator
import com.gewuyou.forgeboot.trace.config.entities.TraceProperties
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties
import org.slf4j.MDC
import org.springframework.core.task.TaskDecorator

View File

@ -1,4 +1,4 @@
package com.gewuyou.forgeboot.trace.extension
package com.gewuyou.forgeboot.trace.impl.extension
import jakarta.servlet.http.HttpServletRequest
import org.springframework.http.HttpMethod

View File

@ -1,11 +1,12 @@
package com.gewuyou.forgeboot.trace.filter
package com.gewuyou.forgeboot.trace.impl.filter
import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.trace.config.entities.TraceProperties
import com.gewuyou.forgeboot.trace.extension.isSkipRequest
import com.gewuyou.forgeboot.trace.util.RequestIdUtil
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties
import com.gewuyou.forgeboot.trace.impl.extension.isSkipRequest
import com.gewuyou.forgeboot.trace.impl.util.RequestIdUtil
import org.slf4j.MDC
import org.springframework.web.server.ServerWebExchange
import org.springframework.web.server.WebFilter
@ -36,10 +37,10 @@ class ReactiveRequestIdFilter(
val requestIdMdcKey = traceProperties.requestIdMdcKey
// 尝试从请求头中获取 requestId如果存在则设置到 RequestIdUtil 中,否则生成一个新的 requestId
request.headers[requestIdHeader]?.let {
it.firstOrNull()?.let(RequestIdUtil::setRequestId) ?: RequestIdUtil.generateRequestId()
it.firstOrNull()?.let(RequestIdUtil::requestId::set) ?: RequestIdUtil.generateRequestId()
} ?: RequestIdUtil.generateRequestId()
// 获取当前的 requestId
val currentRequestId = RequestIdUtil.getRequestId()
val currentRequestId = RequestIdUtil.requestId
// 将 requestId 设置到日志中
MDC.put(requestIdMdcKey, currentRequestId)
log.info("设置 Request id: $currentRequestId")
@ -53,7 +54,7 @@ class ReactiveRequestIdFilter(
return chain.filter(mutatedExchange)
// ✅ 让 Reactor 线程也能获取 requestId
// 将 requestId 写入 Reactor 的上下文中,以便在异步处理中也能访问
.contextWrite { ctx -> ctx.put(requestIdMdcKey, currentRequestId) }
.contextWrite { ctx -> ctx.put(requestIdMdcKey, currentRequestId!!) }
.doFinally {
// 清理 MDC 中的 requestId避免内存泄漏
MDC.remove(requestIdMdcKey)

View File

@ -1,10 +1,11 @@
package com.gewuyou.forgeboot.trace.filter
package com.gewuyou.forgeboot.trace.impl.filter
import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.trace.config.entities.TraceProperties
import com.gewuyou.forgeboot.trace.extension.isSkipRequest
import com.gewuyou.forgeboot.trace.util.RequestIdUtil
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties
import com.gewuyou.forgeboot.trace.impl.extension.isSkipRequest
import com.gewuyou.forgeboot.trace.impl.util.RequestIdUtil
import jakarta.servlet.FilterChain
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
@ -39,13 +40,13 @@ class RequestIdFilter(
try {
// 尝试从请求头中获取 requestId
request.getHeader(requestIdHeader)?.also(
RequestIdUtil::setRequestId
RequestIdUtil::requestId::set
) ?: run {
// 如果没有,则生成新的 requestId
RequestIdUtil.generateRequestId()
}
// 获取 requestId
val requestId = RequestIdUtil.getRequestId()
val requestId = RequestIdUtil.requestId
// 将requestId 设置到日志中
MDC.put(requestIdMdcKey, requestId)
log.info("设置 Request id: $requestId")

View File

@ -1,9 +1,10 @@
package com.gewuyou.forgeboot.trace.filter
package com.gewuyou.forgeboot.trace.impl.filter
import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.trace.config.entities.TraceProperties
import com.gewuyou.forgeboot.trace.extension.isSkipRequest
import com.gewuyou.forgeboot.trace.util.RequestIdUtil
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties
import com.gewuyou.forgeboot.trace.impl.extension.isSkipRequest
import com.gewuyou.forgeboot.trace.impl.util.RequestIdUtil
import org.slf4j.MDC
import org.springframework.web.reactive.function.client.ClientRequest
import org.springframework.web.reactive.function.client.ClientResponse
@ -35,10 +36,10 @@ class WebClientRequestIdFilter(
val requestIdMdcKey = traceProperties.requestIdMdcKey
// 尝试从请求头中获取 requestId如果存在则设置到 RequestIdUtil 中,否则生成一个新的 requestId
request.headers()[requestIdHeader]?.let {
it.firstOrNull()?.let(RequestIdUtil::setRequestId) ?: RequestIdUtil.generateRequestId()
it.firstOrNull()?.let(RequestIdUtil::requestId::set) ?: RequestIdUtil.generateRequestId()
} ?: RequestIdUtil.generateRequestId()
// 获取当前的 requestId
val currentRequestId = RequestIdUtil.getRequestId()
val currentRequestId = RequestIdUtil.requestId
// 将 requestId 设置到日志中
MDC.put(requestIdMdcKey, currentRequestId)
log.info("设置 Request id: $currentRequestId")

View File

@ -1,10 +1,10 @@
package com.gewuyou.forgeboot.trace.interceptor
package com.gewuyou.forgeboot.trace.impl.interceptor
import com.gewuyou.forgeboot.core.extension.log
import com.gewuyou.forgeboot.trace.config.entities.TraceProperties
import com.gewuyou.forgeboot.trace.util.RequestIdUtil
import com.gewuyou.forgeboot.trace.impl.config.TraceProperties
import com.gewuyou.forgeboot.trace.impl.util.RequestIdUtil
import feign.RequestInterceptor
import feign.RequestTemplate
@ -19,7 +19,7 @@ class FeignRequestIdInterceptor(
) : RequestInterceptor {
override fun apply(template: RequestTemplate) {
// 尝试获取当前请求的请求id
val requestId = RequestIdUtil.getRequestId()
val requestId = RequestIdUtil.requestId
requestId?.let {
// 如果请求id存在则添加到请求头中
template.header(traceProperties.requestIdHeaderName, requestId)

View File

@ -1,7 +1,8 @@
package com.gewuyou.forgeboot.trace.provider
package com.gewuyou.forgeboot.trace.impl.provider
import com.gewuyou.forgeboot.trace.api.RequestIdProvider
import com.gewuyou.forgeboot.trace.impl.util.RequestIdUtil
import com.gewuyou.forgeboot.common.result.api.RequestIdProvider
import com.gewuyou.forgeboot.trace.util.RequestIdUtil
/**
*跟踪请求ID提供商
@ -18,6 +19,6 @@ class TraceRequestIdProvider: RequestIdProvider {
* @return 请求ID的字符串表示
*/
override fun getRequestId(): String {
return RequestIdUtil.getRequestId()
return RequestIdUtil.requestId?:throw RuntimeException("requestId is null")
}
}

View File

@ -0,0 +1,26 @@
package com.gewuyou.forgeboot.trace.impl.util
import java.util.*
/**
* 请求 ID Util
* 这个类需配合 RequestIdFilter 使用用于生成请求 ID并将其绑定到线程变量中供后续可能需要的地方使用
* @author gewuyou
* @since 2025-01-02 14:27:45
*/
object RequestIdUtil {
private val REQUEST_ID_HOLDER = ThreadLocal<String>()
fun generateRequestId() {
REQUEST_ID_HOLDER.set(UUID.randomUUID().toString())
}
var requestId: String?
get() = REQUEST_ID_HOLDER.get()
set(uuid) {
REQUEST_ID_HOLDER.set(uuid)
}
fun removeRequestId() {
REQUEST_ID_HOLDER.remove()
}
}

View File

@ -0,0 +1 @@
spring.application.name=impl

View File

@ -1,54 +0,0 @@
package com.gewuyou.forgeboot.trace.config.entities;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 跟踪属性
* 该类用于配置和管理请求跟踪相关的属性通过这些属性可以对请求进行唯一的标识和跟踪
* 主要功能包括定义请求ID的HTTP头名称请求ID在MDC中的键名称以及忽略跟踪的URL模式
*
* @author gewuyou
* @since 2025-05-02 20:58:45
*/
@ConfigurationProperties(prefix = "forgeboot.trace")
public class TraceProperties {
/**
* HTTP请求头中用于传递请求ID的字段名称默认为"X-Request-Id"
*/
private String requestIdHeaderName = "X-Request-Id";
/**
* MDCMapped Diagnostic Context中用于存储请求ID的键名默认为"requestId"
*/
private String requestIdMdcKey = "requestId";
/**
* 配置忽略日志记录的路径模式通常用于静态资源文件
* 默认忽略以.css.js.png等结尾的静态资源请求
*/
private String[] ignorePatten = new String[]{".*\\.(css|js|png|jpg|jpeg|gif|svg)"};
public String getRequestIdHeaderName() {
return requestIdHeaderName;
}
public String[] getIgnorePatten() {
return ignorePatten;
}
public void setIgnorePatten(String[] ignorePatten) {
this.ignorePatten = ignorePatten;
}
public void setRequestIdHeaderName(String requestIdHeaderName) {
this.requestIdHeaderName = requestIdHeaderName;
}
public String getRequestIdMdcKey() {
return requestIdMdcKey;
}
public void setRequestIdMdcKey(String requestIdMdcKey) {
this.requestIdMdcKey = requestIdMdcKey;
}
}

View File

@ -1,30 +0,0 @@
package com.gewuyou.forgeboot.trace.util;
import java.util.UUID;
/**
* 请求 ID Util
* 这个类需配合 RequestIdFilter 使用用于生成请求 ID并将其绑定到线程变量中供后续可能需要的地方使用
* @author gewuyou
* @since 2025-01-02 14:27:45
*/
public class RequestIdUtil {
private static final ThreadLocal<String> REQUEST_ID_HOLDER = new ThreadLocal<>();
private RequestIdUtil() {
}
public static void generateRequestId() {
REQUEST_ID_HOLDER.set(UUID.randomUUID().toString());
}
public static String getRequestId() {
return REQUEST_ID_HOLDER.get();
}
public static void setRequestId(String uuid) {
REQUEST_ID_HOLDER.set(uuid);
}
public static void removeRequestId() {
REQUEST_ID_HOLDER.remove();
}
}

View File

@ -1 +0,0 @@
com.gewuyou.forgeboot.trace.config.TraceAutoConfiguration