@@ -0,0 +1,100 @@
|
||||
package ginzap
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"91porn-server/common/hevcpull"
|
||||
"91porn-server/common/log"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func Logger(ctxKeys []string) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
start := time.Now()
|
||||
path := c.Request.URL.Path
|
||||
query := hevcpull.RedactText(c.Request.URL.RawQuery)
|
||||
c.Next()
|
||||
end := time.Now()
|
||||
latency := end.Sub(start)
|
||||
if len(c.Errors) > 0 {
|
||||
for _, e := range c.Errors.Errors() {
|
||||
log.Error(e, log.R(c))
|
||||
}
|
||||
} else {
|
||||
l := []log.Field{
|
||||
log.R(c),
|
||||
log.Any("status", c.Writer.Status()),
|
||||
log.Any("method", c.Request.Method),
|
||||
log.Any("path", path),
|
||||
log.Any("query", query),
|
||||
log.Any("user-agent", c.Request.UserAgent()),
|
||||
log.Any("time", end.Format("2006-01-02 15:04:05")),
|
||||
log.Any("latency", latency),
|
||||
}
|
||||
for _, k := range ctxKeys {
|
||||
v, e := c.Get(k)
|
||||
if e {
|
||||
l = append(l, log.Any(k, v))
|
||||
}
|
||||
}
|
||||
log.Info(path, l...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RecoveryWithZap returns a gin.HandlerFunc (middleware)
|
||||
// that recovers from any panics and logs requests using uber-go/zap.
|
||||
// All errors are logged using zap.Error().
|
||||
// stack means whether output the stack info.
|
||||
// The stack info is easy to find where the error occurs but the stack info is too large.
|
||||
func Recovery(stack bool, do func(err interface{})) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
if do != nil {
|
||||
do(err)
|
||||
}
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Record request identity without exposing authentication headers or body.
|
||||
requestFields := []log.Field{
|
||||
log.R(c),
|
||||
log.Any("method", c.Request.Method),
|
||||
log.Any("path", c.Request.URL.Path),
|
||||
log.Any("panic", err),
|
||||
}
|
||||
if brokenPipe {
|
||||
log.Error(c.Request.URL.Path, requestFields...)
|
||||
// If the connection is dead, we can't write a status to it.
|
||||
c.Error(err.(error)) // nolint: errcheck
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
if stack {
|
||||
requestFields = append(requestFields, log.Any("stack", string(debug.Stack())))
|
||||
}
|
||||
log.Error("[Recovery from panic]", requestFields...)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
|
||||
"result": false,
|
||||
"error": http.StatusText(http.StatusInternalServerError),
|
||||
})
|
||||
}
|
||||
}()
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user