| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 | package middlewareimport (	"bytes"	"io/ioutil"	"net"	"net/http"	"net/http/httputil"	"os"	"runtime/debug"	"strings"	"time"	"gitee.com/xuyiping_admin/pkg/logger/zaplog"	"github.com/gin-gonic/gin"	"go.uber.org/zap")type responseBodyWriter struct {	gin.ResponseWriter	body *bytes.Buffer}type stackErr struct {	Err   error	Stack string}func (s *stackErr) Error() string {	return s.Err.Error()}func (r responseBodyWriter) Write(b []byte) (int, error) {	r.body.Write(b)	return r.ResponseWriter.Write(b)}// GinLogger 接管gin框架默认的日志func GinLogger() gin.HandlerFunc {	return func(c *gin.Context) {		// 获取 response 内容		w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer}		c.Writer = w		var requestBody []byte		if c.Request.Body != nil {			requestBody, _ = ioutil.ReadAll(c.Request.Body)			c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(requestBody))		}		start := time.Now()		c.Next()		cost := time.Since(start)		logFields := []zap.Field{			zap.Int("status", c.Writer.Status()),			zap.String("request", c.Request.Method+" "+c.Request.URL.String()),			zap.String("query", c.Request.URL.RawQuery),			zap.String("ip", c.ClientIP()),			zap.String("user-agent", c.Request.UserAgent()),			//zap.String("errors", c.Errors.ByType(gin.ErrorTypePrivate).String()),			zap.String("time", cost.String()),			zap.String("Request body", string(requestBody)),			zap.String("Response body", w.body.String()),		}		if len(c.Errors) > 0 {			logFields = append(logFields, zap.Any("stack", string(debug.Stack())))			zaplog.Error("Http-Access-Error", logFields...)			c.Abort()		} else {			zaplog.Info("Http-Access-Log", logFields...)		}	}}// GinRecovery recover掉我的项目可能呈现的panicfunc 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 {					zaplog.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 {					zaplog.Error("[Recovery from panic]",						zap.Any("error", err),						zap.String("request", string(httpRequest)),						zap.String("stack", string(debug.Stack())),					)				} else {					zaplog.Error("[Recovery from panic]",						zap.Any("error", err),						zap.String("request", string(httpRequest)),					)				}				c.AbortWithStatus(http.StatusInternalServerError)			}		}()		c.Next()	}}
 |