https://github.com/uber-go/zap
Zap是非常快的、结构化的,分日志级别的Go日志库。是现在的主流, 没有用反射
https://github.com/wangshibiaoFlytiger/apiproject/tree/master/log
1 安装
go get -u go.uber.org/zap
2 如何输出日志
package mainimport "go.uber.org/zap"func main() {// 开发环境logger1, _ := zap.NewDevelopment()defer logger1.Sync()logger1.Info("failed to fetch URL",zap.String("url", "https://imooc.com"),zap.Int("attempt", 3)) // 2021-11-16T10:58:24.906+0800 INFO zap_test/main.go:9 failed to fetch URL {"url": "https://imooc.com", "attempt": 3}// 生产环境logger2, _ := zap.NewProduction()defer logger2.Sync()// 普通logger2logger2.Info("failed to fetch URL",zap.String("url", "https://imooc.com"),zap.Int("attempt", 3)) // {"level":"info","ts":1637031504.9066734,"caller":"zap_test/main.go:17","msg":"failed to fetch URL","url":"https://imooc.com","attempt":3}// 使用语法糖sugar := logger2.Sugar()sugar.Infow("failed to fetch URL","url", "https://imooc.com","attempt", 3) // {"level":"info","ts":1637031504.9067116,"caller":"zap_test/main.go:23","msg":"failed to fetch URL","url":"https://imooc.com","attempt":3}}
3 日志输出到文件
package mainimport ("go.uber.org/zap""time")func NewLogger() (*zap.Logger, error) {cfg := zap.NewProductionConfig()cfg.OutputPaths = []string {"./info.log",}return cfg.Build()}func main() {logger, err := NewLogger()if err != nil {panic(err)}su := logger.Sugar()defer su.Sync()su.Info("failed to fetch URL","url", "https://immoc.com","attempt", 3,"backoff", time.Second,)}
4 封装
package zlog// 简单封装一下对 zap 日志库的使用// 使用方式:// zlog.Debug("hello", zap.String("name", "Kevin"), zap.Any("arbitraryObj", dummyObject))// zlog.Info("hello", zap.String("name", "Kevin"), zap.Any("arbitraryObj", dummyObject))// zlog.Warn("hello", zap.String("name", "Kevin"), zap.Any("arbitraryObj", dummyObject))var logger *zap.Loggerfunc init() {......}func getFileLogWriter() (writeSyncer zapcore.WriteSyncer) {......}func Info(message string, fields ...zap.Field) {callerFields := getCallerInfoForLog()fields = append(fields, callerFields...)logger.Info(message, fields...)}func Debug(message string, fields ...zap.Field) {callerFields := getCallerInfoForLog()fields = append(fields, callerFields...)logger.Debug(message, fields...)}func Error(message string, fields ...zap.Field) {callerFields := getCallerInfoForLog()fields = append(fields, callerFields...)logger.Error(message, fields...)}func Warn(message string, fields ...zap.Field) {callerFields := getCallerInfoForLog()fields = append(fields, callerFields...)logger.Warn(message, fields...)}func getCallerInfoForLog() (callerFields []zap.Field) {pc, file, line, ok := runtime.Caller(2) // 回溯两层,拿到写日志的调用方的函数信息if !ok {return}funcName := runtime.FuncForPC(pc).Name()funcName = path.Base(funcName) //Base函数返回路径的最后一个元素,只保留函数名callerFields = append(callerFields, zap.String("func", funcName), zap.String("file", file), zap.Int("line", line))return}
