// Source: https://github.com/toorop/gin-logrus package log import ( "fmt" "math" "net/http" "os" "time" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" ) // GinLogger integrates logrus with gin func GinLogger(logger logrus.FieldLogger, notLogged ...string) gin.HandlerFunc { hostname, err := os.Hostname() if err != nil { hostname = "unknow" } 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 start := time.Now() 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 _, ok := skip[path]; ok { return } entry := logger.WithFields(logrus.Fields{ "hostname": hostname, "statusCode": statusCode, "latency": latency, "clientIP": clientIP, "method": c.Request.Method, "path": path, "referer": referer, "dataLength": dataLength, "userAgent": clientUserAgent, }) if len(c.Errors) > 0 { entry.Error(c.Errors.ByType(gin.ErrorTypePrivate).String()) } else { msg := fmt.Sprintf("%s [%d] %s %s", clientIP, statusCode, c.Request.Method, path) if statusCode >= http.StatusInternalServerError { entry.Error(msg) } else if statusCode >= http.StatusBadRequest { entry.Warn(msg) } else { entry.Info(msg) } } } }