github.com/jtzjtz/kit@v1.0.2/log/zap_log.go (about) 1 package log 2 3 import ( 4 "errors" 5 "fmt" 6 "github.com/jtzjtz/kit/file" 7 "github.com/lestrrat/go-file-rotatelogs" 8 "go.uber.org/zap" 9 "go.uber.org/zap/zapcore" 10 "io" 11 "time" 12 ) 13 14 //全局日志实例(程序启动前调用InitLog(appName string, logDir string)) 15 var Logger *zap.SugaredLogger 16 17 func initLog(appName string, logDir string) (er error) { 18 defer func() { 19 if err := recover(); err != nil { 20 er = err.(error) 21 } 22 }() 23 if len(logDir) == 0 { 24 logDir = "./" 25 } 26 if exists, _ := file.ExistsDir(logDir); !exists { 27 if er = file.CreateDir(logDir); er != nil { 28 return er 29 } 30 } 31 if exists, _ := file.ExistsDir(logDir + "/backup"); !exists { 32 if er = file.CreateDir(logDir + "/backup"); er != nil { 33 return er 34 } 35 } 36 // 设置一些基本日志格式 具体含义还比较好理解,直接看zap源码也不难懂 37 encoder := zapcore.NewJSONEncoder(zapcore.EncoderConfig{ 38 MessageKey: "msg", 39 LevelKey: "level", 40 EncodeLevel: zapcore.CapitalLevelEncoder, 41 TimeKey: "time", 42 EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { 43 enc.AppendString(t.Format("2006-01-02 15:04:05")) 44 }, 45 CallerKey: "file", 46 EncodeCaller: zapcore.ShortCallerEncoder, 47 EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) { 48 enc.AppendInt64(int64(d) / 1000000) 49 }, 50 }) 51 52 // 实现两个判断日志等级的interface 53 infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { 54 return lvl == zapcore.InfoLevel 55 }) 56 57 errorLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { 58 return lvl == zapcore.ErrorLevel 59 }) 60 debugLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { 61 return lvl == zapcore.DebugLevel 62 }) 63 64 // 获取 info、error日志文件的io.Writer 抽象 getWriter() 在下方实现 65 accessWriter := getWriter(appName, "access", logDir) 66 infoWriter := getWriter(appName, "info", logDir) 67 errorWriter := getWriter(appName, "error", logDir) 68 69 // 最后创建具体的Logger 70 core := zapcore.NewTee( 71 zapcore.NewCore(encoder, zapcore.AddSync(accessWriter), debugLevel), 72 zapcore.NewCore(encoder, zapcore.AddSync(infoWriter), infoLevel), 73 zapcore.NewCore(encoder, zapcore.AddSync(errorWriter), errorLevel), 74 ) 75 76 log := zap.New(core) // 需要传入 zap.AddCaller() 才会显示打日志点的文件名和行数, 有点小坑 77 Logger = log.Sugar() 78 if Logger == nil { 79 return errors.New("初始化日志实例失败") 80 } 81 return nil 82 } 83 84 func getWriter(appName, logType, logDir string) io.Writer { 85 // 生成rotatelogs的Logger 实际生成的文件名 demo.log.YYmmddHH 86 // demo.log是指向最新日志的链接 87 // 保存7天内的日志,每天分割一次日志 88 hook, err := rotatelogs.New( 89 logDir+"/backup/"+appName+"-"+logType+"%Y%m%d.log", 90 rotatelogs.WithLinkName(fmt.Sprintf("%s/%s-%s.log", logDir, appName, logType)), 91 rotatelogs.WithMaxAge(time.Hour*24*365*2), 92 rotatelogs.WithRotationTime(time.Hour*24), 93 ) 94 95 if err != nil { 96 panic(err) 97 } 98 //ch :=make( chan os.Signal) 99 //signal.Notify(ch, syscall.SIGHUP) 100 // 101 //go func(ch chan os.Signal) { 102 // <-ch 103 // hook.Rotate() 104 //}(ch) 105 return hook 106 }