12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 |
- package middleware
- import (
- "github.com/sirupsen/logrus"
- "net"
- "net/http"
- "net/http/httputil"
- "os"
- "runtime/debug"
- "strings"
- "github.com/gin-gonic/gin"
- "go.uber.org/zap"
- )
- // GinRecovery recover掉项目可能出现的panic,并使用zap记录相关日志
- func GinRecovery(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 {
- logrus.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 {
- logrus.Error("[Recovery from panic]",
- zap.Any("error", err),
- zap.String("request", string(httpRequest)),
- zap.String("stack", string(debug.Stack())),
- )
- } else {
- logrus.Error("[Recovery from panic]",
- zap.Any("error", err),
- zap.String("request", string(httpRequest)),
- )
- }
- c.AbortWithStatus(http.StatusInternalServerError)
- }
- }()
- c.Next()
- }
- }
|