百木园-与人分享,
就是让自己快乐。

Golang Zap日志

Zap日志解析

Config.yaml

zap:
  level: \'info\' #日志级别
  format: \'console\' #输出的级别,有console和json
  prefix: \'[catering]\' #输出的前缀,[catering]xxxxxxxxxxx
  director: \'log\' #存放的文件夹
  show-line: true #是否显示行号
  encode-level: \'LowercaseColorLevelEncoder\' #编码级别,目前支持四种LowercaseLevelEncoder,LowercaseColorLevelEncoder,CapitalLevelEncoder,CapitalColorLevelEncoder
  stacktrace-key: \'stacktrace\' #栈名
  log-in-console: true #输出控制台

配置文件

package config

type Zap struct {
	Level         string `mapstructure:\"level\" json:\"level\" yaml:\"level\"`                           // 级别
	Format        string `mapstructure:\"format\" json:\"format\" yaml:\"format\"`                        // 输出
	Prefix        string `mapstructure:\"prefix\" json:\"prefix\" yaml:\"prefix\"`                        // 日志前缀
	Director      string `mapstructure:\"director\" json:\"director\"  yaml:\"director\"`                 // 日志文件夹
	ShowLine      bool   `mapstructure:\"show-line\" json:\"showLine\" yaml:\"showLine\"`                 // 显示行
	EncodeLevel   string `mapstructure:\"encode-level\" json:\"encodeLevel\" yaml:\"encode-level\"`       // 编码级
	StacktraceKey string `mapstructure:\"stacktrace-key\" json:\"stacktraceKey\" yaml:\"stacktrace-key\"` // 栈名
	LogInConsole  bool   `mapstructure:\"log-in-console\" json:\"logInConsole\" yaml:\"log-in-console\"`  // 输出控制台
}

初始化

