github.com/godaddy-x/freego@v1.0.156/zlog/zlog.go (about) 1 package zlog 2 3 import ( 4 "github.com/godaddy-x/freego/utils" 5 "go.uber.org/zap" 6 "go.uber.org/zap/zapcore" 7 "gopkg.in/natefinch/lumberjack.v2" 8 stdlog "log" 9 "os" 10 "strings" 11 "time" 12 ) 13 14 const ( 15 DEBUG = "debug" 16 INFO = "info" 17 WARN = "warn" 18 ERROR = "error" 19 FATAL = "fatal" 20 ) 21 22 var ( 23 layout = "2006-01-02T15:04:05.000" 24 cst_sh, _ = time.LoadLocation("Asia/Shanghai") //上海 25 zapLog = &ZapLog{} 26 ) 27 28 func init() { 29 InitDefaultLog(&ZapConfig{Layout: 0, Location: cst_sh, Level: INFO, Console: true}) 30 } 31 32 type ZapLog struct { 33 l *zap.Logger 34 c *ZapConfig 35 } 36 37 // 第三方发送对象实现 38 type ZapProducer struct { 39 Callfunc func([]byte) error // 回调函数 40 } 41 42 // 第三方发送回调函数实现 43 func (self *ZapProducer) Write(b []byte) (n int, err error) { 44 if err := self.Callfunc(b); err != nil { 45 return 0, err 46 } 47 return len(b), nil 48 } 49 50 // 字符串级别类型转具体类型 51 func GetLevel(str string) zapcore.Level { 52 str = strings.ToLower(str) 53 switch str { 54 case DEBUG: 55 return zap.DebugLevel 56 case INFO: 57 return zap.InfoLevel 58 case WARN: 59 return zap.WarnLevel 60 case ERROR: 61 return zap.ErrorLevel 62 case FATAL: 63 return zap.FatalLevel 64 default: 65 return zapcore.ErrorLevel 66 } 67 } 68 69 // 日志文件输出配置 70 type FileConfig struct { 71 Filename string // 日志文件路径 72 MaxSize int // 每个日志文件保存的最大尺寸 单位:M 73 MaxBackups int // 日志文件最多保存多少个备份 74 MaxAge int // 文件最多保存多少天 75 Compress bool // 是否压缩 76 } 77 78 // 日志初始化配置 79 type ZapConfig struct { 80 Layout int64 // 时间格式, 0.输出日期格式 1.输出毫秒时间戳 81 Location *time.Location // 时间地区, 默认上海 82 Level string // 日志级别 83 Console bool // 是否控制台输出 84 FileConfig *FileConfig // 输出文件配置 85 Callfunc func([]byte) error // 回调函数 86 } 87 88 // 通过配置初始化默认日志对象 89 func InitDefaultLog(config *ZapConfig) *zap.Logger { 90 zapLog.c = config 91 zapLog.l = buildLog(config) 92 return zapLog.l 93 } 94 95 // 通过配置创建新的日志对象 96 func InitNewLog(config *ZapConfig) *zap.Logger { 97 z := &ZapLog{c: config, l: buildLog(config)} 98 return z.l 99 } 100 101 func NewTimeEncoder(layout string, location *time.Location) func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { 102 return func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { 103 type appendTimeEncoder interface { 104 AppendTimeLayout(time.Time, string) 105 } 106 if enc, ok := enc.(appendTimeEncoder); ok { 107 enc.AppendTimeLayout(t, layout) 108 return 109 } 110 enc.AppendString(t.In(location).Format(layout)) 111 } 112 } 113 114 // 通过配置创建日志对象 115 func buildLog(config *ZapConfig) *zap.Logger { 116 // 基础日志配置 117 encoderConfig := zapcore.EncoderConfig{ 118 TimeKey: "time", 119 LevelKey: "level", 120 NameKey: "logger", 121 // CallerKey: "caller", 122 MessageKey: "msg", 123 StacktraceKey: "stacktrace", 124 LineEnding: zapcore.DefaultLineEnding, 125 EncodeLevel: zapcore.LowercaseLevelEncoder, // 小写编码器 126 //EncodeTime: zapcore.ISO8601TimeEncoder, // 毫秒时间戳格式 127 EncodeCaller: zapcore.ShortCallerEncoder, // 全路径编码器 128 EncodeDuration: zapcore.SecondsDurationEncoder, 129 EncodeName: zapcore.FullNameEncoder, 130 } 131 if config.Location == nil { 132 config.Location = cst_sh 133 } 134 if config.Layout == 0 { 135 encoderConfig.EncodeTime = NewTimeEncoder(layout, config.Location) 136 } else { 137 encoderConfig.EncodeTime = zapcore.EpochMillisTimeEncoder 138 } 139 // 设置日志级别 140 atomicLevel := zap.NewAtomicLevel() 141 atomicLevel.SetLevel(GetLevel(config.Level)) 142 // 设置控制台输出模式 143 var writer []zapcore.WriteSyncer 144 if config.Console { 145 writer = append(writer, zapcore.AddSync(os.Stdout)) 146 } 147 // 设置日志文件输出模式 148 conf := config.FileConfig 149 if conf != nil { 150 outfile := lumberjack.Logger{ 151 Filename: conf.Filename, // 日志文件路径 152 MaxSize: conf.MaxSize, // 每个日志文件保存的最大尺寸 单位:M 153 MaxBackups: conf.MaxBackups, // 日志文件最多保存多少个备份 154 MaxAge: conf.MaxAge, // 文件最多保存多少天 155 Compress: conf.Compress, // 是否压缩 156 } 157 writer = append(writer, zapcore.AddSync(&outfile)) 158 } 159 // 设置第三方输出模式 160 if config.Callfunc != nil { 161 writer = append(writer, zapcore.AddSync(&ZapProducer{Callfunc: config.Callfunc})) 162 } 163 // 核心配置 164 core := zapcore.NewCore( 165 zapcore.NewJSONEncoder(encoderConfig), // 编码器配置 166 zapcore.NewMultiWriteSyncer(writer...), // 输出类型,控制台,文件 167 atomicLevel, // 日志级别 168 ) 169 // 开启开发模式,堆栈跟踪 170 caller := zap.AddCaller() 171 // 开启文件及行号 172 development := zap.Development() 173 // 设置初始化字段 174 // filed := zap.Fields(zap.String("serviceName", "serviceName")) 175 // 构造日志 176 return zap.New(core, caller, development) 177 } 178 179 // debug 180 func Debug(msg string, start int64, fields ...zap.Field) { 181 if start > 0 { 182 fields = append(fields, zap.Int64("cost", utils.UnixMilli()-start)) 183 } 184 zapLog.l.Debug(msg, fields...) 185 } 186 187 // info 188 func Info(msg string, start int64, fields ...zap.Field) { 189 if start > 0 { 190 fields = append(fields, zap.Int64("cost", utils.UnixMilli()-start)) 191 } 192 zapLog.l.Info(msg, fields...) 193 } 194 195 // warn 196 func Warn(msg string, start int64, fields ...zap.Field) { 197 if start > 0 { 198 fields = append(fields, zap.Int64("cost", utils.UnixMilli()-start)) 199 } 200 zapLog.l.Warn(msg, fields...) 201 } 202 203 // error 204 func Error(msg string, start int64, fields ...zap.Field) { 205 if start > 0 { 206 fields = append(fields, zap.Int64("cost", utils.UnixMilli()-start)) 207 } 208 zapLog.l.Error(msg, fields...) 209 } 210 211 // dpanic 212 func DPanic(msg string, start int64, fields ...zap.Field) { 213 if start > 0 { 214 fields = append(fields, zap.Int64("cost", utils.UnixMilli()-start)) 215 } 216 zapLog.l.DPanic(msg, fields...) 217 } 218 219 // panic 220 func Panic(msg string, start int64, fields ...zap.Field) { 221 if start > 0 { 222 fields = append(fields, zap.Int64("cost", utils.UnixMilli()-start)) 223 } 224 zapLog.l.Panic(msg, fields...) 225 } 226 227 // fatal 228 func Fatal(msg string, start int64, fields ...zap.Field) { 229 if start > 0 { 230 fields = append(fields, zap.Int64("cost", utils.UnixMilli()-start)) 231 } 232 zapLog.l.Fatal(msg, fields...) 233 } 234 235 // is debug? 236 func IsDebug() bool { 237 if zapLog.c.Level == DEBUG { 238 return true 239 } 240 return false 241 } 242 243 // 兼容原生log.Print 244 func Print(v ...interface{}) { 245 stdlog.Print(v...) 246 } 247 248 // 兼容原生log.Printf 249 func Printf(format string, v ...interface{}) { 250 stdlog.Printf(format, v...) 251 } 252 253 // 兼容原生log.Println 254 func Println(v ...interface{}) { 255 stdlog.Println(v...) 256 }