首页 > 其他分享 >06-Go日志库Zap简单二次封装

06-Go日志库Zap简单二次封装

时间:2022-12-14 10:56:17浏览次数:52  
标签:zapcore 06 err func Go return 日志 Logger Zap

Go日志库Zap简单二次封装

1. 在项目根目录或者项目其他目录下创建二次封装代码存放目录zaplog,其他目录名称也可以

2. 新建config.go文件和zaplog文件,文件内容如下:

config.go
// Package zaplog 封装zap日志库,配置文件
// @Author: Alnk
// @Description: 二次封装开源zap日志库
// @File: zaplog
// @Date: 2022/12/12 14:20
package zaplog

// 定义默认的常量
const (
	defaultBaseDirectoryName  = "logs"      // 日志根目录
	defaultInfoDirectoryName  = "info"      // info日志目录
	defaultWarnDirectoryName  = "warn"      // warn日志目录
	defaultErrorDirectoryName = "error"     // error日志目录
	defaultInfoFileName       = "info.log"  // info日志文件
	defaultWarnFileName       = "warn.log"  // warn日志文件
	defaultErrorFileName      = "error.log" // error日志文件
	defaultLogFileMaxSize     = 128         // 日志文件大小,单位:MB
	defaultLogFileMaxBackups  = 180         // 日志文件保留个数 多于180个文件后,清理比价旧的日志
	defaultLogFileMaxAge      = 1           // 日志文件一天一切隔
	defaultLogFileCompress    = false       // 日志文件是否压缩
	defaultLogPrintTag        = false       // true:在终端和文件同时输出日志; false:只在文件输出日志

)

// Config 配置文件结构体
type Config struct {
	BaseDirectoryName  string
	InfoDirectoryName  string
	WarnDirectoryName  string
	ErrorDirectoryName string
	InfoFileName       string
	WarnFileName       string
	ErrorFileName      string
	LogFileMaxSize     int
	LogFileMaxBackups  int
	LogFileMaxAge      int
	LogFileCompress    bool
	LogPrintTag        bool
}

// Option 定义配置选项函数
type Option func(*Config)

// SetBaseDirectoryName 自定义日志根目录
func SetBaseDirectoryName(name string) Option {
	return func(c *Config) {
		c.BaseDirectoryName = name
	}
}

// SetInfoDirectoryName 自定义info日志目录
func SetInfoDirectoryName(name string) Option {
	return func(c *Config) {
		c.InfoDirectoryName = name
	}
}

// SetWarnDirectoryName 自定义warn日志目录
func SetWarnDirectoryName(name string) Option {
	return func(c *Config) {
		c.WarnDirectoryName = name
	}
}

// SetErrorDirectoryName 自定义error日志目录
func SetErrorDirectoryName(name string) Option {
	return func(c *Config) {
		c.ErrorDirectoryName = name
	}
}

// SetInfoFileName 自定义info文件名
func SetInfoFileName(name string) Option {
	return func(c *Config) {
		c.InfoFileName = name
	}
}

// SetWarnFileName 自定义warn文件名
func SetWarnFileName(name string) Option {
	return func(c *Config) {
		c.WarnFileName = name
	}
}

// SetErrorFileName 自定义error文件名
func SetErrorFileName(name string) Option {
	return func(c *Config) {
		c.ErrorFileName = name
	}
}

// SetLogFileMaxSize 自定义日志文件大小
func SetLogFileMaxSize(size int) Option {
	return func(c *Config) {
		c.LogFileMaxSize = size
	}
}

// SetLogFileMaxBackups 自定义日志文件保留个数
func SetLogFileMaxBackups(size int) Option {
	return func(c *Config) {
		c.LogFileMaxBackups = size
	}
}

// SetLogFileMaxAge 自定义日志文件切隔间隔
func SetLogFileMaxAge(size int) Option {
	return func(c *Config) {
		c.LogFileMaxAge = size
	}
}

// SetLogFileCompress 自定义日志文件是否压缩
func SetLogFileCompress(compress bool) Option {
	return func(c *Config) {
		c.LogFileCompress = compress
	}
}

// SetLogPrintTag 自定义日志输出标记位 true:在终端和文件同时输出日志; false:只在文件输出日志
func SetLogPrintTag(tag bool) Option {
	return func(c *Config) {
		c.LogPrintTag = tag
	}
}

// NewConfig 应用函数选项配置
func NewConfig(opts ...Option) Config {
	// 初始化默认值
	defaultConfig := Config{
		BaseDirectoryName:  defaultBaseDirectoryName,
		InfoDirectoryName:  defaultInfoDirectoryName,
		WarnDirectoryName:  defaultWarnDirectoryName,
		ErrorDirectoryName: defaultErrorDirectoryName,
		InfoFileName:       defaultInfoFileName,
		WarnFileName:       defaultWarnFileName,
		ErrorFileName:      defaultErrorFileName,
		LogFileMaxSize:     defaultLogFileMaxSize,
		LogFileMaxBackups:  defaultLogFileMaxBackups,
		LogFileMaxAge:      defaultLogFileMaxAge,
		LogFileCompress:    defaultLogFileCompress,
		LogPrintTag:        defaultLogPrintTag,
	}

	// 依次调用opts函数列表中的函数,为结构体成员赋值
	for _, opt := range opts {
		opt(&defaultConfig)
	}

	return defaultConfig
}
zaplog.go
// Package zaplog 封装zap日志库主程序文件
// @Author: Alnk
// @Description: 二次封装开源zap日志库
// @File: zaplog
// @Date: 2022/12/12 17:43
package zaplog

