github.com/JohanShen/go-utils@v1.1.4-0.20201117124024-901319a2b2a0/logger/zap_logger.go (about) 1 package logger 2 3 import ( 4 "fmt" 5 "github.com/JohanShen/go-utils/utils" 6 "go.uber.org/zap" 7 "go.uber.org/zap/zapcore" 8 "os" 9 "os/signal" 10 "sync" 11 "syscall" 12 "time" 13 ) 14 15 // zap 日志的具体实现 16 // 可能存在的BUG: 17 // 1 日志不是顺序输出的 18 // 2 日志没有按生成时间输出到对应文件 19 // 20 type zapLogger struct { 21 config *Config 22 logger *zap.Logger 23 sugarLogger *zap.SugaredLogger 24 delayQueue []*ZapBody // 存放延迟处理的列队 25 delayNum int // 延迟写入的数量 26 ticker *time.Ticker // 用于处理延迟数据 27 stopTicker chan os.Signal 28 locker *sync.Mutex 29 } 30 31 var createdObject map[string]*zapLogger 32 33 func NewZapLogger(config *Config) *zapLogger { 34 35 if len(config.Name) == 0 { 36 config.Name = "default" 37 } 38 39 if obj, ok := createdObject[config.Name]; ok { 40 return obj 41 } 42 43 obj := &zapLogger{ 44 config: config, 45 } 46 47 if config.WriteDelay > 0 { 48 //delay = queue.NewDelayQueue(config.WriteMode, obj.callback) 49 config.WriteDelay = utils.IfElseInt(config.WriteDelay > 10, config.WriteDelay, 10) 50 config.WriteDelay = utils.IfElseInt(config.WriteDelay > 10000, 10000, config.WriteDelay) 51 52 obj.locker = &sync.Mutex{} 53 obj.delayQueue = make([]*ZapBody, 0, 10000) 54 obj.delayNum = 10000 55 obj.stopTicker = make(chan os.Signal, 1) 56 obj.ticker = time.NewTicker(time.Duration(config.WriteDelay) * time.Millisecond) 57 signal.Notify(obj.stopTicker, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) 58 59 go obj.listenTicker() 60 } 61 62 cores := make([]zapcore.Core, 0, 2) 63 // 实现多个输出 64 if len(config.LogPath) > 0 { 65 encoder := getEncoder() 66 writer := getLogWriter(config.LogPath) 67 cores = append(cores, zapcore.NewCore(encoder, writer, zapcore.DebugLevel)) 68 } 69 if config.ConsoleLog { 70 cores = append(cores, zapcore.NewCore(zapcore.NewConsoleEncoder(getEncoderConfig()), zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)), zapcore.DebugLevel)) 71 } 72 core := zapcore.NewTee(cores...) 73 74 //zap.New(core, zap.AddCaller(), zap.AddStacktrace(zap.WarnLevel)) 75 obj.logger = zap.New(core, zap.AddStacktrace(zap.WarnLevel)) 76 obj.sugarLogger = obj.logger.Sugar() 77 78 return obj 79 } 80 81 func getEncoderConfig() zapcore.EncoderConfig { 82 encoderConfig := zap.NewProductionEncoderConfig() 83 encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder 84 encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder 85 encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder 86 return encoderConfig 87 } 88 func getEncoder() zapcore.Encoder { 89 encoderConfig := getEncoderConfig() 90 return zapcore.NewJSONEncoder(encoderConfig) 91 } 92 93 func getLogWriter(path string) zapcore.WriteSyncer { 94 //now := time.Now() 95 //logPath := utils.XTime(now).Format(path) 96 //file, _ := os.OpenFile(logPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) 97 file := NewTimeWriter(path) 98 return zapcore.AddSync(file) 99 } 100 101 // 监听定时器 102 func (z *zapLogger) listenTicker() { 103 104 defer z.ticker.Stop() 105 106 Loop: 107 for { 108 select { 109 case <-z.ticker.C: 110 111 len1 := len(z.delayQueue) 112 idx := utils.IfElseInt(len1 > z.delayNum, z.delayNum, len1) 113 114 if idx > 0 { 115 z.locker.Lock() 116 //单次回调传入的数组 117 result := z.delayQueue[:idx] 118 //从原数组中移除已经回调的数据 119 z.delayQueue = z.delayQueue[idx:] 120 //result1 := make([]ZapBody,1000) 121 //copy(result1, result) 122 z.locker.Unlock() 123 124 fmt.Println("总长度:", len1, "取出数:", idx) 125 // 将最终的执行函数单独包装成方法 126 // 有利于其中一个或多个回调函数出错时,保证程序继续运行 127 go z.writeMsg(result...) 128 } 129 130 case <-z.stopTicker: 131 z.locker.Lock() 132 len1 := len(z.delayQueue) 133 if len1 > 0 { 134 // 将剩余未写入的一次性写入 135 //fmt.Println("剩余:", len1) 136 go z.writeMsg(z.delayQueue...) 137 } 138 z.locker.Unlock() 139 140 break Loop 141 142 } 143 } 144 //println("退出延迟等候列队") 145 } 146 147 func (z *zapLogger) writeMsg(bodies ...*ZapBody) { 148 149 defer func() { 150 if err := recover(); err != nil { 151 // 这个位置出错说明IO操作出现问题 152 // 无法写入到错误 为了程序稳定 也不宜 panic 153 println("写入日志时出错 writeMsg() panic ", err) 154 } 155 }() 156 157 defer func() { 158 if err := z.logger.Sync(); err != nil { 159 println("写入日志时出错 writeMsg() Sync() ", err) 160 } 161 }() 162 163 for _, body := range bodies { 164 fields := make([]zap.Field, 0, len(body.TopLevelData)+2) 165 fields = append(fields, zap.String("name", z.config.Name)) 166 for key, val := range body.TopLevelData { 167 fields = append(fields, zap.Any(key, val)) 168 } 169 if body.Data != nil { 170 fields = append(fields, zap.Any("data", body.Data)) 171 } 172 173 switch body.LogLevel { 174 case DebugLevel: 175 z.logger.Debug(body.Desc, fields...) 176 case ErrorLevel: 177 z.logger.Error(body.Desc, fields...) 178 case WarnLevel: 179 z.logger.Warn(body.Desc, fields...) 180 case PanicLevel: 181 z.logger.Panic(body.Desc, fields...) 182 case FatalLevel: 183 z.logger.Fatal(body.Desc, fields...) 184 default: 185 z.logger.Info(body.Desc, fields...) 186 } 187 } 188 } 189 190 func (z *zapLogger) write(level Level, desc string, args ...*LogArg) { 191 192 body := &ZapBody{ 193 LogLevel: level, 194 Desc: desc, 195 TopLevelData: make(map[string]interface{}), 196 } 197 for _, item := range args { 198 if len(z.config.ShowInTopLevel) > 0 && utils.IndexOfWithoutCase(z.config.ShowInTopLevel, item.Key) > -1 { 199 body.TopLevelData[item.Key] = item.Value 200 } else { 201 if body.Data == nil { 202 body.Data = make(map[string]interface{}) 203 } 204 body.Data[item.Key] = item.Value 205 } 206 207 } 208 209 if z.config.WriteDelay == 0 { 210 //需要即时处理的数据 211 go z.writeMsg(body) 212 } else { 213 //延迟处理的数据 214 //此处可能会存在性能问题 215 z.locker.Lock() 216 z.delayQueue = append(z.delayQueue, body) 217 z.locker.Unlock() 218 } 219 220 } 221 222 func (z *zapLogger) Debug(desc string, args ...*LogArg) { 223 z.write(DebugLevel, desc, args...) 224 } 225 func (z *zapLogger) Error(desc string, args ...*LogArg) { 226 z.write(ErrorLevel, desc, args...) 227 } 228 func (z *zapLogger) Fatal(desc string, args ...*LogArg) { 229 z.write(FatalLevel, desc, args...) 230 } 231 func (z *zapLogger) Info(desc string, args ...*LogArg) { 232 z.write(InfoLevel, desc, args...) 233 } 234 func (z *zapLogger) Panic(desc string, args ...*LogArg) { 235 z.write(PanicLevel, desc, args...) 236 } 237 func (z *zapLogger) Warn(desc string, args ...*LogArg) { 238 z.write(WarnLevel, desc, args...) 239 }