广告位联系
返回顶部
分享到

golang日志库ZAP[uber-go zap]示例介绍

Golang 来源:互联网 作者:佚名 发布时间:2024-10-25 22:37:40 人浏览
摘要

golang 日志库ZAP[uber-go zap] 1. 简要说明 zap 是 uber 开源的 Go 高性能日志库,支持不同的日志级别, 能够打印基本信息等,但不支持日志的分割,这里我们可以使用 lumberjack 也是 zap 官方推荐用于

golang 日志库ZAP[uber-go zap] 

1. 简要说明

zap 是 uber 开源的 Go 高性能日志库,支持不同的日志级别, 能够打印基本信息等,但不支持日志的分割,这里我们可以使用 lumberjack 也是 zap 官方推荐用于日志分割,结合这两个库我们就可以实现以下功能的日志机制:

能够将事件记录到文件中,而不是应用程序控制台;日志切割能够根据文件大小、时间或间隔等来切割日志文件;支持不同的日志级别,例如 DEBUG , INFO , WARN , ERROR 等;能够打印基本信息,如调用文件、函数名和行号,日志时间等;官网地址:https://github.com/uber-go/zap

2. 下载安装

1

2

3

4

5

6

7

8

9

// 初始化go mod 通过mod管理扩展包

go mod init zaplog

//使用下面命令安装

go get -u go.uber.org/zap

//如果下载失败,则使用以下命令重新下载安装

go get github.com/uber-go/zap

//下载安装成功后还有如下提示:

package github.com/uber-go/zap: code in directory

src/github.com/uber-go/zap expects import "go.uber.org/zap"

3. 配置 zap Logger

zap 提供了两种类型的日志记录器—和 Logger 和 Sugared Logger 。两者之间的区别是:

  • 在每一微秒和每一次内存分配都很重要的上下文中,使用Logger。它甚至比SugaredLogger更快,内存分配次数也更少,但它只支持强类型的结构化日志记录。
  • 在性能很好但不是很关键的上下文中,使用SugaredLogger。它比其他结构化日志记录包快 4-10 倍,并且支持结构化和 printf 风格的日志记录。
  • 所以一般场景下我们使用 Sugared Logger 就足够了。

3.1 Logger

  • 通过调用zap.NewProduction()/zap.NewDevelopment()或者zap.NewExample()创建一个 Logger 。
  • 上面的每一个函数都将创建一个 logger 。唯一的区别在于它将记录的信息不同。例如 production logger 默认记录调用函数信息、日期和时间等。
  • 通过 Logger 调用 INFO 、 ERROR 等。
  • 默认情况下日志都会打印到应用程序的 console 界面。

3.1.1 NewExample

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

//代码示例:

package main

import (

    "go.uber.org/zap"

)

func main() {

    log := zap.NewExample()

    log.Debug("this is debug message")

    log.Info("this is info message")

    log.Info("this is info message with fileds",

        zap.Int("age", 24), zap.String("agender", "man"))

    log.Warn("this is warn message")

    log.Error("this is error message")

    log.Panic("this is panic message")

}

//输出结果:

{"level":"debug","msg":"this is debug message"}

{"level":"info","msg":"this is info message"}

{"level":"info","msg":"this is info message with fileds","age":24,"agender":"man"}

{"level":"warn","msg":"this is warn message"}

{"level":"error","msg":"this is error message"}

{"level":"panic","msg":"this is panic message"}

panic: this is panic message

3.1.2 NewDevelopment

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

//代码示例:

func main() {

    log, _ := zap.NewDevelopment()

    log.Debug("this is debug message")

    log.Info("this is info message")

    log.Info("this is info message with fileds",

        zap.Int("age", 24), zap.String("agender", "man"))

    log.Warn("this is warn message")

    log.Error("this is error message")

    // log.DPanic("This is a DPANIC message")  

    // log.Panic("this is panic message")

    // log.Fatal("This is a FATAL message")

}

//输出结果:

2020-06-12T18:51:11.457+0800    DEBUG   task/main.go:9  this is debug message

2020-06-12T18:51:11.457+0800    INFO    task/main.go:10 this is info message

2020-06-12T18:51:11.457+0800    INFO    task/main.go:11 this is info message with fileds    {"age": 24, "agender": "man"}

2020-06-12T18:51:11.457+0800    WARN    task/main.go:13 this is warn message

main.main

    /home/wohu/GoCode/src/task/main.go:13

runtime.main

    /usr/local/go/src/runtime/proc.go:200

