GO语言使用Zap日志库(小白文)

目录

前言

一、介绍

二、使用步骤

2.1.配置 zap Logger

2.2 Logger模式

2.3 Sugared Logger模式

三、性能对比

总结


前言

本文介绍非常流行的Uber开源的zap日志库,

下面将介绍zap提供的两种类型的日志记录器LoggerSugared Logger,

同时介绍了如何搭配Lumberjack实现日志的切割和归档,十分实用!


一、介绍

zap 是 uber 开源的 Go 高性能日志库,支持不同的日志级别,

能够打印基本信息等,但不支持日志的分割,

这里我们可以使用 lumberjack 也是 zap 官方推荐用于日志分割,

结合这两个库我们就可以实现

以下功能的日志机制:

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

二、使用步骤

2.1.配置 zap Logger

zap提供了两种类型的日志记录器Logger Sugared Logger

区别是:

  1. 在每一微秒和每一次内存分配都很重要的上下文中,使用Logger。它比Sugared Logger更快,内存分配次数也更少,但它只支持强类型的结构化日志记录,无法扩展日志中打印的key-value。
  2. 在性能很好但不是很关键的上下文中,使用SugaredLogger。它比其他结构化日志记录包快4-10被,并且支持结构化和printf风格的日志记录。

2.2 Logger模式

代码如下(示例):

package main

import (
	zap "github.com/openownworld/go-utils/log/zaplog"
)

func main() {
	err := zap.InitLoggerFile("./log.ini")
	if err != nil {
		fmt.Printf("InitLoggerFile error:%v", err)
        return
	}
	zap.Info("test log")
}

配置文件(示例):

#json log key
serviceName = testService
#时间格式  2022-12-21T15:04:43.697+0800
customTimeEnable = false
#日志文件路径
logFileName = ./log/log.log
errorFileName = ./log/error.log
#MaxBackups和MaxAge 任意达到限制,对应的文件就会被清理,maxSize和maxBackups计算出最大日志总量,在最大天数内不超过日志总量
#最大文件大小 M字节
maxSize = 100
#最多保留30个备份
maxBackups = 30
#最多保留多少天
maxDays = 30
#开启日志压缩
compress = true
#日志级别 debug info warn error dpanic panic fatal
level = debug
#打印堆栈跟踪日志级别
stacktraceLevel = panic
#分开写的错误文件级别warn和error
errorFileLevel = warn
#日志开启关闭
fileLogger = true
consoleLogger = true
fileLoggerJSON = true
consoleLoggerJSON = true
#推送日志到socket,暂不支持tcp
socketLoggerEnable = false
socketLoggerJSON = false
socketType = udp
socketIP = 127.0.0.1
socketPort = 9990
#动态设置日志级别
levelHttpEnable = false
levelHttpApi = /api/v1/log/level
levelHttpPort = 9090
#curl -H "Content-Type:application/json" -X PUT --data "{\"level\":\"error\"}" http://localhost:9090/api/v1/log/level

输出结果:

{"level":"info","time":"2023-05-06T11:24:48.184+0800","caller":"zaplog/zaplog.go:123","msg":"DefaultLogger init success [debug]","service":"testService"}
{"level":"error","time":"2023-05-06T11:24:48.185+0800","caller":"zaplog/zaplog.go:123","msg":"DefaultLogger init success [debug]","service":"testService"}
{"level":"info","time":"2023-05-06T11:24:48.186+0800","caller":"zaplog/logger_test.go:13","msg":"test log","service":"testService"}

2.3 Sugared Logger模式

代码如下(示例):

搭配 lumberjack 进行日志切割归档

package main

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

const (
	LogPath = "log"
)

type BackOption struct {
	LogPath    string
	MaxSize    int
	MaxAge     int
	MaxBackups int
	SkipCaller int
}

type ZapCoreBase struct {
	Enc   zapcore.Encoder
	Ws    zapcore.WriteSyncer
	Zopts []zap.Option
}

type LogConf struct {
	Service    string
	Path       string //日志打印路径
	LogName    string //日志文件名
	Level      string
	LoggerJSON bool //json格式输出日志
	Stdout     bool //标准输出、方便
}

type Logger struct {
	*zap.SugaredLogger
	level    zap.AtomicLevel
	coreBase *ZapCoreBase
}

