majianyu
1/12/2019 - 8:44 AM

mid_log

gin 记录输入输出中间件

// Author: Mjy
// Create Date: 2018-12-18
package middleware

import (
	"b.com/dsers/components"
	"b.com/dsers/handler"
	"bytes"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/willf/pad"
	"io/ioutil"
	"time"
)

type bodyLogWriter struct {
	gin.ResponseWriter
	body *bytes.Buffer
}

func (this bodyLogWriter) Write(b []byte) (int, error) {
	this.body.Write(b)
	return this.ResponseWriter.Write(b)
}

func Logging(tag string) gin.HandlerFunc {
	return func(c *gin.Context) {
		start := time.Now().UTC()
		path := c.Request.URL.Path

		var bodyBytes []byte
		if c.Request.Body != nil {
			bodyBytes, _ = ioutil.ReadAll(c.Request.Body)
		}
		// 恢复 body
		c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))

		method := c.Request.Method
		ip := c.ClientIP()

		blw := &bodyLogWriter{
			body:           bytes.NewBufferString(""),
			ResponseWriter: c.Writer,
		}
		c.Writer = blw

		c.Next()
		end := time.Now().UTC()
		latency := end.Sub(start)

		var response handler.JsonResponse
		if err := json.Unmarshal(blw.body.Bytes(), &response); err != nil {
			components.Logger.Errorf("response body can not unmarshal to model.Response struct, body: '%s', err:%v", blw.body.Bytes, err)
		}
		components.Logger.Infof("%s |%-13s | %-12s | %s %s | %v | %v", tag, latency, ip, pad.Right(method, 5, ""), path, string(bodyBytes), blw.body.String())
	}
}