竹简文档
辅助中间件

请求上下文

RequestContext 为每个请求生成唯一标识符和记录开始时间

请求上下文

RequestContext 为每个 HTTP 请求生成唯一标识符 (UUID) 并记录请求开始时间,用于请求追踪和性能监控。

RequestContext

context.go
func RequestContext() gin.HandlerFunc

实现:

context.go
func RequestContext() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 1. 生成请求唯一 ID (UUID)
        requestID := uuid.NewString()

        // 2. 设置响应头 X-Request-UUID
        c.Writer.Header().Set(xHttp.HeaderRequestUUID.String(), requestID)

        // 3. 存储到 Gin Context
        c.Set(xCtx.RequestKey.String(), requestID)
        c.Set(xCtx.UserStartTimeKey.String(), time.Now())

        // 4. 注入到标准 context (供 slog 日志使用)
        ctx := context.WithValue(c.Request.Context(), xCtx.RequestKey, requestID)
        c.Request = c.Request.WithContext(ctx)

        c.Next()
    }
}

注入的上下文键

字段

类型

响应头

中间件会在响应头中添加请求 UUID:

X-Request-UUID: 550e8400-e29b-41d4-a716-446655440000

使用示例

基础使用

main.go
func main() {
    router := gin.New()

    // 注册请求上下文中间件(应该最先注册)
    router.Use(xHelper.RequestContext())

    router.GET("/api/users", getUsers)
    router.Run(":8080")
}

获取请求 UUID

handler/user.go
func GetUser(ctx *gin.Context) {
    // 从 Gin Context 获取
    requestID := ctx.GetString(xCtx.RequestKey.String())

    // 用于日志记录
    xLog.WithName(xLog.NamedCONT).SugarInfo(ctx, "处理用户请求",
        "request_id", requestID,
    )
}

计算请求耗时

middleware/timing.go
func TimingMiddleware() gin.HandlerFunc {
    return func(ctx *gin.Context) {
        ctx.Next()

        // 获取开始时间并计算耗时
        if startTime, exists := ctx.Get(xCtx.UserStartTimeKey.String()); exists {
            elapsed := time.Since(startTime.(time.Time))
            xLog.WithName(xLog.NamedMIDE).SugarInfo(ctx, "请求耗时",
                "elapsed_ms", elapsed.Milliseconds(),
            )
        }
    }
}

传递到 Service 层

handler/user.go
func GetUser(ctx *gin.Context) {
    // ctx 已包含 RequestKey,可直接传递
    user, err := userService.FindByID(ctx, id)
    // ...
}
service/user.go
func (s *UserService) FindByID(ctx context.Context, id string) (*entity.User, error) {
    // 日志会自动提取 RequestKey 作为 Trace ID
    xLog.WithName(xLog.NamedSERV).Info(ctx, "查询用户")

    // GORM 操作也会继承 Trace ID
    return s.repo.FindByID(ctx, id)
}

工作流程

下一步

On this page