package middleware import ( "bytes" "encoding/json" "fmt" "io" "strings" "time" "github.com/gin-gonic/gin" ) // LogLayout 日志layout type LogLayout struct { Time time.Time `json:"time"` Metadata map[string]interface{} `json:"metadata,omitempty"` Path string `json:"path"` Query string `json:"query,omitempty"` Body string `json:"body,omitempty"` IP string `json:"ip"` UserAgent string `json:"user_agent"` Error string `json:"error,omitempty"` Cost time.Duration `json:"cost"` Source string `json:"source"` } // Logger 日志中间件配置 type Logger struct { // Filter 用户自定义过滤 Filter func(c *gin.Context) bool // FilterKeyword 关键字过滤 FilterKeyword func(layout *LogLayout) bool // AuthProcess 鉴权处理 AuthProcess func(c *gin.Context, layout *LogLayout) // Print 日志处理 Print func(LogLayout) // Source 服务唯一标识 Source string } // SetLoggerMiddleware 设置日志中间件 func (l Logger) SetLoggerMiddleware() gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() path := c.Request.URL.Path query := c.Request.URL.RawQuery var body []byte if l.Filter != nil && !l.Filter(c) { body, _ = c.GetRawData() // 将原body塞回去 c.Request.Body = io.NopCloser(bytes.NewBuffer(body)) } c.Next() cost := time.Since(start) layout := LogLayout{ Time: time.Now(), Path: path, Query: query, IP: c.ClientIP(), UserAgent: c.Request.UserAgent(), Error: strings.TrimRight(c.Errors.ByType(gin.ErrorTypePrivate).String(), "\n"), Cost: cost, Source: l.Source, } if l.Filter != nil && !l.Filter(c) { layout.Body = string(body) } if l.AuthProcess != nil { l.AuthProcess(c, &layout) } if l.FilterKeyword != nil { l.FilterKeyword(&layout) } l.Print(layout) } } // DefaultLogger 默认日志中间件 func DefaultLogger() gin.HandlerFunc { return Logger{ Print: func(layout LogLayout) { v, _ := json.Marshal(layout) fmt.Println(string(v)) }, Source: "KRA", }.SetLoggerMiddleware() }