136 lines
3.3 KiB
Go
136 lines
3.3 KiB
Go
package middleware
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.com/gin-gonic/gin"
|
|
"service/library/logger"
|
|
"strings"
|
|
"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 bodyBytes []byte
|
|
body, ok := c.Get(gin.BodyBytesKey)
|
|
if ok {
|
|
bodyBytes = body.([]byte)
|
|
}
|
|
if _, ok := NoLogRoutesMap[param.Path]; !ok {
|
|
logger.Info("%s params: %s", formatter(param), string(bodyBytes))
|
|
}
|
|
if strings.Contains(param.Path, "is_there_a_new_version_available") {
|
|
logger.Info("%s response: %s", formatter(param), blw.body.String())
|
|
}
|
|
|
|
bReq := BaseRequest{}
|
|
_ = json.Unmarshal(bodyBytes, &bReq)
|
|
if bReq.Mid == 161 {
|
|
logger.Info("%s xresponse: %s", formatter(param), blw.body.String())
|
|
}
|
|
|
|
//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())
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
|
|
var NoLogRoutesMap = map[string]bool{
|
|
"/healthcheck": true,
|
|
}
|
|
|
|
type BaseRequest struct {
|
|
Mid int64 `json:"b_mid"` // 用户id
|
|
Did string `json:"b_did"` // 设备id
|
|
Version string `json:"b_ver"` // 版本
|
|
OsVersion string `json:"b_osver"` // 系统版本
|
|
DevType int32 `json:"b_dt"` // 设备类型
|
|
Channel string `json:"b_ch"` // 渠道
|
|
Model string `json:"b_model"` // 机型
|
|
NetType string `json:"b_nt"` // 网络类型
|
|
Timestamp int64 `json:"b_ts"` // 时间戳,毫秒
|
|
Token string `json:"b_token"` // 令牌
|
|
Location struct {
|
|
Lat float64 `json:"b_lat"`
|
|
Lon float64 `json:"b_lon"`
|
|
} `json:"b_loc"` // 经纬度
|
|
}
|