-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrequest-log.go
105 lines (91 loc) · 2.42 KB
/
request-log.go
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package ginmiddleware
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"time"
"github.com/gin-gonic/gin"
bbpool "github.com/valyala/bytebufferpool"
"github.com/waro163/gin-middleware/utils"
)
const (
RequestLogChar string = "RequestLog"
ResponseLogChar string = "ResponseLog"
TimeStamp string = "TimeStamp"
Method string = "Method"
Host string = "Host"
Uri string = "Uri"
ReqHeader string = "ReqHeader"
ReqBody string = "ReqBody"
RespHeader string = "RespHeader"
RespBody string = "RespBody"
StatusCode string = "StatusCode"
Latency string = "Latency"
)
type PathSettings struct {
Path string
DisableLogs bool
DisableBodies bool
}
type RequestLog struct {
Output io.Writer
Settings []PathSettings
MaskedFields []string
TimeFormat string
}
func (l *RequestLog) AddRequestLog() gin.HandlerFunc {
if l.Output == nil {
l.Output = os.Stdout
}
if l.TimeFormat == "" {
l.TimeFormat = "2006-01-02 15:04:05.000"
}
return func(c *gin.Context) {
ctx := c.Request.Context()
logger := CtxLogger(ctx).Output(l.Output)
start := time.Now()
host := c.Request.Host
uri := c.Request.RequestURI
method := c.Request.Method
headerBytes, _ := json.Marshal(c.Request.Header)
subLog := logger.With().
Str(TimeStamp, start.Format(l.TimeFormat)).
Str(Method, method).
Str(Host, host).
Str(Uri, uri).
Logger()
reqBody, _ := io.ReadAll(c.Request.Body)
c.Request.Body = io.NopCloser(bytes.NewReader(reqBody))
reqLog := subLog.With().
RawJSON(ReqHeader, headerBytes).
RawJSON(ReqBody, reqBody).
Logger()
reqLog.Info().Msg(RequestLogChar)
bbuffer := bbpool.Get()
// if status is 404 or 405, gin will handle those at last, but our *utils.WrapResponseWriter had been put nil
status := c.Writer.Status()
if status != http.StatusNotFound && status != http.StatusMethodNotAllowed {
c.Writer = &utils.WrapResponseWriter{
ResponseWriter: c.Writer,
ByteBuffer: bbuffer,
}
}
defer func() {
bbpool.Put(bbuffer)
}()
c.Next()
latency := time.Since(start)
status = c.Writer.Status()
respHeaderBytes, _ := json.Marshal(c.Writer.Header())
respLog := subLog.With().
Int(StatusCode, status).
RawJSON(RespHeader, respHeaderBytes).
RawJSON(RespBody, bbuffer.Bytes()).
Str(Latency, fmt.Sprintf("%v", latency)).
Logger()
respLog.Info().Msg(ResponseLogChar)
}
}