package middleware import ( "bytes" "encoding/json" "fmt" "gitee.com/danlansky/go-library/logs" "github.com/gin-gonic/gin" "github.com/willf/pad" "go.uber.org/zap" "io/ioutil" "time" ) type bodyLogWriter struct { gin.ResponseWriter body *bytes.Buffer } func (w bodyLogWriter) Write(b []byte) (int, error) { w.body.Write(b) return w.ResponseWriter.Write(b) } // Logging is a middleware function that logs the each request. func Logging() gin.HandlerFunc { return func(c *gin.Context) { start := time.Now().UTC() // Read the Body content var bodyBytes []byte if c.Request.Body != nil { bodyBytes, _ = ioutil.ReadAll(c.Request.Body) } // Restore the io.ReadCloser to its original state c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) // The basic informations. method := c.Request.Method ip := c.ClientIP() //log.Debugf("New request come in, path: %s, Method: %s, body `%s`", path, method, string(bodyBytes)) blw := &bodyLogWriter{ body: bytes.NewBufferString(""), ResponseWriter: c.Writer, } c.Writer = blw // Continue. c.Next() // Calculates the latency. end := time.Now().UTC() latency := end.Sub(start) var code int var message string // 移除json不必要的空格,即json字符串压缩 var postJsonStr bytes.Buffer _ = json.Compact(&postJsonStr, bodyBytes) // get code and message if json.Valid(blw.body.Bytes()) == false { code = 500 message = "err response,not json" } else { code = 200 message = "ok" } str := fmt.Sprintf("%s|%s|%s|%d|%s|{code: %d, message: %s}", latency, ip, pad.Right(method, 5, ""), blw.ResponseWriter.Status(), c.Request.URL.RequestURI(), code, message) logs.AccessLog(str, zap.String("reqid", c.GetString("X-Request-Id")), zap.String("post", postJsonStr.String())) } }