Some checks failed
CI / Build & Test (push) Failing after 33s
- 37 个端点全部添加 godoc Swagger 注解(RBAC 11 / Org 5 / Audit 1 / Settings 7 / Notification 7) - 重新生成 docs/(swagger.json/yaml/docs.go) - M8 质量横切:IP 限流、安全头、Body 限制、结构化日志增强、优雅关闭 - 新增 Dockerfile 多阶段构建 + .dockerignore - 新增 testutil 测试工具包 - 修复 testutil.go 编译错误
73 lines
1.6 KiB
Go
73 lines
1.6 KiB
Go
package middleware
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func RequestID() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
traceID := c.GetHeader("X-Request-ID")
|
|
if traceID == "" {
|
|
traceID = uuid.New().String()
|
|
}
|
|
c.Set("trace_id", traceID)
|
|
c.Header("X-Request-ID", traceID)
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
func RequestLogger(log *zap.Logger) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
start := time.Now()
|
|
path := c.Request.URL.Path
|
|
query := c.Request.URL.RawQuery
|
|
|
|
c.Next()
|
|
|
|
latency := time.Since(start)
|
|
status := c.Writer.Status()
|
|
|
|
fields := []zap.Field{
|
|
zap.Int("status", status),
|
|
zap.String("method", c.Request.Method),
|
|
zap.String("path", path),
|
|
zap.String("query", query),
|
|
zap.String("ip", c.ClientIP()),
|
|
zap.String("user-agent", c.Request.UserAgent()),
|
|
zap.Duration("latency", latency),
|
|
zap.String("trace_id", c.GetString("trace_id")),
|
|
}
|
|
|
|
if c.Writer.Status() >= 500 {
|
|
log.Error("request completed with server error", fields...)
|
|
} else if c.Writer.Status() >= 400 {
|
|
log.Warn("request completed with client error", fields...)
|
|
} else {
|
|
log.Info("request", fields...)
|
|
}
|
|
}
|
|
}
|
|
|
|
func Recovery(log *zap.Logger) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
log.Error("panic recovered",
|
|
zap.Any("error", r),
|
|
zap.String("path", c.Request.URL.Path),
|
|
zap.String("trace_id", c.GetString("trace_id")),
|
|
)
|
|
c.AbortWithStatusJSON(500, gin.H{
|
|
"error": "INTERNAL_ERROR",
|
|
"message": "internal server error",
|
|
})
|
|
}
|
|
}()
|
|
c.Next()
|
|
}
|
|
}
|