log.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. package middleware
  2. import (
  3. "bytes"
  4. "io/ioutil"
  5. "net"
  6. "net/http"
  7. "net/http/httputil"
  8. "os"
  9. "runtime/debug"
  10. "strings"
  11. "time"
  12. "gitee.com/xuyiping_admin/pkg/logger/zaplog"
  13. "github.com/gin-gonic/gin"
  14. "go.uber.org/zap"
  15. )
  16. type responseBodyWriter struct {
  17. gin.ResponseWriter
  18. body *bytes.Buffer
  19. }
  20. type stackErr struct {
  21. Err error
  22. Stack string
  23. }
  24. func (s *stackErr) Error() string {
  25. return s.Err.Error()
  26. }
  27. func (r responseBodyWriter) Write(b []byte) (int, error) {
  28. r.body.Write(b)
  29. return r.ResponseWriter.Write(b)
  30. }
  31. // GinLogger 接管gin框架默认的日志
  32. func GinLogger() gin.HandlerFunc {
  33. return func(c *gin.Context) {
  34. // 获取 response 内容
  35. w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer}
  36. c.Writer = w
  37. var requestBody []byte
  38. if c.Request.Body != nil {
  39. requestBody, _ = ioutil.ReadAll(c.Request.Body)
  40. c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(requestBody))
  41. }
  42. start := time.Now()
  43. c.Next()
  44. cost := time.Since(start)
  45. logFields := []zap.Field{
  46. zap.Int("status", c.Writer.Status()),
  47. zap.String("request", c.Request.Method+" "+c.Request.URL.String()),
  48. zap.String("query", c.Request.URL.RawQuery),
  49. zap.String("ip", c.ClientIP()),
  50. zap.String("user-agent", c.Request.UserAgent()),
  51. //zap.String("errors", c.Errors.ByType(gin.ErrorTypePrivate).String()),
  52. zap.String("time", cost.String()),
  53. zap.String("Request body", string(requestBody)),
  54. zap.String("Response body", w.body.String()),
  55. }
  56. if len(c.Errors) > 0 {
  57. logFields = append(logFields, zap.Any("stack", string(debug.Stack())))
  58. zaplog.Error("Http-Access-Error", logFields...)
  59. c.Abort()
  60. } else {
  61. zaplog.Info("Http-Access-Log", logFields...)
  62. }
  63. }
  64. }
  65. // GinRecovery recover掉我的项目可能呈现的panic
  66. func GinRecovery(stack bool) gin.HandlerFunc {
  67. return func(c *gin.Context) {
  68. defer func() {
  69. if err := recover(); err != nil {
  70. // Check for a broken connection, as it is not really a
  71. // condition that warrants a panic stack trace.
  72. var brokenPipe bool
  73. if ne, ok := err.(*net.OpError); ok {
  74. if se, ok := ne.Err.(*os.SyscallError); ok {
  75. if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
  76. brokenPipe = true
  77. }
  78. }
  79. }
  80. httpRequest, _ := httputil.DumpRequest(c.Request, false)
  81. if brokenPipe {
  82. zaplog.Error(c.Request.URL.Path,
  83. zap.Any("error", err),
  84. zap.String("request", string(httpRequest)),
  85. )
  86. // If the connection is dead, we can't write a status to it.
  87. c.Error(err.(error)) // nolint: errcheck
  88. c.Abort()
  89. return
  90. }
  91. if stack {
  92. zaplog.Error("[Recovery from panic]",
  93. zap.Any("error", err),
  94. zap.String("request", string(httpRequest)),
  95. zap.String("stack", string(debug.Stack())),
  96. )
  97. } else {
  98. zaplog.Error("[Recovery from panic]",
  99. zap.Any("error", err),
  100. zap.String("request", string(httpRequest)),
  101. )
  102. }
  103. c.AbortWithStatus(http.StatusInternalServerError)
  104. }
  105. }()
  106. c.Next()
  107. }
  108. }