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 请求动态改变日志组件级别。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271