golang zaplog使用(转)

zap 使用

uber 开源,zap 可以在控制面板、文档甚至发送数据到其他系统中,以此来记录日志。我们可以指定日志的级别,支持 json 结构化,方便查询。

和 logrus 类似,简单来讲,日志有两个概念:字段和消息。字段用来结构化输出错误相关的上下文环境,而消息简明扼要的阐述错误本身。

开发模式下是普通文本的结构:

package main

import (
 "go.uber.org/zap"
 "time"
)

func () {

 logger, _ := zap.NewDevelopment() 

 defer logger.Sync()
 logger.Info("无法获取网址",
 zap.String("url", "http://www.baidu.com"),
 zap.Int("attempt", 3),
 zap.Duration("backoff", time.Second),
 )
}

|

自定义配置:

func main() {
 encoderConfig := zapcore.EncoderConfig{
 TimeKey:        "time",
 LevelKey:       "level",
 NameKey:        "logger",
 CallerKey:      "caller",
 MessageKey:     "msg",
 StacktraceKey:  "stacktrace",
 LineEnding:     zapcore.DefaultLineEnding,
 EncodeLevel:    zapcore.LowercaseLevelEncoder, 
 EncodeTime:     zapcore.ISO8601TimeEncoder,     // ISO8601 UTC 时间格式
 EncodeDuration: zapcore.SecondsDurationEncoder,
 EncodeCaller:   zapcore.FullCallerEncoder,      // 全路径编码器
 }

 // 设置日志级别
 atom := zap.NewAtomicLevelAt(zap.DebugLevel)

 config := zap.Config{
 Level:            atom,                                                // 日志级别
 Development:      true,                                                // 开发模式,堆栈跟踪
 Encoding:         "json",                                              // 输出格式 console 或 json
 EncoderConfig:    encoderConfig,                                       // 编码器配置
 InitialFields:    map[string]interface{}{"serviceName": "spikeProxy"}, // 初始化字段,如:添加一个服务器名称
 OutputPaths:      []string{"stdout", "./logs/spikeProxy.log"},         // 输出到指定文档 stdout(标准输出,正常颜色) stderr(错误输出,红色)
 ErrorOutputPaths: []string{"stderr"},
 }

 // 构建日志
 logger, err := config.Build()
 if err != nil {
 panic(fmt.Sprintf("log 初始化失败: %v", err))
 }
 logger.Info("log 初始化成功")

 logger.Info("无法获取网址",
 zap.String("url", "http://www.baidu.com"),
 zap.Int("attempt", 3),
 zap.Duration("backoff", time.Second),
 )
}

lumberjack 归档

日志文档越来越大,我们根据大小、日期进行归档。
zap 可以写入文档,但是并没有归档的功能。借助于 lumberjack 第三方库,利用 hook 进行归档。

import (
 "go.uber.org/zap"
 "go.uber.org/zap/zapcore"
 "time"
 "gopkg.in/natefinch/lumberjack.v2"
 "os"
)

func main() {
 hook := lumberjack.Logger{
 Filename:   "./logs/spikeProxy1.log", // 日志文档路径
 MaxSize:    128,                      // 每个日志文档保存的最大尺寸 单位:M
 MaxBackups: 30,                       // 日志文档最多保存多少个备份
 MaxAge:     7,                        // 文档最多保存多少天
 Compress:   true,                     // 是否压缩
 }

 encoderConfig := zapcore.EncoderConfig{
 TimeKey:        "time",
 LevelKey:       "level",
 NameKey:        "logger",
 CallerKey:      "linenum",
 MessageKey:     "msg",
 StacktraceKey:  "stacktrace",
 LineEnding:     zapcore.DefaultLineEnding,
 EncodeLevel:    zapcore.LowercaseLevelEncoder,  // 小写编码器
 EncodeTime:     zapcore.ISO8601TimeEncoder,     // ISO8601 UTC 时间格式
 EncodeDuration: zapcore.SecondsDurationEncoder, //
 EncodeCaller:   zapcore.FullCallerEncoder,      // 全路径编码器
 EncodeName:     zapcore.FullNameEncoder,
 }

 // 设置日志级别
 atomicLevel := zap.NewAtomicLevel()
 atomicLevel.SetLevel(zap.InfoLevel)

 core := zapcore.NewCore(
 zapcore.NewJSONEncoder(encoderConfig),                                           // 编码器配置
 zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // 打印到控制面板和文档
 atomicLevel,                                                                     // 日志级别
 )

 // 开启开发模式,堆栈跟踪
 caller := zap.AddCaller()
 // 开启文档及行号
 development := zap.Development()
 // 设置初始化字段
 filed := zap.Fields(zap.String("serviceName", "serviceName"))
 // 构造日志
 logger := zap.New(core, caller, development, filed)

 logger.Info("log 初始化成功")
 logger.Info("无法获取网址",
 zap.String("url", "[http://www.baidu.com](http://www.baidu.com/)"),
 zap.Int("attempt", 3),
 zap.Duration("backoff", time.Second))
}

zap 优势及原理

标准 log 没有日志分级。seelog 可分级,支持归档,比较灵活,但是利用反射,效率低。

避免 GC: 对象复用

zap 通过 sync.Pool 提供的对象池,复用了大量可以复用的对象,避开了 gc 这个大麻烦。

内建的 Encoder: 避免反射

标准库中的 json.Marshaler 提供的是基于类型反射的拼接方式,代价是高昂的。

zap 选择了自己实现 json Encoder。 通过明确的类型调用,直接拼接字符串,最小化性能开销。

level handler

level handler 是 zap 提供的一种 level 的处理方式,通过 http 请求动态改变日志组件级别。

你可能感兴趣的:(golang zaplog使用(转))