2020-06-12T18:51:11.457+0800    ERROR   task/main.go:14 this is error message

main.main

    /home/wohu/GoCode/src/task/main.go:14

runtime.main

    /usr/local/go/src/runtime/proc.go:200

3.1.3 NewProduction

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

代码示例:

func main() {

    log, _ := zap.NewProduction()

    log.Debug("this is debug message")

    log.Info("this is info message")

    log.Info("this is info message with fileds",

        zap.Int("age", 24), zap.String("agender", "man"))

    log.Warn("this is warn message")

    log.Error("this is error message")

    // log.DPanic("This is a DPANIC message")  

    // log.Panic("this is panic message")

    // log.Fatal("This is a FATAL message")

}

输出结果:

{"level":"info","ts":1591959367.316352,"caller":"task/main.go:10","msg":"this is info message"}

{"level":"info","ts":1591959367.3163702,"caller":"task/main.go:11","msg":"this is info message with fileds","age":24,"agender":"man"}

{"level":"warn","ts":1591959367.3163917,"caller":"task/main.go:13","msg":"this is warn message"}

{"level":"error","ts":1591959367.3163974,"caller":"task/main.go:14","msg":"this is error message","stacktrace":"main.main\n\t/home/wohu/GoCode/src/task/main.go:14\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:200"}

3.1.4 对比总结

Example和Production使用的是 json 格式输出,Development 使用行的形式输出

  • Development
    • 从警告级别向上打印到堆栈中来跟踪
    • 始终打印包/文件/行(方法)
    • 在行尾添加任何额外字段作为 json 字符串
    • 以大写形式打印级别名称
    • 以毫秒为单位打印 ISO8601 格式的时间戳
  • Production
    • 调试级别消息不记录
    • Error , Dpanic 级别的记录,会在堆栈中跟踪文件, Warn 不会
    • 始终将调用者添加到文件中
    • 以时间戳格式打印日期
    • 以小写形式打印级别名称
    • 在上面的代码中,我们首先创建了一个 Logger ,然后使用 Info / Error 等 Logger 方法记录消息。

日志记录器方法的语法是这样的:

1

func (log *Logger) MethodXXX(msg string, fields ...Field)

其中 MethodXXX 是一个可变参数函数,可以是 Info / Error / Debug / Panic 等。每个方法都接受一个消息字符串和任意数量的 zapcore.Field 长参数。

每个 zapcore.Field 其实就是一组键值对参数。

3.2 Sugared Logger

默认的 zap 记录器需要结构化标签,即对每个标签,需要使用特定值类型的函数。

1

log.Info("this is info message with fileds",zap.Int("age", 24), zap.String("agender", "man"))

虽然会显的很长,但是对性能要求较高的话,这是最快的选择。也可以使用suger logger, 它基于 printf 分割的反射类型检测,提供更简单的语法来添加混合类型的标签。

我们使用 Sugared Logger 来实现相同的功能。

  • 大部分的实现基本都相同;
  • 惟一的区别是,我们通过调用主 logger 的.Sugar()方法来获取一个SugaredLogger;
  • 然后使用SugaredLogger以printf格式记录语句;

1

2

3

4

5

6

7

8

9

10

11

12

13

func main() {

    logger, _ := zap.NewDevelopment()

    slogger := logger.Sugar()

    slogger.Debugf("debug message age is %d, agender is %s", 19, "man")

    slogger.Info("Info() uses sprint")

    slogger.Infof("Infof() uses %s", "sprintf")

    slogger.Infow("Infow() allows tags", "name", "Legolas", "type", 1)

}

//输出结果:

2020-06-12T19:23:54.184+0800    DEBUG   task/main.go:11 debug message age is 19, agender is man

2020-06-12T19:23:54.185+0800    INFO    task/main.go:12 Info() uses sprint

2020-06-12T19:23:54.185+0800    INFO    task/main.go:13 Infof() uses sprintf

2020-06-12T19:23:54.185+0800    INFO    task/main.go:14 Infow() allows tags {"name": "Legolas", "type": 1}

如果需要,可以随时使用记录器上的 .Desugar() 方法从 sugar logger 切换到标准记录器。

1

2

3

4

log := slogger.Desugar()

log.Info("After Desugar; INFO message")

log.Warn("After Desugar; WARN message")

log.Error("After Desugar; ERROR message")

4. 将日志写入文件

我们将使用zap.New(…)方法来手动传递所有配置,而不是使用像zap.NewProduction()这样的预置方法来创建 logger 。

1

func New(core zapcore.Core, options ...Option) *Logger