func CapitalLevel(level string) zapcore.Level {
	trans := []struct {
		text  string
		level zapcore.Level
	}{
		{"DEBUG", zapcore.DebugLevel},
		{"INFO", zapcore.InfoLevel},
		{"WARN", zapcore.WarnLevel},
		{"ERROR", zapcore.ErrorLevel},
	}
	for _, tt := range trans {
		if strings.ToUpper(level) == tt.text {
			return tt.level
		}
	}
	return zapcore.InfoLevel
}

func NewWriteCloser(opts *BackOption, filename string) io.WriteCloser {
	wc := &lumberjack.Logger{
		Filename:   opts.LogPath + "/" + filename, //filePath
		MaxSize:    opts.MaxSize,                  //单个日志文件最大大小(以MB为单位)
		MaxBackups: opts.MaxBackups,               //保留旧文件的最大个数
		MaxAge:     opts.MaxAge,                   //保留旧文件的最大天数
		Compress:   false,                         //是否压缩
	}
	return wc
}

// 创建logger
func NewLogger(config *LogConf) *Logger {
	var (
		defLogger    *Logger
		defaultLevel = CapitalLevel(config.Level)
		opts         = &BackOption{
			LogPath:    config.Path,
			MaxSize:    512, //512MB
			MaxAge:     10,
			MaxBackups: 10,
		}
	)

	if opts.LogPath == "" {
		opts.LogPath = LogPath
	}
	if config.LogName == "" {
		config.LogName = "log.log"
	}

	lmfile := NewWriteCloser(opts, config.LogName)
	enConfig := zap.NewProductionEncoderConfig() //生成配置
	//  调整时间格式
	enConfig.EncodeTime = zapcore.ISO8601TimeEncoder
	lvl := zap.NewAtomicLevelAt(defaultLevel)

	var writes = []zapcore.WriteSyncer{zapcore.AddSync(lmfile)}
	if config.Stdout {
		writes = append(writes, zapcore.AddSync(os.Stdout))
	}

	var encoder = zapcore.NewConsoleEncoder(enConfig)
	var logOpts = []zap.Option{zap.AddCaller()}
	if config.LoggerJSON { // 按json格式 输出
		//
		encoder = zapcore.NewJSONEncoder(enConfig)
		logOpts = append(logOpts,
			zap.Fields(zap.String("service", config.Service)))
	}

	zCoreBase := &ZapCoreBase{
		Enc:   encoder,
		Ws:    zapcore.NewMultiWriteSyncer(writes...),
		Zopts: logOpts,
	}
	core := zapcore.NewCore(
		encoder,
		zapcore.NewMultiWriteSyncer(writes...), // 打印到控制台和文件
		lvl,                                    // 日志级别
	)
	logger := zap.New(core, zCoreBase.Zopts...)
	defLogger = &Logger{
		SugaredLogger: logger.Sugar(),
		level:         lvl,
		coreBase:      zCoreBase,
	}

	fmt.Println("create.logger complete...")
	return defLogger
}

func main() {
	conf := &LogConf{
		Service:    "testLog",
		Path:       "./log",
		LogName:    "log.log",
		Level:      "debug",
		LoggerJSON: true,
	}
	log := NewLogger(conf)
	log.Infof("log init success, time:%v", time.Now())
	log.Infow("扩展Json字段的日志打印", "ip", "1.1.1.1")
}
 
  

日志文件打印结果:

{"level":"info","ts":"2023-05-06T15:13:46.759+0800","caller":"main/main.go:146","msg":"log init success, time:2023-05-06 15:13:46.759339 +0800 CST m=+0.001190552","service":"testLog"}
{"level":"info","ts":"2023-05-06T15:13:46.760+0800","caller":"main/main.go:147","msg":"扩展Json字段的日志打印","service":"testLog","ip":"1.1.1.1"}

三、性能对比

Zap是非常快的、结构化的,分日志级别的Go日志库。

为什么选择Uber-go zap

  • 它同时提供了结构化日志记录和printf风格的日志记录
  • 它非常的快

根据Uber-go Zap的文档,它的性能比类似的结构化日志包更好——也比标准库更快。 以下是Zap发布的基准测试信息

记录一条消息和10个字段:

GO语言使用Zap日志库(小白文)_第1张图片 


总结

至此,我们总结了如何将Zap日志程序集成到Go应用程序项目中。

你可能感兴趣的:(日志系列,golang,go,开发语言,后端)