Go | zap

这篇具有很好参考价值的文章主要介绍了Go | zap。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Go | zap

1. 简介

那些介绍、性能比较直接看参考中zap链接,这里只介绍该日志库用法,方便快速上手。

package main

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

func main() {
	logger, _ := zap.NewProduction()
	defer logger.Sync()

	logger.Info("hello world",
		zap.String("name", "yimt"),
	)

	// 可以将结构化日志转为fmt包形式
	sugar := logger.Sugar()
	sugar.Infof("name %s", "yimt")
}

输出

{"level":"info","ts":1684460836.884597,"caller":"hello-go/main.go:11","msg":"hello world","name":"yimt"}
{"level":"info","ts":1684460836.88468,"caller":"hello-go/main.go:17","msg":"name yimt"}

2. NewDevelopment & NewProduction区别

接下来通过查看NewDevelopmentNewProduction实现,简单了解下zap的配置,为后续学习zapcore.Core打下基础。

2.1. 实现

NewDevelopment

func NewDevelopment(options ...Option) (*Logger, error) {
	return NewDevelopmentConfig().Build(options...)
}
func NewDevelopmentConfig() Config {
	return Config{
		Level:            NewAtomicLevelAt(DebugLevel),
		Development:      true,
		Encoding:         "console",
		EncoderConfig:    NewDevelopmentEncoderConfig(),
		OutputPaths:      []string{"stderr"},
		ErrorOutputPaths: []string{"stderr"},
	}
}
func NewDevelopmentEncoderConfig() zapcore.EncoderConfig {
	return zapcore.EncoderConfig{
		// Keys can be anything except the empty string.
		TimeKey:        "T",
		LevelKey:       "L",
		NameKey:        "N",
		CallerKey:      "C",
		FunctionKey:    zapcore.OmitKey,
		MessageKey:     "M",
		StacktraceKey:  "S",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.CapitalLevelEncoder,
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.StringDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}
}

NewProduction

func NewProduction(options ...Option) (*Logger, error) {
	return NewProductionConfig().Build(options...)
}
func NewProductionConfig() Config {
	return Config{
		Level:       NewAtomicLevelAt(InfoLevel),
		Development: false,
		Sampling: &SamplingConfig{
			Initial:    100,
			Thereafter: 100,
		},
		Encoding:         "json",
		EncoderConfig:    NewProductionEncoderConfig(),
		OutputPaths:      []string{"stderr"},
		ErrorOutputPaths: []string{"stderr"},
	}
}
func NewProductionEncoderConfig() zapcore.EncoderConfig {
	return zapcore.EncoderConfig{
		TimeKey:        "ts",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "caller",
		FunctionKey:    zapcore.OmitKey,
		MessageKey:     "msg",
		StacktraceKey:  "stacktrace",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.LowercaseLevelEncoder,
		EncodeTime:     zapcore.EpochTimeEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}
}

2.2. 执行结果

NewDevelopment

func main() {
	logger, _ := zap.NewDevelopment()
	defer logger.Sync()

	logger.Info("hello world",
		zap.String("name", "yimt"),
	)
}

输出

2023-05-17T14:07:09.722+0800    INFO    hello-go/main.go:11     hello world     {"name": "yimt"}

NewProduction

func main() {
	logger, _ := zap.NewProduction()
	defer logger.Sync()

	logger.Info("hello world",
		zap.String("name", "yimt"),
	)
}

输出

{"level":"info","ts":1684303547.31098,"caller":"hello-go/main.go:11","msg":"hello world","name":"yimt"}

3. zapcore.Core接口

  • zapcore.NewCore(enc Encoder, ws WriteSyncer, enab LevelEnabler)
  • zapcore.NewNopCore()
  • zapcore.NewIncreaseLevelCore(core Core, level LevelEnabler) (Core, error)
  • zapcore.NewTee()

3.1. zapcore.NewCore(enc Encoder, ws WriteSyncer, enab LevelEnabler)

3.1.1. Encoder
  • zapcore.NewJSONEncoder(cfg EncoderConfig):以JSON形式编码。
  • zapcore.NewConsoleEncoder(cfg EncoderConfig):以console形式编码。

zapcore.EncoderConfig

主要用于配置日志编码,包括时间格式,日志键名,每条日志是否换行等。

  • zap.NewDevelopmentEncoderConfig()
  • zap.NewProductionEncoderConfig()
  • zapcore.EncoderConfig{}:可以自定义配置。

控制日志编码格式,正常控制台显示console形式编码,日志文件记录JSON形式编码。

