127 lines
2.8 KiB
Go
127 lines
2.8 KiB
Go
package middleware
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"math"
|
|
"strings"
|
|
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// 需要记录响应内容的 API 路径前缀
|
|
var logResponsePaths = []string{
|
|
"/api/v1/message/send",
|
|
"/api/v2/message/send",
|
|
}
|
|
|
|
// responseBodyWriter 用于捕获响应内容
|
|
type responseBodyWriter struct {
|
|
gin.ResponseWriter
|
|
body *bytes.Buffer
|
|
}
|
|
|
|
func (w responseBodyWriter) Write(b []byte) (int, error) {
|
|
w.body.Write(b)
|
|
return w.ResponseWriter.Write(b)
|
|
}
|
|
|
|
// LogMiddleware Logger is the logrus logger handler
|
|
func LogMiddleware(notLogged ...string) gin.HandlerFunc {
|
|
//hostname, err := os.Hostname()
|
|
//if err != nil {
|
|
// hostname = "unknown"
|
|
//}
|
|
|
|
var skip map[string]struct{}
|
|
|
|
if length := len(notLogged); length > 0 {
|
|
skip = make(map[string]struct{}, length)
|
|
for _, p := range notLogged {
|
|
skip[p] = struct{}{}
|
|
}
|
|
}
|
|
|
|
return func(c *gin.Context) {
|
|
path := c.Request.URL.Path
|
|
raw := c.Request.URL.RawQuery
|
|
start := time.Now()
|
|
|
|
// 判断是否需要捕获响应内容
|
|
needCaptureResponse := false
|
|
for _, logPath := range logResponsePaths {
|
|
if strings.HasPrefix(path, logPath) {
|
|
needCaptureResponse = true
|
|
break
|
|
}
|
|
}
|
|
|
|
var bodyWriter *responseBodyWriter
|
|
if needCaptureResponse {
|
|
bodyWriter = &responseBodyWriter{
|
|
ResponseWriter: c.Writer,
|
|
body: bytes.NewBufferString(""),
|
|
}
|
|
c.Writer = bodyWriter
|
|
}
|
|
|
|
c.Next()
|
|
|
|
stop := time.Since(start)
|
|
latency := int(math.Ceil(float64(stop.Nanoseconds()) / 1000000.0))
|
|
statusCode := c.Writer.Status()
|
|
clientIP := c.ClientIP()
|
|
//clientUserAgent := c.Request.UserAgent()
|
|
//referer := c.Request.Referer()
|
|
dataLength := c.Writer.Size()
|
|
if dataLength < 0 {
|
|
dataLength = 0
|
|
}
|
|
if raw != "" {
|
|
raw, _ := url.QueryUnescape(raw)
|
|
path = path + "?" + raw
|
|
}
|
|
if _, ok := skip[path]; ok {
|
|
return
|
|
}
|
|
|
|
entry := logrus.WithFields(logrus.Fields{
|
|
////"hostname": hostname,
|
|
//"statusCode": statusCode,
|
|
//"latency": latency,
|
|
//"clientIP": clientIP,
|
|
//"method": c.Request.Method,
|
|
//"path": path,
|
|
////"referer": referer,
|
|
//"dataLength": dataLength,
|
|
////"userAgent": clientUserAgent,
|
|
"prefix": "[Gin]",
|
|
})
|
|
|
|
if len(c.Errors) > 0 {
|
|
entry.Error(c.Errors.ByType(gin.ErrorTypePrivate).String())
|
|
} else {
|
|
msg := fmt.Sprintf("%s [%s] %s %d %d (%dms)", clientIP, c.Request.Method, path, statusCode, dataLength, latency)
|
|
|
|
// 如果是发送消息的 API,打印返回内容
|
|
if needCaptureResponse && bodyWriter != nil {
|
|
responseBody := bodyWriter.body.String()
|
|
msg = fmt.Sprintf("%s | Response: %s", msg, responseBody)
|
|
}
|
|
|
|
if statusCode >= http.StatusInternalServerError {
|
|
entry.Error(msg)
|
|
} else if statusCode >= http.StatusBadRequest {
|
|
entry.Warn(msg)
|
|
} else {
|
|
entry.Info(msg)
|
|
}
|
|
}
|
|
}
|
|
}
|