zapcore.Core需要三个配置——Encoder,WriteSyncer,LogLevel。

Encoder :编码器(如何写入日志)。我们将使用开箱即用的 NewConsoleEncoder() ,并使用预先设置的 ProductionEncoderConfig() 。

1

zapcore.NewConsoleEncoder(zap.NewProductionEncoderConfig())

WriterSyncer :指定日志将写到哪里去。我们使用 zapcore.AddSync() 函数并且将打开的文件句柄传进去。

1

2

file, _ := os.Create("./test.log")

writeSyncer := zapcore.AddSync(file)

Log Level :哪种级别的日志将被写入。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

// 代码示例:

package main

import (

    "os"

    "go.uber.org/zap"

    "go.uber.org/zap/zapcore"

)

var sugarLogger *zap.SugaredLogger

func InitLogger() {

    encoder := getEncoder()

    writeSyncer := getLogWriter()

    core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)

    // zap.AddCaller()  添加将调用函数信息记录到日志中的功能。

    logger := zap.New(core, zap.AddCaller())

    sugarLogger = logger.Sugar()

}

func getEncoder() zapcore.Encoder {

    encoderConfig := zap.NewProductionEncoderConfig()

    encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder // 修改时间编码器

    // 在日志文件中使用大写字母记录日志级别

    encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder

    // NewConsoleEncoder 打印更符合人们观察的方式

    return zapcore.NewConsoleEncoder(encoderConfig)

}

func getLogWriter() zapcore.WriteSyncer {

    file, _ := os.Create("./test.log")

    return zapcore.AddSync(file)

}

func main() {

    InitLogger()

    sugarLogger.Info("this is info message")

    sugarLogger.Infof("this is %s, %d", "aaa", 1234)

    sugarLogger.Error("this is error message")

    sugarLogger.Info("this is info message")

}

// 输出日志文件:

2020-06-16T09:01:06.192+0800    INFO    task/main.go:40 this is info message

2020-06-16T09:01:06.192+0800    INFO    task/main.go:41 this is aaa, 1234

2020-06-16T09:01:06.192+0800    ERROR   task/main.go:42 this is error message

2020-06-16T09:01:06.192+0800    INFO    task/main.go:43 this is info message


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • 使用go实现创建WebSocket服务器
    使用Go语言创建WebSocket服务器可以利用现有的库来简化开发过程。gorilla/websocket是一个非常流行且功能强大的库,适用于Go语言的WebSocket应用
  • golang日志库ZAP[uber-go zap]示例介绍
    golang 日志库ZAP[uber-go zap] 1. 简要说明 zap 是 uber 开源的 Go 高性能日志库,支持不同的日志级别, 能够打印基本信息等,但不支持日志的分割
  • golang并发编程使用Select语句的实现介绍
    在 Go 语言中,select语句是一种控制结构,允许一个 Goroutine 同时等待多个通道操作。select语句会阻塞,直到其中的一个case可以继续执行,然
  • go语言time.After()的作用介绍
    time.After是一个非常实用的函数,它返回一个用于读取的单向通道(-chan time.Time),这个通道会在指定的时间间隔之后发送当前时间。这个机
  • go实现一个内存缓存系统的代码
    面试内容: 支持设定过期时间,精度到秒 支持设定最大内存,当内存超出时做出合适的处理 支持并发安全 要求按照以下接口实现 1 2 3 4
  • Golang Map简介以及底层原理介绍
    在Go语言中提供了map数据结构来存储键值对数据。map的数据类型为map[K]V,其中K为键的类型,V为值的类型。map的键类型必须支持==操作符,用
  • Go语言中的switch高级用法介绍
    最近翻开源代码的时候看到了一种很有意思的switch用法,分享一下。 注意这里讨论的不是typed switch,也就是case语句后面是类型的那种。 直
  • Go语言sync.Map介绍及使用场景
    在 Go 语言中,sync.Map是一个并发安全的映射结构,专门用于在高并发场景下处理键值对数据。它的并发安全是通过内部实现机制来保证的,
  • 怎么使用工具自动监测SSL证书有效期并发送提醒
    自从云厂商的免费ssl证书改成3个月,而且证书数量还是20个之后,自己网站的ssl证书就换成了其它免费方案。但是免费方案不会提醒证书过
  • Go语言字符串处理库strings包介绍

    Go语言字符串处理库strings包介绍
    Golang字符串处理库strings 在Go语言中,strings包是一个非常重要且功能丰富的标准库,它提供了一系列用于操作字符串的函数。从基本的字符串
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计