import (
	"fmt"
	"io"
	"os"
	"time"

	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

// Logger 全局变量,导出给调用者使用
var Logger *zap.Logger

// Init 初始化日志相关目录
func Init(config Config) error {
	// 创建日志根目录
	if _, err := os.Stat(config.BaseDirectoryName); os.IsNotExist(err) {
		err := os.MkdirAll(config.BaseDirectoryName, os.ModePerm)
		if err != nil {
			return fmt.Errorf("error creating directory, err: %v", err)
		}
	}

	// 创建日志子目录
	if err := os.MkdirAll(fmt.Sprintf("%s/%s", config.BaseDirectoryName, config.InfoDirectoryName), os.ModePerm); err != nil {
		return fmt.Errorf("error creating info directory, err: %v", err)
	}
	if err := os.MkdirAll(fmt.Sprintf("%s/%s", config.BaseDirectoryName, config.WarnDirectoryName), os.ModePerm); err != nil {
		return fmt.Errorf("error creating warn directory, err: %v", err)
	}
	if err := os.MkdirAll(fmt.Sprintf("%s/%s", config.BaseDirectoryName, config.ErrorDirectoryName), os.ModePerm); err != nil {
		return fmt.Errorf("error creating err directory, err: %v", err)
	}

	// 自定义初始化zap库
	initLogger(config)

	return nil
}

// getWriter 获取wirter文件写入
func getWriter(logBasePath, logLevelPath, LogFileName string, config Config) io.Writer {
	return &lumberjack.Logger{
		Filename:   fmt.Sprintf("%s/%s/%s", logBasePath, logLevelPath, LogFileName),
		MaxBackups: config.LogFileMaxBackups,
		MaxSize:    config.LogFileMaxSize,
		MaxAge:     config.LogFileMaxAge,
		Compress:   config.LogFileCompress,
	}
}

// initLog 初始化日志
func initLogger(c Config) {
	// 获取io.Writer实现
	infoWriter := getWriter(c.BaseDirectoryName, c.InfoDirectoryName, c.InfoFileName, c)
	warnWriter := getWriter(c.BaseDirectoryName, c.WarnDirectoryName, c.WarnFileName, c)
	errWriter := getWriter(c.BaseDirectoryName, c.ErrorDirectoryName, c.ErrorFileName, c)

	// 获取日志默认配置
	encoderConfig := zap.NewProductionEncoderConfig()

	// 自定义日志输出格式
	// 修改TimeKey
	encoderConfig.TimeKey = "time"
	// 修改MessageKey
	encoderConfig.MessageKey = "message"
	// 时间格式符合人类观看
	encoderConfig.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
		enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
	}
	// 日志等级大写INFO
	encoderConfig.EncodeLevel = func(lvl zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
		enc.AppendString(lvl.CapitalString())
	}
	// 日志打印时所处代码位置
	encoderConfig.EncodeCaller = func(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
		enc.AppendString(caller.TrimmedPath())
	}
	// 加载自定义配置为json格式
	encoder := zapcore.NewJSONEncoder(encoderConfig)

	// 自定义日志级别 info
	infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl <= zap.InfoLevel && lvl >= zap.DebugLevel
	})
	// 自定义日志级别 warn
	warnLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl <= zap.WarnLevel && lvl > zap.InfoLevel
	})
	// 自定义日志级别 err
	errLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl <= zap.FatalLevel && lvl > zap.WarnLevel
	})

	// 日志文件输出位置
	var core zapcore.Core
	if c.LogPrintTag {
		//同时在文件和终端输出日志
		core = zapcore.NewTee(
			zapcore.NewCore(encoder, zapcore.AddSync(infoWriter), infoLevel), // info级别日志
			zapcore.NewCore(encoder, zapcore.AddSync(warnWriter), warnLevel), // warn级别日志
			zapcore.NewCore(encoder, zapcore.AddSync(errWriter), errLevel),   // error级别日志
			zapcore.NewCore(encoder, zapcore.Lock(os.Stdout), zap.DebugLevel),
		)
	} else {
		//只在文件输出日志
		core = zapcore.NewTee(
			zapcore.NewCore(encoder, zapcore.AddSync(infoWriter), infoLevel), // info级别日志
			zapcore.NewCore(encoder, zapcore.AddSync(warnWriter), warnLevel), // warn级别日志
			zapcore.NewCore(encoder, zapcore.AddSync(errWriter), errLevel),   // error级别日志
		)
	}

	Logger = zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1))
}

3. 导入zaplog包,进行初始化以及日志记录(示例)

package main

import (
	"fmt"
	"log"
	"time"

	"github.com/alnkzap/zaplog"
)

