欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

GoLang基于zap日志庫的封裝過程詳解

 更新時(shí)間:2023年05月20日 10:44:19   作者:三杯溫開水  
Zap是我個(gè)人比較喜歡的日志庫,是uber開源的,有較好的性能,在項(xiàng)目開發(fā)中,經(jīng)常需要把程序運(yùn)行過程中各種信息記錄下來,有了詳細(xì)的日志有助于問題排查和功能優(yōu)化,這篇文章主要介紹了GoLang基于zap日志庫的封裝過程,想要詳細(xì)了解可以參考下文

zap日志封裝

Zap是一個(gè)高性能、結(jié)構(gòu)化日志庫,專為Go語言設(shè)計(jì)。它由Uber開源,并且在Go社區(qū)中非常受歡迎。它的設(shè)計(jì)目標(biāo)是提供一個(gè)簡單易用、高效穩(wěn)定、靈活可擴(kuò)展的日志系統(tǒng)。

以下是Zap的一些主要特點(diǎn):

1.高性能:Zap的性能非常出色,可以在不影響應(yīng)用程序性能的情況下記錄大量的日志。它的性能比其他Go語言的日志庫高出數(shù)倍,這使得它成為高負(fù)載生產(chǎn)環(huán)境中的不錯(cuò)選擇。

2.結(jié)構(gòu)化日志:Zap支持結(jié)構(gòu)化日志,這意味著你可以在日志中包含結(jié)構(gòu)化數(shù)據(jù),而不是只是簡單的文本。這個(gè)功能非常有用,因?yàn)樗梢宰屇愀菀椎貙θ罩具M(jìn)行分析和搜索。

3.可擴(kuò)展:Zap提供了一個(gè)靈活的接口,可以讓你輕松地添加自定義的日志輸出器和格式化器。這使得它非常適合在大型項(xiàng)目中使用。

4.模塊化:Zap提供了一個(gè)模塊化的設(shè)計(jì),可以讓你選擇僅使用你需要的功能。這使得它非常適合在不同的項(xiàng)目中使用,因?yàn)槟憧梢灾皇褂媚阈枰墓δ?,而不必使用整個(gè)庫。

5.安全:Zap使用了一個(gè)嚴(yán)格的日志記錄器接口,這可以確保你的應(yīng)用程序的日志記錄不會被惡意軟件篡改或刪除。

實(shí)現(xiàn)方式

yaml配置文件

在根目錄下創(chuàng)建一個(gè)configs文件夾,然后再創(chuàng)建zap.debug.yaml

# zap logger configuration
Zap:
  Level: 'info'
  Prefix: 'gin-vue-admin'
  Format: 'console'
  Director: 'logs'
  EncodeLevel: 'LowercaseColorLevelEncoder'
  StacktraceKey: 'stacktrace'
  MaxAge: 30 # 默認(rèn)日志留存默認(rèn)以天為單位
  ShowLine: true
  LogInConsole: true

放置在全局Config中config.go

我的創(chuàng)建是使用protobuf快速創(chuàng)建出來的,如果你不是使用protobuf,你可以忽略這個(gè)tag。在根目錄下創(chuàng)建一個(gè)config文件,然后創(chuàng)建一個(gè)config.go 文件用來存放全局的config。

config.go 文件

type Config struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields
	Zap     *Zap     `protobuf:"bytes,2,opt,name=Zap,proto3" json:"Zap,omitempty"`
}
// Zap zap logger config
type Zap struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields
	// Level 級別
	Level string `protobuf:"bytes,1,opt,name=Level,proto3" json:"Level,omitempty"`
	// Prefix 日志前綴
	Prefix string `protobuf:"bytes,2,opt,name=Prefix,proto3" json:"Prefix,omitempty"`
	// Format 輸出
	Format string `protobuf:"bytes,3,opt,name=Format,proto3" json:"Format,omitempty"`
	// Director 日志文件夾
	Director string `protobuf:"bytes,4,opt,name=Director,proto3" json:"Director,omitempty"`
	// EncodeLevel 編碼級
	EncodeLevel string `protobuf:"bytes,5,opt,name=EncodeLevel,proto3" json:"EncodeLevel,omitempty"`
	// StacktraceKey 棧名
	StacktraceKey string `protobuf:"bytes,6,opt,name=StacktraceKey,proto3" json:"StacktraceKey,omitempty"`
	// MaxAge 日志留存時(shí)間
	MaxAge int64 `protobuf:"varint,7,opt,name=MaxAge,proto3" json:"MaxAge,omitempty"`
	// ShowLine 顯示行
	ShowLine bool `protobuf:"varint,8,opt,name=ShowLine,proto3" json:"ShowLine,omitempty"`
	// LogInConsole 輸出控制臺
	LogInConsole bool `protobuf:"varint,9,opt,name=LogInConsole,proto3" json:"LogInConsole,omitempty"`
}

創(chuàng)建zap.go

然后再config文件夾再創(chuàng)建zap.go文件,該文件主要是用來將我們配置文件的內(nèi)容轉(zhuǎn)換成為zap所認(rèn)識的內(nèi)容。