3.1.2. zapcore.WriteSyncer
  • zapcore.AddSync(f):指定日志输出位置。

控制日志输出位置,主要有控制台和日志文件。

3.1.3. zapcore.LevelEnabler
  • zap.NewAtomicLevel():可以运行过程中线程安全的调节日志等级。
  • zap.LevelEnablerFunc:以回调形式控制日志等级。

用于控制日志等级。

3.1.4. 演示
package main

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
)

func main() {
	core := zapcore.NewCore(zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), zapcore.AddSync(os.Stdout), zap.NewAtomicLevel())
	logger := zap.New(core)
	defer logger.Sync()

	logger.Info("hello world")
}

控制台输出

{"level":"info","ts":1684459049.47701,"msg":"hello world"}

3.2. zapcore.NewNopCore()

package main

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

func main() {
	logger := zap.New(zapcore.NewNopCore())
	defer logger.Sync()

	logger.Info("hello world")
}

执行完什么都不会发生,可以直接看NewNopCore()内实现,上面Core所有功能都不处理。

type nopCore struct{}

// NewNopCore returns a no-op Core.
func NewNopCore() Core                                        { return nopCore{} }
func (nopCore) Enabled(Level) bool                            { return false }
func (n nopCore) With([]Field) Core                           { return n }
func (nopCore) Check(_ Entry, ce *CheckedEntry) *CheckedEntry { return ce }
func (nopCore) Write(Entry, []Field) error                    { return nil }
func (nopCore) Sync() error                                   { return nil }

3.3. zapcore.NewIncreaseLevelCore(core Core, level LevelEnabler) (Core, error)

实现

func NewIncreaseLevelCore(core Core, level LevelEnabler) (Core, error) {
	for l := _maxLevel; l >= _minLevel; l-- {
		if !core.Enabled(l) && level.Enabled(l) {
			return nil, fmt.Errorf("invalid increase level, as level %q is allowed by increased level, but not by existing core", l)
		}
	}

	return &levelFilterCore{core, level}, nil
}

直接在已有一个Core下降1个日志等级,以显示更多日志。

3.4. zapcore.NewTee()

上面示例都有一个问题,日志只能输出到一个Core。在有的时候我们需要日志以console形式输出到控制台,以json形式输出到日志文件时就用到了NewTee,可以将日志一次输入到多个Core处理。

package main

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
)

func main() {
	f, err := os.Create("log.txt")
	if err != nil {
		panic(err)
	}
	// 日志已json形式输出文件
	outputFileCore := zapcore.NewCore(zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), zapcore.AddSync(f), zap.NewAtomicLevel())
	// 日志已console形式输出到控制台
	outputConsoleCore := zapcore.NewCore(zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()), zapcore.AddSync(os.Stdout), zap.NewAtomicLevel())
	tee := zapcore.NewTee(outputFileCore, outputConsoleCore)
	logger := zap.New(tee)
	defer logger.Sync()

	logger.Info("hello world")
}

log.txt

{"level":"info","ts":1684459649.253505,"msg":"hello world"}

控制台

2023-05-19T09:27:29.253+0800    INFO    hello world

4. 输出日志文件问题

上面示例虽然可以输出日志文件,但是还存在以下问题。

  1. 单个日志文件大小无法限制,单个日志文件过大最直观的麻烦是我们用文件编辑器打开经常未响应。
  2. 日志文件不会自己删除,在生产服务器可能会存在大量日志文件,占用硬盘空间。应该有不少人在MySQL的binlog日志文件上踩过坑吧。
  3. 旧日志压缩存储,节约硬盘空间。

下面就介绍lumberjack库,帮助我们自己管理日志文件,直接看下面示例就可以了。

package main

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

func main() {
	writeSyncer := zapcore.AddSync(&lumberjack.Logger{
		Filename:   "log.txt",
		MaxSize:    500, // megabytes
		MaxBackups: 3,
		MaxAge:     28,   //days
		Compress:   true, // disabled by default
	})
	core := zapcore.NewCore(zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), writeSyncer, zap.NewAtomicLevel())
	logger := zap.New(core)
	defer logger.Sync()

	logger.Info("hello world")
}

5. 最终示例

功能文章来源地址https://www.toymoban.com/news/detail-451238.html

  1. 同时输出控制台和日志文件
  2. 日志文件达到限制大小自动创建新日志文件。
  3. 自己删除过期日志。
  4. 旧日志文件自动压缩。
package main

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

