zhangqian
2023-08-26 5193dcb9336e853502baf8a539d3f45efebe2f86
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package middleware
 
import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "strings"
    "time"
 
    "github.com/gin-gonic/gin"
)
 
// LogLayout 日志layout
type LogLayout struct {
    Time      time.Time
    Metadata  map[string]interface{} // 存储自定义原数据
    Path      string                 // 访问路径
    Query     string                 // 携带query
    Body      string                 // 携带body数据
    IP        string                 // ip地址
    UserAgent string                 // 代理
    Error     string                 // 错误
    Cost      time.Duration          // 花费时间
    Source    string                 // 来源
}
 
type Logger struct {
    // Filter 用户自定义过滤
    Filter func(c *gin.Context) bool
    // FilterKeyword 关键字过滤(key)
    FilterKeyword func(layout *LogLayout) bool
    // AuthProcess 鉴权处理
    AuthProcess func(c *gin.Context, layout *LogLayout)
    // 日志处理
    Print func(LogLayout)
    // Source 服务唯一标识
    Source string
}
 
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 {
            // 自行判断key/value 脱敏等
            l.FilterKeyword(&layout)
        }
        // 自行处理日志
        l.Print(layout)
    }
}
 
func DefaultLogger() gin.HandlerFunc {
    return Logger{
        Print: func(layout LogLayout) {
            // 标准输出,k8s做收集
            v, _ := json.Marshal(layout)
            fmt.Println(string(v))
        },
        Source: "GVA",
    }.SetLoggerMiddleware()
}