func main() {
    // 自定义配置,每个配置项的含义可以查看封装代码中的注释
	//c := NewConfig(
	//	SetBaseDirectoryName("alnklog"),
	//	SetInfoDirectoryName("alnkinfo"),
	//	SetWarnDirectoryName("alnkwarn"),
	//	SetErrorDirectoryName("alnkerr"),
	//	SetInfoFileName("alnk_info"),
	//	SetWarnFileName("alnk_warn"),
	//	SetErrorFileName("alnk_err"),
	//	SetLogFileMaxSize(1),
	//	SetLogFileMaxBackups(1),
	//	SetLogFileMaxAge(1),
	//	SetLogFileCompress(true),
	//	SetLogPrintTag(true),
	//)
    
    // 默认配置
	c := zaplog.NewConfig() 
	if err := zaplog.Init(c); err != nil {
		log.Println(err)
	}

	testLogger()

}

func testLogger() {
	startTime := time.Now()
    
	for i := 0; i < 1000000; i++ {
        // 标准记录
		zaplog.Logger.Info("Logger info")
		zaplog.Logger.Warn("Logger warn")
		zaplog.Logger.Error("Logger err")
        
        // 添加其他的key-value
        Logger.Info("Logger info", zap.Any("user", "alnk"))
	    Logger.Warn("Logger Warn", zap.Any("user", "alnk"))
	    Logger.Error("Logger Error", zap.Any("user", "alnk"))
	}
    
	fmt.Println("Logger执行时间: ", time.Since(startTime))
}

/* 输出记录
{"level":"ERROR","time":"2022-12-14 10:47:30.178","caller":"testing/testing.go:1439","message":"Logger err"}
{"level":"ERROR","time":"2022-12-14 10:47:30.179","caller":"testing/testing.go:1439","message":"Logger Error","user":"alnk"}

{"level":"INFO","time":"2022-12-14 10:47:30.131","caller":"testing/testing.go:1439","message":"Logger info"}
{"level":"INFO","time":"2022-12-14 10:47:30.179","caller":"testing/testing.go:1439","message":"Logger info","user":"alnk"}

{"level":"WARN","time":"2022-12-14 10:47:30.178","caller":"testing/testing.go:1439","message":"Logger warn"}
{"level":"WARN","time":"2022-12-14 10:47:30.179","caller":"testing/testing.go:1439","message":"Logger Warn","user":"alnk"}
*/

标签:zapcore,06,err,func,Go,return,日志,Logger,Zap
From: https://www.cnblogs.com/lichengguo/p/16981490.html

相关文章

  • go windows开发环境安装
    安装golang下载下载地址:https://golang.org/dl/安装默认安装路径:C:\ProgramFiles\Go一路点击下一步PS:升级go版本可以直接卸载旧版本,然后安装新版本,环境变量与已经......
  • 006 编程语言分类(我总不能扣内存条用计算机吧)
    把目录提前写出来(1),还是讲着讲着写出来(2)1:00操作系统协调硬件和软件(应用程序)英国的大资本家()--》奴隶主--》有一堆奴隶我是程序猿--》操作系统--》计算机编程语言人和计算机......
  • go实现聊天室【简洁版】
    go写了一个简洁版的聊天室实现功能1.广播用户登录2.广播群发消息3.修改当前登录用户名4.广播用户退出服务端代码packagemainimport( "log" "net" "strings")......
  • go 镜像输出一个树 mac模式
    递归写的很low,mac模式packagemainimport"fmt"typeTreeNodestruct{ Valueint Left*TreeNode right*TreeNode}funcmirrorTree(root*TreeNode)*TreeNo......
  • springMVC06(1-响应,2-类返回成JSON数据)
    一、大纲二、响应JSON数据(把你给的"类"转化成"JSON"数据)2.1:需要有"@ResponseBody"这个注解2.2:需要导入JSON坐标<dependency><groupId>com.fasterxml.......
  • golang的net包net.Dial和net.Listen
    在Go中,网络编程主要通过net包实现。支持包括TCP/IP、UDP、域名解析和Unix域socket等连接,此外,还通过net/http,net/rpc等提供了HTTP,RPC等主流应用层的连接协议。TCP服......
  • Go-15 Golang语言中time包以及日期函数
    packagemainimport( "fmt" "time")//Golangtime包以及日期函数funcmain(){ /* 1.time.Now()获取当前时间 2.Format方法会格式化输出日期字符串 3......
  • Django路由层补充,视图层解析
    目录Django路由层补充,视图层解析今日内容概要今日内容详细路由分发名称空间虚拟环境视图层之必会三板斧前端出现乱码JsonResponse对象视图层之request对象获取文件视图层之......
  • django框架四
    路由分发django中每个应用都可以有自己独立的urls.py(路由层)、templates文件夹(模板层)、static文件夹(静态文件资源)。基于以上特性多人开发项目就可以完全解耦合,之后......
  • Django路由层相关知识
    昨日内容回顾Django请求生命周期图处理一条请求与7个部分关联:客户端、网关服务接口、Django中间件、路由层、视图层、模板层、模型层。Django路由层的匹配静态......