12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- package middlewares
- import (
- "github.com/gin-gonic/gin"
- "go.uber.org/zap"
- "net"
- "net/http"
- "net/http/httputil"
- "os"
- "runtime/debug"
- "strings"
- "time"
- )
- func GinLogger(logger *zap.Logger) gin.HandlerFunc {
- return func(c *gin.Context) {
- timeFormat := "ISO8601"
- utc := true
- start := time.Now()
- // some evil middlewares modify this values
- path := c.Request.URL.Path
- query := c.Request.URL.RawQuery
- c.Next()
- end := time.Now()
- latency := end.Sub(start)
- if utc {
- end = end.UTC()
- }
- if len(c.Errors) > 0 {
- // Append error field if this is an erroneous request.
- for _, e := range c.Errors.Errors() {
- logger.Error(e)
- }
- } else {
- logger.Info(path,
- zap.Int("status", c.Writer.Status()),
- zap.String("method", c.Request.Method),
- zap.String("path", path),
- zap.String("query", query),
- zap.String("ip", c.ClientIP()),
- zap.String("user-agent", c.Request.UserAgent()),
- zap.String("time", end.Format(timeFormat)),
- zap.Duration("latency", latency),
- )
- }
- }
- }
- func RecoveryWithZap(logger *zap.Logger, stack bool) gin.HandlerFunc {
- return func(c *gin.Context) {
- defer func() {
- if err := recover(); err != nil {
- // Check for a broken connection, as it is not really a
- // condition that warrants a panic stack trace.
- var brokenPipe bool
- if ne, ok := err.(*net.OpError); ok {
- if se, ok := ne.Err.(*os.SyscallError); ok {
- if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
- brokenPipe = true
- }
- }
- }
- httpRequest, _ := httputil.DumpRequest(c.Request, false)
- if brokenPipe {
- logger.Error(c.Request.URL.Path,
- zap.Any("error", err),
- zap.String("request", string(httpRequest)),
- )
- // If the connection is dead, we can't write a status to it.
- c.Error(err.(error)) // nolint: errcheck
- c.Abort()
- return
- }
- if stack {
- logger.Error("[Recovery from panic]",
- zap.Time("time", time.Now()),
- zap.Any("error", err),
- zap.String("request", string(httpRequest)),
- zap.String("stack", string(debug.Stack())),
- )
- } else {
- logger.Error("[Recovery from panic]",
- zap.Time("time", time.Now()),
- zap.Any("error", err),
- zap.String("request", string(httpRequest)),
- )
- }
- c.AbortWithStatus(http.StatusInternalServerError)
- }
- }()
- c.Next()
- }
- }
|