提交 acc0fc8d 编写于 作者: Sliver_Horn's avatar Sliver_Horn

新增zap日志库的支持,并提供Recovery的中间件

上级 8fa34807
......@@ -64,4 +64,12 @@ log:
prefix: '[GIN-VUE-ADMIN]'
log-file: true
stdout: 'DEBUG'
file: 'DEBUG'
\ No newline at end of file
file: 'DEBUG'
# zap logger configuration
zap:
level: "debug"
file: "DEBUG"
max_size: 200
max_age: 30
max_backups: 7
\ No newline at end of file
......@@ -10,6 +10,7 @@ type Server struct {
JWT JWT `mapstructure:"jwt" json:"jwt" yaml:"jwt"`
Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"`
Log Log `mapstructure:"log" json:"log" yaml:"log"`
Zap Zap `mapstructure:"zap" json:"zap" yaml:"zap"`
LocalUpload LocalUpload `mapstructure:"localUpload" json:"localUpload" yaml:"localUpload"`
}
......@@ -78,3 +79,11 @@ type Sqlite struct {
Config string `mapstructure:"config" json:"config" yaml:"config"`
LogMode bool `mapstructure:"log-mode" json:"logMode" yaml:"log-mode"`
}
type Zap struct {
Level string `json:"level"`
File string `json:"file"`
MaxSize int `json:"maxsize"`
MaxAge int `json:"max_age"`
MaxBackups int `json:"max_backups"`
}
package core
import (
"fmt"
"gin-vue-admin/global"
"gin-vue-admin/utils"
zaprotatelogs "github.com/lestrrat-go/file-rotatelogs"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"os"
"time"
)
const (
zapLogDir = "log"
zapLogSoftLink = "latest_log"
zapModule = "gin-vue-admin"
)
func init() {
if global.GVA_CONFIG.Zap.File == "" {
global.GVA_CONFIG.Zap.File = "DEBUG"
}
if ok, _ := utils.PathExists(zapLogDir); !ok {
// directory not exist
fmt.Println("create log directory")
_ = os.Mkdir(zapLogDir, os.ModePerm)
}
var l = new(zapcore.Level)
writeSyncer, err := getWriteSyncer()
if err != nil {
fmt.Printf("Get Write Syncer Failed err:%v", err.Error())
return
}
encoder := getEncoderConfig()
if err := l.UnmarshalText([]byte(global.GVA_CONFIG.Zap.Level)); err != nil {
fmt.Printf("Unmarshal Level Failed err:%v", err.Error())
return
}
core := zapcore.NewCore(encoder, writeSyncer, l)
global.GVA_ZAP = zap.New(core, zap.AddCaller())
}
// getWriteSyncer zap logger中加入file-rotatelogs
func getWriteSyncer() (zapcore.WriteSyncer, error) {
fileWriter, err := zaprotatelogs.New(
zapLogDir + string(os.PathSeparator) + "%Y-%m-%d-%H-%M.log",
zaprotatelogs.WithLinkName(zapLogSoftLink),
zaprotatelogs.WithMaxAge(7*24*time.Hour),
zaprotatelogs.WithRotationTime(24*time.Hour),
)
return zapcore.AddSync(fileWriter), err
}
// getEncoderConfig 获取zapcore.Encoder
func getEncoderConfig() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.TimeKey = "time"
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder
encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
return zapcore.NewConsoleEncoder(encoderConfig)
}
package global
import (
"go.uber.org/zap"
"gin-vue-admin/config"
"github.com/go-redis/redis"
oplogging "github.com/op/go-logging"
......@@ -14,4 +16,5 @@ var (
GVA_CONFIG config.Server
GVA_VP *viper.Viper
GVA_LOG *oplogging.Logger
GVA_ZAP *zap.Logger
)
......@@ -20,6 +20,8 @@ require (
github.com/golang/protobuf v1.4.2 // indirect
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect
github.com/json-iterator/go v1.1.10 // indirect
github.com/lestrrat-go/file-rotatelogs v2.3.0+incompatible
github.com/lestrrat-go/strftime v1.0.3 // indirect
github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 // indirect
github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f
github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 // indirect
......@@ -43,6 +45,7 @@ require (
github.com/tebeka/strftime v0.1.3 // indirect
github.com/unrolled/secure v1.0.7
github.com/urfave/cli v1.22.2 // indirect
go.uber.org/zap v1.10.0
golang.org/x/net v0.0.0-20200320220750-118fecf932d8 // indirect
golang.org/x/sys v0.0.0-20200610111108-226ff32320da // indirect
golang.org/x/tools v0.0.0-20200324003944-a576cf524670 // indirect
......
package middleware
import (
"gin-vue-admin/global"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"net"
"net/http"
"net/http/httputil"
"os"
"runtime/debug"
"strings"
)
// 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 {
global.GVA_ZAP.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 {
global.GVA_ZAP.Error("[Recovery from panic]",
zap.Any("error", err),
zap.String("request", string(httpRequest)),
zap.String("stack", string(debug.Stack())),
)
} else {
global.GVA_ZAP.Error("[Recovery from panic]",
zap.Any("error", err),
zap.String("request", string(httpRequest)),
)
}
c.AbortWithStatus(http.StatusInternalServerError)
}
}()
c.Next()
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册