type LevelEncoder int
// ZapEncodeLevel 根據(jù) EncodeLevel 返回 zapcore.LevelEncoder
func (x *Zap) ZapEncodeLevel() zapcore.LevelEncoder {
	switch {
	case x.EncodeLevel == "LowercaseLevelEncoder": // 小寫編碼器(默認(rèn))
		return zapcore.LowercaseLevelEncoder
	case x.EncodeLevel == "LowercaseColorLevelEncoder": // 小寫編碼器帶顏色
		return zapcore.LowercaseColorLevelEncoder
	case x.EncodeLevel == "CapitalLevelEncoder": // 大寫編碼器
		return zapcore.CapitalLevelEncoder
	case x.EncodeLevel == "CapitalColorLevelEncoder": // 大寫編碼器帶顏色
		return zapcore.CapitalColorLevelEncoder
	default:
		return zapcore.LowercaseLevelEncoder
	}
}
// TransportLevel 根據(jù)字符串轉(zhuǎn)化為 zapcore.Level
func (x *Zap) TransportLevel() zapcore.Level {
	x.Level = strings.ToLower(x.Level)
	switch x.Level {
	case "debug":
		return zapcore.DebugLevel
	case "info":
		return zapcore.InfoLevel
	case "warn":
		return zapcore.WarnLevel
	case "error":
		return zapcore.WarnLevel
	case "dpanic":
		return zapcore.DPanicLevel
	case "panic":
		return zapcore.PanicLevel
	case "fatal":
		return zapcore.FatalLevel
	default:
		return zapcore.DebugLevel
	}
}

創(chuàng)建核心文件core

這里我主要放置一些Initialization 初始化的方法,比如gorm、viper、zap等一些核心的內(nèi)容。

創(chuàng)建zap.go

在core文件中創(chuàng)建zap.go 文件,該文件主要是初始化自己配置的zap日志,一般會把日志分割、日志存放地、注冊到全局等放置在這里,當(dāng)然為了讓代碼更加整潔和可閱讀性下,我們會對這里封裝成為方法。注: _zap 命名方式是因?yàn)楹蛕ap包重名了,可以根據(jù)自己喜好命名,但是這樣的命明也就是僅在該文件下生效,你可以認(rèn)為這樣變成了所謂的私有性

core/zap.go

var Zap = new(_zap)
type _zap struct{}
// Initialization 初始化
func (c *_zap) Initialization() {
	ok, _ := utils.Directory.PathExists(global.Config.Zap.Director)
	if !ok { // 判斷是否有 global.Config.Zap.Director 文件夾
		fmt.Printf("create %v directory\n", global.Config.Zap.Director)
		_ = os.Mkdir(global.Config.Zap.Director, os.ModePerm)
	}
	cores := internal.Zap.GetZapCores()         // 獲取 zap 核心切片
	logger := zap.New(zapcore.NewTee(cores...)) // 初始化 zap.Logger
	if global.Config.Zap.ShowLine {             // 判斷是否顯示行
		logger = logger.WithOptions(zap.AddCaller())
	}
	zap.ReplaceGlobals(logger) // logger 注冊到全局, 通過 zap.L() 調(diào)用日志組件
}

創(chuàng)建私有訪問方法

在core文件夾下創(chuàng)建interal文件中,這個(gè)internal的方法僅能在這個(gè)core下的文件才可以進(jìn)行訪問,其他文件夾比如service、api、util等文件夾無法訪問,這樣使得這些方法不會泄漏導(dǎo)致程序結(jié)構(gòu)的污染性,我個(gè)人也比較喜歡這樣去命名以及去寫代碼。注:下列寫法:core/interal/zap.go ,但是我們調(diào)取interal文件夾的方法不需要通過core去調(diào)取,直接使用interal進(jìn)行訪問。

core/interal/zap.go

