package middleware import ( "bytes" "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 bodyStr string body, ok := c.Get(gin.BodyBytesKey) if ok { bodyStr = string(body.([]byte)) } if _, ok := NoLogRoutesMap[param.Path]; !ok { logger.Info("%s params: %s", formatter(param), bodyStr) } if strings.Contains(param.Path, "is_there_a_new_version_available") { logger.Info("%s response: %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, }