func main() {
	writeSyncer := zapcore.AddSync(&lumberjack.Logger{
		Filename:   "log.txt",
		MaxSize:    500, // megabytes
		MaxBackups: 3,
		MaxAge:     28,   //days
		Compress:   true, // disabled by default
	})
	// 日志已json形式输出文件
	outputFileCore := zapcore.NewCore(zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), writeSyncer, zap.NewAtomicLevel())
	// 日志已console形式输出到控制台
	outputConsoleCore := zapcore.NewCore(zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()), zapcore.AddSync(os.Stdout), zap.NewAtomicLevel())
	tee := zapcore.NewTee(outputFileCore, outputConsoleCore)
	logger := zap.New(tee)
	defer logger.Sync()

	logger.Info("hello world")
}

6. 参考

  • zap
  • lumberjack

到了这里,关于Go | zap的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • go: 高性能json工具 easyjson 简介

    先安装easyjson 在结构体上加//easyjson:json的注解 执行命令生成easyjson文件 使用示例

    2024年02月10日
    浏览(41)
  • 比较器的工作原理及性能指标介绍

    一、什么是比较器 比较器的功能是比较两个或更多数据项,以确定它们是否相等,或者确定它们之间的大小关系和排列顺序,这称为比较。可以实现此比较功能的电路或设备称为比较器。比较器是将模拟电压信号与参考电压进行比较的电路。比较器的两个输入是模拟信号,输

    2024年02月11日
    浏览(41)
  • Go 语言之在 gin 框架中使用 zap 日志库

    gin.Default() 的源码 Logger(), Recovery() 实操 运行并访问:http://localhost:8080/hello test.log 其它参考:https://github.com/gin-contrib/zap

    2024年02月09日
    浏览(41)
  • GO微服务简介及特性介绍

    互联网技术发展迅速的今天,微服务倍受关注:文章、博客、社交媒体讨论和会议演讲都在谈论。与此同时,也有持怀疑态度的软件社区人员认为微服务没什么新鲜可言。反对者声称它的思想只是面向服务架构的重塑。然而,无论是炒作还是怀疑,不可否认,微服务架构模式

    2024年02月12日
    浏览(43)
  • golang常用库包:log日志记录-uber的Go日志库zap使用详解

    Go 日志记录库:uber-go 的日志操作库 zap 使用 zap 是 uber 开源的一个高性能,结构化,分级记录的日志记录包。 go1.20.2 zap v1.24.0 高性能:zap 对日志输出进行了多项优化以提高它的性能 日志分级:有 Debug,Info,Warn,Error,DPanic,Panic,Fatal 等 日志记录结构化:日志内容记录是结

    2023年04月11日
    浏览(45)
  • Go 性能压测工具之wrk介绍与使用

    在项目正式上线之前,我们通常需要通过压测来评估当前系统能够支撑的请求量、排查可能存在的隐藏bug;压力测试(压测)是确保系统在高负载情况下仍能稳定运行的重要步骤。通过模拟高并发场景,可以评估系统的性能瓶颈、可靠性和稳定性,进而优化系统架构和资源配

    2024年04月08日
    浏览(54)
  • 新旧数据比较 直接可用

    我自定义的函数式编程自定义接口 可替换为java.util.function.Function 对比类 使用 具体比较哪些字段,需要在对象重写的equals和hashCode自定义

    2024年02月02日
    浏览(35)
  • 【性能优化】聊聊性能优化那些事

    针对于互联网应用来说,性能优化其实就是一直需要做的事情,因为系统响应慢,是非常影响用户的体验,可能回造成用户流失。所以对于性能非常重要。最近正好接到一个性能优化的需求,需要对所负责的系统进行性能提升。目前接口耗时基本在30S左右,争取可以提升到

    2024年02月10日
    浏览(60)
  • GO 的那些 IDE

    “程序员为什么要使用 IDE”,在一些社区论坛,经常可以看到这样的提问。关于是否应该使用IDE,每个人都有着自己的看法。 早期,程序的开发并不需要 IDE,那是以机器码编程为主的时代。后来随着计算机行业发展,为了进一步提升工程开发效率,IDE就产生了。 要明白的是

    2024年01月23日
    浏览(37)
  • go vet中的那些检测项

    go vet 是 Go 语言自带的一个工具,用于分析 Go 代码中的常见错误和潜在问题。它可以检查代码中可能存在的各种问题,例如: 未使用的变量、函数或包 可疑的函数调用 错误的函数签名 程序中的竞态条件 错误的类型转换等 本文意图指令当前go vet所有的检测项及其作用 目前集

    2024年02月11日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包