123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- package lxzap
- import (
- "fmt"
- "net"
- "net/http"
- "net/http/httputil"
- "os"
- "runtime/debug"
- "strconv"
- "strings"
- "time"
- "github.com/gin-gonic/gin"
- "github.com/natefinch/lumberjack"
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
- )
- var Lg *zap.Logger
- // Level = "info"
- // Filename = "./log/a.log"
- // MaxSize = 2
- // MaxAge = 1000
- // MaxBackups = 1000
- type ZapLogConfig struct {
- Level string `json:"level"`
- Filename string `json:"filename"`
- MaxSize int `json:"maxsize"`
- MaxAge int `json:"max_age"`
- MaxBackups int `json:"max_backups"`
- }
- // InitZapLogger 初始化Logger
- func InitZapLogger(cfg ZapLogConfig, env string) (err error) {
- writeSyncer := getLogWriter(cfg.Filename, cfg.MaxSize, cfg.MaxBackups, cfg.MaxAge)
- encoder := getEncoder(env)
- var l = new(zapcore.Level)
- err = l.UnmarshalText([]byte(cfg.Level))
- if err != nil {
- return
- }
- // 创建 zap 核心
- core := zapcore.NewCore(
- encoder,
- zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), writeSyncer),
- l,
- )
- if env != "dev" {
- core = zapcore.NewCore(encoder, writeSyncer, l)
- }
- // 创建 zap 日志对象
- Lg = zap.New(core, zap.AddCaller())
- zap.ReplaceGlobals(Lg) // 替换zap包中全局的logger实例,后续在其他包中只需使用zap.L()调用即可
- return
- }
- func getEncoder(env string) zapcore.Encoder {
- encoderConfig := zap.NewProductionEncoderConfig()
- encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
- encoderConfig.TimeKey = "time"
- encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
- encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder
- encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
- l := zapcore.NewConsoleEncoder(encoderConfig)
- if env != "dev" {
- l = zapcore.NewJSONEncoder(encoderConfig)
- }
- return l
- }
- func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapcore.WriteSyncer {
- lumberJackLogger := &lumberjack.Logger{
- Filename: filename,
- MaxSize: maxSize,
- MaxBackups: maxBackup,
- MaxAge: maxAge,
- LocalTime: true,
- }
- return zapcore.AddSync(lumberJackLogger)
- }
- // GinLogger 接收gin框架默认的日志
- func GinLogger() gin.HandlerFunc {
- return func(c *gin.Context) {
- start := time.Now()
- path := c.Request.URL.Path
- query := c.Request.URL.RawQuery
- spanID := NewUUID()
- c.Set("X-Span-ID", spanID)
- cost := time.Since(start)
- Lg.Info(path,
- zap.Int("status", c.Writer.Status()),
- zap.String("spanId", strconv.Itoa(int(spanID))),
- zap.String("method", c.Request.Method),
- zap.String("path", path),
- zap.String("query", query),
- zap.String("ip", c.ClientIP()),
- zap.String("user-agent", c.Request.UserAgent()),
- zap.String("errors", c.Errors.ByType(gin.ErrorTypePrivate).String()),
- zap.Duration("cost", cost),
- )
- c.Next()
- }
- }
- // 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 {
- Lg.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 {
- Lg.Error("[Recovery from panic]",
- zap.Any("error", err),
- zap.String("request", string(httpRequest)),
- zap.String("stack", string(debug.Stack())),
- )
- } else {
- Lg.Error("[Recovery from panic]",
- zap.Any("error", err),
- zap.String("request", string(httpRequest)),
- )
- }
- c.AbortWithStatus(http.StatusInternalServerError)
- }
- }()
- c.Next()
- }
- }
- func Log(msg string, c *gin.Context) {
- v, _ := c.Get("X-Span-ID")
- spanId := fmt.Sprintf("%v", v)
- zap.L().Info(`spanId:"` + spanId + `"log:` + msg)
- }
|