123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- package middleware
- import (
- "bytes"
- "io"
- "io/ioutil"
- "net/http"
- "runtime"
- "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("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掉我的项目可能呈现的panic
- 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 {
- 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)),
- )
- }*/
- defer func() {
- if err = recover(); err != nil {
- body, _ := ioutil.ReadAll(c.Request.Body)
- // 获取 panic 发生的位置
- pc, file, line, ok := runtime.Caller(2)
- funcName := ""
- if ok {
- fn := runtime.FuncForPC(pc).Name()
- // 去除包路径,只保留函数名
- /*funcName = filepath.Base(fn)
- file = filepath.Base(file)*/
- parts := strings.Split(fn, "/")
- if len(parts) > 0 {
- lastPart := parts[len(parts)-1]
- parts = strings.Split(lastPart, ".")
- if len(parts) > 0 {
- funcName = parts[len(parts)-1]
- }
- }
- file = strings.TrimPrefix(file, c.Request.Context().Value(gin.ContextKey).(string)+"/") // 尝试去除项目路径前缀(可选)
- }
- zaplog.Error("cors",
- zap.Any("recover", err),
- zap.Any("url", c.Request.URL),
- zap.Any("file", file),
- zap.Any("line", line),
- zap.Any("func", funcName),
- zap.Any("request", string(body)),
- )
- c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
- }
- }()
- c.AbortWithStatus(http.StatusInternalServerError)
- }
- }()
- c.Next()
- }
- }
|