var Zap = new(_zap)
type _zap struct{}
// GetEncoder 獲取 zapcore.Encoder
func (z *_zap) GetEncoder() zapcore.Encoder {
    // 日志的內(nèi)容格式有 控制臺 和 json
	if global.Config.Zap.Format == "json" {
		return zapcore.NewJSONEncoder(z.GetEncoderConfig())
	}
	return zapcore.NewConsoleEncoder(z.GetEncoderConfig())
}
// GetEncoderConfig 獲取zapcore.EncoderConfig
func (z *_zap) GetEncoderConfig() zapcore.EncoderConfig {
	return zapcore.EncoderConfig{
		MessageKey:     "message",
		LevelKey:       "level",
		TimeKey:        "time",
		NameKey:        "logger",
		CallerKey:      "caller",
		StacktraceKey:  global.Config.Zap.StacktraceKey,
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    global.Config.Zap.ZapEncodeLevel(),
		EncodeTime:     z.CustomTimeEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.FullCallerEncoder,
	}
}
// GetEncoderCore 獲取Encoder的 zapcore.Core
func (z *_zap) GetEncoderCore(l zapcore.Level, level zap.LevelEnablerFunc) zapcore.Core {
	syncer, err := FileRotatelogs.GetWriteSyncer(l.String()) // 使用file-rotatelogs進(jìn)行日志分割
	if err != nil {
		fmt.Printf("Get Write Syncer Failed err:%v", err.Error())
		return nil
	}
	return zapcore.NewCore(z.GetEncoder(), syncer, level)
}
// CustomTimeEncoder 自定義日志輸出時(shí)間格式
func (z *_zap) CustomTimeEncoder(t time.Time, encoder zapcore.PrimitiveArrayEncoder) {
	encoder.AppendString(global.Config.Zap.Prefix + " " + t.Format("2006-01-02 15:04:05.000"))
}
// GetZapCores 根據(jù)配置文件的Level獲取 []zapcore.Core
func (z *_zap) GetZapCores() []zapcore.Core {
	cores := make([]zapcore.Core, 0, 7)
	for level := global.Config.Zap.TransportLevel(); level <= zapcore.FatalLevel; level++ {
		cores = append(cores, z.GetEncoderCore(level, z.GetLevelPriority(level)))
	}
	return cores
}
// GetLevelPriority 根據(jù) zapcore.Level 獲取 zap.LevelEnablerFunc
func (z *_zap) GetLevelPriority(level zapcore.Level) zap.LevelEnablerFunc {
	switch level {
	case zapcore.DebugLevel:
		return func(level zapcore.Level) bool { // 調(diào)試級別
			return level == zap.DebugLevel
		}
	case zapcore.InfoLevel:
		return func(level zapcore.Level) bool { // 日志級別
			return level == zap.InfoLevel
		}
	case zapcore.WarnLevel:
		return func(level zapcore.Level) bool { // 警告級別
			return level == zap.WarnLevel
		}
	case zapcore.ErrorLevel:
		return func(level zapcore.Level) bool { // 錯(cuò)誤級別
			return level == zap.ErrorLevel
		}
	case zapcore.DPanicLevel:
		return func(level zapcore.Level) bool { // dpanic級別
			return level == zap.DPanicLevel
		}
	case zapcore.PanicLevel:
		return func(level zapcore.Level) bool { // panic級別
			return level == zap.PanicLevel
		}
	case zapcore.FatalLevel:
		return func(level zapcore.Level) bool { // 終止級別
			return level == zap.FatalLevel
		}
	default:
		return func(level zapcore.Level) bool { // 調(diào)試級別
			return level == zap.DebugLevel
		}
	}
}

在main中注冊

在根目錄下創(chuàng)建一個(gè)main.go文件(這個(gè)就不多啰嗦了…)

main.go

func main() {
	core.Zap.Initialization()
}

到此這篇關(guān)于GoLang基于zap日志庫的封裝過程詳解的文章就介紹到這了,更多相關(guān)Go zap日志封裝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go Java算法之Excel表列名稱示例詳解

    Go Java算法之Excel表列名稱示例詳解

    這篇文章主要為大家介紹了Go Java算法之Excel表列名稱示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • golang遍歷map的方法小結(jié)

    golang遍歷map的方法小結(jié)

    在Go語言中,使用range關(guān)鍵字可以遍歷map,返回鍵和值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • Go 在 MongoDB 中常用查詢與修改的操作

    Go 在 MongoDB 中常用查詢與修改的操作

    這篇文章主要介紹了Go 在 MongoDB 中常用查詢與修改的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • go日志系統(tǒng)logrus顯示文件和行號的操作

    go日志系統(tǒng)logrus顯示文件和行號的操作

    這篇文章主要介紹了go日志系統(tǒng)logrus顯示文件和行號的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • golang中set數(shù)據(jù)結(jié)構(gòu)的使用示例

    golang中set數(shù)據(jù)結(jié)構(gòu)的使用示例

    本文主要介紹了golang中set數(shù)據(jù)結(jié)構(gòu)的使用示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • golang操作Redis的實(shí)現(xiàn)示例

    golang操作Redis的實(shí)現(xiàn)示例

    本文主要介紹了golang操作Redis的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-04-04
  • 使用Golang的Context管理上下文的方法

    使用Golang的Context管理上下文的方法

    這篇文章主要介紹了使用Golang的Context管理上下文的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Golang實(shí)現(xiàn)深拷貝reflect原理示例探究

    Golang實(shí)現(xiàn)深拷貝reflect原理示例探究

    這篇文章主要為大家介紹了Golang實(shí)現(xiàn)reflect深拷貝原理示例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • GoLang sync.Pool簡介與用法

    GoLang sync.Pool簡介與用法

    這篇文章主要介紹了GoLang sync.Pool簡介與用法,Pool是可伸縮、并發(fā)安全的臨時(shí)對象池,用來存放已經(jīng)分配但暫時(shí)不用的臨時(shí)對象,通過對象重用機(jī)制,緩解GC壓力,提高程序性能
    2023-01-01
  • goland 恢復(fù)已更改文件的操作

    goland 恢復(fù)已更改文件的操作

    這篇文章主要介紹了goland 恢復(fù)已更改文件的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04

最新評論