kra/internal/server/middleware/gin_logger.go

96 lines
2.2 KiB
Go

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