2023-12-21 22:17:40 +08:00
|
|
|
package middleware
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"service/library/logger"
|
2024-05-16 23:18:24 +08:00
|
|
|
"strings"
|
2023-12-21 22:17:40 +08:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
var defaultLogFormatter = func(param gin.LogFormatterParams) string {
|
|
|
|
if param.Latency > time.Minute {
|
|
|
|
// Truncate in a golang < 1.8 safe way
|
|
|
|
param.Latency = param.Latency - param.Latency%time.Second
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("|%3d|%13v|%15s|%-7s %#v\t%s",
|
|
|
|
param.StatusCode,
|
|
|
|
param.Latency,
|
|
|
|
param.ClientIP,
|
|
|
|
param.Method,
|
|
|
|
param.Path,
|
|
|
|
param.ErrorMessage,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
|
|
|
func LoggerMiddleware(conf gin.LoggerConfig) gin.HandlerFunc {
|
|
|
|
formatter := conf.Formatter
|
|
|
|
if formatter == nil {
|
|
|
|
formatter = defaultLogFormatter
|
|
|
|
}
|
|
|
|
|
|
|
|
return func(c *gin.Context) {
|
|
|
|
// Start timer
|
|
|
|
start := time.Now()
|
|
|
|
path := c.Request.URL.Path
|
|
|
|
raw := c.Request.URL.RawQuery
|
|
|
|
|
|
|
|
//body writer
|
|
|
|
blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
|
|
|
|
c.Writer = blw
|
|
|
|
|
|
|
|
// Process request
|
|
|
|
c.Next()
|
|
|
|
|
|
|
|
notlogged := conf.SkipPaths
|
|
|
|
var skip map[string]struct{}
|
|
|
|
if length := len(notlogged); length > 0 {
|
|
|
|
skip = make(map[string]struct{}, length)
|
|
|
|
|
|
|
|
for _, path := range notlogged {
|
|
|
|
skip[path] = struct{}{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Log only when path is not being skipped
|
|
|
|
if _, ok := skip[path]; !ok {
|
|
|
|
param := gin.LogFormatterParams{
|
|
|
|
Request: c.Request,
|
|
|
|
Keys: c.Keys,
|
|
|
|
}
|
|
|
|
// Stop timer
|
|
|
|
param.TimeStamp = time.Now()
|
|
|
|
param.Latency = param.TimeStamp.Sub(start)
|
|
|
|
|
|
|
|
param.ClientIP = c.ClientIP()
|
|
|
|
param.Method = c.Request.Method
|
|
|
|
param.StatusCode = c.Writer.Status()
|
|
|
|
param.ErrorMessage = c.Errors.ByType(gin.ErrorTypePrivate).String()
|
|
|
|
|
|
|
|
param.BodySize = c.Writer.Size()
|
|
|
|
|
|
|
|
if raw != "" {
|
|
|
|
path = path + "?" + raw
|
|
|
|
}
|
|
|
|
|
|
|
|
param.Path = path
|
|
|
|
|
|
|
|
var bodyStr string
|
|
|
|
body, ok := c.Get(gin.BodyBytesKey)
|
|
|
|
if ok {
|
|
|
|
bodyStr = string(body.([]byte))
|
|
|
|
}
|
2024-05-21 17:16:39 +08:00
|
|
|
if _, ok := NoLogRoutesMap[param.Path]; !ok {
|
|
|
|
logger.Info("%s params: %s", formatter(param), bodyStr)
|
|
|
|
}
|
2024-05-16 23:18:24 +08:00
|
|
|
if strings.Contains(param.Path, "is_there_a_new_version_available") {
|
|
|
|
logger.Info("%s response: %s", formatter(param), blw.body.String())
|
|
|
|
}
|
2023-12-21 22:17:40 +08:00
|
|
|
|
|
|
|
//logger.WithCtx(c.Request.Context()).Info("%s params: %s", formatter(param), bodyStr)
|
|
|
|
//if accessConf.LogResponseEnabled {
|
|
|
|
// logger.WithCtx(c.Request.Context()).Info("%s response: %s", formatter(param), blw.body.String())
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-05-21 17:16:39 +08:00
|
|
|
|
|
|
|
var NoLogRoutesMap = map[string]bool{
|
|
|
|
"/healthcheck": true,
|
|
|
|
}
|