如何初始化 zap 记录器一次并在其他 Go 文件中重用它?

我正在尝试从漂亮的 Logrus(对调试非常有帮助)迁移我的应用程序,并引入 Uber 日志框架 Zap。


使用 Logrus,我只能初始化记录器一次并从其他 Go 文件中重用它,例如:


package main

import(

    // Print filename on log

    filename "github.com/onrik/logrus/filename"

    // Very nice log library

    log "github.com/sirupsen/logrus"

)


func main(){


// ==== SET LOGGING

    Formatter := new(log.TextFormatter)

    Formatter.TimestampFormat = "Jan _2 15:04:05.000000000"

    Formatter.FullTimestamp = true

    Formatter.ForceColors = true

    log.AddHook(filename.NewHook()) // Print filename + line at every log

    log.SetFormatter(Formatter)


}

从其他 Go 文件中,我可以重用该记录器而无需任何其他初始化:


// VerifyCommandLineInput is delegated to manage the inputer parameter provide with the input flag from command line

func VerifyCommandLineInput() datastructures.Configuration {

    log.Debug("VerifyCommandLineInput | Init a new configuration from the conf file")

    c := flag.String("config", "./conf/test.json", "Specify the configuration file.")

    flag.Parse()

    if strings.Compare(*c, "") == 0 {

        log.Fatal("VerifyCommandLineInput | Call the tool using --config conf/config.json")

    }

    file, err := os.Open(*c)

    if err != nil {

        log.Fatal("VerifyCommandLineInput | can't open config file: ", err)

    }

    defer file.Close()

    decoder := json.NewDecoder(file)

    cfg := datastructures.Configuration{}

    err = decoder.Decode(&cfg)

    if err != nil {

        log.Fatal("VerifyCommandLineInput | can't decode config JSON: ", err)

    }

    log.Debug("VerifyCommandLineInput | Conf loaded -> ", cfg)


    return cfg

}


我的问题是:使用 Zap 日志框架,如何在 main 函数中初始化日志并使用其他 Go 文件中的记录器?


慕无忌1623718
浏览 134回答 4
4回答

慕仙森

用 zaps 的实现替换默认的 go Global 记录器是可能的,但不鼓励。为什么要包含包全局记录器?由于许多其他日志记录包都包含全局记录器,因此许多应用程序并未设计为接受记录器作为显式参数。更改函数签名通常是一个重大更改,因此 zap 包含全局记录器来简化迁移。尽可能避免它们。根据您的需要,您可以在 main 中创建一个记录器并将其传递,或者在每个包中创建一个新的记录器。我选择在 main 中创建一个并将其传递,因为我使用的是 Atomic 记录器,它允许我在应用程序通过 API 调用运行时更改日志级别。有着使用 DI 和整合代码的悠久历史,它确实感觉像代码味道,但显然它对于 zap 如何通过单例或全局传递它的性能明显更高。

长风秋雁

您可以在主函数中设置记录器并调用zap.ReplaceGlobals以将其用作默认的全局记录器。ReplaceGlobals 替换全局 Logger 和 SugaredLogger,并返回一个函数来恢复原始值。并发使用是安全的。

慕哥6287543

我认为避免替换默认的 go 记录器是个好主意,我的方法是为 zap 记录器的配置和初始化创建一个单独的包。它还提供了包装函数实现,在将 zap 更改为另一个日志记录工具时非常有用。package loggerimport (    "go.uber.org/zap"    "go.uber.org/zap/zapcore")var zapLog *zap.Loggerfunc init() {    var err error    config := zap.NewProductionConfig()    enccoderConfig := zap.NewProductionEncoderConfig()    zapcore.TimeEncoderOfLayout("Jan _2 15:04:05.000000000")    enccoderConfig.StacktraceKey = "" // to hide stacktrace info    config.EncoderConfig = enccoderConfig    zapLog, err = config.Build(zap.AddCallerSkip(1))    if err != nil {        panic(err)    }}func Info(message string, fields ...zap.Field) {    zapLog.Info(message, fields...)}func Debug(message string, fields ...zap.Field) {    zapLog.Debug(message, fields...)}func Error(message string, fields ...zap.Field) {    zapLog.Error(message, fields...)}func Fatal(message string, fields ...zap.Field) {    zapLog.Fatal(message, fields...)}所以您的项目中的任何其他文件将如下所示import "github.com/[your_repo_path_here]/logger"func SomeFunc() datastructures.Configuration {    logger.Debug("VerifyCommandLineInput | Init a new configuration from the conf file")    c := flag.String("config", "./conf/test.json", "Specify the configuration file.")    flag.Parse()if strings.Compare(*c, "") == 0 {        logger.Fatal("VerifyCommandLineInput | Call the tool using --config conf/config.json")    }    file, err := os.Open(*c)    if err != nil {        logger.Fatal("VerifyCommandLineInput | can't open config file: ", err)    }    defer file.Close()    decoder := json.NewDecoder(file)    cfg := datastructures.Configuration{}    err = decoder.Decode(&cfg)    if err != nil {        logger.Fatal("VerifyCommandLineInput | can't decode config JSON: ", err)    }    logger.Debug("VerifyCommandLineInput | Conf loaded -> ", cfg)    return cfg}

交互式爱情

初始化一个新日志并将其设置为全局。package mainimport(    "go.uber.org/zap"    "go.uber.org/zap/zapcore")func initZapLog() *zap.Logger {    config := zap.NewDevelopmentConfig()    config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder    config.EncoderConfig.TimeKey = "timestamp"    config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder    logger, _ := config.Build()    return logger}func main() {    loggerMgr := initZapLog()    zap.ReplaceGlobals(loggerMgr)    defer loggerMgr.Sync() // flushes buffer, if any    logger := loggerMgr.Sugar()    logger.Debug("START!")    db2.GetToken(`alessio`, `savi`, `pass`)    datastructure.LoadConfiguration()}您可以在其他 Go 文件中使用记录器:func GetToken(url, user, pass string) string {    var User datastructure.User    var data string    var jsonData []byte    User.User = user    User.Pass = pass    jsonData, err := json.Marshal(User)    if err != nil {        zap.S().Errorw("Error during marshalling...", err)        return ""    }    data = string(jsonData)    zap.S().Info("Data encoded => ", data)    return ""}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go