
为什么要用zap来写日志
原来是写PHP的,一直用的error_log,第一次写Go项目的时候,还真不知道该怎么写日志,后来就按照PHP的写法自己不成规范的捣鼓写。去了新公司之后,发现用的是zap。后来查询 了解了下zap,前同事反应他们很多大公司都在使用zap写日志,GitHub上star 高达7K多,足以说明它受欢迎的程度。
1.zap是Uber开源的日志库;2.很多大的公司和小的公司都在使用;3.跟seelog、logrus等类库相比,高性能是它最突出的优势;我想以上几个原因就已经说明了它的广泛性、稳定性,就值得我们去尝试。
怎么使用zap
我们说下简单的使用案例 首相当然是下载 go get -u go.uber.org/zap 先贴一个我这边常用的zap的配置
zap.Config{ Level: zap.NewAtomicLevelAt(zap.DebugLevel), Development :true, Encoding :"json", EncoderConfig: zapcore.EncoderConfig{ TimeKey:"t", LevelKey:"level", NameKey:"log", CallerKey:"caller", MessageKey:" msg ", StacktraceKey:"trace", LineEnding: zapcore.DefaultLineEnding, EncodeLevel: zapcore.LowercaseLevelEncoder, EncodeTime:时间格式函数, EncodeDuration: zapcore.SecondsDurationEncoder, EncodeCaller: zapcore.ShortCallerEncoder, }, output Paths:[]string{"/tmp/zap.log"}, ErrorOutputPaths:[]string{"/tmp/zap.log"}, InitialFields: map[string]interface{}{ "app":"test", }, }
基本配置的说明
Level:日志级别,跟其他语言是一样的。只不过它需要的类型是AtomicLevel。所以需要使用zap.NewAtomicLevelAt做下如下的转化。
zap.NewAtomicLevelAt(zap.DebugLevel) zap.DebugLevel zap.InfoLevel zap.WarnLevel zap.ErrorLevel
Development: bool 是否是开发环境。如果是开发模式,对DPanicLevel进行堆栈跟踪 DisableCaller:bool 禁止使用调用函数的文件名和行号来注释日志。默认进行注释日志 DisableStacktrace:bool 是否禁用堆栈跟踪捕获。默认对Warn级别以上和生产error级别以上的进行堆栈跟踪。Encoding:编码类型,目前两种json 和 console【按照空格隔开】,常用json EncoderConfig:生成格式的一些配置–TODO 后面我们详细看下EncoderConfig配置各个说明 OutputPaths:[]string 日志写入文件的地址 ErrorOutputPaths:[]string 将系统内的error记录到文件的地址 InitialFields:map[string]interface{} 加入一些初始的字段数据,比如项目名 当然了,如果想控制台输出,OutputPaths和ErrorOutputPaths不能配置为文件地址,而应该改为 stdout 。
关于config的配置,具体的可以参考文件里面的注释 go.uber.org/zap/config.go type Config struct
EncoderConfig配置说明
MessageKey:输入信息的key名 LevelKey:输出日志级别的key名 TimeKey:输出时间的key名 NameKey CallerKey StacktraceKey跟以上类似,看名字就知道 LineEnding:每行的分隔符。基本zapcore.DefaultLineEnding 即”\n” EncodeLevel:基本zapcore.LowercaseLevelEncoder。将日志级别字符串转化为小写 EncodeTime:输出的时间格式 EncodeDuration:一般zapcore.SecondsDurationEncoder,执行消耗的时间转化成浮点型的秒 EncodeCaller:一般zapcore.ShortCallerEncoder,以包/文件:行号 格式化调用堆栈 EncodeName:可选值。
具体EncoderConfig的说明,可以参考文件里面的注释 go.uber.org/zapcore/encoder.go type EncoderConfig struct
举个栗子
你扯这么多配置说明,谁有时间看这玩意,写个常用的让大家照着用就好了嘛。
package main import( "fmt" "go.uber.org/zap" "go.uber.org/zap/zapcore" "time" ) var logger *zap.Logger func formatEncodeTime(t time.Time, enc zapcore.PrimitiveArrayEncoder){ enc.AppendString(fmt.Sprintf("%d%02d%02d_%02d%02d%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second())) } func FormateLog(args []interface{})*zap.Logger{ log := logger.With(ToJsonData(args)) return log } func Debug(msg string, args ...interface{}){ FormateLog(args).Sugar().Debugf(msg) } func ToJsonData(args []interface{}) zap.Field{ det := make([]string,0) if len(args)>0{ for _, v := range args { det = append(det, fmt.Sprintf("%+v", v)) } } zap := zap.Any("detail", det) return zap } func InitZapLog(){ cfg := zap.Config{ Level: zap.NewAtomicLevelAt(zap.DebugLevel), Development:true, Encoding:"json", EncoderConfig: zapcore.EncoderConfig{ TimeKey:"t", LevelKey:"level", NameKey:"logger", CallerKey:"caller", MessageKey:"msg", StacktraceKey:"trace", LineEnding: zapcore.DefaultLineEnding, EncodeLevel: zapcore.LowercaseLevelEncoder, EncodeTime: formatEncodeTime, EncodeDuration: zapcore.SecondsDurationEncoder, EncodeCaller: zapcore.ShortCallerEncoder, }, OutputPaths:[]string{"/tmp/zap.log"}, ErrorOutputPaths:[]string{"/tmp/zap.log"}, InitialFields: map[string]interface{}{ "app":"test", }, } var err error logger, err = cfg.Build() if err !=nil{ panic("log init fail:"+ err.Error()) } } func main(){ InitZapLog() defer logger.Sync() a :=[]string{"test","hello","world"} Debug("output",a) }
执行下,就会在日志文件上输入按照我们配置日志格式。
tail -f /tmp/zap.log {"level":"debug","t":"20190630_044053","caller":"myproject/main.go:21","msg":"output","app":"test","detail":["[test hello world]"]}
然后我们试下控制台输出,修改三个console相关的配置代码 ··· OutputPaths: []string{“stdout”}, ErrorOutputPaths: []string{“stdout”}, 控制台窗口就会输出 {“level”:”debug”,”t”:”20190630_092533″,”caller”:”myproject/main.go:21″,”msg”:”output”,”app”:”test”,”detail”:[“[test hello world]”]} ···
当然了,zap最想的使用和文档,看官网嘛