func InitZap() {
	cfg := global.Config.Zap //获取上述的配置文件
    
    // 判断是否有Director文件夹
	if ok, _ := pkg.PathExists(cfg.Director); !ok { 
		fmt.Printf(\"create %v directory\\n\", cfg.Director)
		_ = os.Mkdir(cfg.Director, os.ModePerm)
	}
    
    // zap.LevelEnablerFunc(func(lev zapcore.Level) bool 用来划分不同级别的输出
    // 根据不同的级别输出到不同的日志文件
    
	// 调试级别
	debugPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
		return lev == zap.DebugLevel
	})
	// 日志级别
	infoPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
		return lev == zap.InfoLevel
	})
	// 警告级别
	warnPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
		return lev == zap.WarnLevel
	})
	// 错误级别
	errorPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
		return lev >= zap.ErrorLevel
	})

	cores := [...]zapcore.Core{
		getEncoderCore(fmt.Sprintf(\"./%s/server_debug.log\", cfg.Director), debugPriority),
		getEncoderCore(fmt.Sprintf(\"./%s/server_info.log\", cfg.Director), infoPriority),
		getEncoderCore(fmt.Sprintf(\"./%s/server_warn.log\", cfg.Director), warnPriority),
		getEncoderCore(fmt.Sprintf(\"./%s/server_error.log\", cfg.Director), errorPriority),
	}
    
    //zapcore.NewTee(cores ...zapcore.Core) zapcore.Core
    //NewTee创建一个Core,将日志条目复制到两个或更多的底层Core中
    
	logger := zap.New(zapcore.NewTee(cores[:]...))

    //用文件名、行号和zap调用者的函数名注释每条消息
	if cfg.ShowLine {
		logger = logger.WithOptions(zap.AddCaller())
	}

    //把初始化好的logger赋值到全局日志变量中
	global.Log = logger
}

getEncoderCode函数

// getEncoderCore 获取Encoder的zapcore.Core
func getEncoderCore(fileName string, level zapcore.LevelEnabler) (core zapcore.Core) {
	writer := pkg.GetWriteSyncer(fileName) // 使用file-rotatelogs进行日志分割
	return zapcore.NewCore(getEncoder(), writer, level)
}

getEncoder函数

// getEncoder 获取zapcore.Encoder
func getEncoder() zapcore.Encoder {
    //获取配置文件的输出格式,json or console
	cfg := global.Config.Zap
	if cfg.Format == \"json\" {
		return zapcore.NewJSONEncoder(getEncoderConfig())
	}
	return zapcore.NewConsoleEncoder(getEncoderConfig())
}

getEncoderConfig函数

获取自定义的编码器的配置

// getEncoderConfig 获取zapcore.EncoderConfig
func getEncoderConfig() (config zapcore.EncoderConfig) {
	cfg := global.Config.Zap
	config = zapcore.EncoderConfig{
		MessageKey:     \"message\",
		LevelKey:       \"level\",
		TimeKey:        \"time\",
		NameKey:        \"logger\",
		CallerKey:      \"caller\",
		StacktraceKey:  cfg.StacktraceKey, //栈名
		LineEnding:     zapcore.DefaultLineEnding, //默认的结尾\\n
		EncodeLevel:    zapcore.LowercaseLevelEncoder, //小写字母输出
		EncodeTime:     CustomTimeEncoder, //自定义时间格式
		EncodeDuration: zapcore.SecondsDurationEncoder, //编码间隔 s
		EncodeCaller:   zapcore.FullCallerEncoder, //控制打印的文件位置是绝对路径,ShortCallerEncoder 是相对路径
	}
    //根据配置文件重新配置编码颜色和字体
	switch {
	case cfg.EncodeLevel == \"LowercaseLevelEncoder\": // 小写编码器(默认)
		config.EncodeLevel = zapcore.LowercaseLevelEncoder
	case cfg.EncodeLevel == \"LowercaseColorLevelEncoder\": // 小写编码器带颜色
		config.EncodeLevel = zapcore.LowercaseColorLevelEncoder
	case cfg.EncodeLevel == \"CapitalLevelEncoder\": // 大写编码器
		config.EncodeLevel = zapcore.CapitalLevelEncoder
	case cfg.EncodeLevel == \"CapitalColorLevelEncoder\": // 大写编码器带颜色
		config.EncodeLevel = zapcore.CapitalColorLevelEncoder
	default:
		config.EncodeLevel = zapcore.LowercaseLevelEncoder
	}
	return config
}

CustomTimeEncoder函数

用于自定义日志前缀的输出格式

// 自定义日志输出时间格式
// 输出格式为 prfix + 具体的时间日期
func CustomTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
	cfg := global.Config.Zap
	enc.AppendString(t.Format(cfg.Prefix + \"2006-01-02 15:04:05.000\"))
}

pkg.GetWriteSyncer函数

用于切割文件,防止日志文件过大

func GetWriteSyncer(file string) zapcore.WriteSyncer {
	lumberJackLogger := &lumberjack.Logger{
		Filename:   file, // 日志文件的位置
		MaxSize:    10,   // 在进行切割之前,日志文件的最大大小(以MB为单位)
		MaxBackups: 200,  // 保留旧文件的最大个数
		MaxAge:     30,   // 保留旧文件的最大天数
		Compress:   true, // 是否压缩/归档旧文件
	}

	if global.Config.Zap.LogInConsole {
		return zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(lumberJackLogger))
	}
	return zapcore.AddSync(lumberJackLogger)
}

用法

伪代码,切勿直接粘贴复制

package global

var log *zap.Logger
package main

import (
	\"catering/initialize\"
    \"catering/global\"
)

func main() {
    initialize.InitZap()
    global.log.Info(\"test\")
}

打印日志示例

log
├── server_error.log
├── server_info.log

server_info.log

[catering]2022-03-17 17:36:42.200	[34minfo[0m	E:/GoPath/project/go-catering/admin/initialize/router.go:32	use middleware logger
[catering]2022-03-17 17:36:42.201	[34minfo[0m	E:/GoPath/project/go-catering/admin/initialize/router.go:36	use middleware cors
[catering]2022-03-17 17:36:42.201	[34minfo[0m	E:/GoPath/project/go-catering/admin/initialize/router.go:38	register swagger handler
[catering]2022-03-17 17:36:42.225	[34minfo[0m	E:/GoPath/project/go-catering/admin/initialize/router.go:104	router register success
[catering]2022-03-17 17:36:42.228	[34minfo[0m	E:/GoPath/project/go-catering/admin/core/server.go:27	server run success on 	{\"address\": \":8888\"}

server_error.log

[catering]2022-03-09 21:35:33.812	[31merror[0m	D:/goProject/src/catering/admin/pkg/app/request.go:13	Id.Required.	{\"message\": \"Id Can not be empty\"}
[catering]2022-03-09 21:35:33.813	[31merror[0m	D:/goProject/src/catering/admin/pkg/app/request.go:13	LevelName.Required.	{\"message\": \"LevelName Can not be empty\"}
[catering]2022-03-09 21:35:33.813	[31merror[0m	D:/goProject/src/catering/admin/pkg/app/request.go:13	UpNeedIntegration.Required.	{\"message\": \"UpNeedIntegration Can not be empty\"}

来源:https://www.cnblogs.com/xiaofua/p/16173894.html
本站部分图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » Golang Zap日志

相关推荐

  • 暂无文章